KrisLibrary  1.0.0
arraynd.h
1 #ifndef ARRAY_ND
2 #define ARRAY_ND
3 
4 #include <KrisLibrary/Logger.h>
5 #include "array2d.h"
6 #include "array3d.h"
7 #include <KrisLibrary/utils/IntTuple.h>
8 #include <vector>
9 #include <assert.h>
10 
11 template <class T> class ArrayND;
12 template <class T> class ArrayNDRef;
13 
14 template <class T>
15 class ArrayND
16 {
17  public:
18  ArrayND();
19  ArrayND(const ArrayND<T>& rhs);
20  ArrayND(const Array2D<T>& rhs);
21  ArrayND(const Array3D<T>& rhs);
22  ArrayND(int dim1);
23  ArrayND(int dim1,int dim2);
24  ArrayND(int dim1,int dim2,int dim3);
25  ArrayND(const std::vector<int>& dims);
26  ArrayND(const IntTuple& dims);
27 
28  void clear();
29  inline size_t numDims() const { return dims.size(); }
30  inline size_t numValues() const { return values.size(); }
31  inline const std::vector<int>& size() const { return dims; }
32 
34  void resize(const std::vector<int>& newdims);
35  inline void resize(const IntTuple& dims) { resize(dims.elements); }
36  inline void resize(int dim1) { resize(IntTuple(dim1)); }
37  inline void resize(int dim1,int dim2) { resize(IntTuple(dim1,dim2)); }
38  inline void resize(int dim1,int dim2,int dim3) { resize(IntTuple(dim1,dim2,dim3)); }
39 
40  inline void set(T val) { std::fill(values.begin(),values.end(),val); }
41 
42  const ArrayND<T>& operator = (const ArrayND<T>& rhs);
43  const ArrayND<T>& operator = (const std::vector<T>& rhs);
44  const ArrayND<T>& operator = (const Array2D<T>& rhs);
45  const ArrayND<T>& operator = (const Array3D<T>& rhs);
46 
47  bool operator == (const ArrayND<T>& rhs) const;
48  ArrayNDRef<T> operator [] (int i);
49  T& operator [] (const std::vector<int>& index);
50  const T& operator [] (const std::vector<int>& index) const;
51  inline T& operator [] (const IntTuple& index) { return operator [](index.elements); }
52  inline const T& operator [] (const IntTuple& index) const { return operator [](index.elements); }
53 
54  void getSubArray(const std::vector<int>& imin,const std::vector<int>& imax,ArrayND<T>& subArray) const;
55  void setSubArray(const std::vector<int>& imin,const std::vector<int>& imax,const ArrayND<T>& subArray);
56  void getSlice(const std::vector<int>& dimIndices,ArrayND<T>& slice) const;
57  void setSlice(const std::vector<int>& dimIndices,const ArrayND<T>& slice);
58 
59  int indexToOffset(const std::vector<int>& index) const;
60  inline void indexToOffset(const IntTuple& index) const { return indexToOffset(index.elements); }
61  inline int incOffset(int offset,int dim) const { return offset+strides[dim]; }
62  inline int decOffset(int offset,int dim) const { return offset-strides[dim]; }
63  std::vector<int> offsetToIndex(int offset) const;
64 
65  struct iterator
66  {
67  iterator& operator ++();
68  iterator& operator --();
69  iterator& operator +=(int skip);
70  iterator& operator -=(int skip);
71  void inc(int dim);
72  void inc(int dim,int count);
73  void dec(int dim);
74  void dec(int dim,int count);
75  inline bool operator == (const iterator& it) const { return it.obj == obj && it.offset == offset; }
76  inline bool operator != (const iterator& it) const { return !operator == (it); }
77  inline bool operator < (const iterator& it) const { return it.obj == obj && it.offset > offset; }
78  inline bool operator > (const iterator& it) const { return it.obj == obj && it.offset < offset; }
79  inline int operator - (const iterator& it) const { assert(it.obj == obj); return offset-it.offset; }
80  inline T& operator * () {
81  assert(offset >= 0 && offset<obj->values.size());
82  return obj->values[offset];
83  }
84  inline T* operator -> () {
85  assert(offset >= 0 && offset<obj->values.size());
86  return &obj->values[offset];
87  }
88 
89  ArrayND<T>* obj;
90  std::vector<int> index;
91  int offset;
92  };
93 
94  iterator begin();
95  iterator begin(const std::vector<int>& index);
96  iterator end();
97 
98  std::vector<int> dims;
99  std::vector<int> strides;
100  std::vector<T> values;
101 };
102 
103 template <class T>
104 class ArrayNDRef
105 {
106  public:
107  ArrayNDRef<T>();
108  ArrayNDRef<T>(const ArrayNDRef<T>& rhs);
109  ArrayNDRef<T>(ArrayND<T>* obj,int offset,int curDim);
110  const ArrayNDRef<T>& operator = (T val);
111  const ArrayNDRef<T>& operator = (const ArrayND<T>& val);
112  operator T ();
113  ArrayNDRef<T> operator [] (int i);
114 
115  ArrayND<T>* obj;
116  int offset;
117  int curDim;
118 };
119 
120 template <class T>
122 {}
123 
124 template <class T>
126  :dims(rhs.dims),strides(rhs.strides),values(rhs.values)
127 {}
128 
129 
130 template <class T>
132  :dims(2),strides(2),values(rhs.getData(),rhs.getData()+rhs.m*rhs.n)
133 {
134  dims[0] = rhs.m;
135  dims[1] = rhs.n;
136  strides[0] = rhs.n;
137  strides[1] = 1;
138 }
139 
140 template <class T>
142  :dims(3),strides(3),values(rhs.getData(),rhs.getData()+rhs.m*rhs.n*rhs.p)
143 {
144  dims[0] = rhs.m;
145  dims[1] = rhs.n;
146  dims[2] = rhs.p;
147  strides[0] = rhs.n*rhs.p;
148  strides[1] = rhs.p;
149  strides[2] = 1;
150 }
151 
152 template <class T>
153 ArrayND<T>::ArrayND(int dim1)
154 {
155  resize(dim1);
156 }
157 
158 template <class T>
159 ArrayND<T>::ArrayND(int dim1,int dim2)
160 {
161  resize(dim1,dim2);
162 }
163 
164 template <class T>
165 ArrayND<T>::ArrayND(int dim1,int dim2,int dim3)
166 {
167  resize(dim1,dim2,dim3);
168 }
169 
170 template <class T>
171 ArrayND<T>::ArrayND(const std::vector<int>& dims)
172 {
173  resize(dims);
174 }
175 
176 template <class T>
177 ArrayND<T>::ArrayND(const IntTuple& dims)
178 {
179  resize(dims);
180 }
181 
182 template <class T>
183 void ArrayND<T>::clear()
184 {
185  dims.clear();
186  strides.clear();
187  values.clear();
188 }
189 
190 template <class T>
191 void ArrayND<T>::resize(const std::vector<int>& newdims)
192 {
193  if(newdims.empty()) {
194  clear();
195  return;
196  }
197  dims = newdims;
198  int nv = 1;
199  for(size_t i=0;i<newdims.size();i++)
200  nv *= newdims[i];
201  values.resize(nv);
202  strides.resize(dims.size());
203  strides[dims.size()-1] = 1;
204  for(size_t i=dims.size()-1;i>0;i--)
205  strides[i-1] = dims[i]*strides[i];
206 }
207 
208 template <class T>
210 {
211  dims = rhs.dims;
212  strides = rhs.strides;
213  values = rhs.value;
214 }
215 
216 template <class T>
217 const ArrayND<T>& ArrayND<T>::operator = (const std::vector<T>& rhs)
218 {
219  resize(rhs.size());
220  std::copy(rhs.begin(),rhs.end(),values.begin());
221 }
222 
223 template <class T>
225 {
226  resize(rhs.m,rhs.n);
227  std::copy(rhs.getData(),rhs.getData()+values.size(),values.begin());
228 }
229 
230 template <class T>
232 {
233  resize(rhs.m,rhs.n,rhs.p);
234  std::copy(rhs.getData(),rhs.getData()+values.size(),values.begin());
235 }
236 
237 template <class T>
238 bool ArrayND<T>::operator == (const ArrayND<T>& rhs) const
239 {
240  if(dims != rhs.dims) return false;
241  if(values != rhs.values) return false;
242  return true;
243 }
244 
245 template <class T>
247 {
248  assert(!dims.empty());
249  int offset = i*strides[0];
250  return ArrayNDRef<T>(this,offset,0);
251 }
252 
253 
254 template <class T>
255 T& ArrayND<T>::operator [] (const std::vector<int>& index)
256 {
257  int offset=indexToOffset(index);
258  for(size_t i=0;i<index.size();i++)
259  assert(index[i] >= 0 && index[i] < dims[i]);
260  return values[offset];
261 }
262 
263 template <class T>
264 const T& ArrayND<T>::operator [] (const std::vector<int>& index) const
265 {
266  int offset=indexToOffset(index);
267  for(size_t i=0;i<index.size();i++)
268  assert(index[i] >= 0 && index[i] < dims[i]);
269  return values[offset];
270 }
271 
272 /*
273 template <class T>
274 void ArrayND<T>::getSubArray(const std::vector<int>& imin,const std::vector<int>& imax,ArrayND<T>& subArray);
275 template <class T>
276 void ArrayND<T>::setSubArray(const std::vector<int>& imin,const std::vector<int>& imax,const ArrayND<T>& subArray);
277 template <class T>
278 void ArrayND<T>::getSlice(const std::vector<int>& dimIndices,ArrayND<T>& slice);
279 template <class T>
280 void ArrayND<T>::setSlice(const std::vector<int>& dimIndices,ArrayND<T>& slice);
281 */
282 
283 template <class T>
284 int ArrayND<T>::indexToOffset(const std::vector<int>& index) const
285 {
286  assert(index.size()==strides.size());
287  int offset = 0;
288  for(size_t i=0;i<index.size();i++)
289  offset += index[i]*strides[i];
290  return offset;
291 }
292 
293 template <class T>
294 std::vector<int> ArrayND<T>::offsetToIndex(int offset) const
295 {
296  std::vector<int> index(strides.size());
297  for(size_t i=0;i<index.size();i++) {
298  index[i] = offset/strides[i];
299  offset = offset%strides[i];
300  }
301  return index;
302 }
303 
304 template <class T>
306 {
307  iterator res;
308  res.obj = this;
309  res.offset = 0;
310  res.index.resize(dims.size(),0);
311  return res;
312 }
313 
314 template <class T>
315 typename ArrayND<T>::iterator ArrayND<T>::begin(const std::vector<int>& index)
316 {
317  iterator res;
318  res.obj = this;
319  res.offset = indexToOffset(index);
320  res.index = index;
321  return res;
322 }
323 
324 template <class T>
326 {
327  iterator res;
328  res.obj = this;
329  res.offset = int(values.size());
330  res.index.resize(dims.size(),0);
331  res.index[0] = dims[0];
332  return res;
333 }
334 
335 
336 
337 
338 template <class T>
340 {
341  offset++;
342  for(int i=(int)index.size()-1;i>=0;i--) {
343  index[i]++;
344  if(index[i]==obj->dims[i])
345  index[i] = 0;
346  else {
347  assert(index[i] < obj->dims[i]);
348  break;
349  }
350  }
351  return *this;
352 }
353 
354 template <class T>
356 {
357  offset--;
358  for(int i=(int)index.size()-1;i>=0;i--) {
359  index[i]--;
360  if(index[i] < 0)
361  index[i] = obj->dims[i]-1;
362  else {
363  assert(index[i] >= 0);
364  break;
365  }
366  }
367  return *this;
368 }
369 
370 template <class T>
372 {
373  offset+=skip;
374  for(int i=(int)index.size()-1;i>=0;i--) {
375  index[i]+=skip;
376  if(index[i] < obj->dims[i]) break;
377  assert(obj->dims[i] > 0);
378  skip = index[i]/obj->dims[i];
379  index[i]=index[i]%obj->dims[i];
380  }
381  return *this;
382 }
383 
384 template <class T>
386 {
387  offset-=skip;
388  for(int i=(int)index.size()-1;i>=0;i--) {
389  index[i]-=skip;
390  if(index[i] >=0) break;
391  //TODO: faster version of this
392  assert(obj->dims[i] > 0);
393  skip=0;
394  while(index[i] < 0) {
395  skip++;
396  index[i]+=obj->dims[i];
397  }
398  }
399  return *this;
400 }
401 
402 template <class T>
403 void ArrayND<T>::iterator::inc (int dim)
404 {
405  assert(dim >= 0 && dim < (int)index.size());
406  index[dim]++;
407  offset += obj->strides[dim];
408 }
409 
410 template <class T>
411 void ArrayND<T>::iterator::inc (int dim,int count)
412 {
413  assert(dim >= 0 && dim < (int)index.size());
414  index[dim]+=count;
415  offset += count*obj->strides[dim];
416 }
417 
418 template <class T>
419 void ArrayND<T>::iterator::dec (int dim)
420 {
421  assert(dim >= 0 && dim < (int)index.size());
422  index[dim]--;
423  offset -= obj->strides[dim];
424 }
425 
426 template <class T>
427 void ArrayND<T>::iterator::dec (int dim,int count)
428 {
429  assert(dim >= 0 && dim < (int)index.size());
430  index[dim]-=count;
431  offset -= count*obj->strides[dim];
432 }
433 
434 
435 template <class T>
437  :obj(NULL),offset(0),curDim(0)
438 {}
439 
440 template <class T>
442  :obj(rhs.obj),offset(rhs.offset),curDim(rhs.curDim)
443 {}
444 
445 template <class T>
446 ArrayNDRef<T>::ArrayNDRef(ArrayND<T>* _obj,int _offset,int _curDim)
447  :obj(_obj),offset(_offset),curDim(_curDim)
448 {}
449 
450 template <class T>
452 {
453  assert(curDim+1 == (int)obj->dims.size());
454  obj->values[offset] = val;
455  return *this;
456 }
457 
458 template <class T>
460 {
461  assert(curDim+val.dims.size() == (int)obj->dims.size());
462  LOG4CXX_ERROR(KrisLibrary::logger(),"TODO: copy slices\n");
463  abort();
464  return *this;
465 }
466 
467 template <class T>
469 {
470  assert(curDim+1 == (int)obj->dims.size());
471  return obj->values[offset];
472 }
473 
474 template <class T>
476 {
477  assert(curDim+1 < (int)obj->dims.size());
478  return ArrayNDRef<T>(obj,offset+obj->strides[curDim+1]*i,curDim+1);
479 }
480 
481 
482 #endif // ARRAY_ND
An integer tuple class.
Definition: IntTuple.h:14
void resize(const std::vector< int > &newdims)
note: resize is destructive
Definition: arraynd.h:191
A two-dimensional m x n array.
Definition: array2d.h:30
void copy(const T &a, T *out, int n)
Definition: arrayutils.h:34
Definition: arraynd.h:12
Definition: arraynd.h:11
The logging system used in KrisLibrary.
Definition: arraynd.h:65
A three-dimensional m x n x parray.
Definition: array3d.h:31