n62@nikhefh.hep.nl (Klamer Schutte) (01/20/88)
>Spencer@ogg.cgrg.ohio-state.edu (PROCEED) writes: >>Maybe this can't be done. Maybe I'm not thinking about it the right way. >>But I can't figure out how to dynamically allocate a two-dimensional >>array of floats. (I have to have an N by N matrix of floats, but don't >>know N beforehand.) Can anyone help me on this one? Thanks. and as a proposed solution: >#define malloc_matrix(p,n,m,t) ((p) = ((t) *) malloc((n)*(m)*sizeof(t))) >#define matrix(p,n,m,x,y) ((p)[(n)*(x)+(y)]) Why not simple something like this: struct matrix { float data[n][m]; } *foo; ... foo = ( struct matrix * )malloc( sizeof( struct matrix )); and accessing the data like: foo->data[n][m]; In this way the source code will reflect ecxactly how the data is accessed; I think C programming should be done that way.
chris@mimsy.UUCP (Chris Torek) (01/21/88)
[These attributions look vaguely suspicious, but are as they were in the parent article (do I *really* need to put in such disclaimers?)] >>Spencer@ogg.cgrg.ohio-state.edu (PROCEED) writes: >>>... how to dynamically allocate a two-dimensional >>>array of floats. (I have to have an N by N matrix of floats, but don't >>>know N beforehand.) >>#define malloc_matrix(p,n,m,t) ((p) = ((t) *) malloc((n)*(m)*sizeof(t))) >>#define matrix(p,n,m,x,y) ((p)[(n)*(x)+(y)]) In article <419@nikhefh.hep.nl> n62@nikhefh.hep.nl (Klamer Schutte) writes: >Why not simple something like this: > >struct matrix >{ float data[n][m]; >} *foo; > >... > >foo = ( struct matrix * )malloc( sizeof( struct matrix )); > >and accessing the data like: > >foo->data[n][m]; Why not indeed. Have you tried it? 1 f() 2 { 3 int n, m; 4 struct matrix { 5 float data[n][m]; 6 } *foo; 7 } xx.c, line 5: constant expected xx.c, line 5: constant expected >In this way the source code will reflect exactly how the data is accessed; >I think C programming should be done that way. As much as possible, certainly. But arrays must have all but the first dimension declared as a compile-time constant. The various previous solutions (which include vectors of vectors) will work. Incidentally, one solution I did not see is this: typedef float data_t; /* whatever we are storing in matrices */ /* (please change `data' to reflect the actual stuff) */ /* * Create an N by N matrix of data type data_t. * Return NULL if it cannot be made. */ data_t ** create_matrix(n) int n; { register data_t *mem; register data_t **rows; register int i; mem = (data_t *)malloc(n * n * sizeof(*mem)); if (mem == NULL) return (NULL); rows = (data_t **)malloc(n * sizeof(*rows)); if (rows == NULL) { free((char *)mem); return (NULL); } for (i = 0; i < n; i++) { rows[i] = mem; mem += n; } return (rows); } /* * Free such a matrix. Note that we need not know N. */ void free_matrix(mat) data_t **mat; { free((char *)*mat); free((char *)mat); } How it works, and how to modify it for M by N matrices, and for matrices of higher dimensionality, is left as an exercise for the reader. ===== Exercises: 1. How *does* it work? 2. Modify it to create a four-dimensional matrix of size W by X by Y by Z. 3. Modify it to produce upper or lower triangular matrices, without using any more calls to malloc, and without wasting space (no `mem' elements left over). -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
ix426@sdcc6.ucsd.EDU (tom stockfish) (01/22/88)
In article <10278@mimsy.UUCP> chris@mimsy.UUCP (Chris Torek) writes: X X [code defining create_matrix() which returns "data_t **", a "matrix" of X the sort that "argv" is, and free_matrix() ] X X Exercises: X 1. How *does* it work? X 2. Modify it to create a four-dimensional matrix of size W by X by X Y by Z. X 3. Modify it to produce upper or lower triangular matrices, without X using any more calls to malloc, and without wasting space (no X `mem' elements left over). 4. Modify it so that it uses only *one* malloc() call, the pointer it returns can be handed *directly* to free() (no "free_matrix()" routine needed), and a "true" matrix (or rather, pointer to the first element of it) can be easily obtained so it can be sent to a fortran routine (assuming the fortran routine can operate on the transpose). Oh yes, it must be portable, too. (Solution to follow at later date). 5. Prove that #4 cannot be done portably if the type of the matrix is not specified at compile time. -- || Tom Stockfisch, UCSD Chemistry tps@chem.ucsd.edu
blarson@skat.usc.edu (Bob Larson) (01/22/88)
In article <3590@sdcc6.ucsd.EDU> ix426@sdcc6.ucsd.edu.UUCP (tom stockfish) writes: >4. ... so it can be sent to a fortran routine ... >5. Prove that #4 cannot be done portably if the type of the matrix > is not specified at compile time. How many proofs do you want? A. I don't have fortran on my qt+, so calling fortran is unportable. (dito A for upteen machines where fortran is either unavailable or prohibitavly expensive.) B. Fortran calling in Prime C is completly different that that in 4.2 BSD C. (Dito B for upteen trillion combiniations of operating systems and compilers.) Why would I want to mess things up with a matrix in my proof? [Repeat after me: all the world is not a vax 780 running 4.1c BSD with no modifacations.] -- Bob Larson Arpa: Blarson@Ecla.Usc.Edu blarson@skat.usc.edu Uucp: {sdcrdcf,cit-vax}!oberon!skat!blarson Prime mailing list: info-prime-request%fns1@ecla.usc.edu oberon!fns1!info-prime-request