Basic2DArray.h

00001 /*  _________________________________________________________________________
00002  *
00003  *  UTILIB: A utility library for developing portable C++ codes.
00004  *  Copyright (c) 2001, Sandia National Laboratories.
00005  *  This software is distributed under the GNU Lesser General Public License.
00006  *  For more information, see the README file in the top UTILIB directory.
00007  *  _________________________________________________________________________
00008  */
00009 
00010 //
00011 // Basic2DArray.h
00012 //
00024 #ifndef __Basic2DArray_h
00025 #define __Basic2DArray_h
00026 
00027 #ifdef __GNUC__
00028 #pragma interface
00029 #endif
00030 
00031 #ifdef NON_ANSI
00032 #include <iostream.h>
00033 #else
00034 #include <iostream>
00035 using namespace std;
00036 #endif
00037 #ifndef ANSI_HDRS
00038 #include <stdlib.h>
00039 #include <assert.h>
00040 #else
00041 #include <cstdlib>
00042 #include <cassert>
00043 #endif
00044 #include "_generic.h"
00045 #include "BasicArray.h"
00046 
00047 #ifndef SWIG
00048 
00061 #if !defined(TwoDArraySanityChecking)
00062 #define TwoDArraySanityChecking    1
00063 #endif
00064 
00065 template <class T>
00066 class UTILIB_API Basic2DArray;
00067 
00068 template <class T>
00069 class UTILIB_API Simple2DArray;
00070 
00071 template <class T>
00072 class UTILIB_API Num2DArray;
00073 
00074 
00081 template <class T>
00082 class UTILIB_API Basic2DArrayRep {
00083  
00084   friend class Basic2DArray<T>;
00085   friend class Simple2DArray<T>;
00086   friend class Num2DArray<T>;
00087 
00088 protected:
00089  
00091   Basic2DArrayRep() {ref=1; Nrows=0; Ncols=0; Data=0;}
00093   T** Data; 
00095   int ref;
00097   size_type Nrows;
00099   size_type Ncols;
00101   EnumDataOwned own_data;
00103   EnumDataOwned own_ptrs;
00104 
00105 };
00106 #endif // SWIG
00107 
00108 
00109 #ifdef SWIG
00110 template <class T>
00111 class Basic2DArray
00112 #else
00113 template <class T>
00114 class UTILIB_API Basic2DArray
00115 #endif
00116 {
00117 public:
00118 
00120   Basic2DArray()
00121                 {construct(0,0,(T*)0);}
00127   Basic2DArray(const BasicArray<T>& array, const size_type nrows=1, 
00128                 const EnumDataOwned own=DataNotOwned)
00129                 {construct(nrows,array.size()/nrows,array,own);}
00135   Basic2DArray(const size_type nrows, const size_type ncols, T *d=((T*)0), 
00136                 const EnumDataOwned own=DataNotOwned)
00137                 {construct(nrows,ncols,d,own);}
00143   Basic2DArray(const size_type nrows, const size_type ncols, 
00144                 const BasicArray<T>& array, 
00145                 const EnumDataOwned own=DataNotOwned)
00146                 {construct(nrows,ncols,array,own);}
00148   Basic2DArray(const Basic2DArray& array)
00149                 {construct(array.a->Nrows,array.a->Ncols,array.a->Data,
00150                                 AcquireOwnership);}
00151 
00153   virtual ~Basic2DArray()
00154         {free();}
00155 
00157   int resize(const size_type nrows, const size_type ncols);
00159   size_type nrows() const
00160         {return a->Nrows;}
00162   size_type ncols() const
00163         {return a->Ncols;}
00165   operator T** () const
00166         {return a->Data;}
00168   T** data() const
00169         {return a->Data;}
00171   int nrefs() const
00172         {return a->ref;}
00174   T* operator[](const int i);
00176   T* operator[](const int i) const;
00178   T* operator[](const size_type i);
00180   T* operator[](const size_type i) const;
00182   T& operator()(const size_type row, const size_type col);
00184   const T& operator()(const size_type row, const size_type col) const;
00185 
00187   Basic2DArray<T>& operator=(const Basic2DArray<T>& array);
00189   Basic2DArray<T>& operator&=(const Basic2DArray<T>& array);
00191   Basic2DArray<T>& operator<<(const Basic2DArray<T>& array);
00193   Basic2DArray<T>& operator=(const T& val);
00195   Basic2DArray<T>& operator=(const BasicArray<T>& val);
00196 
00202   Basic2DArray<T>& set_data(const size_type len, T* data,
00203                                 const EnumDataOwned o=DataNotOwned);
00205   Basic2DArray<T>& set_data(const BasicArray<T>& array,
00206                                 const EnumDataOwned o=DataNotOwned)
00207                 {return set_data(array.size(),array,o);}
00208 
00209 /* BUG??  Where are these defined?
00210   friend Basic2DArray<T> T(const BasicArray<T>& array);
00212   friend Basic2DArray<T> T(const Basic2DArray<T>& array);
00213 */
00214 
00215 protected:
00216 
00218   Basic2DArrayRep<T>* a;
00220   void construct(const size_type nrows, const size_type ncols, T *d, 
00221                 const EnumDataOwned o=DataNotOwned);
00223   void construct(const size_type nrows, const size_type ncols, T** d, 
00224                 const EnumDataOwned o=DataNotOwned);
00226   void free();
00227 
00228 };
00229 
00230 
00231 template <class T>
00232 inline T* Basic2DArray<T>::operator[](const int idx)
00233 {
00234 #if (TwoDArraySanityChecking==1)
00235 if ((idx < 0) || ((size_type)idx >= a->Nrows))
00236    ErrAbort(errmsg("Basic2DArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,a->Nrows));
00237 #endif
00238  
00239 return a->Data[idx];
00240 }
00241  
00242  
00243 template <class T>
00244 inline T* Basic2DArray<T>::operator[](const int idx) const
00245 {
00246 #if (TwoDArraySanityChecking==1)
00247 if ((idx < 0) || ((size_type)idx >= a->Nrows))
00248    ErrAbort(errmsg("Basic2DArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,a->Nrows));
00249 #endif
00250  
00251 return a->Data[idx];
00252 }
00253 
00254 
00255 template <class T>
00256 inline T* Basic2DArray<T>::operator[](const size_type idx)
00257 {
00258 #if (TwoDArraySanityChecking==1)
00259 if (idx >= a->Nrows)
00260    ErrAbort(errmsg("Basic2DArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,a->Nrows));
00261 #endif
00262  
00263 return a->Data[idx];
00264 }
00265  
00266  
00267 template <class T>
00268 inline T* Basic2DArray<T>::operator[](const size_type idx) const
00269 {
00270 #if (TwoDArraySanityChecking==1)
00271 if (idx >= a->Nrows)
00272    ErrAbort(errmsg("Basic2DArray<T>::operator[] : iterator out of range. idx=%d len=%d",idx,a->Nrows));
00273 #endif
00274  
00275 return a->Data[idx];
00276 }
00277 
00278 
00279 template <class T>
00280 inline T& Basic2DArray<T>::operator()(const size_type row, const size_type col)
00281 {
00282 #if (TwoDArraySanityChecking==1)
00283 if ((row >= a->Nrows) || (col >= a->Ncols))
00284    ErrAbort(errmsg("Basic2DArray<T>::operator() : iterator out of range. %dx%d not in %dx%d",row,col,a->Nrows,a->Ncols));
00285 #endif
00286  
00287 return a->Data[row][col];
00288 }
00289  
00290  
00291 template <class T>
00292 inline const T& Basic2DArray<T>::operator()(const size_type row, const size_type col) const
00293 {
00294 #if (TwoDArraySanityChecking==1)
00295 if ((row >= a->Nrows) || (col >= a->Ncols))
00296    ErrAbort(errmsg("Basic2DArray<T>::operator() : iterator out of range. %dx%d not in %dx%d",row,col,a->Nrows,a->Ncols));
00297 #endif
00298  
00299 return a->Data[row][col];
00300 }
00301 
00302 
00303 template <class T>
00304 void Basic2DArray<T>::construct(const size_type nrows, const size_type ncols, T * d, 
00305                                         const EnumDataOwned o)
00306 {
00307 a = new Basic2DArrayRep<T>;
00308 assert(a != 0);
00309 
00310 a->Nrows = nrows;
00311 a->Ncols = ncols;
00312 if (d == NULL) {
00313    if (nrows > 0) {
00314       a->Data = new T* [nrows] ;
00315       assert(a != 0);
00316       for (size_type i=0; i<nrows; i++) {
00317          a->Data[i] = new T [ncols] ;
00318          assert(a->Data[i] != 0);
00319          }
00320       }
00321    else
00322       a->Data = NULL;
00323    a->own_ptrs = AcquireOwnership;
00324    a->own_data = AcquireOwnership;
00325    }
00326 
00327 else {
00328    if (o == AcquireOwnership) {
00329       if (nrows > 0)  {
00330          a->Data = new T* [nrows] ;
00331          assert(a->Data != 0);
00332          for (size_type i=0; i<nrows; i++) {
00333             a->Data[i] = new T [ncols] ;
00334             assert(a->Data[i] != 0);
00335             }
00336          size_type ndx=0;
00337          for (size_type ii=0; ii<nrows; ii++)
00338            for (size_type jj=0; jj<ncols; jj++)
00339              a->Data[ii][jj] = d[ndx++];
00340          }
00341       else
00342          a->Data = NULL;
00343       a->own_ptrs = AcquireOwnership;
00344       a->own_data = AcquireOwnership;
00345       }
00346    else {
00347       if (nrows > 0)  {
00348          a->Data = new T* [nrows] ;
00349          assert(a->Data != 0);
00350          T* tmp = d;
00351          for (size_type i=0; i<ncols; i++) {
00352             a->Data[i] = tmp;
00353             tmp+= ncols;
00354             }
00355          }
00356       else
00357          a->Data = NULL;
00358       a->own_ptrs = AcquireOwnership;
00359       a->own_data = DataNotOwned;
00360       }
00361    }
00362 }
00363 
00364 
00365 template <class T>
00366 void Basic2DArray<T>::construct(const size_type nrows, const size_type ncols, T **d, 
00367                                         const EnumDataOwned o)
00368 {
00369 a = new Basic2DArrayRep<T>;
00370 assert(a != 0);
00371 
00372 a->Nrows = nrows;
00373 a->Ncols = ncols;
00374 if (d == NULL) {
00375    if (nrows > 0) {
00376       a->Data = new T* [nrows] ;
00377       assert(a != 0);
00378       for (size_type i=0; i<nrows; i++) {
00379          a->Data[i] = new T [ncols] ;
00380          assert(a->Data[i] != 0);
00381          }
00382       }
00383    else
00384       a->Data = NULL;
00385    a->own_ptrs = AcquireOwnership;
00386    a->own_data = AcquireOwnership;
00387    }
00388 
00389 else {
00390    if (o == AcquireOwnership) {
00391       if (nrows > 0)  {
00392          a->Data = new T* [nrows] ;
00393          assert(a->Data != 0);
00394          for (size_type i=0; i<nrows; i++) {
00395             a->Data[i] = new T [ncols] ;
00396             assert(a->Data[i] != 0);
00397             }
00398          for (size_type ii=0; ii<nrows; ii++)
00399            for (size_type jj=0; jj<ncols; jj++)
00400              a->Data[ii][jj] = d[ii][jj];
00401          }
00402       else
00403          a->Data = NULL;
00404       a->own_ptrs = AcquireOwnership;
00405       a->own_data = AcquireOwnership;
00406       }
00407    else {
00408       a->Data=d;
00409       a->own_ptrs = DataNotOwned;
00410       a->own_data = DataNotOwned;
00411       }
00412    }
00413 }
00414 
00415 
00416 template <class T>
00417 void Basic2DArray<T>::free()
00418 {
00419 if (--a->ref == 0) {
00420    if ((a->Data) && (a->Nrows>0)) {
00421       if (a->own_data && (a->Ncols > 0)) {
00422          for (size_type i=0; i<a->Nrows; i++)
00423            delete [] a->Data[i];
00424          }
00425       if (a->own_ptrs)
00426          delete [] a->Data;
00427       }
00428    delete a;
00429    }
00430 }
00431 
00432 
00433 template <class T>
00434 int Basic2DArray<T>::resize(const size_type nrows, const size_type ncols)
00435 {
00436 //
00437 // Maybe we get lucky.
00438 //
00439 if ((ncols == a->Ncols) && (nrows == a->Nrows))
00440    return OK;
00441 
00442 //
00443 // Need to completely replace old data.
00444 //
00445 if ((ncols != a->Ncols) && (nrows != a->Nrows)) {
00446    //
00447    // Delete old data (if owned)
00448    //
00449    if ((a->Data) && (a->Nrows>0)) {
00450       if (a->own_data && (a->Ncols > 0)) {
00451          for (size_type i=0; i<a->Nrows; i++)
00452            delete [] a->Data[i];
00453          }
00454       if (a->own_ptrs)
00455          delete [] a->Data;
00456       }
00457    //
00458    // Make new data
00459    //
00460    if (nrows > 0) {
00461       a->Data = new T* [nrows] ;
00462       assert(a != 0);
00463       for (size_type i=0; i<nrows; i++) {
00464          a->Data[i] = new T [ncols] ;
00465          assert(a->Data[i] != 0);
00466          }
00467       }
00468    else
00469       a->Data = NULL;
00470    a->own_ptrs = AcquireOwnership;
00471    a->own_data = AcquireOwnership;
00472    a->Nrows = nrows;
00473    a->Ncols = ncols;
00474    return OK;
00475    }
00476 
00477 //
00478 // We need to simply resize the number of rows.
00479 //
00480 if (nrows != a->Nrows) {
00481    T **d=NULL;
00482    if (nrows > 0) {
00483       d = new T* [nrows];
00484       assert(d != 0);
00485       // 
00486       // Note:  the new memory is not initialized beyond what the constructors
00487       // do.
00488       //
00489       if (a->Nrows > 0) {
00490          for (size_type i=0; i<min(nrows,a->Nrows); i++)
00491            d[i] = a->Data[i];
00492          }
00493       }
00494  
00495    if (a->Data && a->own_ptrs && (a->Nrows > 0))
00496       delete [] a->Data;
00497  
00498    a->Data = d;
00499    a->Nrows = nrows;
00500    }
00501 
00502 //
00503 // We need to simply resize the number of columns
00504 //
00505 if (ncols != a->Ncols) {
00506    if (ncols > 0) {
00507       for (size_type j=0; j<a->Nrows; j++) {
00508         T* d=NULL;
00509         d = new T [ncols];
00510         assert(d != 0);
00511         // 
00512         // Note:  the new memory is not initialized beyond what the constructors
00513         // do.
00514         //
00515         if (a->Ncols > 0) {
00516            for (size_type i=0; i<min(ncols,a->Ncols); i++)
00517              d[i] = a->Data[j][i];
00518            }
00519         if (a->Data && a->own_data && (a->Ncols > 0))
00520            delete [] a->Data[j];
00521         a->Data[j] = d;
00522         }
00523       }
00524    else 
00525       if (a->Data && a->own_data && (a->Ncols > 0))
00526          for (size_type i=0; i<a->Nrows; i++) {
00527            delete [] a->Data[i];
00528            a->Data[i] = NULL;
00529            }
00530  
00531    a->Ncols = ncols;
00532    }
00533 
00534 return OK;
00535 }
00536 
00537 
00538 template <class T>
00539 Basic2DArray<T>& Basic2DArray<T>::operator=(const Basic2DArray<T>& array)
00540 {
00541 //ErrAbort("Basic2DArray<T>::operator= : has been temporarily disabled during the transition to the new vector classes.");
00542 
00543 if (this != &array) {
00544    free();
00545    construct(array.nrows(),array.ncols(),array.data(),AcquireOwnership);
00546    }
00547 return *this;
00548 }
00549 
00550 
00551 template <class T>
00552 Basic2DArray<T>& Basic2DArray<T>::operator<<(const Basic2DArray<T>& array)
00553 {
00554 if (array.a == a)
00555    return *this;
00556 if ((array.a->Nrows != a->Nrows) || (array.a->Ncols != a->Ncols))
00557    ErrAbort(errmsg("Basic2DArray<T>::operator<< : Unequal vector matrices %dx%d and %dx%d.",a->Nrows,a->Ncols,array.a->Nrows,array.a->Ncols));
00558  
00559 for (size_type i=0; i<a->Nrows; i++)
00560   for (size_type j=0; j<a->Ncols; j++)
00561     a->Data[i][j] = array.a->Data[i][j];
00562  
00563 return *this;
00564 }
00565 
00566 
00567 
00568 template <class T>
00569 Basic2DArray<T>& Basic2DArray<T>::operator&=(const Basic2DArray<T>& array)
00570 {
00571 if (array.a == a) return *this;
00572 
00573 free();
00574 a = array.a;
00575 a->ref++;
00576 return *this;
00577 }
00578 
00579 
00580 
00581 template <class T>
00582 Basic2DArray<T>& Basic2DArray<T>::operator=(const T& val)
00583 {
00584 for (size_type i=0; i<a->Nrows; i++)
00585   for (size_type j=0; j<a->Ncols; j++)
00586     a->Data[i][j] = ( T ) val;
00587 return *this;
00588 }
00589 
00590 
00591 
00592 template <class T>
00593 Basic2DArray<T>& Basic2DArray<T>::operator=(const BasicArray<T>& val)
00594 {
00595 if (a->Ncols != val.size())
00596    ErrAbort(errmsg("Basic2DArray<T>::operator= : Array length does not equal the 2DArray columns %d and %d",val.size(),a->Ncols));
00597 
00598 for (size_type i=0; i<a->Nrows; i++)
00599   for (size_type j=0; j<a->Ncols; j++)
00600     a->Data[i][j] = val[j];
00601 return *this;
00602 }
00603 
00604 template <class T>
00605 Basic2DArray<T>& Basic2DArray<T>::set_data(const size_type len, T * data, const EnumDataOwned o)
00606 {
00607 #if TwoDArraySanityChecking==1
00608 if ( (nrows()*ncols()) != len)
00609    ErrAbort(errmsg("Basic2DArray<T>::set_data : bad vector size %d != %d.",
00610                         (nrows()*ncols()),len));
00611 #endif
00612 
00613 if (a->own_data && (a->Ncols > 0)) {
00614    for (size_type i=0; i<a->Nrows; i++)
00615      delete [] a->Data[i];
00616    }
00617 size_type ndx=0;
00618 for (size_type i=0; i<a->Nrows; i++) {
00619   a->Data[i] = &(data[ndx]);
00620   ndx += a->Ncols;
00621   }
00622 
00623 //
00624 // BUG: I need to fix the model of ownership here.
00625 //
00626 a->own_data = DataNotOwned;
00627 return *this;
00628 }
00629 #endif