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

Generated on Sat Jul 9 2011 15:21:29 for IT++ by Doxygen 1.7.4