NUMCXX  0.13.20181108
Numerical library for small projects and teaching purposes
tarray.ixx
Go to the documentation of this file.
1 #include <cstdlib>
6 #include <cmath>
7 
8 namespace numcxx
9 {
10 
11  template<typename T>
12  inline TArray<T>::TArray(const std::initializer_list<T> &il ):TArray(il.size())
13  {
14  index i=0;
15  for (auto x = il.begin() ; x != il.end(); x++,i++) _data[i]= *x;
16  }
17 
18 
19  template <typename T>
20  inline TArray<T>::TArray(const std::initializer_list<std::initializer_list<T>> &il):
21  TArray(il.size(), il.begin()->size())
22  {
23  index i=0;
24 
25  for (auto jl = il.begin() ; jl != il.end(); jl++,i++)
26  {
27  index j=0;
28  for (auto x = jl->begin() ; x != jl->end(); x++,j++)
29  _data[_idx(i,j)]= *x;
30  }
31  }
32 
33  template <typename T, typename EXPR,
34  typename= typename std::enable_if<std::is_class<EXPR>::value, EXPR>::type>
35  inline TArray<T>& assign(TArray<T>& A, const EXPR& expr , const EXPR *x=0)
36  {
37  A.resize( expr.size() );
38  T *data=A.data();
39  for(index i=0; i<expr.size(); i++ ) data[i] = expr[i];
40  return A;
41  }
42 
43  template <typename T, typename VAL,
44  typename= typename std::enable_if<!std::is_class<VAL>::value, VAL>::type>
45  inline TArray<T>& assign(TArray<T>& A, const VAL& a)
46  {
47  T *data=A.data();
48  for(index i=0; i<A.size(); i++ ) data[i] = a;
49  return A;
50  }
51 
52  template <typename T, typename EXPR,
53  typename= typename std::enable_if<std::is_class<EXPR>::value, EXPR>::type>
54  inline void xadd(TArray<T>& A, const EXPR& expr , const EXPR *x=0)
55  {
56  A.resize( expr.size() );
57  T *data=A.data();
58  for(index i=0; i<expr.size(); i++ ) data[i] += expr[i];
59  }
60 
61 
62  template <typename T, typename VAL,
63  typename= typename std::enable_if<!std::is_class<VAL>::value, VAL>::type>
64  inline void xadd(TArray<T>& A, const VAL& a)
65  {
66  T *data=A.data();
67  for(index i=0; i<A.size(); i++ )data[i] += a;
68  }
69 
70 
71  template <typename T, typename EXPR,
72  typename= typename std::enable_if<std::is_class<EXPR>::value, EXPR>::type>
73  inline void xsub(TArray<T>& A, const EXPR& expr , const EXPR *x=0)
74  {
75  A.resize( expr.size() );
76  T *data=A.data();
77  for(index i=0; i<expr.size(); i++ ) data[i] -= expr[i];
78  }
79 
80 
81  template <typename T, typename VAL,
82  typename= typename std::enable_if<!std::is_class<VAL>::value, VAL>::type>
83  inline void xsub(TArray<T>& A, const VAL& a)
84  {
85  T *data=A.data();
86  for(index i=0; i<A.size(); i++ )data[i] -= a;
87  }
88 
89 
90  template <typename T, typename EXPR,
91  typename= typename std::enable_if<std::is_class<EXPR>::value, EXPR>::type>
92  inline void xmul(TArray<T>& A, const EXPR& expr , const EXPR *x=0)
93  {
94  A.resize( expr.size() );
95  T *data=A.data();
96  for(index i=0; i<expr.size(); i++ ) data[i] *= expr[i];
97  }
98 
99 
100  template <typename T, typename VAL,
101  typename= typename std::enable_if<!std::is_class<VAL>::value, VAL>::type>
102  inline void xmul(TArray<T>& A, const VAL& a)
103  {
104  T *data=A.data();
105  for(index i=0; i<A.size(); i++ )data[i] *= a;
106  }
107 
108 
109  template <typename T, typename EXPR,
110  typename= typename std::enable_if<std::is_class<EXPR>::value, EXPR>::type>
111  inline void xdiv(TArray<T>& A, const EXPR& expr , const EXPR *x=0)
112  {
113  A.resize( expr.size() );
114  T *data=A.data();
115  for(index i=0; i<expr.size(); i++ ) data[i] /= expr[i];
116  }
117 
118 
119  template <typename T, typename VAL,
120  typename= typename std::enable_if<!std::is_class<VAL>::value, VAL>::type>
121  inline void xdiv(TArray<T>& A, const VAL& a)
122  {
123  T *data=A.data();
124  for(index i=0; i<A.size(); i++ )data[i] /= a;
125  }
126 
127  template <typename T>
128  inline void TArray<T>::_check_bounds(index acc_dim, index acc_ndim, index acc_idx) const
129  {
130  if (acc_ndim!=_ndim)
131  {
132  char errormsg[80];
133  snprintf(errormsg,80,"numcxx::TArray::_check_bounds: attempt of %uD access of %uD array",acc_ndim,_ndim);
134  throw std::out_of_range(errormsg);
135  }
136  if ((acc_idx<0) || (acc_idx>=_shape[acc_dim]))
137  {
138  char errormsg[80];
139  snprintf(errormsg,80,"numcxx::TArray::_check_bounds: _shape[%u]=%u but i%u=%u",acc_dim,_shape[acc_dim],acc_dim,acc_idx);
140  throw std::out_of_range(errormsg);
141  }
142  }
143 
144  template <typename T>
145  inline void TArray<T>::_assert_square() const
146  {
147  if (_ndim!=2 || _shape[0]!=_shape[1])
148  {
149  char errormsg[80];
150  snprintf(errormsg,80,"numcxx::TArray::_assert_square: unexpected non-equal array dimensions\n");
151  throw std::length_error(errormsg);
152  }
153  }
154 
155  template <typename T>
156  inline index TArray<T>::_idx(index i0) const
157  {
158 #ifdef NUMCXX_CHECK_BOUNDS
159  _check_bounds(0,1,i0);
160 #endif
161  return i0;
162  }
163 
164  template <typename T>
165  inline index TArray<T>::_idx(index i0,index i1) const
166  {
167 #ifdef NUMCXX_CHECK_BOUNDS
168  _check_bounds(0,2,i0);
169  _check_bounds(1,2,i1);
170 #endif
171  return i0*_shape[1]+i1;
172  }
173 
174  template <typename T>
175  inline index TArray<T>::_idx(index i0,index i1, index i2) const
176  {
177 #ifdef NUMCXX_CHECK_BOUNDS
178  _check_bounds(0,3,i0);
179  _check_bounds(1,3,i1);
180  _check_bounds(2,3,i2);
181 #endif
182  return (i0*_shape[0]+i1)*_shape[1]+i2;
183  }
184 
185  template <typename T>
186  inline TArray<T>::TArray(index n0, index n1):
187  _ndim(2),
188  _shape{n0,n1},
189  _size((size_t)n0*(size_t)n1),
190  _data((T*)malloc(sizeof(T)*_size)),
191  _deleter([](T*p){free(p);})
192  {if (_data==nullptr) throw std::runtime_error("numcxx: TArray::TArray(): Memory allocation failed"); };
193 
194  template <typename T>
196  _ndim(1),
197  _shape{n0},
198  _size(n0),
199  _data((T*)malloc(sizeof(T)*_size)),
200  _deleter([](T*p){free(p);})
201  {if (_data==nullptr) throw std::runtime_error("numcxx: TArray::TArray(): Memory allocation failed"); };
202 
203  template <typename T>
204  inline TArray<T>::TArray(index n0, T*data,std::function<void(T*p)> deleter):
205  _data(data),
206  _ndim(1),
207  _shape{n0},
208  _size(n0),
209  _deleter(deleter)
210  {};
211 
212  template <typename T>
213  inline TArray<T>::TArray(index n0, T*data,std::shared_ptr<void> datamanager):
214  TArray(n0,data,[](T*p){;}){_datamanager=datamanager;};
215 
216  template <typename T>
217  inline TArray<T>::TArray(index n0, index n1,T*data, std::function<void(T*p)> deleter):
218  _data(data),
219  _ndim(2),
220  _shape{n0,n1},
221  _size(n0*n1),
222  _deleter(deleter)
223  {};
224 
225 
226 
227 
228  template <typename T>
229  inline TArray<T>::TArray(index n0, index n1, T*data,std::shared_ptr<void> datamanager):
230  TArray(n0,n1,data, [](T*p){;})
231  {_datamanager=datamanager;};
232 
233  template <typename T>
235  {
236  if (_datamanager==nullptr)
237  {
238  _deleter(_data);
239  }
240  // otherwise we assume that datamaager takes care
241  // of the data pointer
242  };
243 
244  template <typename T>
246  _data(0),
247  _size(0),
248  _ndim(1),
249  _shape{0,0},
250  _deleter([](T*p){;})
251  {};
252 
253  template <typename T>
254  inline void TArray<T>::_nullify()
255  {
256  _shape[0]=0;
257  _shape[1]=0;
258  _shape[2]=0;
259  _size=0;
260  _deleter=[](T*p){;};
261  _datamanager=nullptr;
262  _data=nullptr;
263  }
264 
265  template <typename T>
266  inline void TArray<T>::_setshape(index shape0)
267  {
268  if (_ndim!=1)
269  {
270  char errormsg[80];
271  snprintf(errormsg,80,"numcxx::TArray::resize: unable to set 1D shape for 2D array.\n");
272  throw std::runtime_error(errormsg);
273  }
274  _shape[0]=shape0;
275  _shape[1]=0;
276  _shape[2]=0;
277  _size=shape0;
278  }
279 
280 
281  template <typename T>
282  inline void TArray<T>::resize(size_t n)
283  {
284  if (_size==n) return;
285 
286  if (_ndim>1)
287  {
288  char errormsg[80];
289  snprintf(errormsg,80,"numcxx::TArray::resize: unable to resize 2D Array to 1D.\n");
290  throw std::runtime_error(errormsg);
291  }
292 
293  if (_datamanager==nullptr)
294  {
295  _deleter(_data);
296  _data=(T*)malloc(sizeof(T)*n);
297  if (_data==nullptr) throw std::runtime_error("numcxx: TArray::resize(): Memory allocation failed");
298  _deleter=[](T*p){free(p);};
299  _size=n;
300  _shape[0]=n;
301  _shape[1]=0;
302  }
303  else
304  {
305  char errormsg[80];
306  snprintf(errormsg,80,"numcxx::TArray::resize: unable to resize - data managed by different object.\n");
307  throw std::runtime_error(errormsg);
308  }
309  }
310 
311 
312 
313  template <typename T>
314  inline void TArray<T>::operate(std::function< void ( T& a, T&b)> f, TArray<T> & A, TArray<T> & B)
315  {
316  for(index i=0;i<A._size;i++) f(A._data[i],B._data[i]);
317  }
318 
319  template <typename T>
320  inline void TArray<T>::operate(std::function< void ( T& a, T&b,T&c)> f, TArray<T> & A, TArray<T> & B,TArray<T> & C)
321  {
322  for(index i=0;i<A._size;i++) f(A._data[i],B._data[i],C._data[i]);
323  }
324 
325 
326 
327  template<typename T>
328  inline std::ostream & operator << (std::ostream & s, TArray<T> &A)
329  {
330  if (A.ndim()==1)
331  for (index i=0;i<A.size();i++) s <<"[" << i << "]: " <<A(i) << std::endl << std::flush;
332  else
333  {
334  s << " ";
335  for (index j=0;j<A.shape(1);j++)
336  s << "[" << j << "] ";
337  s<< "\n";
338  for (index i=0;i<A.shape(0);i++)
339  {
340  s << "[" << i << "]: ";
341  for (index j=0;j<A.shape(1);j++)
342  s << A(i,j) << " ";
343  s<< "\n";
344  }
345  }
346  return s;
347  }
348 
349 
350  template <typename T>
351  inline void TArray<T>::savetxt(std::ostream &s) const
352  {
353  if (ndim()==1)
354  for (index i=0;i<size();i++) s << _data[i] << std::endl << std::flush;
355  else
356  {
357  for (index i=0;i<shape(0);i++)
358  {
359  for (index j=0;j<shape(1);j++)
360  s << _data[_idx(i,j)] << " ";
361  s<< std::endl;
362  }
363  s << std::flush;
364  }
365  }
366 
367 }
void _assert_square() const
Check if all shapes are the same.
Definition: tarray.ixx:145
void savetxt(std::ostream &s) const
Definition: tarray.ixx:351
index _shape[3]
Shape vector.
Definition: tarray.hxx:149
index _idx(index i0) const
1D Array index calculation with optional bounds check.
Definition: tarray.ixx:156
void xdiv(TArray< T > &A, const EXPR &expr, const EXPR *x=0)
Definition: tarray.ixx:111
std::function< void(T *p)> _deleter
Deleter method.
Definition: tarray.hxx:172
TArray is the common template base class for arrays and dense matrices of the numcxx project...
Definition: tarray.hxx:17
size_t size() const
Obtain size of array.
Definition: tarray.hxx:58
~TArray()
Destructor.
Definition: tarray.ixx:234
void xadd(TArray< T > &A, const EXPR &expr, const EXPR *x=0)
Definition: tarray.ixx:54
void _check_bounds(index acc_dim, index acc_ndim, index acc_idx) const
Bounds checker.
Definition: tarray.ixx:128
void _nullify()
Nullify contents of array (for move constructors)
Definition: tarray.ixx:254
TArray()
Construct an zero length 1D array.
Definition: tarray.ixx:245
void xmul(TArray< T > &A, const EXPR &expr, const EXPR *x=0)
Definition: tarray.ixx:92
unsigned int index
Definition: numcxx.hxx:21
static void operate(std::function< void(T &a, T &b)> f, TArray< T > &A, TArray< T > &B)
Binary operation on arrays.
Definition: tarray.ixx:314
void xsub(TArray< T > &A, const EXPR &expr, const EXPR *x=0)
Definition: tarray.ixx:73
size_t _size
Size of array.
Definition: tarray.hxx:146
index ndim() const
Obtain tensor dimension of array.
Definition: tarray.hxx:52
T * _data
Data pointer.
Definition: tarray.hxx:186
void _setshape(index shape0)
Set shape of 1D array (for move constructors)
Definition: tarray.ixx:266
void resize(size_t n)
Resize array.
Definition: tarray.ixx:282
double B(double x)
Numcxx template library.
Definition: expression.ixx:41
TArray< T > & assign(TArray< T > &A, const EXPR &expr, const EXPR *x=0)
Definition: tarray.ixx:35
index shape(const index dim) const
Obtain shape of array for given dimension.
Definition: tarray.hxx:68
std::shared_ptr< void > _datamanager
Data manager.
Definition: tarray.hxx:183
const index _ndim
Tensor dimension.
Definition: tarray.hxx:143
T * data() const
Obtain C-pointer of data array.
Definition: tarray.hxx:128