2D/3D array P.S.

Masaharu Goto (MXJ02154@nifty.ne.jp)
Mon, 20 Jul 1998 21:42:00 +0900


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;