depmaker
[tridge/junkcode.git] / any_matrix.c
1 #include <stdio.h>
2 #include <malloc.h>
3 #include <stdarg.h>
4
5 /*******************************************************************
6 create a matrix of any dimension. The return must be cast correctly.
7 ********************************************************************/
8 void *any_matrix(int dimension, int el_size, ...)
9 {
10         int *dims=NULL;
11         void **mat;
12         int i,j,size,ptr_size,ppos,prod;
13         int padding;
14         void *next_ptr;
15         va_list ap;
16         
17         if (dimension <= 0) return(NULL);
18         if (el_size <= 0) return(NULL);
19         
20         dims = (int *)malloc(dimension * sizeof(int));
21         if (dims == NULL) return(NULL);
22
23         /* gather the arguments */
24         va_start(ap, el_size);
25         for (i=0;i<dimension;i++) {
26                 dims[i] = va_arg(ap, int);
27         }
28         va_end(ap);
29         
30         /* now we've disected the arguments we can go about the real
31            business of creating the matrix */
32         
33         /* calculate how much space all the pointers will take up */
34         ptr_size = 0;
35         for (i=0;i<(dimension-1);i++) {
36                 prod=sizeof(void *);
37                 for (j=0;j<=i;j++) prod *= dims[j];
38                 ptr_size += prod;
39         }
40
41         /* padding overcomes potential alignment errors */
42         padding = (el_size - (ptr_size % el_size)) % el_size;
43         
44         /* now calculate the total memory taken by the array */
45         prod=el_size;
46         for (i=0;i<dimension;i++) prod *= dims[i];
47         size = prod + ptr_size + padding;
48
49         /* allocate the matrix memory */
50         mat = (void **)malloc(size);
51
52         if (mat == NULL) {
53                 fprintf(stdout,"Error allocating %d dim matrix of size %d\n",dimension,size);
54                 free(dims);
55                 return(NULL);
56         }
57
58         /* now fill in the pointer values */
59         next_ptr = (void *)&mat[dims[0]];
60         ppos = 0;
61         prod = 1;
62         for (i=0;i<(dimension-1);i++) {
63                 int skip;
64                 if (i == dimension-2) {
65                         skip = el_size*dims[i+1];
66                         next_ptr = (void *)(((char *)next_ptr) + padding); /* add in the padding */
67                 } else {
68                         skip = sizeof(void *)*dims[i+1];
69                 }
70
71                 for (j=0;j<(dims[i]*prod);j++) {
72                         mat[ppos++] = next_ptr;
73                         next_ptr = (void *)(((char *)next_ptr) + skip);
74                 }
75                 prod *= dims[i];
76         }
77
78         free(dims);
79         return((void *)mat);
80 }
81
82
83
84
85 /*
86   double ****x;
87   double ***y;
88
89   x = (double ****)any_matrix(4, sizeof(double), 3, 6, 8, 2);
90
91   x[0][3][4][1] = 5.0;
92
93   y = x[1];
94
95   y[2][3][4] = 7.0;
96
97   free(x);
98 */