The Machine Perception Toolbox

[Introduction]- [News]- [Download]- [Screenshots]- [Manual (pdf)]- [Forums]- [API Reference]- [Repository ]

 

Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Array.h

Go to the documentation of this file.
00001 /*
00002  *  Array.h
00003  *  
00004  *
00005  *  Created by John Hershey 2002.
00006  *  Copyright (c) 2003 Machine Perception Laboratory
00007  *  University of California San Diego.
00008  *  Please read the disclaimer and notes about redistribution
00009  *  at the end of this file.
00010  *
00011  *  Authors: John Hershey, Josh Susskind
00012  */
00013 #ifndef ARRAY_H
00014 #define ARRAY_H
00015 
00016 #include "preprocessor.h"
00017 
00018 #include <algorithm>
00019 #include <vector>
00020 #include "assert.h"
00021 
00022 //*****************************************************************************
00023 // Class Template for a Generic Resizable N Dimensional Array        (for N>=2)
00024 // By Giovanni Bavestrelli                  Copyright 1999 Giovanni Bavestrelli 
00025 // Any feedback is welcome, you can contact me at gbavestrelli@yahoo.com
00026 //
00027 // This is the version for Microsoft Visual C++ 6.0, and perhaps for other 
00028 // compilers which do not support partial specialization. 
00029 // To make my classes work, I had to use a trick. I moved the RefArray classes 
00030 // as nested classes withing class Array, removing template parameter T from 
00031 // them, allowing me to use full specialization for class RefArray. 
00032 // I don't think this is up to standard C++. If your compiler supports partial
00033 // specialization, be sure to use the other version of these classes.
00034 // Thanks to Andrei Alexandrescu for suggesting this trick, which makes my 
00035 // classes work well with Visual C++, although the solution is not standard.
00036 //*****************************************************************************
00037 
00038 
00039 //=============================================================================
00040 // Classes for passing a typesafe vector of dimensions to the Array constructor
00041 //=============================================================================
00042 
00043 template <unsigned int N>
00044 class ArraySize
00045 {
00046      std::vector<unsigned int> & Vector;
00047 
00048      ArraySize<N>(std::vector<unsigned int> & v)
00049         :Vector(v)
00050      {}
00051 
00052   public:
00053 
00054      ArraySize<N+1> operator () (unsigned int dim) 
00055      { 
00056         if (Vector.size()>N) Vector.resize(N);
00057         Vector.push_back(dim);
00058         return ArraySize<N+1>(Vector);
00059      }
00060 
00061      const std::vector<unsigned int> & Vect() const 
00062      {
00063         assert(Vector.size()==N); 
00064         return Vector;
00065      }
00066 
00067      friend class ArraySizes;
00068      friend class ArraySize<N-1>;
00069 };
00070 
00071 class ArraySizes
00072 {
00073      std::vector<unsigned int> Vector;
00074  
00075   public:
00076       
00077      explicit ArraySizes(unsigned int dim) 
00078      { 
00079         Vector.push_back(dim); 
00080      }
00081 
00082      ArraySize<2> operator () (unsigned int dim) 
00083      { 
00084         if (Vector.size()>1) Vector.resize(1);
00085         Vector.push_back(dim);
00086         return ArraySize<2>(Vector);
00087      }
00088 };
00089 
00090 //=============================================================================
00091 // Class Template for a Generic Resizable N Dimensional Array
00092 //=============================================================================
00093 
00094 template <typename T, unsigned int N>
00095 class Array
00096 {
00097  public:
00098 
00099     //-----------------------------------------------------------------------------
00100     // Class Template for N Dimensional SubArrays within an Array
00101     //-----------------------------------------------------------------------------
00102 
00103     template <unsigned int N>
00104     class RefArray
00105     {
00106      public:
00107 
00108        // STL-like types
00109        typedef T         value_type;
00110        typedef T &       reference;
00111        typedef const T & const_reference;
00112        typedef T *       pointer;
00113        typedef const T * const_pointer;
00114        typedef T *       iterator;
00115        typedef const T * const_iterator;
00116        typedef size_t    size_type;
00117        typedef ptrdiff_t difference_type;
00118 
00119        // Give access to number of dimensions
00120        enum  { array_dims = N };
00121 
00122      private:
00123 
00124        const size_type * const m_pNDimensions; // Array dimensions
00125        const size_type * const m_pSubArrayLen; // SubArray dimensions
00126 
00127        T   * const m_pElements; // Point to SubArray with elements within Array
00128 
00129        RefArray<N>(T * pElements, const size_type * pNDimensions, 
00130                                   const size_type * pSubArrayLen)
00131          :m_pElements(pElements),m_pNDimensions(pNDimensions),
00132                                  m_pSubArrayLen(pSubArrayLen)
00133        { 
00134           assert(m_pElements && m_pNDimensions && m_pSubArrayLen); 
00135           assert(m_pNDimensions[0]>0 && m_pSubArrayLen[0]>0); 
00136        }  
00137 
00138      public:
00139 
00140        RefArray<N-1> operator [](size_type Index)
00141        {
00142           assert(m_pElements);
00143           assert(Index<m_pNDimensions[0]);
00144           return RefArray<N-1>(&m_pElements[Index*m_pSubArrayLen[0]],
00145                                 m_pNDimensions+1,m_pSubArrayLen+1);
00146        }
00147 
00148        const RefArray<N-1> operator [](size_type Index) const
00149        {
00150           assert(m_pElements);
00151           assert(Index<m_pNDimensions[0]);
00152           return RefArray<N-1>(&m_pElements[Index*m_pSubArrayLen[0]],
00153                                 m_pNDimensions+1,m_pSubArrayLen+1);
00154        }
00155 
00156        // Return STL-like iterators
00157        iterator       begin()       { return m_pElements; }
00158        const_iterator begin() const { return m_pElements; }
00159        iterator       end()         { return m_pElements+size(); }
00160        const_iterator end()   const { return m_pElements+size(); } 
00161 
00162        // Return size of array
00163        size_type size() const { return m_pNDimensions[0]*m_pSubArrayLen[0]; }
00164 
00165        // Return size of subdimensions
00166        size_type size(unsigned int Dim) const 
00167        {  
00168           assert(Dim>=1 && Dim<=N); 
00169           return m_pNDimensions[Dim-1];  
00170        }
00171 
00172        // Return number of dimensions 
00173        unsigned int dimensions()  const { return N; }
00174 
00175      protected:
00176 
00177        // The following are protected mainly because they are not exception-safe
00178        // but the way they are used in the rest of the class is exception-safe
00179 
00180        // Copy the elements of another subarray on this one where possible
00181        // Where not possible, initialize them to a specified value Init
00182        void copy(const RefArray<N> & SA, const T & Init=T())
00183        {
00184            size_type below=std::_MIN(size(1),SA.size(1));
00185            size_type above=size(1);
00186 
00187            // Copy the elements we can copy
00188            for (size_type i=0;i<below;i++) 
00189                (*this)[i].copy(SA[i],Init);
00190 
00191            // Reset the elements we can't copy
00192            for (size_type j=below;j<above;j++)
00193                (*this)[j].initialize(Init);
00194        }
00195 
00196        // Reset all the elements
00197        void initialize(const T & Init=T())
00198        {
00199            std::fill(begin(),end(),Init);
00200        }
00201     
00202        friend class Array<T,N>;
00203        friend class Array<T,N+1>; 
00204        friend class RefArray<N+1>; 
00205     };
00206 
00207 
00208     //-----------------------------------------------------------------------------
00209     // Partial Specialization for Monodimensional SubArray within an Array
00210     //-----------------------------------------------------------------------------
00211 
00212     template <>
00213     class RefArray<1>
00214     {
00215      public:
00216 
00217        // STL-like types
00218        typedef T         value_type;
00219        typedef T &       reference;
00220        typedef const T & const_reference;
00221        typedef T *       pointer;
00222        typedef const T * const_pointer;
00223        typedef T *       iterator;
00224        typedef const T * const_iterator;
00225        typedef size_t    size_type;
00226        typedef ptrdiff_t difference_type;
00227 
00228        // Give access to number of dimensions
00229        enum  { array_dims = 1 };
00230 
00231      private:
00232 
00233        const size_type * const m_pNDimensions; // Array dimension
00234 
00235        T   * const     m_pElements; // Point to elements within Array
00236 
00237        RefArray<1>(T * pElements, const size_type * pNDimensions, 
00238                                   const size_type * pSubArrayLen)
00239          :m_pElements(pElements),m_pNDimensions(pNDimensions)
00240        { 
00241           assert(m_pElements && m_pNDimensions && pSubArrayLen); 
00242           assert(m_pNDimensions[0]>0 && pSubArrayLen[0]==1); // We found the elements
00243        } 
00244 
00245      public:
00246 
00247        reference operator [](size_type Index)
00248        {
00249           assert(m_pElements);
00250           assert(Index<m_pNDimensions[0]);
00251           return m_pElements[Index];
00252        }
00253 
00254        const_reference operator [](size_type Index) const
00255        {
00256           assert(m_pElements);
00257           assert(Index<m_pNDimensions[0]);
00258           return m_pElements[Index];
00259        }
00260 
00261        // Return STL-like iterators
00262        iterator       begin()       { return m_pElements; }
00263        const_iterator begin() const { return m_pElements; }
00264        iterator       end()         { return m_pElements+size(); }
00265        const_iterator end()   const { return m_pElements+size(); }
00266 
00267        // Return size of array
00268        size_type size()  const { return m_pNDimensions[0]; } 
00269 
00270        // Return size of subdimensions
00271        size_type size(unsigned int Dim) const 
00272        {  
00273           assert(Dim==1); 
00274           return m_pNDimensions[0];  
00275        }
00276 
00277        // Return number of dimensions 
00278        unsigned int dimensions()  const { return 1; }
00279 
00280      protected:
00281 
00282        // The following are protected mainly because they are not exception-safe
00283        // but the way they are used in the rest of the class is exception-safe
00284 
00285        // Copy the elements of another subarray on this one where possible
00286        // Where not possible, initialize them to a specified value Init
00287        void copy(const RefArray<1> & SA, const T & Init=T())
00288        {
00289            size_type below=std::_MIN(size(1),SA.size(1));
00290            size_type above=size(1);
00291 
00292            // Copy the elements we can copy
00293            for (size_type i=0;i<below;i++)
00294               m_pElements[i]=SA.m_pElements[i];
00295 
00296            // Reset the elements we can't copy
00297            for (size_type j=below;j<above;j++)
00298               m_pElements[j]=Init;
00299        }
00300 
00301        // Reset all the elements
00302        void initialize(const T & Init=T())
00303        {
00304            std::fill(begin(),end(),Init);
00305        }
00306 
00307        friend class Array<T,1>;
00308        friend class Array<T,2>;
00309        friend class RefArray<2>; 
00310     };
00311 
00312 
00313 //-----------------------------------------------------------------------------
00314 // Class Template for a Generic Resizable N Dimensional Array
00315 //-----------------------------------------------------------------------------
00316 
00317  public:
00318 
00319    // STL-like types
00320    typedef T         value_type;
00321    typedef T &       reference;
00322    typedef const T & const_reference;
00323    typedef T *       pointer;
00324    typedef const T * const_pointer;
00325    typedef T *       iterator;
00326    typedef const T * const_iterator;
00327    typedef size_t    size_type;
00328    typedef ptrdiff_t difference_type;
00329 
00330    // Give access to number of dimensions
00331    enum  { array_dims = N };
00332 
00333  private:
00334 
00335    T *        m_pArrayElements; // Pointer to actual array elements
00336    size_type  m_nArrayElements; // Total number of array elements
00337 
00338    size_type  m_NDimensions[N];  // Size of the N array dimensions
00339    size_type  m_SubArrayLen[N];  // Size of each subarray
00340 
00341  public:
00342 
00343    // Default constructor
00344    Array<T,N>()
00345       :m_pArrayElements(NULL),m_nArrayElements(0)
00346    {
00347       std::fill(m_NDimensions,m_NDimensions+N,0);
00348       std::fill(m_SubArrayLen,m_SubArrayLen+N,0);
00349    }
00350    
00351    // This takes an array of N values representing the size of the N dimensions 
00352    explicit Array<T,N>(const unsigned int * Dimensions, const T & Init=T())
00353       :m_pArrayElements(NULL),m_nArrayElements(0)
00354    { 
00355       std::fill(m_NDimensions,m_NDimensions+N,0);
00356       std::fill(m_SubArrayLen,m_SubArrayLen+N,0);
00357 
00358       resize(Dimensions,Init); 
00359    }
00360 
00361    // This takes an ArraySize object with the N dimensions
00362    explicit Array<T,N>(const ArraySize<N> & Dimensions, const T & Init=T())
00363       :m_pArrayElements(NULL),m_nArrayElements(0)
00364    { 
00365       std::fill(m_NDimensions,m_NDimensions+N,0);
00366       std::fill(m_SubArrayLen,m_SubArrayLen+N,0);
00367 
00368       resize(Dimensions,Init); 
00369    }
00370 
00371    // Copy constructor
00372    Array<T,N>(const Array<T,N> & A)
00373       :m_pArrayElements(NULL),m_nArrayElements(0)
00374    {
00375       std::fill(m_NDimensions,m_NDimensions+N,0);
00376       std::fill(m_SubArrayLen,m_SubArrayLen+N,0);
00377 
00378       Array<T,N> Temp;
00379       if (!A.empty() && Temp.resize(A.m_NDimensions))
00380          std::copy(A.begin(),A.end(),Temp.begin());
00381       swap(Temp);
00382    }
00383 
00384    // Destructor
00385   ~Array<T,N>() 
00386    { 
00387       delete [] m_pArrayElements; 
00388    }
00389 
00390    // Indexing Array
00391    RefArray<N-1> operator [](size_type Index) 
00392    {  
00393       assert(m_pArrayElements);
00394       assert(Index<m_NDimensions[0]);
00395       return RefArray<N-1>(&m_pArrayElements[Index*m_SubArrayLen[0]],
00396                             m_NDimensions+1,m_SubArrayLen+1);
00397    }
00398 
00399    // Indexing Constant Array
00400    const RefArray<N-1> operator [](size_type Index) const 
00401    {  
00402       assert(m_pArrayElements);
00403       assert(Index<m_NDimensions[0]);
00404       return RefArray<N-1>(&m_pArrayElements[Index*m_SubArrayLen[0]],
00405                             m_NDimensions+1,m_SubArrayLen+1);
00406    }
00407 
00408    // Return RefArray referencing entire Array 
00409    RefArray<N> GetRefArray() 
00410    {  
00411       assert(m_pArrayElements);
00412       return RefArray<N>(m_pArrayElements,m_NDimensions,m_SubArrayLen);
00413    }
00414 
00415    // Return constant RefArray referencing entire Array 
00416    const RefArray<N> GetRefArray() const 
00417    {  
00418       assert(m_pArrayElements);
00419       return RefArray<N>(m_pArrayElements,m_NDimensions,m_SubArrayLen);
00420    }
00421 
00422    // Set the size of each array dimension
00423    // Visual C++ does not accept parameter defined so: const unsigned int (&)[N]
00424    // so I accepted a solution which is not type-safe: use it judiciously
00425    bool resize(const unsigned int * Dimensions, const T & Init=T(), bool PreserveElems=false)
00426    {
00427       assert(Dimensions);
00428       
00429       Array<T,N> Temp; 
00430 
00431       // Calculate all the information you need to use the array
00432       Temp.m_nArrayElements=1;
00433       for (int i=0;i<N;i++)     
00434       {
00435          if (Dimensions[i]==0) 
00436             return false; // Check that no dimension was zero 
00437          Temp.m_nArrayElements*=Dimensions[i]; 
00438          Temp.m_NDimensions[i]=Dimensions[i];
00439          Temp.m_SubArrayLen[i]=1;              
00440          for (int k=N-1;k>i;k--)
00441             Temp.m_SubArrayLen[i]*=Dimensions[k];
00442       }  
00443 
00444       // Allocate new elements, let exception propagate 
00445       Temp.m_pArrayElements=new T[Temp.m_nArrayElements];
00446  
00447       // Some compilers might not throw exception if allocation fails
00448       if (!Temp.m_pArrayElements) 
00449           return false;
00450 
00451       // Copy the elements from the previous array if requested
00452       if (PreserveElems && !empty())
00453           Temp.copy(*this,Init);
00454       // Otherwise initialize them to the specified value
00455       else 
00456           Temp.initialize(Init);
00457 
00458       // Now swap this object with the temporary
00459       swap(Temp);
00460 
00461       return true; 
00462    }
00463 
00464    // resize accepting a fixed ArraySize, this solution is type-safe
00465    bool resize(const ArraySize<N> & Dimensions, const T & Init=T(), bool PreserveElems=false)
00466    {
00467       unsigned int Dims[N];
00468       std::copy(Dimensions.Vect().begin(),Dimensions.Vect().end(),Dims);
00469       return resize(Dims,Init,PreserveElems);
00470    }
00471 
00472    // Delete the complete Array
00473    void clear()
00474    { 
00475       delete [] m_pArrayElements; 
00476       m_pArrayElements=NULL; 
00477       m_nArrayElements=0;
00478 
00479       std::fill(m_NDimensions,m_NDimensions+N,0);
00480       std::fill(m_SubArrayLen,m_SubArrayLen+N,0);
00481    }
00482 
00483    // Assignment operator
00484    Array<T,N> & operator = (const Array<T,N> & A)
00485    {
00486       if (&A!=this) // For efficiency 
00487       {
00488         Array<T,N> Temp(A);
00489         swap(Temp);
00490       }
00491       return *this;
00492    }
00493 
00494    // Return STL-like iterators
00495    iterator       begin()       { return m_pArrayElements; }
00496    const_iterator begin() const { return m_pArrayElements; }
00497    iterator       end()         { return m_pArrayElements+m_nArrayElements; }
00498    const_iterator end()   const { return m_pArrayElements+m_nArrayElements; }
00499 
00500    // Some more STL-like size members
00501    size_type size()       const { return m_nArrayElements; }
00502 
00503    // Return the size of each dimension, 1 to N 
00504    size_type size(unsigned int Dim) const 
00505    {  
00506       assert(Dim>=1 && Dim<=N); 
00507       return m_NDimensions[Dim-1];  
00508    }
00509 
00510    // Say if the array is empty
00511    bool empty()           const { return m_nArrayElements==0; }
00512 
00513    // Return number of dimensions
00514    unsigned int dimensions()  const { return N; } 
00515 
00516    // Swap this array with another, a'la STL 
00517    void swap(Array<T,N> & A)
00518    {
00519       std::swap(m_pArrayElements,A.m_pArrayElements); 
00520       std::swap(m_nArrayElements,A.m_nArrayElements); 
00521 
00522       std::swap_ranges(m_NDimensions,m_NDimensions+N,A.m_NDimensions);
00523       std::swap_ranges(m_SubArrayLen,m_SubArrayLen+N,A.m_SubArrayLen);
00524    }
00525 
00526  protected:
00527 
00528    // The following are protected mainly because they are not exception-safe
00529    // but the way they are used in the rest of the class is exception-safe
00530 
00531    // Copy the elements of another array on this one where possible
00532    // Where not possible, initialize them to a specified value Init
00533    void copy(const Array<T,N> & A, const T & Init=T())
00534    {
00535         size_type below=std::_MIN(size(1),A.size(1));
00536         size_type above=size(1);
00537 
00538         // Copy the elements we can copy
00539         for (size_type i=0;i<below;i++) 
00540             (*this)[i].copy(A[i],Init);
00541 
00542         // Reset the elements we can't copy
00543         for (size_type j=below;j<above;j++)
00544             (*this)[j].initialize(Init);
00545    }
00546 
00547    // Initialize all the array elements
00548    void initialize(const T & Init=T())
00549    {
00550       std::fill(begin(),end(),Init);
00551    }
00552 
00553    // Prefer non-member operator ==, but it needs to be a friend 
00554    friend bool operator == (const Array<T,N> & A, const Array<T,N> & B);
00555 };
00556 
00557 
00558 // Test for equality between two arrays
00559 template <typename T, unsigned int N>
00560 bool operator == (const Array<T,N> & A, const Array<T,N> & B)
00561 {
00562    return std::equal(A.m_NDimensions,A.m_NDimensions+N,B.m_NDimensions)
00563        && std::equal(A.begin(),A.end(),B.begin());
00564 }
00565 
00566 // Test for inequality between two arrays
00567 template <typename T, unsigned int N>
00568 bool operator != (const Array<T,N> & A, const Array<T,N> & B) 
00569 {
00570    return !(A==B); 
00571 }
00572 
00573 
00574 /* The following don't work for Visual C++
00575 
00576 // Not implemented, meaningless to have 0 dimensions
00577 template <typename T>
00578 class Array<T,0>
00579 {
00580 };
00581 
00582 // Not implemented, use std::vector for one dimensional arrays
00583 template <typename T>
00584 class Array<T,1>
00585 {
00586 };
00587 
00588 */
00589 
00590 #endif
00591 
00592 /*
00593  * 
00594  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
00595  * 
00596  *    1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
00597  *    2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
00598  *    3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
00599  * 
00600  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00601  * 
00602  */
00603 
00604 

Generated on Mon Nov 8 17:07:30 2004 for MPT by  doxygen 1.3.9.1