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-2015 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 stm> class arrT: public arr_ref<T>
00178   {
00179   private:
00180     bool own;
00181 
00182     void reset()
00183       { this->d=0; this->s=0; own=true; }
00184 
00185   public:
00186     /*! Creates a zero-sized array. */
00187     arrT() : arr_ref<T>(0,0), own(true) {}
00188     /*! Creates an array with \a sz entries. */
00189     explicit arrT(tsize sz) : arr_ref<T>(stm::alloc(sz),sz), own(true) {}
00190     /*! Creates an array with \a sz entries, and initializes them with
00191         \a inival. */
00192     arrT(tsize sz, const T &inival) : arr_ref<T>(stm::alloc(sz),sz), own(true)
00193       { this->fill(inival); }
00194     /*! Creates an array with \a sz entries, which uses the memory pointed
00195         to by \a ptr.
00196         \note \a ptr will <i>not</i> be deallocated by the destructor.
00197         \warning Only use this if you REALLY know what you are doing.
00198         In particular, this is only safely usable if
00199           <ul>
00200           <li>\a T is a POD type</li>
00201           <li>\a ptr survives during the lifetime of the array object</li>
00202           <li>\a ptr is not subject to garbage collection</li>
00203           </ul>
00204         Other restrictions may apply. You have been warned. */
00205     arrT (T *ptr, tsize sz): arr_ref<T>(ptr,sz), own(false) {}
00206     /*! Creates an array which is a copy of \a orig. The data in \a orig
00207         is duplicated. */
00208     arrT (const arrT &orig): arr_ref<T>(stm::alloc(orig.s),orig.s), own(true)
00209       { for (tsize m=0; m<this->s; ++m) this->d[m] = orig.d[m]; }
00210     /*! Frees the memory allocated by the object. */
00211     ~arrT() { if (own) stm::dealloc(this->d); }
00212 
00213     /*! Allocates space for \a sz elements. The content of the array is
00214         undefined on exit. \a sz can be 0. If \a sz is the
00215         same as the current size, no reallocation is performed. */
00216     void alloc (tsize sz)
00217       {
00218       if (sz==this->s) return;
00219       if (own) stm::dealloc(this->d);
00220       this->s = sz;
00221       this->d = stm::alloc(sz);
00222       own = true;
00223       }
00224     /*! Allocates space for \a sz elements. If \a sz is the
00225         same as the current size, no reallocation is performed.
00226         All elements are set to \a inival. */
00227     void allocAndFill (tsize sz, const T &inival)
00228       { alloc(sz); this->fill(inival); }
00229     /*! Deallocates the memory held by the array, and sets the array size
00230         to 0. */
00231     void dealloc() {if (own) stm::dealloc(this->d); reset();}
00232     /*! Resizes the array to hold \a sz elements. The existing content of the
00233         array is copied over to the new array to the extent possible.
00234         \a sz can be 0. If \a sz is the same as the current size, no
00235         reallocation is performed. */
00236     void resize (tsize sz)
00237       {
00238       using namespace std;
00239       if (sz==this->s) return;
00240       T *tmp = stm::alloc(sz);
00241       for (tsize m=0; m<min(sz,this->s); ++m)
00242         tmp[m]=this->d[m];
00243       if (own) stm::dealloc(this->d);
00244       this->s = sz;
00245       this->d = tmp;
00246       own = true;
00247       }
00248 
00249     /*! Changes the array to be a copy of \a orig. */
00250     arrT &operator= (const arrT &orig)
00251       {
00252       if (this==&orig) return *this;
00253       alloc (orig.s);
00254       for (tsize m=0; m<this->s; ++m) this->d[m] = orig.d[m];
00255       return *this;
00256       }
00257 
00258     /*! Changes the array to be a copy of the std::vector \a orig. */
00259     template<typename T2> void copyFrom (const std::vector<T2> &orig)
00260       {
00261       alloc (orig.size());
00262       for (tsize m=0; m<this->s; ++m) this->d[m] = orig[m];
00263       }
00264     /*! Changes the std::vector \a vec to be a copy of the object. */
00265     template<typename T2> void copyTo (std::vector<T2> &vec) const
00266       {
00267       vec.clear(); vec.reserve(this->s);
00268       for (tsize m=0; m<this->s; ++m) vec.push_back(this->d[m]);
00269       }
00270 
00271     /*! Reserves space for \a sz elements, then copies \a sz elements
00272         from \a ptr into the array. */
00273     template<typename T2> void copyFromPtr (const T2 *ptr, tsize sz)
00274       {
00275       alloc(sz);
00276       for (tsize m=0; m<this->s; ++m) this->d[m]=ptr[m];
00277       }
00278 
00279     /*! Assigns the contents and size of \a other to the array.
00280         \note On exit, \a other is zero-sized! */
00281     void transfer (arrT &other)
00282       {
00283       if (own) stm::dealloc(this->d);
00284       this->d=other.d;
00285       this->s=other.s;
00286       own=other.own;
00287       other.reset();
00288       }
00289     /*! Swaps contents and size with \a other. */
00290     void swap (arrT &other)
00291       {
00292       std::swap(this->d,other.d);
00293       std::swap(this->s,other.s);
00294       std::swap(own,other.own);
00295       }
00296   };
00297 
00298 /*! One-dimensional array type. */
00299 template <typename T>
00300   class arr: public arrT<T,normalAlloc__<T> >
00301   {
00302   public:
00303     /*! Creates a zero-sized array. */
00304     arr() : arrT<T,normalAlloc__<T> >() {}
00305     /*! Creates an array with \a sz entries. */
00306     explicit arr(tsize sz) : arrT<T,normalAlloc__<T> >(sz) {}
00307     /*! Creates an array with \a sz entries, and initializes them with
00308         \a inival. */
00309     arr(tsize sz, const T &inival) : arrT<T,normalAlloc__<T> >(sz,inival) {}
00310     /*! Creates an array with \a sz entries, which uses the memory pointed
00311         to by \a ptr.
00312         \note \a ptr will <i>not</i> be deallocated by the destructor.
00313         \warning Only use this if you REALLY know what you are doing.
00314         In particular, this is only safely usable if
00315           <ul>
00316           <li>\a T is a POD type</li>
00317           <li>\a ptr survives during the lifetime of the array object</li>
00318           <li>\a ptr is not subject to garbage collection</li>
00319           </ul>
00320         Other restrictions may apply. You have been warned. */
00321     arr (T *ptr, tsize sz): arrT<T,normalAlloc__<T> >(ptr,sz) {}
00322     /*! Creates an array which is a copy of \a orig. The data in \a orig
00323         is duplicated. */
00324     arr (const arr &orig): arrT<T,normalAlloc__<T> >(orig) {}
00325   };
00326 
00327 /*! One-dimensional array type, with selectable storage alignment. */
00328 template <typename T, int align>
00329   class arr_align: public arrT<T,alignAlloc__<T,align> >
00330   {
00331   public:
00332     /*! Creates a zero-sized array. */
00333     arr_align() : arrT<T,alignAlloc__<T,align> >() {}
00334     /*! Creates an array with \a sz entries. */
00335     explicit arr_align(tsize sz) : arrT<T,alignAlloc__<T,align> >(sz) {}
00336     /*! Creates an array with \a sz entries, and initializes them with
00337         \a inival. */
00338     arr_align(tsize sz, const T &inival)
00339       : arrT<T,alignAlloc__<T,align> >(sz,inival) {}
00340   };
00341 
00342 
00343 /*! Two-dimensional array type, with selectable storage management.
00344     The storage ordering is the same as in C.
00345     An entry is located by address arithmetic, not by double dereferencing.
00346     The indices start at zero. */
00347 template <typename T, typename storageManager> class arr2T
00348   {
00349   private:
00350     tsize s1, s2;
00351     arrT<T, storageManager> d;
00352 
00353   public:
00354     /*! Creates a zero-sized array. */
00355     arr2T() : s1(0), s2(0) {}
00356     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00357     arr2T(tsize sz1, tsize sz2)
00358       : s1(sz1), s2(sz2), d(s1*s2) {}
00359     /*! Creates an array with the dimensions  \a sz1 and \a sz2
00360         and initializes them with \a inival. */
00361     /*! Creates an array with the dimensions \a sz1 and \a sz2 from existing
00362         pointer. */
00363     arr2T(T* p, tsize sz1, tsize sz2)
00364       : s1(sz1), s2(sz2), d(p, s1*s2) {}
00365     arr2T(tsize sz1, tsize sz2, const T &inival)
00366       : s1(sz1), s2(sz2), d (s1*s2)
00367       { fill(inival); }
00368     /*! Creates the array as a copy of \a orig. */
00369     arr2T(const arr2T &orig)
00370       : s1(orig.s1), s2(orig.s2), d(orig.d) {}
00371     /*! Frees the memory associated with the array. */
00372     ~arr2T() {}
00373 
00374     /*! Returns the first array dimension. */
00375     tsize size1() const { return s1; }
00376     /*! Returns the second array dimension. */
00377     tsize size2() const { return s2; }
00378     /*! Returns the total array size, i.e. the product of both dimensions. */
00379     tsize size () const { return s1*s2; }
00380 
00381     /*! Allocates space for an array with \a sz1*sz2 elements.
00382         The content of the array is undefined on exit.
00383         \a sz1 or \a sz2 can be 0. If \a sz1*sz2 is the same as the
00384         currently allocated space, no reallocation is performed. */
00385     void alloc (tsize sz1, tsize sz2)
00386       {
00387       if (sz1*sz2 != d.size())
00388         d.alloc(sz1*sz2);
00389       s1=sz1; s2=sz2;
00390       }
00391     /*! Allocates space for an array with \a sz1*sz2 elements.
00392         All elements are set to \a inival.
00393         \a sz1 or \a sz2 can be 0. If \a sz1*sz2 is the same as the
00394         currently allocated space, no reallocation is performed. */
00395     void allocAndFill (tsize sz1, tsize sz2, const T &inival)
00396       { alloc(sz1,sz2); fill(inival); }
00397     /*! Allocates space for an array with \a sz1*sz2 elements.
00398         The content of the array is undefined on exit.
00399         \a sz1 or \a sz2 can be 0. If \a sz1*sz2 is smaller than the
00400         currently allocated space, no reallocation is performed. */
00401     void fast_alloc (tsize sz1, tsize sz2)
00402       {
00403       if (sz1*sz2<=d.size())
00404         { s1=sz1; s2=sz2; }
00405       else
00406         alloc(sz1,sz2);
00407       }
00408     /*! Deallocates the space and makes the array zero-sized. */
00409     void dealloc () {d.dealloc(); s1=0; s2=0;}
00410 
00411     /*! Sets all array elements to \a val. */
00412     void fill (const T &val)
00413       { for (tsize m=0; m<s1*s2; ++m) d[m]=val; }
00414 
00415     /*! Multiplies all array elements by \a val. */
00416     void scale (const T &val)
00417       { for (tsize m=0; m<s1*s2; ++m) d[m]*=val; }
00418 
00419     /*! Changes the array to be a copy of \a orig. */
00420     arr2T &operator= (const arr2T &orig)
00421       {
00422       if (this==&orig) return *this;
00423       alloc (orig.s1, orig.s2);
00424       d = orig.d;
00425       return *this;
00426       }
00427 
00428     /*! Returns a pointer to the beginning of slice \a n. */
00429     template<typename T2> T *operator[] (T2 n) {return &d[n*s2];}
00430     /*! Returns a constant pointer to the beginning of slice \a n. */
00431     template<typename T2> const T *operator[] (T2 n) const {return &d[n*s2];}
00432 
00433     /*! Returns a reference to the element with the indices \a n1 and \a n2. */
00434     template<typename T2, typename T3> T &operator() (T2 n1, T3 n2)
00435       {return d[n1*s2 + n2];}
00436     /*! Returns a constant reference to the element with the indices
00437         \a n1 and \a n2. */
00438     template<typename T2, typename T3> const T &operator() (T2 n1, T3 n2) const
00439       {return d[n1*s2 + n2];}
00440 
00441     /*! Returns the minimum and maximum entry in \a minv and \a maxv,
00442         respectively. Throws an exception if the array is zero-sized. */
00443     void minmax (T &minv, T &maxv) const
00444       {
00445       planck_assert(s1*s2>0,
00446         "trying to find min and max of a zero-sized array");
00447       minv=maxv=d[0];
00448       for (tsize m=1; m<s1*s2; ++m)
00449         {
00450         if (d[m]<minv) minv=d[m];
00451         if (d[m]>maxv) maxv=d[m];
00452         }
00453       }
00454 
00455     /*! Swaps contents and sizes with \a other. */
00456     void swap (arr2T &other)
00457       {
00458       d.swap(other.d);
00459       std::swap(s1,other.s1);
00460       std::swap(s2,other.s2);
00461       }
00462 
00463     /*! Returns \c true if the array and \a other have the same dimensions,
00464         else \c false. */
00465     template<typename T2, typename T3> bool conformable
00466       (const arr2T<T2,T3> &other) const
00467       { return (other.size1()==s1) && (other.size2()==s2); }
00468   };
00469 
00470 /*! Two-dimensional array type. The storage ordering is the same as in C.
00471     An entry is located by address arithmetic, not by double dereferencing.
00472     The indices start at zero. */
00473 template <typename T>
00474   class arr2: public arr2T<T,normalAlloc__<T> >
00475   {
00476   public:
00477     /*! Creates a zero-sized array. */
00478     arr2() : arr2T<T,normalAlloc__<T> > () {}
00479     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00480     arr2(tsize sz1, tsize sz2) : arr2T<T,normalAlloc__<T> > (sz1,sz2) {}
00481     /*! Creates an array with the dimensions \a sz1 and \a sz2 from existing
00482         pointer. */
00483     arr2(T* p, tsize sz1, tsize sz2) : arr2T<T,normalAlloc__<T> > (p,sz1,sz2) {}
00484     /*! Creates an array with the dimensions  \a sz1 and \a sz2
00485         and initializes them with \a inival. */
00486     arr2(tsize sz1, tsize sz2, const T &inival)
00487       : arr2T<T,normalAlloc__<T> > (sz1,sz2,inival) {}
00488   };
00489 
00490 /*! Two-dimensional array type, with selectable storage alignment.
00491     The storage ordering is the same as in C.
00492     An entry is located by address arithmetic, not by double dereferencing.
00493     The indices start at zero. */
00494 template <typename T, int align>
00495   class arr2_align: public arr2T<T,alignAlloc__<T,align> >
00496   {
00497   public:
00498     /*! Creates a zero-sized array. */
00499     arr2_align() : arr2T<T,alignAlloc__<T,align> > () {}
00500     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00501     arr2_align(tsize sz1, tsize sz2)
00502       : arr2T<T,alignAlloc__<T,align> > (sz1,sz2) {}
00503     /*! Creates an array with the dimensions  \a sz1 and \a sz2
00504         and initializes them with \a inival. */
00505     arr2_align(tsize sz1, tsize sz2, const T &inival)
00506       : arr2T<T,alignAlloc__<T,align> > (sz1,sz2,inival) {}
00507   };
00508 
00509 /*! Two-dimensional array type. An entry is located by double dereferencing,
00510     i.e. via an array of pointers. The indices start at zero. */
00511 template <typename T> class arr2b
00512   {
00513   private:
00514     tsize s1, s2;
00515     arr<T> d;
00516     arr<T *> d1;
00517 
00518     void fill_d1()
00519       { for (tsize m=0; m<s1; ++m) d1[m] = &d[m*s2]; }
00520 
00521   public:
00522     /*! Creates a zero-sized array. */
00523     arr2b() : s1(0), s2(0), d(0), d1(0) {}
00524     /*! Creates an array with the dimensions \a sz1 and \a sz2. */
00525     arr2b(tsize sz1, tsize sz2)
00526       : s1(sz1), s2(sz2), d(s1*s2), d1(s1)
00527       { fill_d1(); }
00528     /*! Creates the array as a copy of \a orig. */
00529     arr2b(const arr2b &orig)
00530       : s1(orig.s1), s2(orig.s2), d(orig.d), d1(s1)
00531       { fill_d1(); }
00532     /*! Frees the memory associated with the array. */
00533     ~arr2b() {}
00534 
00535     /*! Returns the first array dimension. */
00536     tsize size1() const { return s1; }
00537     /*! Returns the second array dimension. */
00538     tsize size2() const { return s2; }
00539     /*! Returns the total array size, i.e. the product of both dimensions. */
00540     tsize size () const { return s1*s2; }
00541 
00542     /*! Allocates space for an array with \a sz1*sz2 elements.
00543         The content of the array is undefined on exit. */
00544     void alloc (tsize sz1, tsize sz2)
00545       {
00546       if ((s1==sz1) && (s2==sz2)) return;
00547       s1=sz1; s2=sz2;
00548       d.alloc(s1*s2);
00549       d1.alloc(s1);
00550       fill_d1();
00551       }
00552     /*! Deallocates the space and makes the array zero-sized. */
00553     void dealloc () {d.dealloc(); d1.dealloc(); s1=0; s2=0;}
00554 
00555     /*! Sets all array elements to \a val. */
00556     void fill (const T &val)
00557       { d.fill(val); }
00558 
00559     /*! Changes the array to be a copy of \a orig. */
00560     arr2b &operator= (const arr2b &orig)
00561       {
00562       if (this==&orig) return *this;
00563       alloc (orig.s1, orig.s2);
00564       for (tsize m=0; m<s1*s2; ++m) d[m] = orig.d[m];
00565       return *this;
00566       }
00567 
00568     /*! Returns a pointer to the beginning of slice \a n. */
00569     template<typename T2> T *operator[] (T2 n) {return d1[n];}
00570     /*! Returns a constant pointer to the beginning of slice \a n. */
00571     template<typename T2> const T *operator[] (T2 n) const {return d1[n];}
00572 
00573     /*! Returns a pointer to the beginning of the pointer array. */
00574     T **p0() {return &d1[0];}
00575   };
00576 
00577 
00578 /*! Three-dimensional array type. The storage ordering is the same as in C.
00579     An entry is located by address arithmetic, not by multiple dereferencing.
00580     The indices start at zero. */
00581 template <typename T> class arr3
00582   {
00583   private:
00584     tsize s1, s2, s3, s2s3;
00585     arr<T> d;
00586 
00587   public:
00588     /*! Creates a zero-sized array. */
00589     arr3() : s1(0), s2(0), s3(0), s2s3(0), d(0) {}
00590     /*! Creates an array with the dimensions \a sz1, \a sz2 and \a sz3. */
00591     arr3(tsize sz1, tsize sz2, tsize sz3)
00592       : s1(sz1), s2(sz2), s3(sz3), s2s3(s2*s3), d(s1*s2*s3) {}
00593     /*! Creates the array as a copy of \a orig. */
00594     arr3(const arr3 &orig)
00595       : s1(orig.s1), s2(orig.s2), s3(orig.s3), s2s3(orig.s2s3), d(orig.d) {}
00596     /*! Frees the memory associated with the array. */
00597     ~arr3() {}
00598 
00599     /*! Returns the first array dimension. */
00600     tsize size1() const { return s1; }
00601     /*! Returns the second array dimension. */
00602     tsize size2() const { return s2; }
00603     /*! Returns the third array dimension. */
00604     tsize size3() const { return s3; }
00605     /*! Returns the total array size, i.e. the product of all dimensions. */
00606     tsize size () const { return s1*s2*s3; }
00607 
00608     /*! Allocates space for an array with \a sz1*sz2*sz3 elements.
00609         The content of the array is undefined on exit. */
00610     void alloc (tsize sz1, tsize sz2, tsize sz3)
00611       {
00612       d.alloc(sz1*sz2*sz3);
00613       s1=sz1; s2=sz2; s3=sz3; s2s3=s2*s3;
00614       }
00615     /*! Deallocates the space and makes the array zero-sized. */
00616     void dealloc () {d.dealloc(); s1=0; s2=0; s3=0; s2s3=0;}
00617 
00618     /*! Sets all array elements to \a val. */
00619     void fill (const T &val)
00620       { d.fill(val); }
00621 
00622     /*! Changes the array to be a copy of \a orig. */
00623     arr3 &operator= (const arr3 &orig)
00624       {
00625       if (this==&orig) return *this;
00626       alloc (orig.s1, orig.s2, orig.s3);
00627       d = orig.d;
00628       return *this;
00629       }
00630 
00631     /*! Returns a reference to the element with the indices
00632         \a n1, \a n2 and \a n3. */
00633     template<typename T2, typename T3, typename T4> T &operator()
00634       (T2 n1, T3 n2, T4 n3)
00635       {return d[n1*s2s3 + n2*s3 + n3];}
00636     /*! Returns a constant reference to the element with the indices
00637         \a n1, \a n2 and \a n3. */
00638     template<typename T2, typename T3, typename T4> const T &operator()
00639       (T2 n1, T3 n2, T4 n3) const
00640       {return d[n1*s2s3 + n2*s3 + n3];}
00641 
00642     /*! Swaps contents and sizes with \a other. */
00643     void swap (arr3 &other)
00644       {
00645       d.swap(other.d);
00646       std::swap(s1,other.s1);
00647       std::swap(s2,other.s2);
00648       std::swap(s3,other.s3);
00649       std::swap(s2s3,other.s2s3);
00650       }
00651 
00652     /*! Returns \c true if the array and \a other have the same dimensions,
00653         else \c false. */
00654     template<typename T2> bool conformable (const arr3<T2> &other) const
00655       { return (other.size1()==s1)&&(other.size2()==s2)&&(other.size3()==s3); }
00656   };
00657 
00658 /*! \} */
00659 
00660 #endif

Generated on Thu Oct 8 14:48:51 2015 for LevelS C++ support library