Schnek
single-array-allocation.hpp
1 /*
2  * single-array-allocation.hpp
3  *
4  * Created on: 06 Nov 2022
5  * Author: Holger Schmitz
6  * Email: holger@notjustphysics.com
7  *
8  * Copyright 2012-2022 Holger Schmitz
9  *
10  * This file is part of Schnek.
11  *
12  * Schnek is free software: you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation, either version 3 of the License, or
15  * (at your option) any later version.
16  *
17  * Schnek is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with Schnek. If not, see <http://www.gnu.org/licenses/>.
24  *
25  */
26 
27 #ifndef SCHNEK_GRID_GRIDSTORAGE_SINGLEARRAYALLOCATION_HPP_
28 #define SCHNEK_GRID_GRIDSTORAGE_SINGLEARRAYALLOCATION_HPP_
29 
30 #include "../array.hpp"
31 
32 #include <memory>
33 #include <cmath>
34 #include <functional>
35 #include <map>
36 
37 
46 namespace schnek
47 {
48 
49  namespace internal {
57  template <typename T, typename SizeInfo>
59  {
60  public:
61  typedef std::function<void(const SizeInfo&)> UpdaterType;
62  private:
63  std::map<void*, UpdaterType> updaters;
64  public:
65  T *ptr;
66  SingleArrayAllocationData(): ptr(NULL) {}
68  delete[] ptr;
69  }
70 
71  void addUpdater(void* key, const UpdaterType &updater) {
72  updaters[key] = updater;
73  }
74 
75  void removeUpdater(void* key) {
76  updaters.erase(key);
77  }
78 
79  void update(const SizeInfo& sizeInfo) {
80  for (auto& updater: updaters) {
81  updater.second(sizeInfo);
82  }
83  }
84  };
85  }
86 
95  template <typename T, size_t rank>
97  {
98  public:
101 
104  protected:
105  struct SizeInfo {
106  IndexType lo;
107  IndexType hi;
108  };
109 
110  typedef std::function<void()> UpdaterType;
111 
113  std::shared_ptr<internal::SingleArrayAllocationData<T, SizeInfo> > data;
114 
116  size_t size;
117 
119  RangeType range;
120 
122  IndexType dims;
123  public:
128 
133 
138 
143  protected:
148  void resizeImpl(const IndexType &lo, const IndexType &hi);
149 
155  void onUpdate(const UpdaterType &updater);
156 
157  private:
158  UpdaterType updater;
159 
163  void updateSizeInfo(const SizeInfo& sizeInfo);
164 
166  void deleteData();
167 
169  void newData(const IndexType &lo, const IndexType &hi);
170  };
171 
184  template <typename T, size_t rank>
186  {
187  public:
190 
193  protected:
194  struct SizeInfo {
195  IndexType lo;
196  IndexType hi;
197  size_t size;
198  size_t bufSize;
199  double avgSize;
200  double avgVar;
201  };
202 
203 
204  typedef std::function<void()> UpdaterType;
205 
207  std::shared_ptr<internal::SingleArrayAllocationData<T, SizeInfo> > data;
208 
210  size_t size;
211 
213  RangeType range;
214 
216  IndexType dims;
217 
218  private:
220  size_t bufSize;
221 
223  double avgSize;
224 
226  double avgVar;
227 
229  double r;
230 
231  public:
234 
237 
242 
247  protected:
252  void resizeImpl(const IndexType &lo, const IndexType &hi);
253 
259  void onUpdate(const UpdaterType &updater);
260 
261  private:
262  UpdaterType updater;
263 
269  void updateSizeInfo(const SizeInfo& sizeInfo);
270 
272  void deleteData();
273 
275  void newData(size_t size);
276  };
277 
278  //=================================================================
279  //=============== SingleArrayInstantAllocation ====================
280  //=================================================================
281 
282  template <typename T, size_t rank>
284  : data(new internal::SingleArrayAllocationData<T, SizeInfo>()), size(0)
285  {
286  this->data->addUpdater(this, [this](const SizeInfo& sizeInfo) { this->updateSizeInfo(sizeInfo); });
287  }
288 
289  template <typename T, size_t rank>
291  : data(other.data), size(other.size), range(other.range), dims(other.dims)
292  {
293  this->data->addUpdater(this, [this](const SizeInfo& sizeInfo) { this->updateSizeInfo(sizeInfo); });
294  };
295 
296  template <typename T, size_t rank>
298  {
299  this->data = other.data;
300  this->size = other.size;
301  this->range = other.range;
302  this->dims = other.dims;
303  this->data->addUpdater(this, [this](const SizeInfo& sizeInfo) { this->updateSizeInfo(sizeInfo); });
304  return *this;
305  };
306 
307  template <typename T, size_t rank>
309  {
310  this->data->removeUpdater(this);
311  }
312 
313  template <typename T, size_t rank>
314  void SingleArrayInstantAllocation<T, rank>::onUpdate(const UpdaterType &updater)
315  {
316  this->updater = updater;
317  }
318 
319  template <typename T, size_t rank>
321  size = 1;
322  range = RangeType{sizeInfo.lo, sizeInfo.hi};
323 
324  for (size_t d = 0; d < rank; ++d)
325  {
326  dims[d] = sizeInfo.hi[d] - sizeInfo.lo[d] + 1;
327  size *= dims[d];
328  }
329 
330  if (updater) {
331  updater();
332  }
333  }
334 
335  template <typename T, size_t rank>
337  {
338  this->deleteData();
339  this->newData(lo, hi);
340  data->update(SizeInfo{lo, hi});
341  }
342 
343  template <typename T, size_t rank>
345  {
346  if (data->ptr)
347  {
348  delete[] data->ptr;
349  }
350  data->ptr = NULL;
351  size = 0;
352  }
353 
354  template <typename T, size_t rank>
356  const IndexType &lo,
357  const IndexType &hi
358  )
359  {
360  size = 1;
361  range = RangeType{lo, hi};
362 
363  for (size_t d = 0; d < rank; ++d)
364  {
365  dims[d] = hi[d] - lo[d] + 1;
366  size *= dims[d];
367  }
368  data->ptr = new T[size];
369  }
370 
371  //=================================================================
372  //================== SingleArrayLazyAllocation ====================
373  //=================================================================
374 
375  template <typename T, size_t rank>
377  : data(new internal::SingleArrayAllocationData<T, SizeInfo>()),
378  size(0),
379  bufSize(0),
380  avgSize(0.0),
381  avgVar(0.0),
382  r(0.05)
383  {
384  this->data->addUpdater(this, [this](const SizeInfo& sizeInfo) { this->updateSizeInfo(sizeInfo); });
385  }
386 
387  template <typename T, size_t rank>
389  : data(other.data),
390  size(other.size),
391  range(other.range),
392  dims(other.dims),
393  bufSize(other.bufSize),
394  avgSize(other.avgSize),
395  avgVar(other.avgVar),
396  r(other.r)
397  {
398  this->data->addUpdater(this, [this](const SizeInfo& sizeInfo) { this->updateSizeInfo(sizeInfo); });
399  };
400 
401  template <typename T, size_t rank>
403  {
404  this->data = other.data;
405  this->size = other.size;
406  this->range = other.range;
407  this->dims = other.dims;
408  this->data->addUpdater(this, [this](const SizeInfo& sizeInfo) { this->updateSizeInfo(sizeInfo); });
409  return *this;
410  };
411 
412 
413  template <typename T, size_t rank>
415  {
416  this->data->removeUpdater(this);
417  }
418 
419  template <typename T, size_t rank>
420  void SingleArrayLazyAllocation<T, rank>::onUpdate(const UpdaterType &updater)
421  {
422  this->updater = updater;
423  }
424 
425  template <typename T, size_t rank>
427  size = 1;
428  range = RangeType{sizeInfo.lo, sizeInfo.hi};
429 
430  for (size_t d = 0; d < rank; ++d)
431  {
432  dims[d] = sizeInfo.hi[d] - sizeInfo.lo[d] + 1;
433  size *= dims[d];
434  }
435  bufSize = sizeInfo.bufSize;
436  avgSize = sizeInfo.avgSize;
437  avgVar = sizeInfo.avgVar;
438 
439  if (updater) {
440  updater();
441  }
442  }
443 
444  template <typename T, size_t rank>
446  {
447  size_t newSize = 1;
448  range = RangeType{lo, hi};
449 
450  for (size_t d = 0; d < rank; d++)
451  {
452  dims[d] = hi[d] - lo[d] + 1;
453  newSize *= dims[d];
454  }
455 
456  avgSize = r * newSize + (1 - r) * avgSize;
457  ptrdiff_t diff = newSize - avgSize;
458  avgVar = r * diff * diff + (1 - r) * avgVar;
459 
460  if ((newSize > bufSize) || (((newSize + 32.0 * sqrt(avgVar)) < bufSize) && (bufSize > 100)))
461  {
462  this->deleteData();
463  this->newData(newSize);
464  }
465  size = newSize;
466  this->data->update(SizeInfo{lo, hi, size, bufSize, avgSize, avgVar});
467  }
468 
469  template <typename T, size_t rank>
471  {
472  SCHNEK_TRACE_LOG(5, "Deleting pointer (" << (void *)data << "): size=" << size << " avgSize=" << avgSize << " avgVar=" << avgVar << " bufSize=" << bufSize);
473  if (data->ptr)
474  {
475  delete[] data->ptr;
476  }
477  data->ptr = NULL;
478  size = 0;
479  bufSize = 0;
480  }
481 
482  template <typename T, size_t rank>
484  size_t newSize)
485  {
486  bufSize = newSize + (size_t)(4 * sqrt(avgVar));
487  if (bufSize <= 0)
488  {
489  bufSize = 10;
490  }
491  data->ptr = new T[bufSize];
492  }
493 }
494 
495 #endif // SCHNEK_GRID_GRIDSTORAGE_SINGLEARRAYALLOCATION_HPP_
SingleArrayInstantAllocation()
Default constructor.
Definition: single-array-allocation.hpp:283
void resizeImpl(const IndexType &lo, const IndexType &hi)
resizes to grid with lower indices lo[0],...,lo[rank-1] and upper indices hi[0],...,hi[rank-1]
Definition: single-array-allocation.hpp:336
Array< size_t, rank > IndexType
The grid index type.
Definition: single-array-allocation.hpp:189
void onUpdate(const UpdaterType &updater)
Add an updater to the data.
Definition: single-array-allocation.hpp:314
Allocate a single array for multidimensional grids in C ordering.
Definition: single-array-allocation.hpp:96
SingleArrayInstantAllocation< T, rank > & operator=(const SingleArrayInstantAllocation< T, rank > &)
Assignment operator.
Definition: single-array-allocation.hpp:297
size_t size
The length of the allocated array.
Definition: single-array-allocation.hpp:116
Definition: algo.hpp:30
void resizeImpl(const IndexType &lo, const IndexType &hi)
resizes to grid with lower indices lo[0],...,lo[rank-1] and upper indices hi[0],...,hi[rank-1]
Definition: single-array-allocation.hpp:445
std::shared_ptr< internal::SingleArrayAllocationData< T, SizeInfo > > data
The pointer to the data.
Definition: single-array-allocation.hpp:113
~SingleArrayInstantAllocation()
destructor
Definition: single-array-allocation.hpp:308
std::shared_ptr< internal::SingleArrayAllocationData< T, SizeInfo > > data
The pointer to the data.
Definition: single-array-allocation.hpp:207
SingleArrayLazyAllocation()
Default constructor.
Definition: single-array-allocation.hpp:376
size_t size
The length of the array.
Definition: single-array-allocation.hpp:210
RangeType range
The lowest and highest coordinates in the grid (inclusive)
Definition: single-array-allocation.hpp:213
Range< int, rank > RangeType
The grid range type.
Definition: single-array-allocation.hpp:103
Array< int, rank > IndexType
The grid index type.
Definition: single-array-allocation.hpp:100
IndexType dims
The dimensions of the grid dims = high - low + 1
Definition: single-array-allocation.hpp:216
Range< size_t, rank > RangeType
The grid range type.
Definition: single-array-allocation.hpp:192
#define SCHNEK_TRACE_LOG(i, x)
Definition: logger.hpp:54
IndexType dims
The dimensions of the grid dims = high - low + 1
Definition: single-array-allocation.hpp:122
Definition: single-array-allocation.hpp:105
~SingleArrayLazyAllocation()
destructor
Definition: single-array-allocation.hpp:414
RangeType range
The lowest and highest coordinates in the grid (inclusive)
Definition: single-array-allocation.hpp:119
The data for a single array allocation.
Definition: single-array-allocation.hpp:58
SingleArrayLazyAllocation< T, rank > & operator=(const SingleArrayLazyAllocation< T, rank > &)
Assignment operator.
Definition: single-array-allocation.hpp:402
Definition: single-array-allocation.hpp:194
Allocate a single array for multidimensional grids in C ordering.
Definition: single-array-allocation.hpp:185
void onUpdate(const UpdaterType &updater)
Add an updater to the data.
Definition: single-array-allocation.hpp:420