Shark Machine Learning Library
  • About Shark
  • Sourceforge
    • Project Summary
    • Downloads
    • Subversion Repository
  • Getting Started
  • Tutorials
  • FAQ
  • Main Modules
    • ReClaM
    • EALib
    • MOO-EALib
    • Fuzzy
  • Tools
    • Mixture
    • Array
    • Rng
    • LinAlg
    • FileUtil
  • Main Page
  • Modules
  • Classes

Array.h

Go to the documentation of this file.
00001 //===========================================================================
00057 //===========================================================================
00058 
00061 #define __ARRAY_NO_GENERIC_IOSTREAM
00062 
00063 #ifndef __ARRAY_H
00064 #define __ARRAY_H
00065 
00066 
00068 // backwards compatibility
00069 #define Array2D Array
00070 #define Array2DReference ArrayReference
00071 
00072 
00073 #include <SharkDefs.h>
00074 #include <algorithm>
00075 #include <vector>
00076 #include <typeinfo>
00077 
00078 
00079 //==========================================================================
00080 //
00081 // doxygen declarations begin
00082 //
00083 //==========================================================================
00084 
00161 //==========================================================================
00162 //
00163 // doxygen declarations end
00164 //
00165 //==========================================================================
00166 
00167 
00168 // forward declaration
00169 template< class T >
00170 class Array;
00171 
00172 // forward declaration
00173 class ArrayIndex;
00174 
00175 // forward declaration
00176 template< class T >
00177 class ArrayReference;
00178 
00179 //===========================================================================
00200 class ArrayBase
00201 {
00202 public:  // interface of public members
00203 
00204     //========================================================================
00224     unsigned ndim() const
00225     {
00226         return nd;
00227     }
00228 
00229 
00230     //========================================================================
00250     unsigned nelem() const
00251     {
00252         return ne;
00253     }
00254 
00255 
00256     //========================================================================
00279     bool samedim(const ArrayBase& v) const
00280     {
00281         if (nd == v.nd && ne == v.ne)
00282         {
00283             unsigned i;
00284             for (i = 0; i < nd && d[ i ] == v.d[ i ]; i++);
00285             return i == nd;
00286         }
00287         return false;
00288     }
00289 
00290     //========================================================================
00320     void resize(unsigned i, bool copy = false)
00321     {
00322         unsigned _d[ 1 ];
00323         _d[ 0 ] = i;
00324         resize_i(_d, 1, copy);
00325     }
00326 
00327     //========================================================================
00358     void resize(unsigned i, unsigned j, bool copy = false)
00359     {
00360         unsigned _d[ 2 ];
00361         _d[ 0 ] = i;
00362         _d[ 1 ] = j;
00363         resize_i(_d, 2, copy);
00364     }
00365 
00366     //========================================================================
00399     void resize(unsigned i, unsigned j, unsigned k, bool copy = false)
00400     {
00401         unsigned _d[ 3 ];
00402         _d[ 0 ] = i;
00403         _d[ 1 ] = j;
00404         _d[ 2 ] = k;
00405         resize_i(_d, 3, copy);
00406     }
00407 
00408     //========================================================================
00440     void resize(const std::vector< unsigned >& i, bool copy = false)
00441     {
00442         unsigned* _d = new unsigned[ i.size()];
00443 
00444         for (unsigned j = 0; j < i.size(); ++j)
00445             _d[ j ] = i[ j ];
00446 
00447         resize_i(_d, i.size(), copy);
00448 
00449         delete[ ] _d;
00450     }
00451 
00452     //========================================================================
00485     void resize(const ArrayBase& v, bool copy = false)
00486     {
00487         resize_i(v.d, v.nd, copy);
00488     }
00489 
00490     //========================================================================
00511     unsigned dim(unsigned i) const
00512     {
00513         RANGE_CHECK(i < nd)
00514         return d[ i ];
00515     }
00516 
00519     inline unsigned int rows() const
00520     {
00521         if (ndim() == 0) return 0;
00522         else return dim(0);
00523     }
00524 
00527     inline unsigned int cols() const
00528     {
00529         if (ndim() == 0) return 0;
00530         else return dim(ndim() - 1);
00531     }
00532 
00533     //========================================================================
00554     unsigned* dimvec()
00555     {
00556         return d;
00557     }
00558 
00559     //========================================================================
00581     const unsigned* dimvec() const
00582     {
00583         return d;
00584     }
00585 
00586     //========================================================================
00607     virtual ArrayBase* clone() const = 0;
00608 
00609     //========================================================================
00630     virtual ArrayBase* empty() const = 0;
00631 
00632     //========================================================================
00651     virtual ~ArrayBase()
00652     {
00653         if (! stat && nd)
00654         {
00655             delete[ ] d;
00656         }
00657     }
00658 
00659 protected:  // interface of protected members (overloaded by array< T >)
00660 
00661     //========================================================================
00680     ArrayBase()
00681     {
00682         d    = 0;
00683         nd   = 0;
00684         ne   = 0;
00685         stat = false;
00686     }
00687 
00688     //=======================================================================
00712     ArrayBase(const ArrayBase& v)
00713     {
00714         nd    = v.nd;
00715         ne    = v.ne;
00716         stat  = false;
00717 
00718         if (nd)
00719         {
00720             d = new unsigned[ nd ];
00721             for (unsigned i = nd; i--; d[ i ] = v.d[ i ]);
00722         }
00723     }
00724 
00725     //=======================================================================
00759     virtual void resize_i(unsigned* d, unsigned nd, bool copy) = 0;
00760 
00761 #ifndef __ARRAY_NO_GENERIC_IOSTREAM
00762 
00763     //=======================================================================
00789     virtual void readFrom(std::istream& is) = 0;
00790 
00791     //=======================================================================
00815     virtual void writeTo(std::ostream& os) const = 0;
00816 #endif // !__ARRAY_NO_GENERIC_IOSTREAM
00817 
00818     //=======================================================================
00876     unsigned* d;
00877 
00879     unsigned  nd;
00880 
00882     unsigned  ne;
00883 
00885     bool      stat;
00886 
00887 #ifndef __ARRAY_NO_GENERIC_IOSTREAM
00888 
00889     //=======================================================================
00922     friend inline std::istream& operator >> (std::istream& is, ArrayBase& a)
00923     {
00924         a.readFrom(is);
00925         IO_CHECK(is)
00926         return is;
00927     }
00928 
00929     //=======================================================================
00959     friend inline std::ostream& operator << (std::ostream& os, const ArrayBase& a)
00960     {
00961         a.writeTo(os);
00962         IO_CHECK(os)
00963         return os;
00964     }
00965 #endif // __ARRAY_NO_GENERIC_IOSTREAM
00966 };
00967 
00968 //===========================================================================
00987 template< class T >
00988 class Array : public ArrayBase
00989 {
00990     friend class ArrayReference< T >;
00991     friend class ArrayIndex;
00992 
00993 public:
00994 
00997     typedef T* iterator;
00998 
01001     typedef T* const_iterator;
01002 
01003 
01004     //=======================================================================
01021     Array()
01022     {
01023         ne = 0;
01024         e = eEnd = 0;
01025     }
01026 
01027 
01028     //=======================================================================
01048     explicit Array(unsigned i)
01049     {
01050         d      = new unsigned[ 1 ];
01051         d[ 0 ] = i;
01052         nd     = 1;
01053         ne     = i;
01054         e      = 0;
01055         if (ne)
01056         {
01057             e = new T[ ne ];
01058         }
01059         stat = false;
01060         eEnd = e + ne;
01061     }
01062 
01063     //=======================================================================
01084     Array(unsigned i, unsigned j)
01085     {
01086         d      = new unsigned[ 2 ];
01087         d[ 0 ] = i;
01088         d[ 1 ] = j;
01089         nd     = 2;
01090         ne     = i * j;
01091         e      = 0;
01092         if (ne) e = new T[ ne ];
01093         stat = false;
01094         eEnd = e + ne;
01095     }
01096 
01097     //=======================================================================
01119     Array(unsigned i, unsigned j, unsigned k)
01120     {
01121         d      = new unsigned[ 3 ];
01122         d[ 0 ] = i;
01123         d[ 1 ] = j;
01124         d[ 2 ] = k;
01125         nd     = 3;
01126         ne     = i * j * k;
01127         e      = 0;
01128         if (ne)
01129         {
01130             e = new T[ ne ];
01131         }
01132         stat = false;
01133         eEnd = e + ne;
01134     }
01135 
01136     //=======================================================================
01154     Array(std::vector< T >& v)
01155     {
01156         d      = new unsigned[ 1 ];
01157         d[ 0 ] = v.size();
01158         nd     = 1;
01159         ne     = v.size();
01160         e      = 0;
01161         if (ne)
01162         {
01163             e = new T[ ne ];
01164             for (unsigned i = ne; i--; e[ i ] = v[ i ]);
01165         }
01166         stat = false;
01167         eEnd = e + ne;
01168     }
01169 
01170     //=======================================================================
01191     Array(Array< T >& v, bool)
01192     {
01193         d      = v.d;
01194         e      = v.e;
01195         nd     = v.nd;
01196         ne     = v.ne;
01197         stat   = v.stat;
01198         v.nd   = v.ne = 0;
01199         v.stat = true;
01200         eEnd   = e + ne;
01201     }
01202 
01203     //=======================================================================
01222     Array(const Array< T >& v) : ArrayBase(v)
01223     {
01224         if (ne)
01225         {
01226             e = new T[ ne ];
01227             for (unsigned i = ne; i--; e[ i ] = v.e[ i ]);
01228             eEnd = e + ne;
01229         }
01230         else
01231         {
01232             e = eEnd = 0;
01233         }
01234     }
01235 
01236     //=======================================================================
01257     ~Array()
01258     {
01259         if (! stat && ne)
01260         {
01261             if (ne)
01262             {
01263                 delete[ ] e;
01264             }
01265         }
01266     }
01267 
01270     inline unsigned int rows() const
01271     {
01272         return ArrayBase::rows();
01273     }
01274 
01277     inline unsigned int cols() const
01278     {
01279         return ArrayBase::cols();
01280     }
01281 
01282     //=======================================================================
01306     T& operator()()
01307     {
01308         SIZE_CHECK(nd == 0)
01309         RANGE_CHECK(ne == 1)
01310         return e[ 0 ];
01311     }
01312 
01313     //=======================================================================
01338     const T& operator()() const
01339     {
01340         SIZE_CHECK(nd == 0)
01341         RANGE_CHECK(ne == 1)
01342         return e[ 0 ];
01343     }
01344 
01345     //=======================================================================
01367     T& operator()(unsigned i)
01368     {
01369         SIZE_CHECK(nd == 1)
01370         RANGE_CHECK(i < d[ 0 ])
01371         return e[ i ];
01372     }
01373 
01374     //=======================================================================
01397     const T& operator()(unsigned i) const
01398     {
01399         SIZE_CHECK(nd == 1)
01400         RANGE_CHECK(i < d[ 0 ])
01401         return e[ i ];
01402     }
01403 
01404     //=======================================================================
01430     T& operator()(unsigned i, unsigned j)
01431     {
01432         SIZE_CHECK(nd == 2)
01433         RANGE_CHECK(i < d[ 0 ])
01434         RANGE_CHECK(j < d[ 1 ])
01435         return e[ d[ 1 ] * i + j ];
01436     }
01437 
01438     //=======================================================================
01464     const T& operator()(unsigned i, unsigned j) const
01465     {
01466         SIZE_CHECK(nd == 2)
01467         RANGE_CHECK(i < d[ 0 ])
01468         RANGE_CHECK(j < d[ 1 ])
01469         return e[ d[ 1 ] * i + j ];
01470     }
01471 
01472     //=======================================================================
01500     T& operator()(unsigned i, unsigned j, unsigned k)
01501     {
01502         SIZE_CHECK(nd == 3)
01503         RANGE_CHECK(i < d[ 0 ])
01504         RANGE_CHECK(j < d[ 1 ])
01505         RANGE_CHECK(k < d[ 2 ])
01506         return e[ d[ 2 ] * d[ 1 ] * i + d[ 2 ] * j + k ];
01507     }
01508 
01509     //=======================================================================
01537     const T& operator()(unsigned i, unsigned j, unsigned k) const
01538     {
01539         SIZE_CHECK(nd == 3)
01540         RANGE_CHECK(i < d[ 0 ])
01541         RANGE_CHECK(j < d[ 1 ])
01542         RANGE_CHECK(k < d[ 2 ])
01543         return e[ d[ 2 ] * d[ 1 ] * i + d[ 2 ] * j + k ];
01544     }
01545 
01546 
01547     //=======================================================================
01572     T& operator()(const std::vector< unsigned >& i)
01573     {
01574         unsigned l, m, n;
01575         SIZE_CHECK(i.size() == nd)
01576 #ifndef NDEBUG
01577         for (l = nd; l--;)
01578         {
01579             RANGE_CHECK(i[ l ] < d[ l ])
01580         }
01581 #endif
01582         for (l = nd, m = 0, n = 1; l--;)
01583         {
01584             m += i[ l ] * n;
01585             n *= d[ l ];
01586         }
01587 
01588         return e[ m ];
01589     }
01590 
01591 
01592     //=======================================================================
01617     const T& operator()(const std::vector< unsigned >& i) const
01618     {
01619         unsigned l, m, n;
01620         SIZE_CHECK(i.size() == nd)
01621 #ifndef NDEBUG
01622         for (l = nd; l--;)
01623         {
01624             RANGE_CHECK(i[ l ] < d[ l ])
01625         }
01626 #endif
01627         for (l = nd, m = 0, n = 1; l--;)
01628         {
01629             m += i[ l ] * n;
01630             n *= d[ l ];
01631         }
01632 
01633         return e[ m ];
01634     }
01635 
01636 
01637     // Forward reference (see end of class ArrayReference for definition)
01638     ArrayReference< T > operator [ ](unsigned i);
01639 
01640     // Forward reference (see end of class ArrayReference for definition)
01641     const ArrayReference< T > operator [ ](unsigned i) const;
01642 
01643     //========================================================================
01661     Array< T >& operator = (const T& v)
01662     {
01663         for (unsigned i = ne; i--; e[ i ] = v);
01664         return *this;
01665     }
01666 
01667 
01668 
01669 
01670     //========================================================================
01694     Array< T >& operator = (const std::vector< T >& v)
01695     {
01696         resize(v.size());
01697         for (unsigned i = ne; i--; e[ i ] = v[ i ]);
01698         return *this;
01699     }
01700 
01701 
01702 
01703     //========================================================================
01727     Array< T >& operator = (const Array< T >& v)
01728     {
01729         //
01730         // handle the special case of assigning an empty array
01731         // in order to avoid uninitialized memory read (purify)
01732         //
01733         if (v.nd)
01734         {
01735             resize_i(v.d, v.nd, false);
01736             for (unsigned i = ne; i--; e[ i ] = v.e[ i ]);
01737         }
01738         else
01739         {
01740             if (nd)
01741             {
01742                 delete[ ] d;
01743             }
01744             if (ne)
01745             {
01746                 delete[ ] e;
01747             }
01748             nd = ne = 0;
01749         }
01750 
01751         return *this;
01752     }
01753 
01754 
01755 
01756     //========================================================================
01778     T& elem(unsigned i)
01779     {
01780         RANGE_CHECK(i < ne)
01781         return e[ i ];
01782     }
01783 
01784 
01785     //========================================================================
01808     const T& elem(unsigned i) const
01809     {
01810         RANGE_CHECK(i < ne)
01811         return e[ i ];
01812     }
01813 
01814 
01815     //========================================================================
01831     T* elemvec()
01832     {
01833         return e;
01834     }
01835 
01836 
01837     //========================================================================
01853     const T* elemvec() const
01854     {
01855         return e;
01856     }
01857 
01858 
01859     //========================================================================
01883     Array< T >& append_elem(const T& w)
01884     {
01885         SIZE_CHECK(nd == 0 || nd == 1)
01886 
01887         resize(ne + 1, true);
01888         e[ ne - 1 ] = w;
01889         return *this;
01890     }
01891 
01892 
01893     //========================================================================
01921     Array< T >& append_elems(const Array< T >& w)
01922     {
01923         SIZE_CHECK((nd == 0 || nd == 1) && w.nd == 1)
01924 
01925         unsigned i = 0, j = ne;
01926 
01927         resize(ne + w.ne, true);
01928 
01929         while (i < w.ne)
01930         {
01931             e[ j++ ] = w.e[ i++ ];
01932         }
01933 
01934         return *this;
01935     }
01936 
01937 
01938 
01939     //========================================================================
01989     Array< T >& append_rows(const Array< T >& y)
01990     {
01991         SIZE_CHECK(ndim() == 0         ||
01992                    ndim() == y.ndim() ||
01993                    ndim() == y.ndim() + 1)
01994 
01995         unsigned i, pos = nelem();
01996         Array< unsigned > da;//is used as to store the new dimensions
01997 
01998         // Append rows to empty array:
01999         if (ndim() == 0)
02000         {
02001             da.resize(y.ndim() + 1);
02002             da(0) = 1;
02003             for (i = 0; i < y.ndim(); ++i)
02004             {
02005                 da(i + 1) = y.dim(i);
02006             }
02007         }
02008         // Append rows if dimensions are equal
02009         else if (ndim() == y.ndim())
02010         {
02011           //dimarr() returns a copy of the current arrays 
02012           //dimension vector as an array
02013             da = dimarr();
02014             da(0) = dim(0) + y.dim(0);
02015         }
02016         // Append rows if y's dimension is one less the 
02017         // the arrays dimension
02018         else if (ndim() == y.ndim() + 1)
02019         {
02020             da = dimarr();
02021             da(0) ++;
02022         }
02023         // Otherwise do nothing and return the original array
02024         else
02025         {
02026             return *this;
02027         }
02028         // resize the array, keep its elements and fill 
02029         // the new rows with zeros
02030         resize_i(da.elemvec(), da.nelem(), true);
02031         // add the new elements
02032         for (i = 0; i < y.nelem();)
02033         {
02034             elem(pos++) = y.elem(i++);
02035         }
02036 
02037         return *this;
02038     }
02039 
02040 
02041 
02042 
02043     //========================================================================
02070     Array< T >& remove_row(unsigned i)
02071     {
02072         RANGE_CHECK(ndim() > 0 && i < dim(0))
02073 
02074         unsigned k;
02075         unsigned size = nelem() / dim(0);// number of rows
02076 
02077         Array< T        > y;// will be the new array
02078         Array< unsigned > da(dimarr());// stores the new dimensions
02079 
02080         da(0)--;
02081 
02082         y.resize_i(da.elemvec(), da.nelem(), false);
02083         // copy all rows with indices smaller than the deleted row
02084         for (k = 0; k < i * size; ++k)
02085         {
02086             y.elem(k) = elem(k);
02087         }
02088         // copy all rows with indices greater than the deleted row
02089         for (; k < y.nelem(); ++k)
02090         {
02091             y.elem(k) = elem(k + size);
02092         }
02093         // replace the current array by y
02094         return *this = y;
02095     }
02096 
02097 
02098 
02099 
02100     //========================================================================
02126     Array< T > remove_col(unsigned k) const
02127     {
02128         RANGE_CHECK(ndim() > 0 && k < dim(ndim() - 1))
02129 
02130         unsigned i, j, xi, zi;
02131         unsigned xlast = dim(ndim() - 1);
02132         //number of columns
02133         unsigned num   = nelem() / xlast;
02134         //the new array
02135         Array< T > z;
02136         //stores the dimensions of the new array
02137         Array< unsigned > da(dimarr());
02138         //new array has one column less
02139         da(ndim() - 1) = xlast - 1;
02140         //resize z according to da
02141         z.resize_i(da.elemvec(), da.nelem(), false);
02142         // copy all kept columns in z 
02143         for (xi = zi = i = 0; i < num; ++i)
02144         {
02145           // copy all columns with a lower index than k
02146             for (j = 0; j < k; ++j)
02147             {
02148                 z.elem(zi++) = elem(xi++);
02149             }
02150           // copy all columns with a greater index than k
02151             for (++xi, ++j; j < xlast; ++j)
02152             {
02153                 z.elem(zi++) = elem(xi++);
02154             }
02155         }
02156         //return new array
02157         return Array< T > (z, true);
02158     }
02159 
02160 
02161 
02162 
02163     //========================================================================
02186     Array<T>& remove_cols(const Array<unsigned> idx)
02187     {
02188         RANGE_CHECK(ndim() > 0 && idx.ndim() == 1);
02189 
02190         if (idx.nelem() == 0) return *this;
02191         std::sort(idx.begin(), idx.end());
02192 
02193         T* source = e;
02194         T* dest = e;
02195         int i;
02196         int lastDim = ndim() - 1;
02197         int r, rc = idx.nelem();
02198         int f, fc = dim(lastDim);
02199         RANGE_CHECK(idx(rc - 1) < fc);
02200         for (i=0, r=0, f=0; i<ne; i++)
02201         {
02202             if (r < rc && f == idx(r))
02203             {
02204                 source++;
02205                 r++;
02206             }
02207             else
02208             {
02209                 *dest = *source;
02210                 source++;
02211                 dest++;
02212             }
02213             f++;
02214             if (f == fc)
02215             {
02216                 f = 0;
02217                 r = 0;
02218             }
02219         }
02220 
02221         std::vector<unsigned> newdim(ndim());
02222         for (i=0; i<lastDim; i++) newdim[i] = d[i];
02223         newdim[lastDim] = fc - rc;
02224         resize_i(&newdim[0], ndim(), true);
02225 
02226         return *this;
02227     }
02228 
02229 
02230 
02231 
02232     //========================================================================
02262     Array< T > & remove_cols(unsigned i, unsigned j)
02263     {
02264         Array< unsigned > idx(2);
02265 
02266         idx(0) = i;
02267         idx(1) = j;
02268 
02269         return remove_cols(idx);
02270     }
02271 
02272 
02273 
02274     //========================================================================
02305     Array< T > & remove_cols(unsigned i, unsigned j, unsigned k)
02306     {
02307         Array< unsigned > idx(3);
02308 
02309         idx(0) = i;
02310         idx(1) = j;
02311         idx(2) = k;
02312 
02313         return remove_cols(idx);
02314     }
02315 
02316 
02317 
02318     //========================================================================
02350     Array< T > & remove_cols(unsigned i, unsigned j, unsigned k,
02351                            unsigned l)
02352     {
02353         Array< unsigned > idx(4);
02354 
02355         idx(0) = i;
02356         idx(1) = j;
02357         idx(2) = k;
02358         idx(3) = l;
02359 
02360         return remove_cols(idx);
02361     }
02362 
02363 
02364 
02365     //========================================================================
02399     Array< T > & remove_cols(unsigned i, unsigned j, unsigned k,
02400                            unsigned l, unsigned m)
02401     {
02402         Array< unsigned > idx(5);
02403 
02404         idx(0) = i;
02405         idx(1) = j;
02406         idx(2) = k;
02407         idx(3) = l;
02408         idx(4) = m;
02409 
02410         return remove_cols(idx);
02411     }
02412 
02413 
02414 
02415     //========================================================================
02450     Array< T > & remove_cols(unsigned i, unsigned j, unsigned k,
02451                            unsigned l, unsigned m, unsigned n)
02452     {
02453         Array< unsigned > idx(6);
02454 
02455         idx(0) = i;
02456         idx(1) = j;
02457         idx(2) = k;
02458         idx(3) = l;
02459         idx(4) = m;
02460         idx(5) = n;
02461 
02462         return remove_cols(idx);
02463     }
02464 
02465 
02466 
02467     //========================================================================
02503     Array< T > & remove_cols(unsigned i, unsigned j, unsigned k,
02504                            unsigned l, unsigned m, unsigned n,
02505                            unsigned o)
02506     {
02507         Array< unsigned > idx(7);
02508 
02509         idx(0) = i;
02510         idx(1) = j;
02511         idx(2) = k;
02512         idx(3) = l;
02513         idx(4) = m;
02514         idx(5) = n;
02515         idx(6) = o;
02516 
02517         return remove_cols(idx);
02518     }
02519 
02520 
02521 
02522     //========================================================================
02559     Array< T > & remove_cols(unsigned i, unsigned j, unsigned k,
02560                            unsigned l, unsigned m, unsigned n,
02561                            unsigned o, unsigned p)
02562     {
02563         Array< unsigned > idx(8);
02564 
02565         idx(0) = i;
02566         idx(1) = j;
02567         idx(2) = k;
02568         idx(3) = l;
02569         idx(4) = m;
02570         idx(5) = n;
02571         idx(6) = o;
02572         idx(7) = p;
02573 
02574         return remove_cols(idx);
02575     }
02576 
02577 
02578     //========================================================================
02632     Array< T > append_cols(const Array< T >& y) const
02633     {
02634         SIZE_CHECK(ndim() == 0 || ndim() == y.ndim())
02635 
02636         if (ndim() == 0)
02637         {
02638             return y;
02639         }
02640         else
02641         {
02642             unsigned i, j, xi, yi, zi;
02643             //number of last column
02644             unsigned xlast = dim(ndim() - 1);
02645             //number of last columns in y
02646             unsigned ylast = y.dim(y.ndim() - 1);
02647             unsigned num;
02648             //new array
02649             Array< T > z;
02650             //stores new dimensions
02651             Array< unsigned > da(dimarr());
02652             //new number of columns
02653             da(ndim() - 1) = xlast + ylast;
02654             //resize new array according to da
02655             z.resize_i(da.elemvec(), da.nelem(), false);
02656 
02657             num = z.nelem() / (xlast + ylast);//number of rows
02658             for (i = xi = yi = zi = 0; i < num; ++i)
02659             {
02660               //copy all elements from old array
02661                 for (j = 0; j < xlast; ++j)
02662                 {
02663                     z.elem(zi++) = elem(xi++);
02664                 }
02665               //copy all elements from y
02666                 for (j = 0; j < ylast; ++j)
02667                 {
02668                     z.elem(zi++) = y.elem(yi++);
02669                 }
02670             }
02671             //return new array
02672             return Array< T > (z, true);
02673         }
02674     }
02675 
02676 
02677 
02678 
02679     //========================================================================
02735     Array< T > subarr(unsigned from, unsigned to) const
02736     {
02737         SIZE_CHECK(ndim() > 0)
02738         RANGE_CHECK(from <= to && from < dim(0) && to < dim(0))
02739 
02740         unsigned i, j;
02741         //number of first element
02742         unsigned fromi = from   * nelem() / dim(0);
02743         //number of last element
02744         unsigned toi   = (to + 1) * nelem() / dim(0);
02745         //subarray
02746         Array< T > z;
02747         //stores dimensions of subarray
02748         Array< unsigned > da(dimarr());
02749         // number of rows in subarray
02750         da(0) = to - from + 1;
02751         //resize subarray
02752         z.resize_i(da.elemvec(), da.nelem(), false);
02753         //copy elements
02754         for (i = fromi, j = 0; i < toi; z.elem(j++) = elem(i++));
02755         //return subarray
02756         return Array< T > (z, true);
02757     }
02758 
02759 
02760 
02761 
02762     //========================================================================
02796     Array< unsigned > pos2idx(unsigned p)
02797     {
02798         RANGE_CHECK(p < ne)
02799 
02800         Array< unsigned > idx(ndim());
02801         for (unsigned i = 0, j = nelem(); i < ndim(); ++i)
02802         {
02803             p %= j;
02804             j /= dim(i);
02805             idx(i) = p / j;
02806         }
02807         return idx;
02808     }
02809 
02810 
02811 
02812     //========================================================================
02845     void pos2idx(unsigned p, Array<unsigned>& idx)
02846     {
02847         RANGE_CHECK(p < ne)
02848 
02849         idx.resize(ndim());
02850         for (unsigned i = 0, j = nelem(); i < ndim(); ++i)
02851         {
02852             p %= j;
02853             j /= dim(i);
02854             idx(i) = p / j;
02855         }
02856     }
02857 
02858 
02859     //========================================================================
02884     Array< T > row(unsigned i) const
02885     {
02886         return (*this)[ i ];
02887     }
02888 
02889 
02890     //========================================================================
02918     Array< T > rows(const Array< unsigned >& idx) const
02919     {
02920         SIZE_CHECK(ndim() > 0)
02921         SIZE_CHECK(idx.ndim() <= 1)
02922 
02923         unsigned i, j, k, l;
02924         //number of rows
02925         unsigned n = nelem() / dim(0);
02926         //subarray
02927         Array< T > z;
02928         //stores dimensions of subarray
02929         Array< unsigned > da(dimarr());
02930 
02931         da(0) = idx.nelem();
02932         //resize subarray
02933         z.resize_i(da.elemvec(), da.nelem(), false);
02934         //copy all elements mentioned in idx 
02935         for (k = i = 0; i < idx.nelem(); ++i)
02936         {
02937             for (l = idx(i) * n, j = 0; j < n; ++j)
02938             {
02939                 z.elem(k++) = elem(l++);
02940             }
02941         }
02942         //return subarray
02943         return Array< T > (z, true);
02944     }
02945 
02946 
02947 
02948     //========================================================================
02977     Array< T > rows(unsigned i) const
02978     {
02979         Array< unsigned > idx(1);
02980 
02981         idx(0) = i;
02982 
02983         return rows(idx);
02984     }
02985 
02986 
02987 
02988     //========================================================================
03020     Array< T > rows(unsigned i, unsigned j) const
03021     {
03022         Array< unsigned > idx(2);
03023 
03024         idx(0) = i;
03025         idx(1) = j;
03026 
03027         return rows(idx);
03028     }
03029 
03030 
03031 
03032     //========================================================================
03066     Array< T > rows(unsigned i, unsigned j, unsigned k) const
03067     {
03068         Array< unsigned > idx(3);
03069 
03070         idx(0) = i;
03071         idx(1) = j;
03072         idx(2) = k;
03073 
03074         return rows(idx);
03075     }
03076 
03077 
03078 
03079     //========================================================================
03115     Array< T > rows(unsigned i, unsigned j, unsigned k,
03116                     unsigned l) const
03117     {
03118         Array< unsigned > idx(4);
03119 
03120         idx(0) = i;
03121         idx(1) = j;
03122         idx(2) = k;
03123         idx(3) = l;
03124 
03125         return rows(idx);
03126     }
03127 
03128 
03129 
03130     //========================================================================
03169     Array< T > rows(unsigned i, unsigned j, unsigned k,
03170                     unsigned l, unsigned m) const
03171     {
03172         Array< unsigned > idx(5);
03173 
03174         idx(0) = i;
03175         idx(1) = j;
03176         idx(2) = k;
03177         idx(3) = l;
03178         idx(4) = m;
03179 
03180         return rows(idx);
03181     }
03182 
03183 
03184 
03185     //========================================================================
03226     Array< T > rows(unsigned i, unsigned j, unsigned k,
03227                     unsigned l, unsigned m, unsigned n) const
03228     {
03229         Array< unsigned > idx(6);
03230 
03231         idx(0) = i;
03232         idx(1) = j;
03233         idx(2) = k;
03234         idx(3) = l;
03235         idx(4) = m;
03236         idx(5) = n;
03237 
03238         return rows(idx);
03239     }
03240 
03241 
03242 
03243     //========================================================================
03286     Array< T > rows(unsigned i, unsigned j, unsigned k,
03287                     unsigned l, unsigned m, unsigned n,
03288                     unsigned o) const
03289     {
03290         Array< unsigned > idx(7);
03291 
03292         idx(0) = i;
03293         idx(1) = j;
03294         idx(2) = k;
03295         idx(3) = l;
03296         idx(4) = m;
03297         idx(5) = n;
03298         idx(6) = o;
03299 
03300         return rows(idx);
03301     }
03302 
03303 
03304 
03305     //========================================================================
03350     Array< T > rows(unsigned i, unsigned j, unsigned k,
03351                     unsigned l, unsigned m, unsigned n,
03352                     unsigned o, unsigned p) const
03353     {
03354         Array< unsigned > idx(8);
03355 
03356         idx(0) = i;
03357         idx(1) = j;
03358         idx(2) = k;
03359         idx(3) = l;
03360         idx(4) = m;
03361         idx(5) = n;
03362         idx(6) = o;
03363         idx(7) = p;
03364 
03365         return rows(idx);
03366     }
03367 
03368 
03369 
03370 
03371     //========================================================================
03396     Array< T > col(unsigned i) const
03397     {
03398         SIZE_CHECK(ndim() > 0)
03399         RANGE_CHECK(i < dim(ndim() - 1))
03400         //subarray
03401         Array< T > z;
03402         //stores dimensions of subarray
03403         Array< unsigned > da(dimarr());
03404         //resize subarray
03405         z.resize_i(da.elemvec(), da.nelem() - 1, false);
03406         //copy i'th  col
03407         for (unsigned k = 0; k < z.nelem(); ++k, i += dim(ndim() - 1))
03408         {
03409             z.elem(k) = elem(i);
03410         }
03411         //return subarry
03412         return z;
03413     }
03414 
03415 
03416 
03417     //========================================================================
03444     Array< T > cols(const Array< unsigned >& idx) const
03445     {
03446         SIZE_CHECK(ndim() > 0)
03447         SIZE_CHECK(idx.ndim() == 1)
03448 
03449         unsigned j, k, m;
03450         //number of columns
03451         unsigned l = dim(ndim() - 1);
03452         //number of rows
03453         unsigned n = nelem() / l;
03454         //subarray
03455         Array< T > z;
03456         Array< unsigned > ix(idx);
03457         //stores dimensions of subarray
03458         Array< unsigned > da(dimarr());
03459 
03460         da(ndim() - 1) = ix.nelem();
03461         //resize subarray
03462         z.resize_i(da.elemvec(), da.nelem(), false);
03463         //copy all elements mentioned in idx
03464         for (k = m = 0; k < n; ++k)
03465         {
03466             for (j = 0; j < ix.nelem(); ++j, ++m)
03467             {
03468                 z.elem(m) = elem(ix(j));
03469                 ix(j) += l;//switch to next row
03470             }
03471         }
03472         //return subarray
03473         return z;
03474     }
03475 
03476 
03477 
03478     //========================================================================
03506     Array< T > cols(unsigned i) const
03507     {
03508         Array< unsigned > idx(1);
03509 
03510         idx(0) = i;
03511 
03512         return cols(idx);
03513     }
03514 
03515 
03516 
03517     //========================================================================
03547     Array< T > cols(unsigned i, unsigned j) const
03548     {
03549         Array< unsigned > idx(2);
03550 
03551         idx(0) = i;
03552         idx(1) = j;
03553 
03554         return cols(idx);
03555     }
03556 
03557 
03558 
03559     //========================================================================
03591     Array< T > cols(unsigned i, unsigned j, unsigned k) const
03592     {
03593         Array< unsigned > idx(3);
03594 
03595         idx(0) = i;
03596         idx(1) = j;
03597         idx(2) = k;
03598 
03599         return cols(idx);
03600     }
03601 
03602 
03603 
03604     //========================================================================
03638     Array< T > cols(unsigned i, unsigned j, unsigned k,
03639                     unsigned l) const
03640     {
03641         Array< unsigned > idx(4);
03642 
03643         idx(0) = i;
03644         idx(1) = j;
03645         idx(2) = k;
03646         idx(3) = l;
03647 
03648         return cols(idx);
03649     }
03650 
03651 
03652 
03653     //========================================================================
03691     Array< T > cols(unsigned i, unsigned j, unsigned k,
03692                     unsigned l, unsigned m) const
03693     {
03694         Array< unsigned > idx(5);
03695 
03696         idx(0) = i;
03697         idx(1) = j;
03698         idx(2) = k;
03699         idx(3) = l;
03700         idx(4) = m;
03701 
03702         return cols(idx);
03703     }
03704 
03705 
03706 
03707     //========================================================================
03747     Array< T > cols(unsigned i, unsigned j, unsigned k,
03748                     unsigned l, unsigned m, unsigned n) const
03749     {
03750         Array< unsigned > idx(6);
03751 
03752         idx(0) = i;
03753         idx(1) = j;
03754         idx(2) = k;
03755         idx(3) = l;
03756         idx(4) = m;
03757         idx(5) = n;
03758 
03759         return cols(idx);
03760     }
03761 
03762 
03763 
03764     //========================================================================
03806     Array< T > cols(unsigned i, unsigned j, unsigned k,
03807                     unsigned l, unsigned m, unsigned n,
03808                     unsigned o) const
03809     {
03810         Array< unsigned > idx(7);
03811 
03812         idx(0) = i;
03813         idx(1) = j;
03814         idx(2) = k;
03815         idx(3) = l;
03816         idx(4) = m;
03817         idx(5) = n;
03818         idx(6) = o;
03819 
03820         return cols(idx);
03821     }
03822 
03823 
03824 
03825     //========================================================================
03869     Array< T > cols(unsigned i, unsigned j, unsigned k,
03870                     unsigned l, unsigned m, unsigned n,
03871                     unsigned o, unsigned p) const
03872     {
03873         Array< unsigned > idx(8);
03874 
03875         idx(0) = i;
03876         idx(1) = j;
03877         idx(2) = k;
03878         idx(3) = l;
03879         idx(4) = m;
03880         idx(5) = n;
03881         idx(6) = o;
03882         idx(7) = p;
03883 
03884         return cols(idx);
03885     }
03886 
03887 
03888 
03889     //========================================================================
03929     Array< T >& transpose()
03930     {
03931         switch (ndim())
03932         {
03933         case 0 :
03934         case 1 :
03935             break;
03936         case 2 :
03937         {
03938             int d0 = d[1];
03939             int d1 = d[0];
03940             int i, j, k, s;
03941             for (i = 0, s = d0 * d1; s > 0; i++)
03942             {
03943                 for (j = (i % d1) * d0 + i / d1; j > i; j = (j % d1) * d0 + j / d1);
03944                 if (j < i) continue;
03945                 for (k = i, j = (i % d1) * d0 + i / d1; j != i; k = j, j = (j % d1) * d0 + j / d1)
03946                 {
03947                     std::swap(e[k], e[j]);
03948                     s--;
03949                 }
03950                 s--;
03951             }
03952             d[0] = d0;
03953             d[1] = d1;
03954             break;
03955         }
03956         default :
03957         {
03958             int d0 = d[1];
03959             int d1 = d[0];
03960             int i, j, k, s;
03961             unsigned a, b, c, size = nelem() / (d0 * d1);
03962             for (i = 0, s = d0 * d1; s > 0; i++)
03963             {
03964                 for (j = (i % d1) * d0 + i / d1; j > i; j = (j % d1) * d0 + j / d1);
03965                 if (j < i) continue;
03966                 for (k = i, j = (i % d1) * d0 + i / d1; j != i; k = j, j = (j % d1) * d0 + j / d1)
03967                 {
03968                     a = k * size;
03969                     b = j * size;
03970                     for (c = 0; c < size; c++)
03971                     {
03972                         std::swap(e[a], e[b]);
03973                         a++;
03974                         b++;
03975                     }
03976                     s--;
03977                 }
03978                 s--;
03979             }
03980             d[0] = d0;
03981             d[1] = d1;
03982             break;
03983         }
03984         }
03985 
03986         return *this;
03987     }
03988 
03989     //========================================================================
04026     Array<T>& rotate_rows(int n)
04027     {
04028         SIZE_CHECK(ndim() > 0);
04029 
04030         int f, fc = d[0];
04031         int i, ic = ne / fc;
04032         std::vector<T> tmp(fc);
04033 
04034         n = n % fc;
04035         if (n < 0) n += fc;
04036         if (n == 0) return *this;
04037         RANGE_CHECK(0 <= n && n < fc);
04038 
04039         T* data = e;
04040         for (i=0; i<ic; i++)
04041         {
04042             for (f=0; f<fc; f++) tmp[f] = data[ic * f];
04043             for (f=0; f<n; f++) data[ic * f] = tmp[f - n + fc];
04044             for (; f<fc; f++) data[ic * f] = tmp[f - n];
04045             data++;
04046         }
04047 
04048         return *this;
04049     }
04050 
04051 
04052     //========================================================================
04095     Array<T>& rotate_cols(int n)
04096     {
04097         SIZE_CHECK(ndim() > 0);
04098 
04099         int lastDim = nd - 1;
04100         int f, fc = d[lastDim];
04101         int i, ic = ne / fc;
04102         std::vector<T> tmp(fc);
04103 
04104         n = n % fc;
04105         if (n < 0) n += fc;
04106         if (n == 0) return *this;
04107         RANGE_CHECK(0 < n && n < fc);
04108 
04109         T* data = e;
04110         for (i=0; i<ic; i++)
04111         {
04112             for (f=0; f<fc; f++) tmp[f] = data[f];
04113             for (f=0; f<n; f++) data[f] = tmp[f - n + fc];
04114             for (; f<fc; f++) data[f] = tmp[f - n];
04115             data += fc;
04116         }
04117 
04118         return *this;
04119     }
04120 
04121 
04122     //========================================================================
04141     Array< unsigned > dimarr() const
04142     {
04143         Array< unsigned > dim(nd);
04144         for (unsigned i = nd; i--; dim(i) = d[ i ]);
04145         return dim;
04146     }
04147 
04148 
04149 
04150     //========================================================================
04171     ArrayBase* clone() const
04172     {
04173         return new Array< T > (*this);
04174     }
04175 
04176 
04177     //========================================================================
04199     ArrayBase* empty() const
04200     {
04201         return new Array< T >();
04202     }
04203 
04204 #ifdef _WIN32
04206     bool operator == (const Array< T >&) const
04207     {
04208         return false;
04209     }
04210 
04212     bool operator != (const Array< T >&) const
04213     {
04214         return false;
04215     }
04216 
04218     bool operator < (const Array< T >&) const
04219     {
04220         return false;
04221     }
04222 
04224     bool operator > (const Array< T >&) const
04225     {
04226         return false;
04227     }
04228 #endif
04229 
04230 
04231     //=======================================================================
04252     inline iterator begin()
04253     {
04254         return e;
04255     }
04256 
04257 
04258     //=======================================================================
04279     inline const const_iterator begin() const
04280     {
04281         return e;
04282     }
04283 
04284     //=======================================================================
04305     inline iterator end()
04306     {
04307         return eEnd;
04308     }
04309 
04310     //=======================================================================
04331     inline const const_iterator end()   const
04332     {
04333         return eEnd;
04334     }
04335 
04336 protected:
04337 
04338     //=======================================================================
04410     T*        e;
04411 
04413     T*        eEnd;
04414 
04415 
04416     //=======================================================================
04460     void resize_i(unsigned* _d, unsigned _nd, bool copy)
04461     {
04462         unsigned j, _ne;
04463 
04464         // Adopt dimension vector if necessary:
04465         if (nd != _nd)
04466         {
04467             // Can only resize non-static arrays:
04468             SIZE_CHECK(! stat)
04469 
04470             // Delete dimension vector if present:
04471             if (nd)
04472             {
04473                 delete[ ] d;
04474             }
04475 
04476             // Create new dimension vector:
04477             if ((nd = _nd) > 0)
04478             {
04479                 d = new unsigned[ _nd ];
04480             }
04481         }
04482 
04483 #ifndef NDEBUG
04484         if (stat)
04485         {
04486             for (j = _nd; j--;)
04487             {
04488                 SIZE_CHECK(d[ j ] == _d[ j ])
04489             }
04490         }
04491 #endif
04492 
04493         //calculate number of elements
04494         for (j = _nd, _ne = 1; j--; _ne *= (d[ j ] = _d[ j ]));
04495         if (_nd == 0)
04496         {
04497             _ne = 0;
04498         }
04499 
04500         if (ne != _ne)  //add or delete elements
04501         {
04502             SIZE_CHECK(! stat);
04503 #ifndef NDEBUG
04504             if (nd != _nd) throw ("Array resize warning: copying elements will not arrange elements correctly");
04505             else
04506             {
04507                 for (j = 1; j < _nd; j++)
04508                 {
04509                     if (d[j] != _d[j])
04510                         throw ("Array resize warning: copying elements will not arrange elements correctly");
04511                 }
04512             }
04513 #endif
04514 
04515             if (copy)   //does not consider structure of elements
04516             {
04517                 T* _e = e;  //create new pointer to old element vector
04518                 if (_ne)    //create new element vector
04519                 {
04520                     e = new T[ _ne ];
04521                 }
04522                 for (j = ne < _ne ? ne : _ne; j--; e[ j ] = _e[ j ]);//copy existing elements, j=min(ne,_ne)
04523                 if (ne)//delete elements, array is empty now
04524                 {
04525                     delete[ ] _e;
04526                 }
04527             }
04528             else//without copying
04529             {
04530                 if (ne)//delete element vector
04531                 {
04532                     delete[ ] e;
04533                 }
04534                 if (_ne)//create new element vector
04535                 {
04536                     e = new T[ _ne ];
04537                 }
04538             }
04539             ne = _ne;//update number of elements in array
04540         }
04541         eEnd = e + ne;//update pointer to end of array
04542     }
04543 
04544 
04545     //=======================================================================
04572     Array(unsigned* _d, T* _e, unsigned _nd, unsigned _ne, bool _stat)
04573     {
04574         d    = _d;
04575         e    = _e;
04576         nd   = _nd;
04577         ne   = _ne;
04578         stat = _stat;
04579         eEnd = e + ne;
04580     }
04581 
04582 #ifndef __ARRAY_NO_GENERIC_IOSTREAM
04583 
04584 
04585     //=======================================================================
04636     void readFrom(std::istream& is)
04637     {
04638         const unsigned     MaxLen = 1024;
04639         char               s[ MaxLen ];
04640         char*              p;
04641         unsigned           i;
04642         std::vector< unsigned > idx; // dimension vector
04643 
04644         // Skip leading whitespaces
04645         is >> std::ws;
04646         is.getline(s, MaxLen);
04647 
04648         // Get end of type definition:
04649         p = strchr(s, '>');
04650         // Go to begin of dimension sizes:
04651         if (p && *p) p++;
04652         if (p && *p) p++;
04653 
04654         // Get single dimension sizes, store them in vector
04655         // and resize current array:
04656         TYPE_CHECK(p && *p)
04657         if (p && *p)
04658         {
04659             do
04660             {
04661                 if (*p == ',')
04662                 {
04663                     p++;
04664                 }
04665                 idx.push_back(unsigned(strtol(p, &p, 10)));
04666             }
04667             while (p && *p == ',');
04668 
04669             TYPE_CHECK(p && *p == ')')
04670 
04671             resize(idx);
04672 
04673             // Get elements of the array:
04674             for (i = 0; i < ne && is.good(); i++)
04675             {
04676                 is >> e[ i ];
04677             }
04678         }
04679 
04680         is >> std::ws;
04681     }
04682 
04683 
04684 
04685     //=======================================================================
04726     void writeTo(std::ostream& os) const
04727     {
04728         unsigned i;
04729 
04730         os << "Array<" << typeid(T).name() << ">(";
04731         for (i = 0; i < nd; i++)
04732         {
04733             if (i) os << ',';
04734             os << d[ i ];
04735         }
04736         os << ")\n";
04737 
04738         for (i = 0; i < ne; i++)
04739         {
04740             if (i) os << '\t';
04741             os << e[ i ];
04742         }
04743         os << std::endl;
04744     }
04745 #endif // !__ARRAY_NO_GENERIC_IOSTREAM
04746 };
04747 
04748 
04749 //===========================================================================
04766 template< class T >
04767 class ArrayReference : public Array< T >
04768 {
04769 public:
04770 
04771     //========================================================================
04788     ArrayReference()
04789             : Array< T >()
04790     {
04791         this->stat = true;
04792         this->d = NULL;
04793         this->e = NULL;
04794         this->nd = 0;
04795         this->ne = 0;
04796     }
04797 
04798 
04799     //========================================================================
04823     ArrayReference(unsigned* _d, T* _e, unsigned _nd, unsigned _ne)
04824             : Array< T >()
04825     {
04826         this->d    = _d;
04827         this->e    = _e;
04828         this->nd   = _nd;
04829         this->ne   = _ne;
04830         this->stat = true;
04831         this->eEnd = this->e + this->ne;
04832     }
04833 
04834 
04835     //========================================================================
04855     ~ArrayReference()
04856     { }
04857 
04858 
04859 
04860     //========================================================================
04879     ArrayReference< T > operator = (const T& v)
04880     {
04881         Array< T >::operator = (v);
04882         return *this;
04883     }
04884 
04885 
04886 
04887     //========================================================================
04912     ArrayReference< T > operator = (const std::vector< T >& v)
04913     {
04914         Array< T >::operator = (v);
04915         return *this;
04916     }
04917 
04918 
04919 
04920     //========================================================================
04945     ArrayReference< T > operator = (const Array< T >& v)
04946     {
04947         Array< T >::operator = (v);
04948         return *this;
04949     }
04950 
04951 
04952     //========================================================================
04970     ArrayReference< T > copyReference(Array< T >& v)
04971     {
04972         this->d    = v.d;
04973         this->e    = v.e;
04974         this->nd   = v.nd;
04975         this->ne   = v.ne;
04976         this->stat = true;
04977         this->eEnd = this->e + this->ne;
04978         return *this;
04979     }
04980 
04981     //========================================================================
05000     ArrayReference< T > copyReference(ArrayReference< T > v)
05001     {
05002         this->d    = v.d;
05003         this->e    = v.e;
05004         this->nd   = v.nd;
05005         this->ne   = v.ne;
05006         this->stat = true;
05007         this->eEnd = this->e + this->ne;
05008         return *this;
05009     }
05010 };
05011 
05012 //========================================================================
05052 template< class T >
05053 inline ArrayReference< T > Array< T >::operator [ ](unsigned i)
05054 {
05055     SIZE_CHECK(nd > 0)
05056     RANGE_CHECK(i < d[ 0 ])
05057     return ArrayReference< T > (d + 1, e + i*(ne / d[ 0 ]), nd - 1, ne / d[ 0 ]);
05058 }
05059 
05060 
05061 //========================================================================
05101 template< class T >
05102 inline const ArrayReference< T > Array< T >::operator [ ](unsigned i) const
05103 {
05104     SIZE_CHECK(nd > 0)
05105     RANGE_CHECK(i < d[ 0 ])
05106     return ArrayReference< T > (d + 1, e + i*(ne / d[ 0 ]), nd - 1, ne / d[ 0 ]);
05107 }
05108 
05109 
05110 #endif //__ARRAY_H
05111