[comp.lang.c] Style for handling matrices in C

alanm@cognos.UUCP (Alan Myrvold) (10/12/89)

There's been another (well deserved) round of bashing 
in comp.lang.c for the way "Numerical Recipes" dynamically 
allocates matrices.

It is kinda too bad that they picked such an ugly (and illegal)
way to handle matrices and vectors. I have their book (in FORTRAN) 
and find it a nice readable introduction to many numerical 
methods. Had they chosen a reasonable style, it might have become
commonplace.

So my question is, what C style SHOULD become commonplace for
allocating matrices :

1) Encapsulate size and data into a struct :
   typedef struct { int row,col; double **x; } matrix;

2) Allocate a matrix as a vector and do arithmetic in subscript
   calculations (like Fortran, but the C compiler probably
   won't optimize the loops as well as Fortran).
 
   typedef double *matrix;
   x = malloc(row*col*sizeof(double));
   x[j*row+i] = 3.0;

3) K&R style 2-d matrices -- number of rows required to free matrix
   typedef double **matrix;

   matrix mat_alloc(row,col)
   int row,col;
   {
      matrix x;

      x = (double **) malloc(row*sizeof(double *));
      for (i = 0; i < row; i++) 
          x[i] = (double *) malloc(col*sizeof(double));
      return x;
   }

   void free_mat(x,row) 
   matrix x;
   int row;
   {
      for (i = row-1; i >= 0; i--) free(x[i]);
      free(x);
   }

4) 2-d matrices -- number of rows NOT required to free matrix
   typedef double **matrix;

   matrix mat_alloc(row,col)
   int row,col;
   {
      matrix x;

      x = (double **) malloc((row+1)*sizeof(double *));
      for (i = 0; i < row; i++) 
          x[i] = (double *) malloc(col*sizeof(double));
      x[row] = NULL;
      return x;
   }

   void free_mat(x) 
   matrix x;
   {
      matrix y;

      for (y = x; *y; y++) free(*y);
      free(x);
   }

5) Are there any other styles commonly used for 
   non-sparse matrices in C ???

---
Alan Myrvold          3755 Riverside Dr.     uunet!mitel!sce!cognos!alanm
Cognos Incorporated   P.O. Box 9707          alanm@cognos.uucp
(613) 738-1440 x5530  Ottawa, Ontario       
                      CANADA  K1G 3Z4       

dave@dsi.COM (Dave Rifkind) (10/16/89)

In article <7229@cognos.UUCP> alanm@cognos.UUCP (Alan Myrvold) writes:
>So my question is, what C style SHOULD become commonplace for
>allocating matrices....

Here's one that doesn't require any special action to free up the
matrix:

     double **mat_alloc(row, col)
     {
	  int i;
	  double *dp, **dpp;

	  dpp = malloc(row * sizeof(double *) + row * col * sizeof(double));
	  if (dpp != NULL) {
	       dp = dpp + row;
	       for (i = 0; i < row; i++)
		    dpp[i] = dp + i * col;
	  }
	  return dpp;
     }

This is off the top of my head and may not make sense.  The idea is to
put the pointer array and all of the row arrays in a single allocated
block.  To get rid of it, you just free it.

harish@csl.ncsu.edu (Harish Hiriyannaiah) (10/17/89)

In article <278@dsi.COM> dave@dsi.UUCP (Dave Rifkind) writes:
-Here's one that doesn't require any special action to free up the
-matrix:
-
-     double **mat_alloc(row, col)
-     {
-	  int i;
-	  double *dp, **dpp;
-
-	  dpp = malloc(row * sizeof(double *) + row * col * sizeof(double));
-	  if (dpp != NULL) {
-	       dp = dpp + row;
-	       for (i = 0; i < row; i++)
-		    dpp[i] = dp + i * col;
-	  }
-	  return dpp;
-     }



	Here you are assuming that the pointers are word aligned, which
	can be pretty dangerous.....

	Consider, for example short pointers to floats. If we have 7 rows
	(or any odd number), then the allocated space for the first float
	will fall on a 16-bit boundary..... 

harish pu. hi.				harish@ecelet.ncsu.edu
					harish@ecebucolix.ncsu.edu