IT++ Logo Newcom Logo

array.h

Go to the documentation of this file.
00001 
00039 #ifndef ARRAY_H
00040 #define ARRAY_H
00041 
00042 #include <itpp/itconfig.h>
00043 #include <itpp/base/itassert.h>
00044 #include <itpp/base/factory.h>
00045 #include <itpp/base/copy_vector.h>
00046 
00047 
00048 namespace itpp {
00049 
00050   // Forward declarations
00051   template<class T> class Array;
00052   template<class T> const Array<T> concat(const Array<T> &a, const T e);
00053   template<class T> const Array<T> concat(const T e, const Array<T> &a);
00054   template<class T> const Array<T> concat(const Array<T> &a1, const Array<T> &a2);
00055   template<class T> const Array<T> concat(const Array<T> &a1, const Array<T> &a2, const Array<T> &a3);
00056 
00096   template<class T>
00097   class Array {
00098   public:
00100     explicit Array(const Factory &f = DEFAULT_FACTORY);
00102     Array(const int n, const Factory &f = DEFAULT_FACTORY);
00104     Array(const Array<T> &a);
00106     Array(const Array<T> &a, const Factory &f);
00107 
00109     virtual ~Array();
00110 
00112     T &operator()(const int i) {
00113       it_assert0(i>=0&&i<ndata,"Array::operator()"); return data[i]; }
00115     const T &operator()(const int i) const {
00116       it_assert0(i>=0&&i<ndata,"Array::operator()"); return data[i]; }
00118     const Array<T> operator()(const int i1, const int i2) const;
00120     const Array<T> operator()(const Array<int> &indices) const;
00121 
00123     Array<T>& operator=(const T &e);
00125     Array<T>& operator=(const Array<T> &a);
00126 
00128     friend const Array<T> concat <>(const Array<T> &a1, const T e);
00130     friend const Array<T> concat <>(const T e, const Array<T> &a);
00132     friend const Array<T> concat <>(const Array<T> &a1,const Array<T> &a2);
00134     friend const Array<T> concat <>(const Array<T> &a1, const Array<T> &a2, const Array<T> &a3);
00135 
00137     int size() const { return ndata; }
00139     int length() const { return ndata; }
00141     void set_size(const int n, const bool copy=false);
00143     void set_length(const int n, const bool copy=false) { set_size(n, copy); }
00144 
00146     T shift_right(const T e);
00148     const Array<T> shift_right(const Array<T> &a);
00150     T shift_left(const T e);
00152     const Array<T> shift_left(const Array<T> &a);
00154     void swap(const int i, const int j);
00155 
00157     void set_subarray(int i1, int i2, const Array<T> &a);
00159     void set_subarray(int i1, int i2, const T t);
00160 
00161   protected:
00163     bool in_range(const int i) { return ((i<ndata) && (i>=0)); }
00165     int ndata;
00167     T *data;
00169     const Factory &factory;
00170 
00171   private:
00172     void alloc(int n);
00173     void free();
00174   };
00175 
00176   // --------------------------- Implementation starts here ----------------------------------
00177 
00178   template<class T>
00179         Array<T>::Array(const Factory &f) : factory(f)
00180         {
00181                 data=NULL;
00182                 ndata=0;
00183         }
00184 
00185   template<class T>
00186         Array<T>::Array(const int n, const Factory &f) : factory(f)
00187         {
00188                 alloc(n);
00189         }
00190 
00191   template<class T>
00192         Array<T>::Array(const Array<T> &a) : factory(a.factory)
00193         {
00194                 alloc(a.ndata);
00195                 for (int i=0; i<a.ndata; i++)
00196                         data[i] = a.data[i];
00197         }
00198 
00199   template<class T>
00200         Array<T>::Array(const Array<T> &a, const Factory &f) : factory(f)
00201         {
00202                 alloc(a.ndata);
00203                 for (int i=0; i<a.ndata; i++)
00204                         data[i] = a.data[i];
00205         }
00206 
00207   template<class T>
00208         Array<T>::~Array()
00209         {
00210                 free();
00211         }
00212 
00213   template<class T>
00214         void Array<T>::alloc(const int n)
00215         {
00216                 if (n == 0) {
00217                         data = NULL;
00218                         ndata = 0;
00219                 }
00220                 else {
00221                         create_elements(data, n, factory);
00222                         it_assert1(data!=0, "Out of memory in Array::alloc");
00223                 }
00224                 ndata = n;
00225         }
00226 
00227   template<class T>
00228         void Array<T>::free()
00229         {
00230                 delete [] data;
00231         
00232                 data = 0;
00233                 ndata = 0;
00234         }
00235 
00236   template<class T>
00237         const Array<T> Array<T>::operator()(const int i1, const int i2) const
00238         {
00239                 it_assert0(i1>=0 && i2>=0 && i1<ndata && i2<ndata && i2>=i1,
00240                                                          "Array::operator()(i1,i2)");
00241                 Array<T> s(i2-i1+1);
00242                 int i;
00243         
00244                 for (i=0; i<s.ndata; i++)
00245                         s.data[i] = data[i1+i];
00246         
00247                 return s;
00248         }
00249 
00250   template<class T>
00251         const Array<T> Array<T>::operator()(const Array<int> &indices) const
00252         {
00253                 Array<T> a(indices.size());
00254 
00255                 for (int i=0; i<a.size(); i++) {
00256                         it_assert0(indices(i)>=0&&indices(i)<ndata,"Array::operator()(indicies)");
00257                         a(i) = data[indices(i)];
00258                 }
00259 
00260                 return a;
00261         }
00262 
00263   template<class T>
00264         Array<T>& Array<T>::operator=(const Array<T> &a)
00265         {
00266                 if (this != &a) {
00267                         set_size(a.ndata);
00268                         for (int i=0; i<ndata; i++)
00269                                 data[i] = a.data[i];
00270                 }
00271                 return *this;
00272         }
00273 
00274   template<class T>
00275         Array<T>& Array<T>::operator=(const T &e)
00276         {
00277                 if (ndata==0) 
00278                         set_size(1);
00279 
00280                 for (int i=0; i<ndata; i++)
00281                         data[i] = e;
00282                 return *this;
00283         }
00284 
00285   template<class T>
00286         void Array<T>::set_size(const int sz, const bool copy)
00287         {
00288                 int i, min;
00289                 T *tmp;
00290 
00291                 if (ndata == sz)
00292                         return;
00293 
00294                 if (copy) {
00295                         tmp = data;
00296                         min = ndata < sz ? ndata : sz;
00297                         alloc(sz);
00298                         for (i=0; i<min; i++)
00299                                 data[i] = tmp[i];
00300                         delete [] tmp;
00301                 } else {
00302                         free();
00303                         alloc(sz);
00304                 }
00305                 ndata = sz;
00306         }
00307 
00308   template<class T>
00309         T Array<T>::shift_right(const T x)
00310         {
00311                 T ret;
00312 
00313                 it_assert1(ndata>0, "shift_right");
00314                 ret = data[ndata-1];
00315                 for (int i=ndata-1; i>0; i--)
00316                         data[i] = data[i-1];
00317                 data[0] = x;
00318         
00319                 return ret;
00320         }
00321 
00322 
00323   template<class T>
00324         const Array<T> Array<T>::shift_right(const Array<T> &a)
00325         {
00326                 int     i;
00327                 Array<T> out(a.ndata);
00328 
00329                 it_assert1(a.ndata<=ndata, "Shift Array too large");
00330                 for (i=0; i<a.ndata; i++)
00331                         out.data[i] = data[ndata-a.ndata+i];
00332                 for (i=ndata-1; i>=a.ndata; i--)
00333                         data[i] = data[i-a.ndata];
00334                 for (i=0; i<a.ndata; i++)
00335                         data[i] = a.data[i];
00336         
00337                 return out;
00338         }
00339 
00340   template<class T>
00341         T Array<T>::shift_left(const T x)
00342         {
00343                 T temp = data[0];
00344         
00345                 for (int i=0; i<ndata-1; i++)
00346                         data[i]=data[i+1];
00347                 data[ndata-1] = x;
00348         
00349                 return temp;
00350         }
00351 
00352   template<class T>
00353         const Array<T> Array<T>::shift_left(const Array<T> &a)
00354         {
00355                 int     i;
00356                 Array<T> out(a.ndata);
00357 
00358                 it_assert1(a.ndata<=ndata, "Shift Array too large");
00359                 for (i=0; i<a.ndata; i++)
00360                         out.data[i] = data[i];
00361                 for (i=0; i<ndata-a.ndata; i++) {
00362                         // out.data[i] = data[i]; removed. Is not necessary
00363                         data[i] = data[i+a.ndata];
00364                 }
00365                 for (i=ndata-a.ndata; i<ndata; i++)
00366                         data[i] = a.data[i-ndata+a.ndata];
00367         
00368                 return out;
00369         }
00370 
00371   template<class T>
00372         void Array<T>::swap(const int i, const int j)
00373         {
00374                 it_assert1(in_range(i) && in_range(j) , "Shift Array too large");
00375     
00376                 T temp = data[i];
00377                 data[i] = data[j];
00378                 data[j] = temp;
00379         }
00380 
00381   template<class T>
00382         void Array<T>::set_subarray(int i1, int i2, const Array<T> &a)
00383         {
00384                 if (i1 == -1) i1 = ndata-1;
00385                 if (i2 == -1) i2 = ndata-1;
00386   
00387                 it_assert1(in_range(i1) && in_range(i2), "Array<T>::set_subarray(): indicies out of range");
00388                 it_assert1(i2>=i1, "Array<T>::set_subarray(): i2 >= i1 necessary");
00389                 it_assert1(i2-i1+1 == a.ndata, "Array<T>::set_subarray(): wrong sizes");
00390 
00391                 copy_vector(a.ndata, a.data, data+i1);
00392         }
00393 
00394   template<class T>
00395         void Array<T>::set_subarray(int i1, int i2, const T t)
00396         {
00397                 if (i1 == -1) i1 = ndata-1;
00398                 if (i2 == -1) i2 = ndata-1;
00399   
00400                 it_assert1(in_range(i1) && in_range(i2), "Array<T>::set_subarray(): indicies out of range");
00401                 it_assert1(i2>=i1, "Array<T>::set_subarray(): i2 >= i1 necessary");
00402 
00403                 for (int i=i1;i<=i2;i++)
00404                         data[i] = t;
00405         }
00406 
00407   template<class T>
00408         const Array<T> concat(const Array<T> &a, const T e)
00409         {
00410                 Array<T> temp(a.size()+1);
00411 
00412                 for (int i=0; i<a.size(); i++)
00413                         temp(i) = a(i);
00414                 temp(a.size()) = e;
00415 
00416                 return temp;
00417         }
00418 
00419   template<class T>
00420         const Array<T> concat(const T e, const Array<T> &a)
00421         {
00422                 Array<T> temp(a.size()+1);
00423 
00424                 temp(0) = e;
00425 
00426                 for (int i=0; i<a.size(); i++)
00427                         temp(i+1) = a(i);
00428 
00429                 return temp;
00430         }
00431 
00432   template<class T>
00433         const Array<T> concat(const Array<T> &a1, const Array<T> &a2)
00434         {
00435                 int i;
00436                 Array<T> temp(a1.size()+a2.size());
00437 
00438                 for (i=0;i<a1.size();i++) {
00439                         temp(i) = a1(i);
00440                 }
00441                 for (i=0;i<a2.size();i++) {
00442                         temp(a1.size()+i) = a2(i);
00443                 }
00444                 return temp;
00445         }
00446 
00447   template<class T>
00448         const Array<T> concat(const Array<T> &a1, const Array<T> &a2, const Array<T> &a3)
00449         {
00450                 // There should be some error control?
00451                 int i;
00452                 Array<T> temp(a1.size()+a2.size()+a3.size());
00453 
00454                 for (i=0;i<a1.size();i++) {
00455                         temp(i) = a1(i);
00456                 }
00457                 for (i=0;i<a2.size();i++) {
00458                         temp(a1.size()+i) = a2(i);
00459                 }
00460                 for (i=0;i<a3.size();i++) {
00461                         temp(a1.size()+a2.size()+i) = a3(i);
00462                 }
00463                 return temp;
00464         }
00465 
00470   template<class T>
00471         std::ostream &operator<<(std::ostream &os, const Array<T> &a)
00472         {
00473                 os << "{";
00474                 for (int i=0; i<a.size()-1; i++)
00475                         os << a(i) << " ";
00476                 if (a.size() > 0)
00477                         os << a(a.size()-1);
00478                 os << "}";
00479 
00480                 return os;
00481         }
00482 
00487   template<class T>
00488         std::istream &operator>>(std::istream &is, Array<T> &a)
00489         {
00490                 int nrof_elements = 0;
00491                 char c;
00492                 is >> c;
00493                 if (c == '{') {
00494                         is >> c;
00495                         while (c != '}') {
00496                                 if (is.eof()) {
00497                                         is.setstate(std::ios_base::failbit);
00498                                         break;
00499                                 }
00500                                 if (c != ',') {  // Discard comma signs between elements
00501                                         is.putback(c);
00502                                 }
00503                                 if (++nrof_elements > a.size()) {
00504                                         a.set_size(nrof_elements, true);  // Too slow?
00505                                 }
00506                                 is >> a(nrof_elements-1);
00507                                 is >> c;
00508                         }
00509                         if (a.size() > nrof_elements) {
00510                                 a.set_size(nrof_elements, true);
00511                         }
00512                 } else {
00513                         is.setstate(std::ios_base::failbit);
00514                 }
00515 
00516                 return is;
00517         }
00518 
00523   template<class T>
00524         void set_array(Array<T> &a, const char *values)
00525         {
00526                 std::istringstream buffer(values);
00527                 buffer >> a;
00528         }
00529 
00534   template<class T>
00535         void set_array(Array<T> &a, const std::string &str)
00536         {
00537                 set_array(a, str.c_str());
00538         }
00539 
00540 } // namespace itpp
00541 
00542 #endif // #ifndef ARRAY_H
SourceForge Logo

Generated on Fri Jun 8 02:08:50 2007 for IT++ by Doxygen 1.5.2