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

Generated on Sun Dec 9 17:30:58 2007 for IT++ by Doxygen 1.5.4