arr.h

Go to the documentation of this file.
00001 /*
00002  *  This file is part of libcxxsupport.
00003  *
00004  *  libcxxsupport is free software; you can redistribute it and/or modify
00005  *  it under the terms of the GNU General Public License as published by
00006  *  the Free Software Foundation; either version 2 of the License, or
00007  *  (at your option) any later version.
00008  *
00009  *  libcxxsupport is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *  GNU General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU General Public License
00015  *  along with libcxxsupport; if not, write to the Free Software
00016  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
00017  */
00018 
00019 /*
00020  *  libcxxsupport is being developed at the Max-Planck-Institut fuer Astrophysik
00021  *  and financially supported by the Deutsches Zentrum fuer Luft- und Raumfahrt
00022  *  (DLR).
00023  */
00024 
00025 /*! \file arr.h
00026  *  Various high-performance array classes used by the Planck LevelS package.
00027  *
00028  *  Copyright (C) 2002-2012 Max-Planck-Society
00029  *  \author Martin Reinecke
00030  */
00031 
00032 #ifndef PLANCK_ARR_H
00033 #define PLANCK_ARR_H
00034 
00035 #include <algorithm>
00036 #include <vector>
00037 #include <cstdlib>
00038 #include "alloc_utils.h"
00039 #include "datatypes.h"
00040 #include "math_utils.h"
00041 
00042 /*! \defgroup arraygroup Array classes */
00043 /*! \{ */
00044 
00045 /*! View of a 1D array */
00046 template <typename T> class arr_ref
00047   {
00048   protected:
00049     tsize s;
00050     T *d;
00051 
00052   public:
00053     /*! Constructs an \a arr_ref of size \a s_, starting at \a d_. */
00054     arr_ref(T *d_, tsize s_) : s(s_),d(d_) {}
00055 
00056     /*! Returns the current array size. */
00057     tsize size() const { return s; }
00058 
00059     /*! Writes \a val into every element of the array. */
00060     void fill (const T &val)
00061       { for (tsize m=0; m<s; ++m) d[m]=val; }
00062 
00063     /*! Returns a reference to element \a n */
00064     template<typename T2> T &operator[] (T2 n) {return d[n];}
00065     /*! Returns a constant reference to element \a n */
00066     template<typename T2> const T &operator[] (T2 n) const {return d[n];}
00067 
00068     /*! Returns a pointer to the first array element, or NULL if the array
00069         is zero-sized. */
00070     T *begin() { return d; }
00071     /*! Returns a pointer to the one-past-last array element, or NULL if the
00072         array is zero-sized. */
00073     T *end() { return d+s; }
00074     /*! Returns a constant pointer to the first array element, or NULL if the
00075         array is zero-sized. */
00076     const T *begin() const { return d; }
00077     /*! Returns a constant pointer to the one-past-last array element, or NULL
00078         if the array is zero-sized. */
00079     const T *end() const { return d+s; }
00080 
00081     /*! Copies all array elements to \a ptr. */
00082     template<typename T2> void copyToPtr (T *ptr) const
00083       { for (tsize m=0; m<s; ++m) ptr[m]=d[m]; }
00084 
00085     /*! Sorts the elements in the array, in ascending order. */
00086     void sort()
00087       { std::sort (d,d+s); }
00088 
00089     /*! Sorts the elements in the array, such that \a comp(d[i],d[j])==true
00090         for \a i<j. */
00091     template<typename Comp> void sort(Comp comp)
00092       { std::sort (d,d+s,comp); }
00093 
00094     /*! Helper function for linear interpolation (or extrapolation).
00095         \a idx and \a val are computed such that
00096         \a val=d[idx]+frac*(d[idx+1]-d[idx]). If \a val<d[0], \a frac will be
00097         negative, if \a val>d[s-1], frac will be larger than 1. In all other
00098         cases \a 0<=frac<=1.
00099 
00100         The array must be ordered in ascending order; no two values may be
00101         equal. */
00102     void interpol_helper (const T &val, tsize &idx, double &frac) const
00103       { ::interpol_helper (d, d+s, val, idx, frac); }
00104 
00105     /*! Helper function for linear interpolation (or extrapolation).
00106         \a idx and \a val are computed such that
00107         \a val=d[idx]+frac*(d[idx+1]-d[idx]). If \a comp(val,d[0])==true,
00108         \a frac will be negative, if \a comp(val,d[s-1])==false, frac will be
00109         larger than 1. In all other cases \a 0<=frac<=1.
00110 
00111         The array must be ordered such that \a comp(d[i],d[j])==true
00112         for \a i<j; no two values may be equal. */
00113     template<typename Comp> void interpol_helper (const T &val, Comp comp,
00114       tsize &idx, double &frac) const
00115       { ::interpol_helper (d, d+s, val, comp, idx, frac); }
00116 
00117     /*! Returns the minimum and maximum entry in \a minv and \a maxv,
00118         respectively. Throws an exception if the array is zero-sized. */
00119     void minmax (T &minv, T &maxv) const
00120       {
00121       planck_assert(s>0,"trying to find min and max of a zero-sized array");
00122       minv=maxv=d[0];
00123       for (tsize m=1; m<s; ++m)
00124         {
00125         if (d[m]<minv) minv=d[m];
00126         else if (d[m]>maxv) maxv=d[m];
00127         }
00128       }
00129 
00130     /*! Returns \a true, if \a val is found in the array, else \a false. */
00131     bool contains (const T &val) const
00132       {
00133       for (tsize m=0; m<s; ++m)
00134         if (d[m]==val) return true;
00135       return false;
00136       }
00137 
00138     /*! Returns the index of the first occurrence of \a val in the array.
00139         If it is not found, an exception is thrown. */
00140     tsize find (const T &val) const
00141       {
00142       for (tsize m=0; m<s; ++m)
00143         if (d[m]==val) return m;
00144       planck_fail ("entry not found in array");
00145       }
00146 
00147     /*! Returns \a true if the array has the same size as \a other and all
00148         elements of both arrays are equal, else \a false. */
00149     bool contentsEqual(const arr_ref &other) const
00150       {
00151       if (s!=other.s) return false;
00152       for (tsize i=0; i<s; ++i)
00153         if (d[i]!=other.d[i]) return false;
00154       return true;
00155       }
00156   };
00157 
00158 /*! An array whose size is known at compile time. Very useful for storing
00159     small arrays on the stack, without need for \a new and \a delete(). */
00160 template <typename T, tsize sz> class fix_arr
00161   {
00162   private:
00163     T d[sz];
00164 
00165   public:
00166     /*! Returns the size of the array. */
00167     tsize size() const { return sz; }
00168 
00169     /*! Returns a reference to element \a n */
00170     template<typename T2> T &operator[] (T2 n) {return d[n];}
00171     /*! Returns a constant reference to element \a n */
00172     template<typename T2> const T &operator[] (T2 n) const {return d[n];}
00173   };
00174 
00175 
00176 /*! One-dimensional array type, with selectable storage management. */
00177 template <typename T, typename storageManager> class arrT: public arr_ref<T>
00178   {
00179   private:
00180     storageManager stm;
00181     bool own;
00182 
00183     void reset()
00184       { this->d=0; this->s=0; own=true; }
00185 
00186   public:
00187     /*! Creates a zero-sized array. */
00188     arrT() : arr_ref<T>(0,0), own(true) {}
00189     /*! Creates an array with \a sz entries. */
00190     arrT(tsize sz) : arr_ref<T>(stm.alloc(sz),sz), own(true) {}
00191     /*! Creates an array with \a sz entries, and initializes them with
00192         \a inival. */
00193     arrT(tsize sz, const T &inival) : arr_ref<T>(stm.alloc(sz),sz), own(true)
00194       { this->fill(inival); }
00195     /*! Creates an array with \a sz entries, which uses the memory pointed
00196         to by \a ptr.
00197         \note \a ptr will <i>not</i> be deallocated by the destructor.
00198         \warning Only use this if you REALLY know what you are doing.
00199         In particular, this is only safely usable if
00200           <ul>
00201           <li>\a T is a POD type</li>
00202           <li>\a ptr survives during the lifetime of the array object</li>
00203           <li>\a ptr is not subject to garbage collection</li>
00204           </ul>
00205         Other restrictions may apply. You have been warned. */
00206     arrT (T *ptr, tsize sz): arr_ref<T>(ptr,sz), own(false) {}
00207     /*! Creates an array which is a copy of \a orig. The data in \a orig
00208         is duplicated. */
00209     arrT (const arrT &orig): arr_ref<T>(stm.alloc(orig.s),orig.s), own(true)
00210       { for (tsize m=0; m<this->s; ++m) this->d[m] = orig.d[m]; }
00211     /*! Frees the memory allocated by the object. */
00212     ~arrT() { if (own) stm.dealloc(this->d); }
00213 
00214     /*! Allocates space for \a sz elements. The content of the array is
00215         undefined on exit. \a sz can be 0. If \a sz is the
00216         same as the current size, no reallocation is performed. */
00217     void alloc (tsize sz)
00218       {
00219       if (sz==this->s) return;
00220       if (own) stm.dealloc(this->d);
00221       this->s = sz;
00222       this->d = stm.alloc(sz);
00223       own = true;
00224       }
00225     /*! Allocates space for \a sz elements. If \a sz is the
00226         same as the current size, no reallocation is performed.
00227         All elements are set to \a inival. */
00228     void allocAndFill (tsize sz, const T &inival)
00229       { alloc(sz); this->fill(inival); }
00230     /*! Deallocates the memory held by the array, and sets the array size
00231         to 0. */
00232     void dealloc() {if (own) stm.dealloc(this->d); reset();}
00233     /*! Resizes the array to hold \a sz elements. The existing content of the
00234         array is copied over to the new array to the extent possible.
00235         \a sz can be 0. If \a sz is the same as the current size, no
00236         reallocation is performed. */
00237     void resize (tsize sz)
00238       {
00239       using namespace std;
00240       if (sz==this->s) return;
00241       T *tmp = stm.alloc(sz);
00242       for (tsize m=0; m<min(sz,this->s); ++m)
00243         tmp[m]=this->d[m];
00244       if (own) stm.dealloc(this->d);
00245       this->s = sz;
00246       this->d = tmp;
00247       own = true;
00248       }
00249 
00250     /*! Changes the array to be a copy of \a orig. */
00251     arrT &operator= (const arrT &orig)
00252       {
00253       if (this==&orig) return *this;
00254       alloc (orig.s);
00255       for (tsize m=0; m<this->s; ++m) this->d[m] = orig.d[m];
00256       return *this;
00257       }
00258 
00259     /*! Changes the array to be a copy of the std::vector \a orig. */
00260     template<typename T2> void copyFrom (const std::vector<T2> &orig)
00261       {
00262       alloc (orig.size());
00263       for (tsize m=0; m<this->s; ++m) this->d[m] = orig[m];
00264       }
00265     /*! Changes the std::vector \a vec to be a copy of the object. */
00266     template<typename T2> void copyTo (std::vector<T2> &vec) const
00267       {
00268       vec.clear(); vec.reserve(this->s);
00269       for (tsize m=0; m<this->s; ++m) vec.push_back(this->d[m]);
00270       }
00271 
00272     /*! Reserves space for \a sz elements, then copies \a sz elements
00273         from \a ptr into the array. */
00274     template<typename T2> void copyFromPtr (const T2 *ptr, tsize sz)
00275       {
00276       alloc(sz);
00277       for (tsize m=0; m<this->s; ++m) this->d[m]=ptr[m];
00278       }
00279 
00280     /*! Assigns the contents and size of \a other to the array.
00281         \note On exit, \a other is zero-sized! */
00282     void transfer (arrT &other)
00283       {
00284       if (own) stm.dealloc(this->d);
00285       this->d=other.d;
00286       this->s=other.s;
00287       own=other.own;
00288       other.reset();
00289       }
00290     /*! Swaps contents and size with \a other. */
00291     void swap (arrT &other)
00292       {
00293       std::swap(this->d,other.d);
00294       std::swap(this->s,other.s);
00295       std::swap(own,other.own);
00296       }
00297   };
00298 
00299 /*! One-dimensional array type. */
00300 template <typename T>
00301   class arr: public arrT<T,normalAlloc__<T> >
00302   {
00303   public:
00304     /*! Creates a zero-sized array. */
00305     arr() : arrT<T,normalAlloc__<T> >() {}
00306     /*! Creates an array with \a sz entries. */
00307     arr(tsize sz) : arrT<T,normalAlloc__<T> >(sz) {}
00308     /*! Creates an array with \a sz entries, and initializes them with
00309         \a inival. */
00310     arr(tsize sz, const T &inival) : arrT<T,normalAlloc__<T> >(sz,inival) {}
00311     /*! Creates an array with \a sz entries, which uses the memory pointed
00312         to by \a ptr.
00313         \note \a ptr will <i>not</i> be deallocated by the destructor.
00314         \warning Only use this if you REALLY know what you are doing.
00315         In particular, this is only safely usable if
00316           <ul>
00317           <li>\a T is a POD type</li>
00318           <li>\a ptr survives during the lifetime of the array object</li>
00319           <li>\a ptr is not subject to garbage collection</li>
00320           </ul>
00321         Other restrictions may apply. You have been warned. */
00322     arr (T *ptr, tsize sz): arrT<T,normalAlloc__<T> >(ptr,sz) {}
00323     /*! Creates an array which is a copy of \a orig. The data in \a orig
00324         is duplicated. */
00325     arr (const arr &orig): arrT<T,normalAlloc__<T> >(orig) {}
00326   };
00327 
00328 /*! One-dimensional array type, with selectable storage alignment. */
00329 template <typename T, int align>
00330   class arr_align: public arrT<T,alignAlloc__<T,align> >
00331   {
00332   public:
00333     /*! Creates a zero-sized array. */
00334     arr_align() : arrT<T,alignAlloc__<T,align> >() {}
00335     /*! Creates an array with \a sz entries. */
00336     arr_align(tsize sz) : arrT<T,alignAlloc__<T,align> >(sz) {}
00337     /*! Creates an array with \a sz entries, and initializes them with
00338         \a inival. */
00339     arr_align(tsize sz, const T &inival)
00340       : arrT<T,alignAlloc__<T,align> >(sz,inival) {}
00341   };
00342 
00343 
00344 /*! Two-dimensional array type, with selectable storage management.
00345     The storage ordering is the same as in C.
00346     An entry is located by address arithmetic, not by double dereferencing.
00347     The indices start at zero. */
00348 template <typename T, typename storageManager> class arr2T
00349   {
00350   private:
00351     tsize s1, s2;
00352     arrT<T, storageManager> d;
00353 
00354   public:
00355     /*! Creates a zero-sized array. */
00356     arr2T() : s1(0), s2(0) {}
00357     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00358     arr2T(tsize sz1, tsize sz2)
00359       : s1(sz1), s2(sz2), d(s1*s2) {}
00360     /*! Creates an array with the dimensions  \a sz1 and \a sz2
00361         and initializes them with \a inival. */
00362     arr2T(tsize sz1, tsize sz2, const T &inival)
00363       : s1(sz1), s2(sz2), d (s1*s2)
00364       { fill(inival); }
00365     /*! Creates the array as a copy of \a orig. */
00366     arr2T(const arr2T &orig)
00367       : s1(orig.s1), s2(orig.s2), d(orig.d) {}
00368     /*! Frees the memory associated with the array. */
00369     ~arr2T() {}
00370 
00371     /*! Returns the first array dimension. */
00372     tsize size1() const { return s1; }
00373     /*! Returns the second array dimension. */
00374     tsize size2() const { return s2; }
00375     /*! Returns the total array size, i.e. the product of both dimensions. */
00376     tsize size () const { return s1*s2; }
00377 
00378     /*! Allocates space for an array with \a sz1*sz2 elements.
00379         The content of the array is undefined on exit.
00380         \a sz1 or \a sz2 can be 0. If \a sz1*sz2 is the same as the
00381         currently allocated space, no reallocation is performed. */
00382     void alloc (tsize sz1, tsize sz2)
00383       {
00384       if (sz1*sz2 != d.size())
00385         d.alloc(sz1*sz2);
00386       s1=sz1; s2=sz2;
00387       }
00388     /*! Allocates space for an array with \a sz1*sz2 elements.
00389         All elements are set to \a inival.
00390         \a sz1 or \a sz2 can be 0. If \a sz1*sz2 is the same as the
00391         currently allocated space, no reallocation is performed. */
00392     void allocAndFill (tsize sz1, tsize sz2, const T &inival)
00393       { alloc(sz1,sz2); fill(inival); }
00394     /*! Allocates space for an array with \a sz1*sz2 elements.
00395         The content of the array is undefined on exit.
00396         \a sz1 or \a sz2 can be 0. If \a sz1*sz2 is smaller than the
00397         currently allocated space, no reallocation is performed. */
00398     void fast_alloc (tsize sz1, tsize sz2)
00399       {
00400       if (sz1*sz2<=d.size())
00401         { s1=sz1; s2=sz2; }
00402       else
00403         alloc(sz1,sz2);
00404       }
00405     /*! Deallocates the space and makes the array zero-sized. */
00406     void dealloc () {d.dealloc(); s1=0; s2=0;}
00407 
00408     /*! Sets all array elements to \a val. */
00409     void fill (const T &val)
00410       { for (tsize m=0; m<s1*s2; ++m) d[m]=val; }
00411 
00412     /*! Multiplies all array elements by \a val. */
00413     void scale (const T &val)
00414       { for (tsize m=0; m<s1*s2; ++m) d[m]*=val; }
00415 
00416     /*! Changes the array to be a copy of \a orig. */
00417     arr2T &operator= (const arr2T &orig)
00418       {
00419       if (this==&orig) return *this;
00420       alloc (orig.s1, orig.s2);
00421       d = orig.d;
00422       return *this;
00423       }
00424 
00425     /*! Returns a pointer to the beginning of slice \a n. */
00426     template<typename T2> T *operator[] (T2 n) {return &d[n*s2];}
00427     /*! Returns a constant pointer to the beginning of slice \a n. */
00428     template<typename T2> const T *operator[] (T2 n) const {return &d[n*s2];}
00429 
00430     /*! Returns a reference to the element with the indices \a n1 and \a n2. */
00431     template<typename T2, typename T3> T &operator() (T2 n1, T3 n2)
00432       {return d[n1*s2 + n2];}
00433     /*! Returns a constant reference to the element with the indices
00434         \a n1 and \a n2. */
00435     template<typename T2, typename T3> const T &operator() (T2 n1, T3 n2) const
00436       {return d[n1*s2 + n2];}
00437 
00438     /*! Returns the minimum and maximum entry in \a minv and \a maxv,
00439         respectively. Throws an exception if the array is zero-sized. */
00440     void minmax (T &minv, T &maxv) const
00441       {
00442       planck_assert(s1*s2>0,
00443         "trying to find min and max of a zero-sized array");
00444       minv=maxv=d[0];
00445       for (tsize m=1; m<s1*s2; ++m)
00446         {
00447         if (d[m]<minv) minv=d[m];
00448         if (d[m]>maxv) maxv=d[m];
00449         }
00450       }
00451 
00452     /*! Swaps contents and sizes with \a other. */
00453     void swap (arr2T &other)
00454       {
00455       d.swap(other.d);
00456       std::swap(s1,other.s1);
00457       std::swap(s2,other.s2);
00458       }
00459 
00460     /*! Returns \c true if the array and \a other have the same dimensions,
00461         else \c false. */
00462     template<typename T2, typename T3> bool conformable
00463       (const arr2T<T2,T3> &other) const
00464       { return (other.size1()==s1) && (other.size2()==s2); }
00465   };
00466 
00467 /*! Two-dimensional array type. The storage ordering is the same as in C.
00468     An entry is located by address arithmetic, not by double dereferencing.
00469     The indices start at zero. */
00470 template <typename T>
00471   class arr2: public arr2T<T,normalAlloc__<T> >
00472   {
00473   public:
00474     /*! Creates a zero-sized array. */
00475     arr2() : arr2T<T,normalAlloc__<T> > () {}
00476     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00477     arr2(tsize sz1, tsize sz2) : arr2T<T,normalAlloc__<T> > (sz1,sz2) {}
00478     /*! Creates an array with the dimensions  \a sz1 and \a sz2
00479         and initializes them with \a inival. */
00480     arr2(tsize sz1, tsize sz2, const T &inival)
00481       : arr2T<T,normalAlloc__<T> > (sz1,sz2,inival) {}
00482   };
00483 
00484 /*! Two-dimensional array type, with selectable storage alignment.
00485     The storage ordering is the same as in C.
00486     An entry is located by address arithmetic, not by double dereferencing.
00487     The indices start at zero. */
00488 template <typename T, int align>
00489   class arr2_align: public arr2T<T,alignAlloc__<T,align> >
00490   {
00491   public:
00492     /*! Creates a zero-sized array. */
00493     arr2_align() : arr2T<T,alignAlloc__<T,align> > () {}
00494     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00495     arr2_align(tsize sz1, tsize sz2)
00496       : arr2T<T,alignAlloc__<T,align> > (sz1,sz2) {}
00497     /*! Creates an array with the dimensions  \a sz1 and \a sz2
00498         and initializes them with \a inival. */
00499     arr2_align(tsize sz1, tsize sz2, const T &inival)
00500       : arr2T<T,alignAlloc__<T,align> > (sz1,sz2,inival) {}
00501   };
00502 
00503 /*! Two-dimensional array type. An entry is located by double dereferencing,
00504     i.e. via an array of pointers. The indices start at zero. */
00505 template <typename T> class arr2b
00506   {
00507   private:
00508     tsize s1, s2;
00509     arr<T> d;
00510     arr<T *> d1;
00511 
00512     void fill_d1()
00513       { for (tsize m=0; m<s1; ++m) d1[m] = &d[m*s2]; }
00514 
00515   public:
00516     /*! Creates a zero-sized array. */
00517     arr2b() : s1(0), s2(0), d(0), d1(0) {}
00518     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00519     arr2b(tsize sz1, tsize sz2)
00520       : s1(sz1), s2(sz2), d(s1*s2), d1(s1)
00521       { fill_d1(); }
00522     /*! Creates the array as a copy of \a orig. */
00523     arr2b(const arr2b &orig)
00524       : s1(orig.s1), s2(orig.s2), d(orig.d), d1(s1)
00525       { fill_d1(); }
00526     /*! Frees the memory associated with the array. */
00527     ~arr2b() {}
00528 
00529     /*! Returns the first array dimension. */
00530     tsize size1() const { return s1; }
00531     /*! Returns the second array dimension. */
00532     tsize size2() const { return s2; }
00533     /*! Returns the total array size, i.e. the product of both dimensions. */
00534     tsize size () const { return s1*s2; }
00535 
00536     /*! Allocates space for an array with \a sz1*sz2 elements.
00537         The content of the array is undefined on exit. */
00538     void alloc (tsize sz1, tsize sz2)
00539       {
00540       if ((s1==sz1) && (s2==sz2)) return;
00541       s1=sz1; s2=sz2;
00542       d.alloc(s1*s2);
00543       d1.alloc(s1);
00544       fill_d1();
00545       }
00546     /*! Deallocates the space and makes the array zero-sized. */
00547     void dealloc () {d.dealloc(); d1.dealloc(); s1=0; s2=0;}
00548 
00549     /*! Sets all array elements to \a val. */
00550     void fill (const T &val)
00551       { d.fill(val); }
00552 
00553     /*! Changes the array to be a copy of \a orig. */
00554     arr2b &operator= (const arr2b &orig)
00555       {
00556       if (this==&orig) return *this;
00557       alloc (orig.s1, orig.s2);
00558       for (tsize m=0; m<s1*s2; ++m) d[m] = orig.d[m];
00559       return *this;
00560       }
00561 
00562     /*! Returns a pointer to the beginning of slice \a n. */
00563     template<typename T2> T *operator[] (T2 n) {return d1[n];}
00564     /*! Returns a constant pointer to the beginning of slice \a n. */
00565     template<typename T2> const T *operator[] (T2 n) const {return d1[n];}
00566 
00567     /*! Returns a pointer to the beginning of the pointer array. */
00568     T **p0() {return &d1[0];}
00569   };
00570 
00571 
00572 /*! Three-dimensional array type. The storage ordering is the same as in C.
00573     An entry is located by address arithmetic, not by multiple dereferencing.
00574     The indices start at zero. */
00575 template <typename T> class arr3
00576   {
00577   private:
00578     tsize s1, s2, s3, s2s3;
00579     arr<T> d;
00580 
00581   public:
00582     /*! Creates a zero-sized array. */
00583     arr3() : s1(0), s2(0), s3(0), s2s3(0), d(0) {}
00584     /*! Creates an array with the dimensions \a sz1, \a sz2 and \a sz3. */
00585     arr3(tsize sz1, tsize sz2, tsize sz3)
00586       : s1(sz1), s2(sz2), s3(sz3), s2s3(s2*s3), d(s1*s2*s3) {}
00587     /*! Creates the array as a copy of \a orig. */
00588     arr3(const arr3 &orig)
00589       : s1(orig.s1), s2(orig.s2), s3(orig.s3), s2s3(orig.s2s3), d(orig.d) {}
00590     /*! Frees the memory associated with the array. */
00591     ~arr3() {}
00592 
00593     /*! Returns the first array dimension. */
00594     tsize size1() const { return s1; }
00595     /*! Returns the second array dimension. */
00596     tsize size2() const { return s2; }
00597     /*! Returns the third array dimension. */
00598     tsize size3() const { return s3; }
00599     /*! Returns the total array size, i.e. the product of all dimensions. */
00600     tsize size () const { return s1*s2*s3; }
00601 
00602     /*! Allocates space for an array with \a sz1*sz2*sz3 elements.
00603         The content of the array is undefined on exit. */
00604     void alloc (tsize sz1, tsize sz2, tsize sz3)
00605       {
00606       d.alloc(sz1*sz2*sz3);
00607       s1=sz1; s2=sz2; s3=sz3; s2s3=s2*s3;
00608       }
00609     /*! Deallocates the space and makes the array zero-sized. */
00610     void dealloc () {d.dealloc(); s1=0; s2=0; s3=0; s2s3=0;}
00611 
00612     /*! Sets all array elements to \a val. */
00613     void fill (const T &val)
00614       { d.fill(val); }
00615 
00616     /*! Changes the array to be a copy of \a orig. */
00617     arr3 &operator= (const arr3 &orig)
00618       {
00619       if (this==&orig) return *this;
00620       alloc (orig.s1, orig.s2, orig.s3);
00621       d = orig.d;
00622       return *this;
00623       }
00624 
00625     /*! Returns a reference to the element with the indices
00626         \a n1, \a n2 and \a n3. */
00627     template<typename T2, typename T3, typename T4> T &operator()
00628       (T2 n1, T3 n2, T4 n3)
00629       {return d[n1*s2s3 + n2*s3 + n3];}
00630     /*! Returns a constant reference to the element with the indices
00631         \a n1, \a n2 and \a n3. */
00632     template<typename T2, typename T3, typename T4> const T &operator()
00633       (T2 n1, T3 n2, T4 n3) const
00634       {return d[n1*s2s3 + n2*s3 + n3];}
00635 
00636     /*! Swaps contents and sizes with \a other. */
00637     void swap (arr3 &other)
00638       {
00639       d.swap(other.d);
00640       std::swap(s1,other.s1);
00641       std::swap(s2,other.s2);
00642       std::swap(s3,other.s3);
00643       std::swap(s2s3,other.s2s3);
00644       }
00645 
00646     /*! Returns \c true if the array and \a other have the same dimensions,
00647         else \c false. */
00648     template<typename T2> bool conformable (const arr3<T2> &other) const
00649       { return (other.size1()==s1)&&(other.size2()==s2)&&(other.size3()==s3); }
00650   };
00651 
00652 /*! \} */
00653 
00654 #endif

Generated on Wed Apr 24 11:31:17 2013 for LevelS C++ support library