Honeycomb  0.1
Component-Model Framework
Storage.h
Go to the documentation of this file.
1 // Honeycomb, Copyright (C) 2015 NewGamePlus Inc. Distributed under the Boost Software License v1.0.
2 #pragma once
3 
5 
6 namespace honey { namespace matrix { namespace priv
7 {
8 
9 template<class Subclass>
11 {
12  typedef typename Traits<Subclass>::Real Real;
13  //Elem type must be tracked because array const-ness must propagate down through descendant blocks and iters
14  typedef typename Traits<Subclass>::ElemT ElemT;
17  static const sdt s_size = s_rows != dynamic && s_cols != dynamic ? s_rows*s_cols : dynamic;
18  static const int options = Traits<Subclass>::options;
19  typedef typename Traits<Subclass>::Alloc Alloc;
20 
21  static_assert((s_rows == dynamic || s_rows >= 0) && (s_cols == dynamic || s_cols >= 0), "Matrix size must be zero or greater");
22 
23  const ElemT& operator()(sdt row, sdt col) const { return subc()(row, col); }
24  ElemT& operator()(sdt row, sdt col) { return subc()(row, col); }
25 
28  {
29  mt_unused(rows); mt_unused(cols);
30  assert(rows == -1 || s_rows == dynamic || rows == s_rows, sout() << "Can't change fixed row count from " << (sdt)s_rows << " to " << rows);
31  assert(cols == -1 || s_cols == dynamic || cols == s_cols, sout() << "Can't change fixed col count from " << (sdt)s_cols << " to " << cols);
32  }
33 
34  sdt rows() const { return subc().rows(); }
35  sdt cols() const { return subc().cols(); }
36  sdt size() const { return subc().size(); }
37 
38  const ElemT* data() const { return subc().data(); }
39  ElemT* data() { return subc().data(); }
40 
42  operator ElemT*() { return data(); }
43  operator const ElemT*() const { return data(); }
44 
46  const Subclass& subc() const { return static_cast<const Subclass&>(*this); }
47  Subclass& subc() { return static_cast<Subclass&>(*this); }
48 
49 protected:
50  void assertIndex(sdt i) const { mt_unused(i); assert(i >= 0 && i < size()); }
51  void assertIndex(sdt row, sdt col) const { mt_unused(row); mt_unused(col); assert(row >= 0 && row < rows() && col >= 0 && col < cols()); }
52  void assertSize(sdt size) const { mt_unused(size); assert(size >= 0 && size <= this->size()); }
53  void assertSize(sdt rows, sdt cols) const { mt_unused(rows); mt_unused(cols); assert(rows >= 0 && rows <= this->rows() && cols >= 0 && cols <= this->cols()); }
54 };
55 
57 template<class Src, class Dst>
59  { if (!src.size()) return; std::copy_n(src.data(), src.size(), dst.data()); }
61 template<class Dst>
62 void storageCopy(const typename StorageDense<Dst>::Real* src, StorageDense<Dst>& dst)
63  { if (!dst.size()) return; std::copy_n(src, dst.size(), dst.data()); }
64 
65 template<class Src>
66 void storageCopy(const StorageDense<Src>& src, typename StorageDense<Src>::Real* dst)
67  { if (!src.size()) return; std::copy_n(src.data(), src.size(), dst); }
68 
70 template<class Src, class Dst, class Func>
71 void storageTransform(const StorageDense<Src>& src, StorageDense<Dst>& dst, Func&& f)
72  { if (!src.size()) return; std::transform(src.data(), src.data() + src.size(), dst.data(), forward<Func>(f)); }
73 
75 template<class T>
77  { if (!store.size()) return; std::fill_n(store.data(), store.size(), f); }
79 template<class T>
80 void storageFillZero(StorageDense<T>& store) { if (!store.size()) return; std::fill_n(reinterpret_cast<uint8*>(store.data()), store.size()*sizeof(typename StorageDense<T>::Real), uint8(0)); }
81 
83 template<class T, class T2>
84 bool storageEqual(const StorageDense<T>& lhs, const StorageDense<T2>& rhs)
85 {
86  static_assert((std::is_same<typename StorageDense<T>::Real, typename StorageDense<T2>::Real>::value), "Different element type comparison not supported");
87  if (!lhs.size()) return true;
88  return memcmp(lhs.data(),rhs.data(),lhs.size()*sizeof(typename StorageDense<T>::Real)) == 0;
89 }
90 
91 
92 template<class Real, sdt Size, szt Align>
94 {
95  Real a[Size > 0 ? Size : 1];
96 };
97 
98 template<class Real, sdt Size>
99 struct StorageAutoArray<Real, Size, 16>
100 {
101  ALIGN(16) Real a[Size > 0 ? Size : 1];
102 };
103 
105 template<class Subclass>
106 class StorageAuto : public StorageDense<Subclass>
107 {
109 public:
110  using typename Super::Real;
111 
113  const Real* operator[](sdt row) const { this->assertIndex(row,0); return &data()[row*cols()]; }
114  Real* operator[](sdt row) { this->assertIndex(row,0); return &data()[row*cols()]; }
116  const Real& operator()(sdt i) const { this->assertIndex(i); return data()[i]; }
117  Real& operator()(sdt i) { this->assertIndex(i); return data()[i]; }
119  const Real& operator()(sdt row, sdt col) const { this->assertIndex(row,col); return data()[row*cols() + col]; }
120  Real& operator()(sdt row, sdt col) { this->assertIndex(row,col); return data()[row*cols() + col]; }
121 
122  sdt rows() const { return Super::s_rows; }
123  sdt cols() const { return Super::s_cols; }
124  sdt size() const { return Super::s_size; }
125 
127  const Real* data() const { return _a.a; }
128  Real* data() { return _a.a; }
129 
130 private:
132 };
133 
135 template<class Subclass>
136 class StorageDynamic : public StorageDense<Subclass>
137 {
139 public:
140  using Super::s_rows;
141  using Super::s_cols;
142  using Super::s_size;
143  using typename Super::Real;
144  using typename Super::Alloc;
145 
147  StorageDynamic() { init(); }
149  StorageDynamic(const StorageDynamic& rhs) { init(); setAllocator(rhs._alloc); operator=(rhs); }
151  StorageDynamic(StorageDynamic&& rhs) { init(); operator=(move(rhs)); }
152 
153  ~StorageDynamic() { freeAligned(_a, _alloc); }
154 
156  {
157  resize(rhs.rows(), rhs.cols());
158  if (size()) storageCopy(rhs, *this);
159  return *this;
160  }
161 
163  {
164  assert(s_rows == dynamic || rhs._rows == s_rows, sout() << "Can't change fixed row count from " << (sdt)s_rows << " to " << rhs._rows);
165  assert(s_cols == dynamic || rhs._cols == s_cols, sout() << "Can't change fixed col count from " << (sdt)s_cols << " to " << rhs._cols);
166  freeAligned(_a, _alloc);
167  _a = rhs._a;
168  _rows = rhs._rows;
169  _cols = rhs._cols;
170  _size = rhs._size;
171  _alloc = move(rhs._alloc);
172  rhs.init();
173  return *this;
174  }
175 
177  const Real* operator[](sdt row) const { this->assertIndex(row,0); return &data()[row*cols()]; }
178  Real* operator[](sdt row) { this->assertIndex(row,0); return &data()[row*cols()]; }
180  const Real& operator()(sdt i) const { this->assertIndex(i); return data()[i]; }
181  Real& operator()(sdt i) { this->assertIndex(i); return data()[i]; }
183  const Real& operator()(sdt row, sdt col) const { this->assertIndex(row,col); return data()[row*cols() + col]; }
184  Real& operator()(sdt row, sdt col) { this->assertIndex(row,col); return data()[row*cols() + col]; }
185 
187  {
188  if (rows == -1) rows = _rows;
189  if (cols == -1) cols = _cols;
190  assert(rows >= 0 && cols >= 0, "Matrix size must be zero or greater");
191  assert(s_rows == dynamic || rows == s_rows, sout() << "Can't change fixed row count from " << (sdt)s_rows << " to " << rows);
192  assert(s_cols == dynamic || cols == s_cols, sout() << "Can't change fixed col count from " << (sdt)s_cols << " to " << cols);
193  sdt size = rows*cols;
194  _rows = rows;
195  _cols = cols;
196  if (size == _size) return;
197  _size = size;
198  freeAligned(_a, _alloc); _a = nullptr;
199  if (_size == 0) return;
200  _a = allocAligned<Real>(_size, Option::getAlign<Super::options>::value, _alloc);
201  }
202 
203  sdt rows() const { return _rows; }
204  sdt cols() const { return _cols; }
205  sdt size() const { return _size; }
206 
208  Real* data() { return _a; }
209  const Real* data() const { return _a; }
210 
211 protected:
212  void setAllocator(const Alloc& alloc) { _alloc = alloc; }
213 
214 private:
215 
216  void init()
217  {
218  _a = nullptr;
219  _rows = s_rows == dynamic ? 0 : s_rows;
220  _cols = s_cols == dynamic ? 0 : s_cols;
221  _size = 0;
222  }
223 
224  Real* _a;
225  sdt _rows;
226  sdt _cols;
227  sdt _size;
228  Alloc _alloc;
229 };
230 
232 template<class Subclass>
233 struct Storage : public std::conditional< Traits<Subclass>::rows != dynamic && Traits<Subclass>::cols != dynamic,
234  StorageAuto<Subclass>, StorageDynamic<Subclass>>::type {};
235 
236 } } }
#define ALIGN(Bytes)
Align stuct.
Definition: Core.h:39
const Real * data() const
Definition: Storage.h:209
const Real * operator[](sdt row) const
Access matrix element with [row][column].
Definition: Storage.h:113
static const sdt dynamic
Definition: Traits.h:23
void storageFillZero(StorageBlock< T > &store)
Fill block storage with zeros.
Definition: Block.h:136
ElemT & operator()(sdt row, sdt col)
Definition: Storage.h:24
sdt size() const
Definition: Storage.h:124
void setAllocator(const Alloc &alloc)
Definition: Storage.h:212
~StorageDynamic()
Definition: Storage.h:153
Traits< Subclass >::Real Real
Definition: Storage.h:12
static const sdt s_cols
Definition: Storage.h:16
Traits< Subclass >::ElemT ElemT
Definition: Storage.h:14
Real & operator()(sdt i)
Definition: Storage.h:117
#define mt_unused(Param)
Remove the unused parameter warning.
Definition: Meta.h:20
Definition: Traits.h:37
Real * operator[](sdt row)
Definition: Storage.h:114
sdt size() const
Definition: Storage.h:36
ptrdiff_t sdt
Size difference type, shorthand for ptrdiff_t.
Definition: Core.h:92
StorageDynamic & operator=(const StorageDynamic &rhs)
Definition: Storage.h:155
const ElemT * data() const
Definition: Storage.h:38
bool storageEqual(const StorageBlock< T > &lhs, const StorageBlock< T2 > &rhs)
Test between block storages.
Definition: Block.h:157
const Real & operator()(sdt i) const
Access matrix element at index.
Definition: Storage.h:180
static const sdt s_rows
Definition: Storage.h:15
static const int options
Definition: Storage.h:18
const ElemT & operator()(sdt row, sdt col) const
Definition: Storage.h:23
Traits< Subclass >::Alloc Alloc
Definition: Storage.h:19
sdt rows() const
Definition: Storage.h:203
Chooses storage based on traits.
Definition: Storage.h:233
Real a[Size > 0?Size:1]
Definition: Storage.h:95
sdt cols() const
Definition: Storage.h:204
const Subclass & subc() const
Get the subclass that inherited from this base class.
Definition: Storage.h:46
static const sdt s_size
Definition: Storage.h:17
sdt size() const
Definition: Storage.h:205
unsigned char uint8
Definition: Core.h:12
void assertIndex(sdt i) const
Definition: Storage.h:50
StorageDynamic()
Default is null array.
Definition: Storage.h:147
ostringstream sout()
Shorthand to create ostringstream.
Definition: Stream.h:15
const Real * operator[](sdt row) const
Access matrix element with [row][column].
Definition: Storage.h:177
Definition: Storage.h:10
void storageTransform(const StorageBlock< Src > &src, StorageBlock< Dst > &dst, Func &&f)
Transform between block and dense storages.
Definition: Block.h:120
#define assert(...)
Forwards to assert_#args. See assert_1(), assert_2().
Definition: Debug.h:24
Definition: Traits.h:20
StorageDynamic(const StorageDynamic &rhs)
Init to copy of rhs.
Definition: Storage.h:149
sdt rows() const
Definition: Storage.h:122
Real * operator[](sdt row)
Definition: Storage.h:178
T * alloc(szt count=1)
Allocate memory for count number of T objects. Objects are not constructed.
Definition: Allocator.h:31
void resize(sdt rows, sdt cols)
Definition: Storage.h:186
Real & operator()(sdt row, sdt col)
Definition: Storage.h:184
sdt cols() const
Definition: Storage.h:123
Real & operator()(sdt i)
Definition: Storage.h:181
Real & operator()(sdt row, sdt col)
Definition: Storage.h:120
Subclass & subc()
Definition: Storage.h:47
Automatic (stack-compatible) dense storage.
Definition: Storage.h:106
StorageDynamic(StorageDynamic &&rhs)
Init to rhs and set rhs array to null.
Definition: Storage.h:151
void storageFill(StorageBlock< T > &store, typename StorageBlock< T >::Real f)
Fill block storage with scalar.
Definition: Block.h:128
Real * data()
Get as array.
Definition: Storage.h:208
Real * data()
Definition: Storage.h:128
sdt cols() const
Definition: Storage.h:35
const Real * data() const
Get as array.
Definition: Storage.h:127
sdt rows() const
Definition: Storage.h:34
StorageDynamic & operator=(StorageDynamic &&rhs)
Definition: Storage.h:162
void assertSize(sdt size) const
Definition: Storage.h:52
void storageCopy(const StorageBlock< Src > &src, StorageBlock< Dst > &dst)
Copy between block and dense storages.
Definition: Block.h:84
void freeAligned(T *p, Alloc &&a)
Deallocate aligned memory. Allocator element type must be int8.
Definition: Allocator.h:61
const Real & operator()(sdt i) const
Access matrix element at index.
Definition: Storage.h:116
dynamic (heap) dense storage
Definition: Storage.h:136
void resize(sdt rows, sdt cols)
Default resize, just asserts that fixed dimensions match args.
Definition: Storage.h:27
const Real & operator()(sdt row, sdt col) const
Access matrix element with (row, column)
Definition: Storage.h:183
Global Honeycomb namespace.
ElemT * data()
Definition: Storage.h:39
const Real & operator()(sdt row, sdt col) const
Access matrix element with (row, column)
Definition: Storage.h:119
void assertIndex(sdt row, sdt col) const
Definition: Storage.h:51
void assertSize(sdt rows, sdt cols) const
Definition: Storage.h:53