IT++ Logo
array.h
Go to the documentation of this file.
1 
29 #ifndef ARRAY_H
30 #define ARRAY_H
31 
32 #include <itpp/base/itassert.h>
33 #include <itpp/base/math/misc.h>
34 #include <itpp/base/factory.h>
35 #include <itpp/base/copy_vector.h>
36 
37 
38 namespace itpp
39 {
40 
41 // Forward declarations
42 template<class T> class Array;
44 template<class T> const Array<T> concat(const Array<T> &a, const T &e);
46 template<class T> const Array<T> concat(const T &e, const Array<T> &a);
48 template<class T> const Array<T> concat(const Array<T> &a1,
49  const Array<T> &a2);
51 template<class T> const Array<T> concat(const Array<T> &a1,
52  const Array<T> &a2,
53  const Array<T> &a3);
54 
103 template<class T>
104 class Array
105 {
106 public:
108  explicit Array(const Factory &f = DEFAULT_FACTORY);
110  Array(int n, const Factory &f = DEFAULT_FACTORY);
112  Array(const Array<T> &a, const Factory &f = DEFAULT_FACTORY);
114  Array(const std::string& values, const Factory &f = DEFAULT_FACTORY);
116  Array(const char* values, const Factory &f = DEFAULT_FACTORY);
117 
119  virtual ~Array();
120 
122  T &operator()(int i);
124  const T &operator()(int i) const;
126  const Array<T> operator()(int i1, int i2) const;
128  const Array<T> operator()(const Array<int> &indices) const;
129 
131  Array<T> left(int n) const;
133  Array<T> right(int n) const;
135  Array<T> mid(int pos, int n) const;
136 
138  Array<T>& operator=(const T &e);
140  Array<T>& operator=(const Array<T> &a);
142  Array<T>& operator=(const char* values);
143 
145  friend const Array<T> concat <>(const Array<T> &a1, const T &e);
147  friend const Array<T> concat <>(const T &e, const Array<T> &a);
149  friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2);
151  friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2,
152  const Array<T> &a3);
153 
155  int size() const { return ndata; }
157  int length() const { return ndata; }
159  void set_size(int n, bool copy = false);
161  void set_length(int n, bool copy = false) { set_size(n, copy); }
162 
164  T shift_right(const T& e);
166  const Array<T> shift_right(const Array<T> &a);
168  T shift_left(const T& e);
170  const Array<T> shift_left(const Array<T> &a);
172  void swap(int i, int j);
173 
175  void set_subarray(int i1, int i2, const Array<T> &a);
177  void set_subarray(int i1, int i2, const T &t);
178 
179 protected:
181  void alloc(int n);
183  void free();
185  bool in_range(int i) const { return ((i < ndata) && (i >= 0)); }
187  int ndata;
189  T *data;
191  const Factory &factory;
192 };
193 
194 // -------------------- Implementation starts here --------------------
195 
196 template<class T> inline
197 void Array<T>::alloc(int n)
198 {
199  if (n > 0) {
200  create_elements(data, n, factory);
201  ndata = n;
202  }
203  else {
204  data = 0;
205  ndata = 0;
206  }
207 }
208 
209 template<class T> inline
211 {
212  destroy_elements(data, ndata);
213  ndata = 0;
214 }
215 
216 template<class T> inline
217 Array<T>::Array(const Factory &f) : ndata(0), data(0), factory(f) {}
218 
219 template<class T> inline
220 Array<T>::Array(const int n, const Factory &f) : ndata(0), data(0), factory(f)
221 {
222  alloc(n);
223 }
224 
225 template<class T> inline
226 Array<T>::Array(const Array<T> &a, const Factory &f)
227  : ndata(0), data(0), factory(f)
228 {
229  alloc(a.ndata);
230  for (int i = 0; i < a.ndata; i++)
231  data[i] = a.data[i];
232 }
233 
234 template<class T> inline
235 Array<T>::Array(const std::string& values, const Factory &f)
236  : ndata(0), data(0), factory(f)
237 {
238  std::istringstream buffer(values);
239  buffer >> *this;
240 }
241 
242 template<class T> inline
243 Array<T>::Array(const char* values, const Factory &f)
244  : ndata(0), data(0), factory(f)
245 {
246  std::istringstream buffer(values);
247  buffer >> *this;
248 }
249 
250 template<class T>
252 {
253  free();
254 }
255 
256 template<class T>
257 void Array<T>::set_size(int size, bool copy)
258 {
259  it_assert_debug(size >= 0, "Array::set_size(): New size must not be negative");
260  if (ndata == size)
261  return;
262  if (copy) {
263  // create a temporary pointer to the allocated data
264  T* tmp = data;
265  // store the current number of elements
266  int old_ndata = ndata;
267  // check how many elements we need to copy
268  int min = (ndata < size) ? ndata : size;
269  // allocate new memory
270  alloc(size);
271  // copy old elements into a new memory region
272  for (int i = 0; i < min; ++i) {
273  data[i] = tmp[i];
274  }
275  // initialize the rest of resized array
276  for (int i = min; i < size; ++i) {
277  data[i] = T();
278  }
279  // delete old elements
280  destroy_elements(tmp, old_ndata);
281  }
282  else {
283  free();
284  alloc(size);
285  }
286 }
287 
288 
289 template<class T> inline
291 {
292  it_assert_debug(in_range(i), "Array::operator(): Improper index");
293  return data[i];
294 }
295 
296 template<class T> inline
297 const T& Array<T>::operator()(int i) const
298 {
299  it_assert_debug(in_range(i), "Array::operator(): Improper index");
300  return data[i];
301 }
302 
303 template<class T> inline
304 const Array<T> Array<T>::operator()(int i1, int i2) const
305 {
306  it_assert_debug(in_range(i1) && in_range(i2) && (i2 >= i1),
307  "Array::operator()(i1, i2): Improper indexes.");
308  Array<T> s(i2 - i1 + 1);
309  for (int i = 0; i < s.ndata; i++)
310  s.data[i] = data[i1+i];
311  return s;
312 }
313 
314 template<class T> inline
315 const Array<T> Array<T>::operator()(const Array<int> &indices) const
316 {
317  Array<T> a(indices.size());
318  for (int i = 0; i < a.size(); i++) {
319  it_assert_debug(in_range(indices(i)),
320  "Array::operator()(indices): Improper indices.");
321  a(i) = data[indices(i)];
322  }
323  return a;
324 }
325 
326 template<class T> inline
328 {
329  if (this != &a) {
330  set_size(a.ndata);
331  for (int i = 0; i < ndata; i++)
332  data[i] = a.data[i];
333  }
334  return *this;
335 }
336 
337 template<class T> inline
339 {
340  if (ndata == 0)
341  set_size(1);
342  for (int i = 0; i < ndata; i++)
343  data[i] = e;
344  return *this;
345 }
346 
347 template<class T>
348 Array<T>& Array<T>::operator=(const char* values)
349 {
350  std::istringstream buffer(values);
351  buffer >> *this;
352  return *this;
353 }
354 
355 
356 template<class T>
358 {
359  it_assert_debug(in_range(n), "Array::left(): Index out of range");
360  Array<T> tmp(n);
361  for (int i = 0; i < n; ++i)
362  tmp.data[i] = data[i];
363  return tmp;
364 }
365 
366 template<class T>
368 {
369  it_assert_debug(in_range(n), "Array::right(): Index out of range");
370  Array<T> tmp(n);
371  for (int i = 0; i < n; ++i)
372  tmp.data[i] = data[ndata-n+i];
373  return tmp;
374 }
375 
376 template<class T>
377 Array<T> Array<T>::mid(int pos, int n) const
378 {
379  it_assert_debug((pos >= 0) && (n > 0) && (pos + n <= ndata), "Array::mid(): Indexing out of range");
380  Array<T> tmp(n);
381  for (int i = 0; i < n; ++i)
382  tmp.data[i] = data[pos+i];
383  return tmp;
384 }
385 
386 
387 template<class T>
389 {
390  it_assert_debug(ndata > 0, "Array::shift_right(x): Array empty!");
391  T ret;
392 
393  ret = data[ndata-1];
394  for (int i = ndata - 1; i > 0; i--)
395  data[i] = data[i-1];
396  data[0] = x;
397 
398  return ret;
399 }
400 
401 
402 template<class T>
404 {
405  it_assert_debug(a.ndata <= ndata, "Array::shift_right(): Shift Array too large");
406  Array<T> out(a.ndata);
407 
408  for (int i = 0; i < a.ndata; i++)
409  out.data[i] = data[ndata-a.ndata+i];
410  for (int i = ndata - 1; i >= a.ndata; i--)
411  data[i] = data[i-a.ndata];
412  for (int i = 0; i < a.ndata; i++)
413  data[i] = a.data[i];
414 
415  return out;
416 }
417 
418 template<class T>
419 T Array<T>::shift_left(const T& x)
420 {
421  T temp = data[0];
422 
423  for (int i = 0; i < ndata - 1; i++)
424  data[i] = data[i+1];
425  data[ndata-1] = x;
426 
427  return temp;
428 }
429 
430 template<class T>
432 {
433  it_assert_debug(a.ndata <= ndata, "Array::shift_left(): Shift Array too large");
434  Array<T> out(a.ndata);
435 
436  for (int i = 0; i < a.ndata; i++)
437  out.data[i] = data[i];
438  for (int i = 0; i < ndata - a.ndata; i++)
439  data[i] = data[i+a.ndata];
440  for (int i = ndata - a.ndata; i < ndata; i++)
441  data[i] = a.data[i-ndata+a.ndata];
442 
443  return out;
444 }
445 
446 template<class T>
447 void Array<T>::swap(int i, int j)
448 {
449  it_assert_debug(in_range(i) && in_range(j),
450  "Array::swap(): Indices out of range.");
451 
452  T temp = data[i];
453  data[i] = data[j];
454  data[j] = temp;
455 }
456 
457 template<class T>
458 void Array<T>::set_subarray(int i1, int i2, const Array<T> &a)
459 {
460  if (i1 == -1) i1 = ndata - 1;
461  if (i2 == -1) i2 = ndata - 1;
462 
463  it_assert_debug(in_range(i1) && in_range(i2),
464  "Array<T>::set_subarray(): Indices out of range.");
465  it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary.");
466  it_assert_debug(i2 - i1 + 1 == a.ndata, "Array<T>::set_subarray(): Wrong sizes.");
467 
468  copy_vector(a.ndata, a.data, data + i1);
469 }
470 
471 template<class T>
472 void Array<T>::set_subarray(int i1, int i2, const T &t)
473 {
474  if (i1 == -1) i1 = ndata - 1;
475  if (i2 == -1) i2 = ndata - 1;
476 
477  it_assert_debug(in_range(i1) && in_range(i2),
478  "Array<T>::set_subarray(): Indices out of range");
479  it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary");
480 
481  for (int i = i1; i <= i2; i++)
482  data[i] = t;
483 }
484 
485 template<class T>
486 const Array<T> concat(const Array<T> &a, const T &e)
487 {
488  Array<T> temp(a.size() + 1);
489 
490  for (int i = 0; i < a.size(); i++)
491  temp(i) = a(i);
492  temp(a.size()) = e;
493 
494  return temp;
495 }
496 
497 template<class T>
498 const Array<T> concat(const T &e, const Array<T> &a)
499 {
500  Array<T> temp(a.size() + 1);
501 
502  temp(0) = e;
503 
504  for (int i = 0; i < a.size(); i++)
505  temp(i + 1) = a(i);
506 
507  return temp;
508 }
509 
510 template<class T>
511 const Array<T> concat(const Array<T> &a1, const Array<T> &a2)
512 {
513  Array<T> temp(a1.size() + a2.size());
514 
515  for (int i = 0; i < a1.size(); i++)
516  temp(i) = a1(i);
517  for (int i = 0; i < a2.size(); i++)
518  temp(a1.size() + i) = a2(i);
519 
520  return temp;
521 }
522 
523 template<class T>
524 const Array<T> concat(const Array<T> &a1, const Array<T> &a2,
525  const Array<T> &a3)
526 {
527  // There should be some error control?
528  Array<T> temp(a1.size() + a2.size() + a3.size());
529 
530  for (int i = 0; i < a1.size(); i++)
531  temp(i) = a1(i);
532  for (int i = 0; i < a2.size(); i++)
533  temp(a1.size() + i) = a2(i);
534  for (int i = 0; i < a3.size(); i++)
535  temp(a1.size() + a2.size() + i) = a3(i);
536 
537  return temp;
538 }
539 
544 template<class T>
545 std::ostream &operator<<(std::ostream &os, const Array<T> &a)
546 {
547  os << "{";
548  for (int i = 0; i < a.size() - 1; i++)
549  os << a(i) << " ";
550  if (a.size() > 0)
551  os << a(a.size() - 1);
552  os << "}";
553 
554  return os;
555 }
556 
561 template<class T>
562 std::istream &operator>>(std::istream &is, Array<T> &a)
563 {
564  int nrof_elements = 0;
565  char c;
566  is >> c;
567  if (c == '{') {
568  is >> c;
569  while (c != '}') {
570  if (is.eof()) {
571  is.setstate(std::ios_base::failbit);
572  break;
573  }
574  if (c != ',') { // Discard comma signs between elements
575  is.putback(c);
576  }
577  if (++nrof_elements > a.size()) {
578  a.set_size(nrof_elements, true); // Too slow?
579  }
580  is >> a(nrof_elements - 1);
581  is >> c;
582  }
583  if (a.size() > nrof_elements) {
584  a.set_size(nrof_elements, true);
585  }
586  }
587  else {
588  is.setstate(std::ios_base::failbit);
589  }
590 
591  return is;
592 }
593 
599 template<class T>
600 void set_array(Array<T> &a, const char *values)
601 {
602  std::istringstream buffer(values);
603  buffer >> a;
604 }
605 
611 template<class T>
612 void set_array(Array<T> &a, const std::string &str)
613 {
614  set_array(a, str.c_str());
615 }
616 
617 } // namespace itpp
618 
619 #endif // #ifndef ARRAY_H
SourceForge Logo

Generated on Sat Jul 6 2013 10:54:19 for IT++ by Doxygen 1.8.2