KrisLibrary  1.0.0
array2d.h
1 #ifndef ARRAY2D_H
2 #define ARRAY2D_H
3 
4 #include <KrisLibrary/File.h>
5 #include <KrisLibrary/errors.h>
6 #include <KrisLibrary/utils/IntPair.h>
7 #include <KrisLibrary/utils/indexing.h>
8 #include <iosfwd>
9 
29 template <class T>
30 class Array2D
31 {
32 public:
33  Array2D();
34  Array2D(int m,int n);
35  Array2D(int m,int n,const T& initVal);
36  Array2D(const Array2D<T>& rhs);
37  Array2D(Array2D<T>&& rhs);
38  ~Array2D();
39 
40  inline T& operator()(int i,int j) { Assert(i>=0&&i<m); Assert(j>=0&&j<n); return items[i*n+j]; }
41  inline const T& operator()(int i,int j) const { Assert(i>=0&&i<m); Assert(j>=0&&j<n); return items[i*n+j]; }
42  inline T& operator()(const IntPair& t) { return operator()(t.a,t.b); }
43  inline const T& operator()(const IntPair& t) const { return operator()(t.a,t.b); }
44  Array2D<T>& operator =(const Array2D<T>& rhs);
45  Array2D<T>& operator =(Array2D<T>&& rhs);
46 
47  bool Read(File& f);
48  bool Write(File& f) const;
49 
50  inline int numRows() const { return m; }
51  inline int numCols() const { return n; }
52  inline IntPair size() const { return IntPair(m,n); }
53  inline bool empty() const { return m==0&&n==0; }
54  void initialize(int m,int n);
55  void initialize(int m,int n,const T& initVal);
56  void resize(int m,int n);
57  void resize(int m,int n,const T& initVal);
58  void reserve(int numItems);
59  void clear();
60 
61  bool find(const T& item,int& i,int& j) const;
62  bool find(const T& item,IntPair& t) const { return find(item,t.a,t.b); }
63  inline bool contains(const T& item) const { int i,j; return find(item,i,j); }
64  void set(const T& item);
65  void set(const Array2D<T>&);
66  void swap(Array2D<T>&);
67  inline T* getData() const { return items; }
68  inline T* getRowData(int i) const { return &items[i*n]; }
69 
70  class iterator
71  {
72  public:
73  explicit iterator(const Array2D<T>* array);
74  explicit iterator(const Array2D<T>* array,int invalid);
75  explicit iterator(const Array2D<T>* array,const Stripe2Indices& range);
76  explicit iterator(const Array2D<T>* array,const Stripe2Indices& range,int invalid);
77  iterator(const iterator& rhs);
78  inline iterator& operator ++() { ++it; return *this; }
79  inline iterator& operator --() { --it; return *this; }
80  inline iterator& operator +=(int skip) { it+=skip; return *this; }
81  inline iterator& operator -=(int skip) { it-=skip; return *this; }
82  inline void incFirst(int skip=1) { it.incFirst(skip); }
83  inline void incSecond(int skip=1) { it.incSecond(skip); }
84  inline T& operator*() { return array->getData()[*it]; }
85  iterator& operator = (const iterator& rhs);
86  inline bool operator == (const iterator& rhs) const { return it == rhs.it && array==rhs.array; }
87  inline bool operator != (const iterator& rhs) const { return !operator==(rhs); }
88  inline bool operator < (const iterator& rhs) const { return it<rhs.it; }
89  IntPair getElement() const {
90  //translate to original coordinates
91  IntPair i=it.getElement();
92  int ibase=range.base/range.istride;
93  int jbase=range.base/range.jstride;
94  int istride=range.istride/(range.jsize*range.jstride);
95  int jstride=range.jstride;
96  return IntPair(i.a*istride+ibase,i.b*jstride+jbase);
97  }
98  //private:
99  const Array2D<T>* array;
100  Stripe2Indices range;
102  };
103  iterator begin() const { return iterator(this); }
104  iterator end() const { return iterator(this,-1); }
105  iterator begin(const Range2Indices& range) const { return iterator(this,range); }
106  iterator end(const Range2Indices& range) const { return iterator(this,range,-1); }
107 
108  //READ ONLY
109  int m,n;
110 protected:
111  T* items;
112  int capacity;
113 };
114 
115 
116 
117 template <class T>
119 :m(0),n(0),items(0),capacity(0)
120 {}
121 
122 template <class T>
123 Array2D<T>::Array2D(int _m,int _n)
124 :m(0),n(0),items(0),capacity(0)
125 {
126  initialize(_m,_n);
127 }
128 
129 template <class T>
130 Array2D<T>::Array2D(int _m,int _n,const T& initVal)
131 :m(0),n(0),items(0),capacity(0)
132 {
133  initialize(_m,_n,initVal);
134 }
135 
136 template <class T>
138 :m(0),n(0),items(0),capacity(0)
139 {
140  set(rhs);
141 }
142 
143 template <class T>
145 :m(rhs.m),n(rhs.n),items(rhs.items),capacity(rhs.capacity)
146 {
147  //prevent deletion
148  rhs.items = 0;
149 }
150 
151 template <class T>
153 {
154  clear();
155 }
156 
157 template <class T>
159 {
160  set(rhs);
161  return *this;
162 }
163 
164 template <class T>
166 {
167  m = rhs.m;
168  n = rhs.n;
169  items = rhs.items;
170  capacity = rhs.capacity;
171  //prevent deletion
172  rhs.items = 0;
173  return *this;
174 }
175 
176 template <class T>
177 bool Array2D<T>::Read(File& f)
178 {
179  if(!ReadFile(f,m)) return false;
180  if(!ReadFile(f,n)) return false;
181  initialize(m,n);
182  if(!ReadArrayFile(f,items,m*n)) return false;
183  return true;
184 }
185 
186 template <class T>
187 bool Array2D<T>::Write(File& f) const
188 {
189  if(!WriteFile(f,m)) return false;
190  if(!WriteFile(f,n)) return false;
191  if(!WriteArrayFile(f,items,m*n)) return false;
192  return true;
193 }
194 
195 template <class T>
196 void Array2D<T>::initialize(int _m,int _n)
197 {
198  clear();
199  m=_m;
200  n=_n;
201  capacity=m*n;
202  items=new T[capacity];
203 }
204 
205 template <class T>
206 void Array2D<T>::initialize(int _m,int _n,const T& initVal)
207 {
208  clear();
209  m=_m;
210  n=_n;
211  capacity=m*n;
212  items=new T[capacity];
213  set(initVal);
214 }
215 
216 template <class T>
217 void Array2D<T>::resize(int _m,int _n)
218 {
219  if(_m*_n > capacity)
220  initialize(_m,_n);
221  m=_m;
222  n=_n;
223 }
224 
225 template <class T>
226 void Array2D<T>::resize(int _m,int _n,const T& initVal)
227 {
228  if(_m*_n > capacity)
229  initialize(_m,_n);
230  m=_m;
231  n=_n;
232  set(initVal);
233 }
234 
235 template <class T>
236 void Array2D<T>::reserve(int cap)
237 {
238  if(cap > capacity) {
239  if(m*n != 0)
240  FatalError("TODO: copy elements in Array2D resize/reserve");
241  if(items) delete [] items;
242  capacity = cap;
243  items = new T[capacity];
244  }
245 }
246 
247 template <class T>
248 void Array2D<T>::clear()
249 {
250  if(items) {
251  delete [] items;
252  items = NULL;
253  }
254  m=n=0;
255  capacity=0;
256 }
257 
258 template <class T>
259 bool Array2D<T>::find(const T& item,int& i,int& j) const
260 {
261  for(int p=0;p<m;p++)
262  for(int q=0;q<n;q++)
263  if(operator()(p,q)==item) {
264  i=p; j=q;
265  return true;
266  }
267  return false;
268 }
269 
270 template <class T>
271 void Array2D<T>::set(const T& item)
272 {
273  for(int i=0;i<m*n;i++) items[i]=item;
274 }
275 
276 template <class T>
277 void Array2D<T>::set(const Array2D<T>& rhs)
278 {
279  resize(rhs.m,rhs.n);
280  for(int i=0;i<m*n;i++) items[i]=rhs.items[i];
281 }
282 
283 template <class T>
285 {
286  int tempm=m,tempn=n;
287  T* tempitems=items;
288  int tempcap=capacity;
289  m=b.m; n=b.n;
290  items=b.items;
291  capacity=b.capacity;
292  b.m=tempm; b.n=tempn;
293  b.items=tempitems;
294  b.capacity=tempcap;
295 }
296 
297 
298 template <class T>
299 std::ostream& operator << (std::ostream& out,const Array2D<T>& a)
300 {
301  out<<a.m<<" "<<a.n<<std::endl;
302  for(int i=0;i<a.m;i++) {
303  for(int j=0;j<a.n;j++) {
304  out<<a(i,j);
305  if(j+1 < a.n) out<<" ";
306  }
307  if(i+1 < a.m) out<<std::endl;
308  }
309  return out;
310 }
311 
312 template <class T>
313 std::istream& operator >> (std::istream& in,Array2D<T>& a)
314 {
315  int m,n;
316  in>>m>>n;
317  if(in.bad()) return in;
318  Assert(m>=0 && n>=0);
319  a.resize(m,n);
320  for(int i=0;i<m;i++) {
321  for(int j=0;j<n;j++) {
322  in>>a(i,j);
323  }
324  }
325  return in;
326 }
327 
328 template <class T>
330  :array(_array),range(_array->m,_array->n),it(&range)
331 {}
332 
333 template <class T>
334 Array2D<T>::iterator::iterator(const Array2D<T>* _array,int invalid)
335  :array(_array),range(_array->m,_array->n),it(range.end())
336 {}
337 
338 template <class T>
339 Array2D<T>::iterator::iterator(const Array2D<T>* _array,const Stripe2Indices& _range)
340  :array(_array),range(_range),it(&range)
341 {}
342 
343 template <class T>
344 Array2D<T>::iterator::iterator(const Array2D<T>* _array,const Stripe2Indices& _range,int invalid)
345  :array(_array),range(_range),it(range.end())
346 {}
347 
348 template <class T>
350  :array(rhs.array),range(rhs.range),it(rhs.it)
351 {
352  it.stripe = &range; //maintain a valid pointer over the iterator's lifetime
353 }
354 
355 template <class T>
357 {
358  it = rhs.it;
359  array = rhs.array;
360  range = rhs.range;
361  it.stripe = &range; //maintain a valid pointer over the iterator's lifetime
362  return *this;
363 }
364 
365 namespace std {
366 
367  template <class T>
368  void swap(Array2D<T>& a,Array2D<T>&b)
369  {
370  a.swap(b);
371  }
372 
373 } //namespace std
374 
375 #endif
Definition: array2d.h:70
bool WriteFile(File &f, const std::vector< type > &v)
WriteFile() for STL vectors. See File.h.
Definition: ioutils.h:81
A lightweight integer 2-tuple class.
Definition: IntPair.h:9
Definition: rayprimitives.h:132
A unified interface for reading/writing binary data to file.
bool ReadFile(File &f, std::vector< type > &v)
ReadFile() for STL vectors. See File.h.
Definition: ioutils.h:69
Definition: utils/indexing.h:258
A two-dimensional m x n array.
Definition: array2d.h:30
A 2D lattice of regular ranges.
Definition: utils/indexing.h:116
A 2D lattice indexing into a linear sequence, in a striping pattern.
Definition: utils/indexing.h:241
A cross-platform class for reading/writing binary data.
Definition: File.h:47