luj@delta.ecn.purdue.edu (Jun Lu) (01/06/91)
It would be nice if I can have a "subroutine" which takes arbitrary matrices as arguments and performs some operations on them. The dimensions of the 2-d array are not known a priori. In other words, how do you add two matrices together portably in C ? ( see following scenario descriptions ) main() { double m1[4][2], m2[4][2], m[4][2]; double a[5][5], b[5][5], c[5][5]; /* init m1, m2 ... */ madd(m1, m2, m, 4, 2); madd(a, b, c, 5, 5); /* ... */ } madd(a, b, c, m, n) /* args --- how ???(Note n is not known at compile time, but we assume that the type of the 2-d array elements are known, i.e. double */ { /* * some work --- how ???? */ for (i = 0; i < m; i++) /* fucntionality of madd() */ for (j = 0; j < n; j++) c[i][j] = a[i][j] + b[i][j]; } No calling Fortran from C please. Any suggestions/comments/pointers are welcome. I'm looking forward to hearing from you ... Thanks, -- -- Jun Lu Internet:luj@ecn.purdue.edu -- -- Aeronautics & Astronautics Bitnet: luj%ecn.purdue.edu@purccvm -- -- Purdue University UUCP: pur-ee!luj -- -- W. Lafayette, IN 47907 Phone:317-494-9410 Fax:317-494-0307 --
henry@zoo.toronto.edu (Henry Spencer) (01/06/91)
In article <1991Jan6.044056.23028@noose.ecn.purdue.edu> luj@delta.ecn.purdue.edu (Jun Lu) writes: >It would be nice if I can have a "subroutine" which takes arbitrary matrices as >arguments and performs some operations on them. The dimensions of the 2-d >array are not known a priori... Can't be done in C. The dimensions of an array, with the exception of the first, must be known at compile time. (Well, "can't be done" is an exaggeration, but what you end up doing is cheating, declaring the arguments as pointers and doing the subscript arithmetic yourself rather than using [] notation.) This is generally considered a deficiency, but it is harder to solve than it looks. Some compilers have extensions to do it, although most of those extensions have problems of one kind or another. There is work being done on finding a good solution. -- If the Space Shuttle was the answer, | Henry Spencer at U of Toronto Zoology what was the question? | henry@zoo.toronto.edu utzoo!henry
rory@maccs.dcss.mcmaster.ca (Rory Jacobs) (01/06/91)
In article <1991Jan6.044056.23028@noose.ecn.purdue.edu> luj@delta.ecn.purdue.edu (Jun Lu) writes: >It would be nice if I can have a "subroutine" which takes arbitrary matrices as >arguments and performs some operations on them. The dimensions of the 2-d >array are not known a priori. In other words, how do you add two >matrices together portably in C ? ( see following scenario descriptions ) > >main() >{ > double m1[4][2], m2[4][2], m[4][2]; > double a[5][5], b[5][5], c[5][5]; > > /* init m1, m2 ... */ > > > madd(m1, m2, m, 4, 2); > madd(a, b, c, 5, 5); > > /* ... */ > >} > >madd(a, b, c, m, n) > /* args --- how ???(Note n is not known at compile time, but we assume that > the type of the 2-d array elements are known, i.e. double */ >{ > /* > * some work --- how ???? > */ > > for (i = 0; i < m; i++) /* fucntionality of madd() */ > for (j = 0; j < n; j++) > c[i][j] = a[i][j] + b[i][j]; > >} Use pointer arithemetic, as in the following way: /*-------------------*/ void madd(a,b,c,m,n) /*-------------------*/ double *a,*b,*c; int m,n; { for (i=0;i<m;i++) { for (j=0;j<n;j++) { *(c+j+i*n) = *(a +j+i*n) + *(b+j+i*n); } } } Explaination: memory is stored sequentially --- including multi-dimensional arrays. Since we know that in C they are stored in row-major form (row-by-row) and that the name of a array can be considered a pointer to the array, we can deal with the pointer. Calculating addresses from a two-dimensional array: -- | a11 a12 ..... a1n | | a21 a22 ..... a2n | | ... | | ai1 ai2 ... aij ... ain | | ... | | am1 am2 ..... amn | -- -- We want to know the number of entries up to and including the aij in the array. This is the number of entries in complete rows before the ith row (i-1) * n , and the number of entries to the aij (which is j) a[i][j] = *(a+(i-1)*n +j) But now we must remember C indices start at 0, so M ranges from 0 to m-1, and N from 0 to n-1, ie. the one is already subtracted for you. thus a[i][j] = *(a+i*n+j) For a more decent treatment of how to calculate addresses (it is a sunday morning after saturday night) see a half-way-descent discrete math book. Sure hope this helps, Rory Jacobs Rory Jacobs Who me?!? rory@maccs.dcss.mcmaster.ca Let's go Flyers! ...!uunet!uati!utgpu!maccs!rory I thought it was easy... Department of Computer Science and Systems Boring (yawn)! McMaster University, Hamilton, Ont Let's have some fun.
tps@chem.ucsd.edu (Tom Stockfisch) (01/08/91)
In article <1991Jan6.044056.23028@noose.ecn.purdue.edu> luj@delta.ecn.purdue.edu (Jun Lu) writes: >It would be nice if I can have a "subroutine" which takes arbitrary matrices as >arguments and performs some operations on them. The dimensions of the 2-d >array are not known a priori. I'm so proud of my clever programming constructs for this I just have to post every time this topic comes up (-: Using your code with my method for handling 2-d arrays in C, main() { double m1[4][2], m2[4][2], m[4][2]; /* init m1, m2 ... */ madd(m1[0], m2[0], m[0], 4, 2); /* ... */ } madd( a, b, c, m, n ) double a[/* m*n */], b[/* m*n */], c[/* m*n */]; # define A(i,j) ( (i) *n+ (j) ) # define B(i,j) ( (i) *n+ (j) ) { int i, j; for (i = 0; i < m; i++) /* fucntionality of madd() */ for (j = 0; j < n; j++) C(i,j) = A(i,j) + B(i,j); } Note the missing declarations for m,n. This is because they appear in the comments inside the array dimensions. Note the macro definitions are analogues of the Fortran "dimension" statement. >No calling Fortran from C please. Certainly not for this. -- || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu
davee@hpcllla.cup.hp.com (Dave Elliott) (01/09/91)
I'm just a C novice, so maybe I'm way off base here... but isn't the solution
something like the following:
madd(a, b, c, m, n)
double *a, *b, *c;
int m, n;
{
double *end;
end = a + m * n;
for ( ; a<end; ++a, ++b, ++c)
*c = *a + *b;
}
- Dave Elliott
davee@hpda.hp.com