[gnu.g++] fetching the multi-dimensional array classes

SAITO@sdr.slb.com ("Naoki Saito Ext. 5471", GEO-002) (06/28/89)

	Hi, there!  A while ago, there was some discussion on fetching method
on multi-dimensional array classes.  For 1D array classes, we can define both
[i] and elem(i) to fetch the i-th element as the BOOK says.  For 2D array
classes, for example, we cannot overload [][].  So instead, I'm using
elem(i,j) to fetch the (i,j)-th element.  However, I recently realized that I
could use operator () to fetch the (i,j)-th element just like Fortran style,
e.g.,

Matrix A(100,100);

int i, j;
for (i = 0; i < 100; i++)
  for (j = 0; j < 100; j++)
    A(i,j) = .....

And the definition of the fetching method is something like this:

float& Matrix::operator(int i, int j)
{
  return buf[i*cols+j]; // return without checking the index.
}

So far, it looks fine, but overloading () does effect something else in the
classes?  If it does not, we can pleasantly use A(i,j) type syntax instead of
A.elem(i,j).  (Of course, it is also good if we could overload [i][j], or
define [i,j])

Please give me some advise,

Regards,
Naoki Saito (saito@sdr.slb.com)
Schlumberger-Doll Research

pcg@aber-cs.UUCP (Piercarlo Grandi) (06/30/89)

In article <8906281652.AA04026@AENEAS.MIT.EDU> SAITO@sdr.slb.com ("Naoki Saito  Ext. 5471", GEO-002) writes:

	[ on multiple dimensional arrays ]

    And the definition of the fetching method is something like this:
    
    float& Matrix::operator(int i, int j)
    {
      return buf[i*cols+j]; // return without checking the index.
    }

Two minor points: you wanted to write "Matrix::operator()(int i,int j)" of
course, and most importantly, I hope you defined it as inline (explcitly or
implicitly within the class definition).

For such small functions, inlining is vital, not just because of speed but
also because it *reduces* total code size, as the function body is tipically
smaller than the code size used by the caller to prepare and close the call
(or the clee to so prologue and epilogue), especially on CISC machines.
-- 
Piercarlo "Peter" Grandi           | ARPA: pcg%cs.aber.ac.uk@nsfnet-relay.ac.uk
Dept of CS, UCW Aberystwyth        | UUCP: ...!mcvax!ukc!aber-cs!pcg
Penglais, Aberystwyth SY23 3BZ, UK | INET: pcg@cs.aber.ac.uk

tobbe@isy.liu.se (Torbjorn Kronander) (07/04/89)

In article <1041@aber-cs.UUCP> pcg@cs.aber.ac.uk (Piercarlo Grandi) writes:
>In article <8906281652.AA04026@AENEAS.MIT.EDU> SAITO@sdr.slb.com ("Naoki Saito  Ext. 5471", GEO-002) writes:
>
>	[ on multiple dimensional arrays ]
>
>    And the definition of the fetching method is something like this:
>    
>    float& Matrix::operator(int i, int j)
>    {
>      return buf[i*cols+j]; // return without checking the index.
>    }
>

There is no need to use (,) type indexing for multiple arrays. By defining
a dummy class, matrow in the exanple below, that is only used for address 
resolving yiu can have ordinary [][] type indeces. 

I enclose source for a generic matrix package as an example. (works
as generic vector and compiles under CFRONT 1.2. I haven tried g++).

/* mat.hxx */

/* This module is a generic matrix module. 

Tobbe K (and ragge N) 880630

If the DEBUG is defined (#define DEBUG) BEFORE! including this file
you will get array bounds checking, if not a more efficient (and
more dangerous) declaration is given.

NOTE if you change anything in declare(), do this in both 
places (i.e.) declare is written twice below, one for each case of DEBUG.

*/


#ifndef MATHXX
#define MATHXX  1

#include <generic.hxx>

#ifndef MATCOMMON
#define MATCOMMON 1

#include <stream.hxx>
#endif


#define MAT(COMPONENT) name2(COMPONENT,mat)
#define MATROW(COMPONENT) name2(COMPONENT,matrow)

#ifndef DEBUG



#define matdeclare(COMPONENT)						\
class MATROW(COMPONENT) {						\
 protected:								\
   COMPONENT* r;							\
 public:								\
   COMPONENT& operator[](int col){ return *(r+col);};			\
   MATROW(COMPONENT)(COMPONENT* p) { r=p;};				\
};									\
									\
									\
									\
class MAT(COMPONENT) {							\
/* allocated size (at allocation = rows*cols) */                        \
 public:								\
   int physicalsize;                                                    \
   COMPONENT* p;							\
   int rows;								\
   int cols;								\
   MAT(COMPONENT)(){							\
	p=0; physicalsize=0;						\
	rows=0; cols=0;							\
	};								\
   MAT(COMPONENT)(int r,int c){						\
	p=new COMPONENT[r*c];  physicalsize=r*c;                        \
	rows=r;cols=c;};	                                        \
   MAT(COMPONENT)(MAT(COMPONENT)&);					\
   ~MAT(COMPONENT)() {delete p;};					\
   MATROW(COMPONENT)& operator[](int row){ 				\
		return( MATROW(COMPONENT)(p+row*cols) );		\
	      };							\
   virtual MAT(COMPONENT)& operator=(MAT(COMPONENT)&);			\
   virtual MAT(COMPONENT)& operator=(COMPONENT);			\
									\
   void transpose();							\
};


#else
// This means array bounds checking is on, somewhat slower....
// but SAFER !!



#define matdeclare(COMPONENT)						\
class MATROW(COMPONENT) {						\
 protected:								\
   COMPONENT* r;							\
   int length;								\
 public:								\
   COMPONENT& operator[](int col)  {					\
     if (col >= length){						\
       cerr << "Error, subsrcipt out of range in MAT, (column)\n";	\
       exit(1);								\
       };								\
     return *(r+col);							\
     };									\
									\
   MATROW(COMPONENT)(COMPONENT* p, int cols) {length=cols; r=p;};	\
};									\
									\
									\
									\
class MAT(COMPONENT) {							\
/* allocated size (at allocation = rows*cols) */			\
 public:								\
    int physicalsize;							\
   COMPONENT* p;							\
   int rows;								\
   int cols;								\
   MAT(COMPONENT)(){							\
	p=0; physicalsize=0;						\
	rows=0; cols=0;							\
	};								\
   MAT(COMPONENT)(int r,int c){						\
	p=new COMPONENT[r*c];  physicalsize=r*c;			\
 	if ((int)p==0) {						\
	  cerr << "Error1, unsuccessful allocation in mat.hxx\n";	\
	  exit(1);							\
	  };								\
	;rows=r;cols=c;};						\
   MAT(COMPONENT)(MAT(COMPONENT)&);					\
   ~MAT(COMPONENT)() {delete p;};					\
   MATROW(COMPONENT)& operator[](int row){				\
     if (row >= rows) {							\
       cerr << "Error, subsrcipt out of range in MAT, (row)\n";		\
       exit(1);								\
       };								\
     return( MATROW(COMPONENT)(p+row*cols,cols) );			\
     };									\
   virtual MAT(COMPONENT)& operator=(MAT(COMPONENT)&);			\
   virtual MAT(COMPONENT)& operator=(COMPONENT);			\
									\
   void transpose();							\
};

#endif





#define matimplement(COMPONENT)						\
MAT(COMPONENT)::MAT(COMPONENT)(MAT(COMPONENT)& in){			\
p=new COMPONENT[in.rows*in.cols];					\
if ((int)p==0) {                                                        \
	  cerr << "Error2,unsuccessful allocation in mat.hxx\n";        \
	  exit(1);                                                      \
	  };                                                            \
memcpy(p,in.p,sizeof(COMPONENT)*in.rows*in.cols);			\
rows=in.rows;								\
cols=in.cols;								\
physicalsize=in.rows*in.cols;                                           \
};									\
									\
MAT(COMPONENT)& MAT(COMPONENT)::operator=(MAT(COMPONENT)& in){		\
if ((rows != in.rows) || (cols != in.cols)){				\
  cerr << "Size must be equal in a MAT(COMPONENT) op= \n";		\
  exit(1);								\
};									\
memcpy(p,in.p,sizeof(COMPONENT)*in.rows*in.cols);			\
return *this;								\
} /*op=*/								\
									\
MAT(COMPONENT)& MAT(COMPONENT)::operator=(COMPONENT x){			\
register int i = rows*cols;						\
register COMPONENT* pu = p;						\
									\
while (i--){								\
 *pu++ = x;								\
};									\
return *this;								\
} /*op=*/								\
									\
									\
void  MAT(COMPONENT)::transpose() {					\
register int ir,ic;							\
MAT(COMPONENT) ut(cols,rows);						\
for (ir=0; ir < rows; ir++)						\
  for (ic=0; ic < cols; ic++) {						\
    *(ut.p+ir+ic*rows)= *(p+ic+cols*ir);				\
  };									\
memcpy(p,ut.p,sizeof(COMPONENT)*rows*cols);				\
int tmp=rows;								\
rows=cols;								\
cols=tmp;								\
}; /*  MAT(COMPONENT)::transpose() */					\
									\
									\
									\

#endif





Good luck.

--
-----------------------------------------------------------------------

Torbj|rn Kronander			Tobbe%joakim@rainier.se
Dept. of EE				T-kronander@linnea.liu.se