home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / lang / c / 19093 < prev    next >
Encoding:
Text File  |  1992-12-31  |  7.0 KB  |  202 lines

  1. Path: sparky!uunet!spool.mu.edu!uwm.edu!ogicse!news.u.washington.edu!carson.u.washington.edu!dfitts
  2. From: dfitts@carson.u.washington.edu (Douglas Fitts)
  3. Newsgroups: comp.lang.c
  4. Subject: Re: Accessing a dynamical 3-D field
  5. Summary: Functions for dynamic allocation with variable bounds
  6. Message-ID: <1hvm0kINN6l2@shelley.u.washington.edu>
  7. Date: 31 Dec 92 20:43:00 GMT
  8. Article-I.D.: shelley.1hvm0kINN6l2
  9. References: <1992Dec29.142134.25641@Informatik.TU-Muenchen.DE>
  10. Sender: dfitts@u.washington.edu <Doug Fitts>
  11. Distribution: world
  12. Organization: University of Washington, Seattle
  13. Lines: 186
  14. NNTP-Posting-Host: carson.u.washington.edu
  15.  
  16. In article <1992Dec29.142134.25641@Informatik.TU-Muenchen.DE> backscha@Informatik.TU-Muenchen.DE (Martin Backschat) writes:
  17. >
  18. >In my program I use 3-D fields of doubles with variable bounds.
  19. >This field is implemented as an array of doubles which is allocated
  20. >dynamically with malloc.
  21. >To access for example the [i][j][k] component in the field f of dimension U,V,W
  22. >I have to write   f[i*V*W + j*W + k].
  23. >
  24. >Now my question:
  25. >
  26. >Is it somehow possible to declare and allocate a 3-D field u (of doubles) with
  27. >variable bounds, allocated by malloc, in such a way that it can be accessed
  28. >with
  29. >u[i,j,k] (with type casting)?
  30.  
  31.  
  32. Yes, if u[i][j][k] will do instead of u[i,j,k].
  33.  
  34. Here are functions similar to ones I use to allocate and free 3-D 
  35. variably-dimensioned arrays in MS C7.  I've modified this, so there 
  36. may be bugs, but it runs with the main() here.  To be less portable 
  37. and more flexible, use the "_far" keyword and _fmalloc().  As the 
  38. comments say, first declare an appropriate pointer to serve as the base 
  39. of the array, then set it equal to the return value using a cast to the 
  40. type.  In your case this would be double, but it could be char, unsigned, 
  41. or long double - whatever.  
  42.  
  43. Access the array as buffer[1][2][0], etc.  As with any array in C, 
  44. be very careful not to overrun the length of any of these arrays - 
  45. always access using the same bounds values & arrays you pass to 
  46. this function.   Also, always immediately check for a NULL buffer 
  47. on return in case you've run out of memory in the segment 
  48. (or write these as _huge if your compiler supports it).   
  49.  
  50. Always free using the special function free3D().  You have to pass 
  51. the freeing function the address of buffer, not just buffer, because you 
  52. can't set the base pointer to NULL otherwise.  Note that the parens
  53. around (*a) are important.  The "if" statements are necessary in case
  54. the call to free3D() is coming from dim3D() with an incompletely
  55. populated array.  It's not necessary to pass array nfst, because the
  56. memory manager remembers how many of these there were (in the heap).  
  57.  
  58. E-mail me if you have any trouble.  Hope it's what you want.
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65. #include <malloc.h> /* _fcalloc(), calloc() */
  66. #include <stdio.h>    /* printf(), NULL */
  67. #include <stdlib.h> /* exit (), for main() only; ANSI calloc() */
  68.  
  69. /* function prototypes */
  70. int main( void );
  71. void  ***dim3D( int, int *, int *, size_t );
  72. void free3D( void ****, int, int * );
  73.  
  74. void ***dim3D( int slow, int *med, int *fast, size_t bytes )
  75. {
  76.     /* slow, dimension of slowest moving pointer */
  77.     /* med, array of intermediate pointers */
  78.     /* fast, array of fastest moving pointers */
  79.     /* bytes, size of data type for final array */
  80.     /* Function call example: */
  81.     /* double  ***buffer; */
  82.     /* int nslo, *nmed, *nfst; */ 
  83.     /* ...   allocate and fill arrays nmed and nfst */                                  
  84.     /* buffer = (double ***) dim3D( nslo, nmed, nfst, sizeof(double) ); */
  85.     /* if (buffer == NULL) { do_disaster_recovery(); } */
  86.     /* Free using free3D(). */
  87.     /* Always check for NULL return buffer - it's easy to chew up 64K! */
  88.  
  89.     void *** a;
  90.     register int i, j; 
  91.    
  92.     /* allocate space for an array of 'slow' pointers: */
  93.     a = (void ***)calloc( slow, sizeof(void **) );
  94.     if (a == NULL) { return(NULL); }   /* check after every allocation */
  95.     else
  96.         {
  97.         for (i = 0; i < slow; i++)  /* for each 'slow' pointer */
  98.             {
  99.             /* allocate space for an array of med void * values */
  100.             a[i] = (void **)calloc( med[i], sizeof(void *) );
  101.             if (a[i] == NULL)
  102.                 { 
  103.                 free3D( &a, slow, med ); 
  104.                 return(NULL); 
  105.                 }    
  106.             for (j = 0; j < med[i]; j++) /* for each med pointer */
  107.                 {
  108.                 a[i][j] = (void *)calloc( fast[j], bytes );
  109.                 if (a[i][j] == NULL)
  110.                     { 
  111.                     free3D( &a, slow, med ); 
  112.                     return(NULL); 
  113.                     }
  114.                 }
  115.             }
  116.         return(a);  /* return *** to void */
  117.         }
  118. }
  119.  
  120. void free3D(void **** a, int slow, int *med)
  121. {
  122.     /* Frees memory allocated by dim3D() */
  123.  
  124.     /* usage:
  125.         double *** buffer;
  126.         int nslo, *nmed, *nfst;  
  127.         ...    allocate and fill arrays nmed and nfst 
  128.         buffer = (double ***)dim3D( nslo, nmed, nfst, sizeof(double) );
  129.         free3D( &buffer, nslo, nmed ); 
  130.                 free( nmed );
  131.                 free( nfst );
  132.     */
  133.  
  134.     register int j, i;
  135.  
  136.     for(i = slow-1; i >= 0; i--)   /* starting with last row */
  137.         {
  138.         for (j = med[i]-1; j >= 0; j--)
  139.             {
  140.             if ((*a)[i][j]) free ((*a)[i][j]);  /* free array */
  141.             (*a)[i][j] = NULL; /* & set to NULL until all freed. */
  142.             }
  143.         if ((*a)[i]) free ((*a)[i]);
  144.         (*a)[i] = NULL;
  145.         }
  146.     if (*a) free (*a);                /* free the pointer to pointer */
  147.     *a = NULL;
  148. }
  149.  
  150. int main( void )
  151. {
  152.     /* sample driver program */
  153.     double *** buffer;
  154.     int nslo, *nmed, *nfst;
  155.     register int i, j, k;
  156.     
  157.     /* You fill in these arbitrary assignments at run-time: */
  158.     nslo = 2;   /* arbitrary assignment number of levels */
  159.     nmed = (int *)calloc( nslo, sizeof(int) );
  160.     nmed[0] = 3; /* arbitrary assignment number of levels */
  161.     nmed[1] = 2; /* arbitrary assignment number of levels */
  162.     nfst = (int *)calloc( (3+2), sizeof(int) );
  163.     nfst[0] = 4; /* arbitrary assignment number of levels */
  164.     nfst[1] = 2; /* arbitrary assignment number of levels */
  165.     nfst[2] = 3; /* arbitrary assignment number of levels */
  166.     nfst[3] = 4; /* arbitrary assignment number of levels */
  167.     nfst[4] = 3; /* arbitrary assignment number of levels */
  168.     
  169.     /* So, there are arbitrarily 2 levels of variable nslo,
  170.         3 and 2 levels of nmed at the two levels of nslo, and
  171.         4, 2, and 3 levels of nfst at the 3 levels of nmed[0], and
  172.         4 and 3 levels of nfst at the 2 levels of nmed[1].
  173.     */
  174.         
  175.     buffer = (double ***)dim3D( nslo, nmed, nfst, sizeof(double) );
  176.     if (buffer == NULL) exit (-1);
  177.     for (i = 0; i < nslo; i++)
  178.         for (j = 0; j < nmed[i]; j++)   /* notice nmed[i], not nmed[j] */
  179.             for (k = 0; k < nfst[j]; k++)  /* nfst[j], not nfst[k] */
  180.                 buffer[i][j][k] = (double)rand();  /* random double */ 
  181.     for (i = 0; i < nslo; i++)
  182.         {
  183.         printf("\n\nFactor nslo level %i\n", i);
  184.         for (j = 0; j < nmed[i]; j++)   /* notice nmed[i], not nmed[j] */
  185.             {
  186.             printf("\nFactor nmed level %i\n", j);
  187.             for (k = 0; k < nfst[j]; k++)  /* nfst[j], not nfst[k] */
  188.                 printf("%lf ", buffer[i][j][k]);    
  189.             }
  190.         }
  191.     free3D( (void ****)&buffer, nslo, nmed ); 
  192.     free( nmed );
  193.     free( nfst );
  194.     exit (0);
  195. }
  196.  
  197.  
  198.  
  199. Doug Fitts
  200. University of Washington, Seattle
  201. Internet: dfitts@u.washington.edu
  202.