IT++ Logo

array.h

Go to the documentation of this file.
00001 
00030 #ifndef ARRAY_H
00031 #define ARRAY_H
00032 
00033 #include <itpp/base/itassert.h>
00034 #include <itpp/base/math/misc.h>
00035 #include <itpp/base/factory.h>
00036 #include <itpp/base/copy_vector.h>
00037 
00038 
00039 namespace itpp
00040 {
00041 
00042 // Forward declarations
00043 template<class T> class Array;
00045 template<class T> const Array<T> concat(const Array<T> &a, const T &e);
00047 template<class T> const Array<T> concat(const T &e, const Array<T> &a);
00049 template<class T> const Array<T> concat(const Array<T> &a1,
00050                                         const Array<T> &a2);
00052 template<class T> const Array<T> concat(const Array<T> &a1,
00053                                         const Array<T> &a2,
00054                                         const Array<T> &a3);
00055 
00104 template<class T>
00105 class Array
00106 {
00107 public:
00109   explicit Array(const Factory &f = DEFAULT_FACTORY);
00111   Array(int n, const Factory &f = DEFAULT_FACTORY);
00113   Array(const Array<T> &a, const Factory &f = DEFAULT_FACTORY);
00115   Array(const std::string& values, const Factory &f = DEFAULT_FACTORY);
00117   Array(const char* values, const Factory &f = DEFAULT_FACTORY);
00118 
00120   virtual ~Array();
00121 
00123   T &operator()(int i);
00125   const T &operator()(int i) const;
00127   const Array<T> operator()(int i1, int i2) const;
00129   const Array<T> operator()(const Array<int> &indices) const;
00130 
00132   Array<T> left(int n) const;
00134   Array<T> right(int n) const;
00136   Array<T> mid(int pos, int n) const;
00137 
00139   Array<T>& operator=(const T &e);
00141   Array<T>& operator=(const Array<T> &a);
00143   Array<T>& operator=(const char* values);
00144 
00146   friend const Array<T> concat <>(const Array<T> &a1, const T &e);
00148   friend const Array<T> concat <>(const T &e, const Array<T> &a);
00150   friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2);
00152   friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2,
00153                                   const Array<T> &a3);
00154 
00156   int size() const { return ndata; }
00158   int length() const { return ndata; }
00160   void set_size(int n, bool copy = false);
00162   void set_length(int n, bool copy = false) { set_size(n, copy); }
00163 
00165   T shift_right(const T& e);
00167   const Array<T> shift_right(const Array<T> &a);
00169   T shift_left(const T& e);
00171   const Array<T> shift_left(const Array<T> &a);
00173   void swap(int i, int j);
00174 
00176   void set_subarray(int i1, int i2, const Array<T> &a);
00178   void set_subarray(int i1, int i2, const T &t);
00179 
00180 protected:
00182   void alloc(int n);
00184   void free();
00186   bool in_range(int i) const { return ((i < ndata) && (i >= 0)); }
00188   int ndata;
00190   T *data;
00192   const Factory &factory;
00193 };
00194 
00195 // -------------------- Implementation starts here --------------------
00196 
00197 template<class T> inline
00198 void Array<T>::alloc(int n)
00199 {
00200   if (n > 0) {
00201     create_elements(data, n, factory);
00202     ndata = n;
00203   }
00204   else {
00205     data = 0;
00206     ndata = 0;
00207   }
00208 }
00209 
00210 template<class T> inline
00211 void Array<T>::free()
00212 {
00213   destroy_elements(data, ndata);
00214   ndata = 0;
00215 }
00216 
00217 template<class T> inline
00218 Array<T>::Array(const Factory &f) : ndata(0), data(0), factory(f) {}
00219 
00220 template<class T> inline
00221 Array<T>::Array(const int n, const Factory &f) : ndata(0), data(0), factory(f)
00222 {
00223   alloc(n);
00224 }
00225 
00226 template<class T> inline
00227 Array<T>::Array(const Array<T> &a, const Factory &f)
00228     : ndata(0), data(0), factory(f)
00229 {
00230   alloc(a.ndata);
00231   for (int i = 0; i < a.ndata; i++)
00232     data[i] = a.data[i];
00233 }
00234 
00235 template<class T> inline
00236 Array<T>::Array(const std::string& values, const Factory &f)
00237     : ndata(0), data(0), factory(f)
00238 {
00239   std::istringstream buffer(values);
00240   buffer >> *this;
00241 }
00242 
00243 template<class T> inline
00244 Array<T>::Array(const char* values, const Factory &f)
00245     : ndata(0), data(0), factory(f)
00246 {
00247   std::istringstream buffer(values);
00248   buffer >> *this;
00249 }
00250 
00251 template<class T>
00252 Array<T>::~Array()
00253 {
00254   free();
00255 }
00256 
00257 template<class T>
00258 void Array<T>::set_size(int size, bool copy)
00259 {
00260   it_assert_debug(size >= 0, "Array::set_size(): New size must not be negative");
00261   if (ndata == size)
00262     return;
00263   if (copy) {
00264     // create a temporary pointer to the allocated data
00265     T* tmp = data;
00266     // store the current number of elements
00267     int old_ndata = ndata;
00268     // check how many elements we need to copy
00269     int min = (ndata < size) ? ndata : size;
00270     // allocate new memory
00271     alloc(size);
00272     // copy old elements into a new memory region
00273     for (int i = 0; i < min; ++i) {
00274       data[i] = tmp[i];
00275     }
00276     // initialize the rest of resized array
00277     for (int i = min; i < size; ++i) {
00278       data[i] = T();
00279     }
00280     // delete old elements
00281     destroy_elements(tmp, old_ndata);
00282   }
00283   else {
00284     free();
00285     alloc(size);
00286   }
00287 }
00288 
00289 
00290 template<class T> inline
00291 T& Array<T>::operator()(int i)
00292 {
00293   it_assert_debug(in_range(i), "Array::operator(): Improper index");
00294   return data[i];
00295 }
00296 
00297 template<class T> inline
00298 const T& Array<T>::operator()(int i) const
00299 {
00300   it_assert_debug(in_range(i), "Array::operator(): Improper index");
00301   return data[i];
00302 }
00303 
00304 template<class T> inline
00305 const Array<T> Array<T>::operator()(int i1, int i2) const
00306 {
00307   it_assert_debug(in_range(i1) && in_range(i2) && (i2 >= i1),
00308                   "Array::operator()(i1, i2): Improper indexes.");
00309   Array<T> s(i2 - i1 + 1);
00310   for (int i = 0; i < s.ndata; i++)
00311     s.data[i] = data[i1+i];
00312   return s;
00313 }
00314 
00315 template<class T> inline
00316 const Array<T> Array<T>::operator()(const Array<int> &indices) const
00317 {
00318   Array<T> a(indices.size());
00319   for (int i = 0; i < a.size(); i++) {
00320     it_assert_debug(in_range(indices(i)),
00321                     "Array::operator()(indices): Improper indices.");
00322     a(i) = data[indices(i)];
00323   }
00324   return a;
00325 }
00326 
00327 template<class T> inline
00328 Array<T>& Array<T>::operator=(const Array<T> &a)
00329 {
00330   if (this != &a) {
00331     set_size(a.ndata);
00332     for (int i = 0; i < ndata; i++)
00333       data[i] = a.data[i];
00334   }
00335   return *this;
00336 }
00337 
00338 template<class T> inline
00339 Array<T>& Array<T>::operator=(const T &e)
00340 {
00341   if (ndata == 0)
00342     set_size(1);
00343   for (int i = 0; i < ndata; i++)
00344     data[i] = e;
00345   return *this;
00346 }
00347 
00348 template<class T>
00349 Array<T>& Array<T>::operator=(const char* values)
00350 {
00351   std::istringstream buffer(values);
00352   buffer >> *this;
00353   return *this;
00354 }
00355 
00356 
00357 template<class T>
00358 Array<T> Array<T>::left(int n) const
00359 {
00360   it_assert_debug(in_range(n), "Array::left(): Index out of range");
00361   Array<T> tmp(n);
00362   for (int i = 0; i < n; ++i)
00363     tmp.data[i] = data[i];
00364   return tmp;
00365 }
00366 
00367 template<class T>
00368 Array<T> Array<T>::right(int n) const
00369 {
00370   it_assert_debug(in_range(n), "Array::right(): Index out of range");
00371   Array<T> tmp(n);
00372   for (int i = 0; i < n; ++i)
00373     tmp.data[i] = data[ndata-n+i];
00374   return tmp;
00375 }
00376 
00377 template<class T>
00378 Array<T> Array<T>::mid(int pos, int n) const
00379 {
00380   it_assert_debug((pos >= 0) && (n > 0) && (pos + n <= ndata), "Array::mid(): Indexing out of range");
00381   Array<T> tmp(n);
00382   for (int i = 0; i < n; ++i)
00383     tmp.data[i] = data[pos+i];
00384   return tmp;
00385 }
00386 
00387 
00388 template<class T>
00389 T Array<T>::shift_right(const T& x)
00390 {
00391   it_assert_debug(ndata > 0, "Array::shift_right(x): Array empty!");
00392   T ret;
00393 
00394   ret = data[ndata-1];
00395   for (int i = ndata - 1; i > 0; i--)
00396     data[i] = data[i-1];
00397   data[0] = x;
00398 
00399   return ret;
00400 }
00401 
00402 
00403 template<class T>
00404 const Array<T> Array<T>::shift_right(const Array<T> &a)
00405 {
00406   it_assert_debug(a.ndata <= ndata, "Array::shift_right(): Shift Array too large");
00407   Array<T> out(a.ndata);
00408 
00409   for (int i = 0; i < a.ndata; i++)
00410     out.data[i] = data[ndata-a.ndata+i];
00411   for (int i = ndata - 1; i >= a.ndata; i--)
00412     data[i] = data[i-a.ndata];
00413   for (int i = 0; i < a.ndata; i++)
00414     data[i] = a.data[i];
00415 
00416   return out;
00417 }
00418 
00419 template<class T>
00420 T Array<T>::shift_left(const T& x)
00421 {
00422   T temp = data[0];
00423 
00424   for (int i = 0; i < ndata - 1; i++)
00425     data[i] = data[i+1];
00426   data[ndata-1] = x;
00427 
00428   return temp;
00429 }
00430 
00431 template<class T>
00432 const Array<T> Array<T>::shift_left(const Array<T> &a)
00433 {
00434   it_assert_debug(a.ndata <= ndata, "Array::shift_left(): Shift Array too large");
00435   Array<T> out(a.ndata);
00436 
00437   for (int i = 0; i < a.ndata; i++)
00438     out.data[i] = data[i];
00439   for (int i = 0; i < ndata - a.ndata; i++)
00440     data[i] = data[i+a.ndata];
00441   for (int i = ndata - a.ndata; i < ndata; i++)
00442     data[i] = a.data[i-ndata+a.ndata];
00443 
00444   return out;
00445 }
00446 
00447 template<class T>
00448 void Array<T>::swap(int i, int j)
00449 {
00450   it_assert_debug(in_range(i) && in_range(j),
00451                   "Array::swap(): Indices out of range.");
00452 
00453   T temp = data[i];
00454   data[i] = data[j];
00455   data[j] = temp;
00456 }
00457 
00458 template<class T>
00459 void Array<T>::set_subarray(int i1, int i2, const Array<T> &a)
00460 {
00461   if (i1 == -1) i1 = ndata - 1;
00462   if (i2 == -1) i2 = ndata - 1;
00463 
00464   it_assert_debug(in_range(i1) && in_range(i2),
00465                   "Array<T>::set_subarray(): Indices out of range.");
00466   it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary.");
00467   it_assert_debug(i2 - i1 + 1 == a.ndata, "Array<T>::set_subarray(): Wrong sizes.");
00468 
00469   copy_vector(a.ndata, a.data, data + i1);
00470 }
00471 
00472 template<class T>
00473 void Array<T>::set_subarray(int i1, int i2, const T &t)
00474 {
00475   if (i1 == -1) i1 = ndata - 1;
00476   if (i2 == -1) i2 = ndata - 1;
00477 
00478   it_assert_debug(in_range(i1) && in_range(i2),
00479                   "Array<T>::set_subarray(): Indices out of range");
00480   it_assert_debug(i2 >= i1, "Array<T>::set_subarray(): i2 >= i1 necessary");
00481 
00482   for (int i = i1; i <= i2; i++)
00483     data[i] = t;
00484 }
00485 
00486 template<class T>
00487 const Array<T> concat(const Array<T> &a, const T &e)
00488 {
00489   Array<T> temp(a.size() + 1);
00490 
00491   for (int i = 0; i < a.size(); i++)
00492     temp(i) = a(i);
00493   temp(a.size()) = e;
00494 
00495   return temp;
00496 }
00497 
00498 template<class T>
00499 const Array<T> concat(const T e, const Array<T> &a)
00500 {
00501   Array<T> temp(a.size() + 1);
00502 
00503   temp(0) = e;
00504 
00505   for (int i = 0; i < a.size(); i++)
00506     temp(i + 1) = a(i);
00507 
00508   return temp;
00509 }
00510 
00511 template<class T>
00512 const Array<T> concat(const Array<T> &a1, const Array<T> &a2)
00513 {
00514   Array<T> temp(a1.size() + a2.size());
00515 
00516   for (int i = 0; i < a1.size(); i++)
00517     temp(i) = a1(i);
00518   for (int i = 0; i < a2.size(); i++)
00519     temp(a1.size() + i) = a2(i);
00520 
00521   return temp;
00522 }
00523 
00524 template<class T>
00525 const Array<T> concat(const Array<T> &a1, const Array<T> &a2,
00526                       const Array<T> &a3)
00527 {
00528   // There should be some error control?
00529   Array<T> temp(a1.size() + a2.size() + a3.size());
00530 
00531   for (int i = 0; i < a1.size(); i++)
00532     temp(i) = a1(i);
00533   for (int i = 0; i < a2.size(); i++)
00534     temp(a1.size() + i) = a2(i);
00535   for (int i = 0; i < a3.size(); i++)
00536     temp(a1.size() + a2.size() + i) = a3(i);
00537 
00538   return temp;
00539 }
00540 
00545 template<class T>
00546 std::ostream &operator<<(std::ostream &os, const Array<T> &a)
00547 {
00548   os << "{";
00549   for (int i = 0; i < a.size() - 1; i++)
00550     os << a(i) << " ";
00551   if (a.size() > 0)
00552     os << a(a.size() - 1);
00553   os << "}";
00554 
00555   return os;
00556 }
00557 
00562 template<class T>
00563 std::istream &operator>>(std::istream &is, Array<T> &a)
00564 {
00565   int nrof_elements = 0;
00566   char c;
00567   is >> c;
00568   if (c == '{') {
00569     is >> c;
00570     while (c != '}') {
00571       if (is.eof()) {
00572         is.setstate(std::ios_base::failbit);
00573         break;
00574       }
00575       if (c != ',') {  // Discard comma signs between elements
00576         is.putback(c);
00577       }
00578       if (++nrof_elements > a.size()) {
00579         a.set_size(nrof_elements, true);  // Too slow?
00580       }
00581       is >> a(nrof_elements - 1);
00582       is >> c;
00583     }
00584     if (a.size() > nrof_elements) {
00585       a.set_size(nrof_elements, true);
00586     }
00587   }
00588   else {
00589     is.setstate(std::ios_base::failbit);
00590   }
00591 
00592   return is;
00593 }
00594 
00600 template<class T>
00601 void set_array(Array<T> &a, const char *values)
00602 {
00603   std::istringstream buffer(values);
00604   buffer >> a;
00605 }
00606 
00612 template<class T>
00613 void set_array(Array<T> &a, const std::string &str)
00614 {
00615   set_array(a, str.c_str());
00616 }
00617 
00618 } // namespace itpp
00619 
00620 #endif // #ifndef ARRAY_H
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
SourceForge Logo

Generated on Tue Feb 2 09:33:28 2010 for IT++ by Doxygen 1.6.2