Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)

toolbox/array.hh
Go to the documentation of this file.
00001 /* Array which does enlarge on request, zero out and more.
00002  * In a sense a very minimalistic implementation of STLs vector.
00003  * It's mainly intended to be an exception safe way to have an array
00004  * of something. Especially suitable for vectors and matrices.
00005  */
00006 
00007 #ifndef Array_hh
00008 #define Array_hh
00009 
00010 #include <cstring>
00011 #include <memory>
00012 #include <iostream>
00013 
00014 #include "basics/typedefs.hh"
00015 #include "basics/vectorsMatrices.hh"
00016 #include "basics/exceptions.hh"
00017 #include "basics/pointerOutput.hh"
00018 
00019 // debugging
00020 #define ArrayConstr_D 0
00021 #define ArrayDestr_D 0
00022 
00023 namespace concepts {
00024 
00025   // **************************************** Output operator for auto_ptr's **
00026 
00029   template<class F>
00030   std::ostream& operator<<(std::ostream& os, std::auto_ptr<F>& a) {
00031     return os << "std::auto_ptr output";
00032   }
00033 
00034   // ***************************************************************** Array **
00035 
00043   template<class F>
00044   class Array {
00045   public:
00047     Array(const uint sz = 0) : data_(sz ? new F[sz] : 0),
00048              size_(sz), n_(sz) {
00049       DEBUGL(ArrayConstr_D, "start: size = " << sz << ", data = " << data_);
00050     }
00057     Array(const uint sz, const F& dft) : data_(sz ? new F[sz] : 0),
00058            size_(sz), n_(sz) {
00059       F* d = data_; for(uint i = size_; i--;) *d++ = dft;
00060     }
00068     Array(const F* dft, const uint sz) : data_(sz ? new F[sz] : 0),
00069             size_(sz), n_(sz) {
00070       memorycpy(data_, dft, sz);
00071     }
00081     Array(const uint sz, const F& first, const F& diff) : 
00082       data_(sz ? new F[sz] : 0), size_(sz), n_(sz) {
00083       if (sz > 0) {
00084         F* d = data_, *e = data_;
00085         *d++ = first;
00086         for(uint i = sz - 1; i--;) *d++ = *e++ + diff;
00087       }
00088     }
00094     template<class H>
00095     Array(const Array<H>& a, F fnc(const H&)) : data_(0), size_(0), n_(0) {
00096       apply(a, fnc);
00097     }
00099     Array(const Array<F>& a) : data_(a.n_ ? new F[a.n_] : 0),
00100              size_(a.n_), n_(a.n_) {
00101       std::memcpy(data_, a.data_, n_*sizeof(F));
00102     }
00104     template<class H>
00105     Array(const Array<H>& a) : data_(0), size_(0), n_(0) { *this = a; }
00106 
00107     ~Array() {
00108       DEBUGL(ArrayDestr_D, "start: size = " << size_ << ", n = " << n_
00109        << ", data = " << data_);
00110       delete[] data_;
00111       DEBUGL(ArrayDestr_D, "done.");
00112     }
00113 
00118     void resize(const uint sz);
00122     void resizePreserve(const uint sz);
00124     void zeros() { std::memset(data_, 0, n_*sizeof(F)); }
00125 
00127     operator F*() { return data_; }
00129     operator const F*() const { return data_; }
00130 
00132     const F& operator[] (const int i) const { 
00133       conceptsAssert3(i < (int)size_, Assertion(),
00134           "i = " << i << ", size = " << size_);
00135       return data_[i];
00136     }
00138     F& operator[] (const int i) { 
00139       conceptsAssert3(i < (int)size_, Assertion(),
00140           "i = " << i << ", size = " << size_);
00141       return data_[i];
00142     }
00143 
00145     template<class G>
00146     Array<F>& operator*=(const G n) {
00147       F* d = data_; 
00148       for(uint i = size_; i--;) *d++ *= n;
00149       return *this;
00150     }
00151 
00153     template<class H>
00154     Array<F>& operator*=(const Array<H>& a) {
00155       conceptsAssert(n_ <= a.size(), Assertion()); 
00156       F* d = data_; const H* e = (const H*)a;
00157       for(uint i = n_; i--;) *d++ *= *e++;
00158       return *this;
00159     }
00160     
00162     Array<F>& operator=(const F n) {
00163       F* d = data_; for(uint i = size_; i--;) *d++ = n;
00164       return *this;
00165     }
00167     Array<F>& operator=(const Array<F>& a) {
00168       resize(a.size());
00169       std::memcpy(data_, a.data_, n_*sizeof(F));
00170       return *this;
00171     }
00173     template<class H>
00174     Array<F>& operator=(const Array<H>& a) {
00175       resize(a.size());
00176       F* d = data_; const H* e = (const H*)a;
00177       for(uint i = size_; i--;) *d++ = *e++;
00178       return *this;
00179     }
00181     Array<F>& operator+=(const F n) {
00182       F* d = data_; for(uint i = size_; i--;) *d++ += n;
00183       return *this;
00184     }
00186     template<class H>
00187     Array<F>& operator+=(const Array<H>& a) {
00188       if (size_ == 0 && a.size() > 0) *this = Array<F>(a.size(), F(0));
00189       F* d = data_; const H* e = (const H*)a;
00190       for(uint i = size_; i--;) *d++ += *e++;
00191       return *this;
00192     }
00194     Array<F>& operator-=(const F n) {
00195       F* d = data_; for(uint i = size_; i--;) *d++ -= n;
00196       return *this;
00197     }
00199     template<class H>
00200     Array<F>& operator-=(const Array<H>& a) {
00201       if (size_ == 0 && a.size() > 0) *this = Array<F>(a.size(), F(0));
00202       F* d = data_; const H* e = (const H*)a;
00203       for(uint i = size_; i--;) *d++ -= *e++;
00204       return *this;
00205     }
00207     Array<F> operator-() const {
00208       Array<F> a(size_);
00209       F* d = (F*)a; const F* e = data_;
00210       for(uint i = size_; i--;) *d++ = -*e++;
00211       return a;
00212     }
00215     Array<F>& apply(F& fnc(F&)) {
00216       F* d = data_; 
00217       for(uint i = size_; i--;++d) *d = fnc(*d);
00218       return *this;
00219     }
00228     template<class H>
00229     Array<F>& apply(const Array<H>& a, F fnc(const H&)) {
00230       resize(a.size());
00231       F* d = data_; const H* e = (const H*)a; 
00232       for(uint i = size_; i--; ++d) 
00233         *d = fnc(*e++);
00234       return *this;
00235     }
00244     template<class H>
00245     Array<F>& apply(const Array<H>& a, F fnc(const H&, const F&)) {
00246       resize(a.size());
00247       F* d = data_; const H* e = (const H*)a; 
00248       for(uint i = n_; i--;++d) { 
00249         *d = fnc(*e++, *d);
00250       }
00251       return *this;
00252     }
00253 
00255     uint size() const { return n_; }
00256 
00258     uint cursize() const { return size_;}
00259 
00261     int memory() const { return size_*sizeof(F); }
00262 
00264     Array<F>& reverse();
00265 
00266     std::ostream& info(std::ostream& os) const;
00267   protected:
00269     F* data_;
00271     uint size_;
00273     uint n_;
00274   };
00275 
00276   template<class F>
00277   void Array<F>::resize(const uint sz) {
00278     if (sz > size_) {
00279       if (size_ > 0) delete[] data_;
00280       data_ = new F[size_ = sz];
00281     }
00282     n_ = sz;
00283   }
00284 
00285   template<class F>
00286   void Array<F>::resizePreserve(const uint sz) {
00287     if (sz > size_) {
00288       F* data = new F[sz];
00289       std::memcpy(data, data_, n_*sizeof(F));
00290       delete[] data_;
00291       data_ = data;
00292       size_ = sz;
00293     }
00294     n_ = sz;
00295   }
00296 
00297   template<class F>
00298   std::ostream& Array<F>::info(std::ostream& os) const {
00299     os << "Array<F>(" << n_ << ", [";
00300     F* d = data_;
00301     for (uint i = n_; i--;)
00302       os << *d++ << ((i == 0) ? "" : ", ");
00303     return os << "])";
00304   }
00305 
00306   template<class F>
00307   Array<F>& Array<F>::reverse() {
00308     F *d = data_, *e = data_ + (n_-1);
00309     for(uint i = std::floor(double(n_)/2.0); i--; )
00310       std::swap(*d++, *e--);
00311     return *this;
00312   }
00313 
00314   template<class F>
00315   std::ostream& operator<<(std::ostream& os, const Array<F>& o) {
00316 #ifdef DEBUG
00317     os << std::flush;
00318 #endif
00319     return o.info(os);
00320   }
00321 
00322   template <class F>
00323   inline bool operator==(const Array<F>& x, const Array<F>& y)
00324   {
00325     uint n = x.size();
00326     if (n != y.size()) return false;
00327     const F* d = (const F*)x; const F* e = (const F*)y;
00328     for (uint i = n; i--;)
00329       if (*d++ != *e++) return false;
00330     return true;
00331   }
00332 
00333   template <class F>
00334   inline bool operator==(const Array<F>& x, F& y)
00335   {
00336     uint n = x.size();
00337     const F* d = (const F*)x;
00338     for (uint i = n; i--;)
00339       if (*d++ != y) return false;
00340     return true;
00341   }
00342 
00343   template <class F>
00344   inline bool operator==(F& y, const Array<F>& x)
00345   {
00346     return x == y;
00347   }
00348 
00354   template<class F, class G>
00355   concepts::Array<typename Combtype<F,G>::type>
00356   operator*(const concepts::Array<F>& array, const G& val) {
00357     concepts::Array<typename Combtype<F,G>::type> result(array.size());
00358     typename Combtype<F,G>::type* r = (typename Combtype<F,G>::type*)result;
00359     const F* a = (const F*)array;
00360     for(uint i = array.size(); i--;) *r++ = *a++ * val;
00361     return result;
00362   }
00363 
00369   template<class F, class G>
00370   Array<typename Combtype<F,G>::type>
00371   operator*(const G& val, const Array<F>& array) {
00372     return array * val;
00373   }
00374 
00375   // ************************************************************** Realtype **
00376 
00377   template<typename F>
00378   struct Realtype<Array<F> > {
00379     typedef typename Realtype<F>::type type;
00380   };
00381 
00382   template<class F>
00383   void pointerOutput(std::ostream& os, const Array<F>& array) {
00384     os << "Array<F>(" << array.size() << ", [";
00385     const F* d = (const F*)array;
00386     for (uint i = array.size(); i--;) {
00387       pointerOutput(os, *d++);
00388       os << ((i == 0) ? "" : ", ");
00389     }
00390     os << "])";
00391   }
00392 
00393 } // namespace concepts
00394 
00395 #endif // Array_hh

Home | Doxygen Documentation | Tutorials | Developer Tools (restricted)