2D/3D array P.S.

From: Masaharu Goto (MXJ02154@nifty.ne.jp)
Date: Mon Jul 20 1998 - 14:42:00 MEST


Rooters,

I refined 2D/3D array class a bit more for C++ beginners. ary3d.h header file
is self documenting.

Masaharu Goto

// ary3d.h ///////////////////////////////////////////////////////////
// 2D/3D array classes 
//  double3d , float3d , int3d , short3d , char3d
//  double2d , float2d , int2d , short2d , char2d
//
//  Usage:
//   int x=5,y=4,z=6,i,j,k;                int x=6,y=5,i,j;
//
//   // declaration                        // declaration
//   double3d a(x,y,z);                    float2d a(x,y);
//
//   // assignment                         // assignment
//   for(i=0;i<x;i++)                      for(i=0;i<x;i++) 
//     for(j=0;j<y;j++)                      for(j=0;j<y;j++)
//       for(k=0;i<z;k++)                      a(i,j) = i*2+j;
//         a(i,j,i) = i*j+k;
//
//   // reference                          // reference
//   for(i=0;i<x;i++)                      for(i=0;i<x;i++)
//     for(j=0;j<y;j++)                      for(j=0;j<y;j++)
//       for(k=0;i<z;k++)                      cout << a(i,j) << endl;
//         cout << a(i,j,i) << endl;
//
// NOTE1:
//   It is recommended to precompile this header file. Precompiled version
//  is faster and more reliable.
//     $  makecint -mk Makefile -dl ary3d.dll -H ary3d.h
//     $  make -f Makefile
//
// NOTE2:
//   Only simple run-time array index check is done. Run-time array index
//  check can be turned off by undefining INDEXCHECK macro.
//
// NOTE3:
//   a[i][j][k] notation is available if INDEXOPR macro is defined.
//  This notation is less efficient compared to a(i,j,k). Not recommended.
//
/////////////////////////////////////////////////////////////////////
#include <iostream.h>

//#define INDEXOPR
#define INDEXCHECK

/////////////////////////////////////////////////////////////////////
// 2 dimentional array class template
/////////////////////////////////////////////////////////////////////
template<class T> class array2d {
 public:
  // constructors
  array2d(int jx,int kx) { 
    maxj=jx; maxk=kx;
    isnew=1;
    p = new T[maxj*maxk];
  }
  array2d(array2d& obj) {copy(obj);}
#ifdef INDEXOPR
  array2d() { p=NULL; }
  //array2d(T* pin,int jx,int kx) {init(pin,jx,kx);}
  void init(T* pin,int jx,int kx) { 
    maxj=jx; maxk=kx;
    isnew=0;
    p = pin;
  } 
#endif

  // destructor
  ~array2d() {if(isnew&&p) delete[] p;}

  // operator overloading
  array2d& operator=(array2d& obj) {
    if(p==obj.p) return(*this);
    if(isnew&&p) delete[] p;
    copy(obj);
    return(*this);
  }
  T& operator()(int j,int k) {
#ifdef INDEXCHECK
    if(j<0||maxj<=j||k<0||maxk<=k) {
      cerr << "Bad index ("<<j<<","<<k<<") > ("<<maxj<<","<<maxk<<")"<< endl;
      return(*p);
    }
#endif
    return( *(p + maxk*j + k) );
  }
#ifdef INDEXOPR
  T* operator[](int j) {return(p+maxk*j);}
#endif
  friend bool operator==(array2d<T>& a,array2d<T>& b);
  friend bool operator!=(array2d<T>& a,array2d<T>& b);
  friend ostream& operator<<(ostream& ost,array2d<T>& a);

 private:
  T* p;
  int maxj,maxk;
  int isnew;

  // utility function
  void copy(array2d& obj) {
    maxj=obj.maxj; maxk=obj.maxk;
    if(isnew) {
      isnew=1;
      p = new T[maxj*maxk];
      memcpy(p,obj.p,sizeof(T)*maxj*maxk);
    }
    else {
      isnew=0;
      p = obj.p;
    }
  }
};

template<class T>
bool operator==(array2d<T>& a,array2d<T>& b) {
  if(a.maxj!=b.maxj || a.maxk!=b.maxk) return(false);
  int i,max=a.maxj*a.maxk;
  for(i=0;i<max;i++) {
    if(a.p[i]!=b.p[i]) return(false);
  }
  return(true);
}

template<class T>
bool operator!=(array2d<T>& a,array2d<T>& b) {
  return(!(a==b));
}

template<class T>
ostream& operator<<(ostream& ost,array2d<T>& a) {
  int j,k;
  ost << '(' ;
  for(j=0;j<a.maxj;j++) {
    if(j) ost << ',';
    ost << '(' ;
    for(k=0;k<a.maxk;k++) {
      if(k) ost << ',';
      ost << a(j,k);
    }
    ost << ')' ;
  }
  ost << ')' ;
  return(ost);
}

/////////////////////////////////////////////////////////////////////
// 3 dimentional array class template
/////////////////////////////////////////////////////////////////////
template<class T> class array3d {
 public:
  // constructor
  array3d(int ix,int jx,int kx) { 
    maxi=ix; maxj=jx; maxk=kx;
    isnew=1;
    p = new T[maxi*maxj*maxk];
  }
  array3d(array3d& obj) {copy(obj);}
#ifdef INDEXOPR
  array3d() {p=NULL;}
  //array3d(T* pin,int ix,int jx,int kx) {init(pin,ix,jx,kx);}
  void init(T* pin,int ix,int jx,int kx) { 
    maxi=ix; maxj=jx; maxk=kx;
    isnew=0;
    p = pin;
  }
#endif

  // destructor
  ~array3d() {if(isnew&&p) delete[] p;}

  // operator overloading
  array3d& operator=(array3d& obj) {
    if(p==obj.p) return(*this);
    if(isnew&&p) delete[] p;
    copy(obj);
    return(*this);
  }
  T& operator()(int i,int j,int k) {
#ifdef INDEXCHECK
    if(i<0||maxi<=i||j<0||maxj<=j||k<0||maxk<=k) {
      cerr << "Bad index ("<<i<<","<<j<<","<<k<<") > (";
      cerr <<maxi<<","<<maxj<<","<<maxk<<")"<< endl;
      return(*p);
    }
#endif
    return( *(p + ((maxj*maxk)*i + maxk*j + k)) );
  }
#ifdef INDEXOPR
  array2d<T>& operator[](int i) {
    subary.init(p+maxj*maxk*i,maxj,maxk);
    return(subary);
  }
#endif
  friend bool operator==(array3d<T>& a,array3d<T>& b);
  friend bool operator!=(array3d<T>& a,array3d<T>& b);
  friend ostream& operator<<(ostream& ost,array3d<T>& a);

 private:
  T* p;
  int maxi,maxj,maxk;
  int isnew;
#ifdef INDEXOPR
  array2d<T> subary;
#endif

  // utility function
  void copy(array3d& obj) {
    maxi=obj.maxi; maxj=obj.maxj; maxk=obj.maxk;
    if(isnew) {
      isnew=1;
      p = new T[maxi*maxj*maxk];
      memcpy(p,obj.p,sizeof(T)*maxi*maxj*maxk);
    }
    else {
      isnew=0;
      p = obj.p;
    }
  }
};

template<class T>
bool operator==(array3d<T>& a,array3d<T>& b) {
  if(a.maxi!=b.maxi || a.maxj!=b.maxj || a.maxk!=b.maxk) return(false);
  int i,max=a.maxi*a.maxj*a.maxk;
  for(i=0;i<max;i++) {
    if(a.p[i]!=b.p[i]) return(false);
  }
  return(true);
}

template<class T>
bool operator!=(array3d<T>& a,array3d<T>& b) {
  return(!(a==b));
}

template<class T>
ostream& operator<<(ostream& ost,array3d<T>& a) {
  int i,j,k;
  ost << '(' ;
  for(i=0;i<a.maxi;i++) {
    if(i) ost << ',';
    ost << '(' ;
    for(j=0;j<a.maxj;j++) {
      if(j) ost << ',';
      ost << '(' ;
      for(k=0;k<a.maxk;k++) {
        if(k) ost << ',';
        ost << a(i,j,k);
      }
      ost << ')' ;
    }
    ost << ')' ;
  }
  ost << ')' ;
  return(ost);
}

/////////////////////////////////////////////////////////////////////
// instantiation of class template as typedef
/////////////////////////////////////////////////////////////////////
typedef array3d<double> double3d;
typedef array2d<double> double2d;
typedef array3d<float>  float3d;
typedef array2d<float>  float2d;
typedef array3d<int>    int3d;
typedef array2d<int>    int2d;
typedef array3d<short>  short3d;
typedef array2d<short>  short2d;
typedef array3d<char>   char3d;
typedef array2d<char>   char2d;



This archive was generated by hypermail 2b29 : Tue Jan 04 2000 - 00:34:35 MET