1 /****************************************************************\
2 *                                                                *
3 *  Simple matrix creation routines                               *
4 *                                                                *
5 *  Guy St.C. Slater..   mailto:guy@ebi.ac.uk                     *
6 *  Copyright (C) 2000-2009.  All Rights Reserved.                *
7 *                                                                *
8 *  This source code is distributed under the terms of the        *
9 *  GNU General Public License, version 3. See the file COPYING   *
10 *  or http://www.gnu.org/licenses/gpl.txt for details            *
11 *                                                                *
12 *  If you use this code, please keep this notice intact.         *
13 *                                                                *
14 \****************************************************************/
15 
16 #include "matrix.h"
17 
Matrix_layout(gpointer * index,gint length,gchar * data,gsize block)18 static void Matrix_layout(gpointer *index, gint length,
19                           gchar *data, gsize block){
20     register gint i;
21     register gchar *p;
22     g_assert(index);
23     g_assert(data);
24     g_assert(length > 0);
25     g_assert(block > 0);
26     for(i = 0, p = data; i < length; i++){
27         index[i] = p;
28         p += block;
29         }
30     return;
31     }
32 
33 /**/
34 
Matrix2d_size(gint a,gint b,gsize cell)35 gsize Matrix2d_size(gint a, gint b, gsize cell){
36     register gulong index_size = a * sizeof(gpointer),
37                     row_size = b * cell,
38                     data_size = a * row_size,
39                     total_size = index_size + data_size;
40     register gdouble check_index_size = a * sizeof(gpointer),
41                      check_row_size = b * cell,
42                      check_data_size = a * check_row_size,
43                      check_total_size = check_index_size
44                                       + check_data_size;
45     g_assert(a > 0);
46     g_assert(b > 0);
47     g_assert(cell > 0);
48     if((check_total_size - total_size) > 1) /* overflow */
49         return 0;
50     return total_size;
51     }
52 
Matrix2d_init(gchar ** m,gint a,gint b,gsize cell)53 void Matrix2d_init(gchar **m, gint a, gint b, gsize cell){
54     Matrix_layout((gpointer*)m, a, (gchar*)&m[a], b*cell);
55     return;
56     }
57 
Matrix2d_create(gint a,gint b,gsize cell)58 gpointer *Matrix2d_create(gint a, gint b, gsize cell){
59     register gchar **m;
60     register gulong index_size = a * sizeof(gpointer),
61                     row_size = b * cell,
62                     data_size = a * row_size;
63     g_assert(a > 0);
64     g_assert(b > 0);
65     g_assert(cell > 0);
66     g_assert(Matrix2d_size(a, b, cell));
67     m = g_malloc0(index_size + data_size);
68     Matrix_layout((gpointer*)m, a, (gchar*)&m[a], row_size);
69     return (gpointer*)m;
70     }
71 
72 /**/
73 
Matrix3d_size(gint a,gint b,gint c,gsize cell)74 gsize Matrix3d_size(gint a, gint b, gint c, gsize cell){
75     register gulong primary_index_size = a * sizeof(gpointer),
76                     secondary_index_size = b * sizeof(gpointer),
77                     row_size  = c * cell,
78                     block_size = secondary_index_size
79                                + (b * row_size),
80                     total_size;
81     register gdouble check_primary_index_size = a * sizeof(gpointer),
82                      check_secondary_index_size = b * sizeof(gpointer),
83                      check_row_size  = c * cell,
84                      check_block_size = check_secondary_index_size
85                                       + (b * check_row_size),
86                      check_total_size;
87     g_assert(a > 0);
88     g_assert(b > 0);
89     g_assert(c > 0);
90     g_assert(cell > 0);
91     block_size += (block_size % sizeof(gpointer)); /* Pad */
92     check_block_size += (block_size % sizeof(gpointer)); /* Pad */
93     total_size = primary_index_size + (a * block_size);
94     check_total_size = check_primary_index_size
95                      + (a * check_block_size);
96     if((check_total_size - total_size) > 1) /* overflow */
97         return 0;
98     return total_size;
99     }
100 
Matrix3d_create(gint a,gint b,gint c,gsize cell)101 gpointer **Matrix3d_create(gint a, gint b, gint c, gsize cell){
102     register gint i;
103     register gchar ***m;
104     register gulong primary_index_size = a * sizeof(gpointer),
105                     secondary_index_size = b * sizeof(gpointer),
106                     row_size  = c * cell,
107                     block_size = secondary_index_size
108                               + (b * row_size),
109                     total_size;
110 
111     g_assert(a > 0);
112     g_assert(b > 0);
113     g_assert(c > 0);
114     g_assert(cell > 0);
115     g_assert(Matrix3d_size(a, b, c, cell));
116     block_size += (block_size % sizeof(gpointer)); /* Pad */
117     total_size = primary_index_size + (a * block_size);
118     m = g_malloc0(total_size);
119     Matrix_layout((gpointer*)m, a, (gchar*)&m[a], block_size);
120     for(i = 0; i < a; i++)
121         Matrix_layout((gpointer*)m[i], b,
122                       (gchar*)m[i]+secondary_index_size, row_size);
123     return (gpointer**)m;
124     }
125 
126 /**/
127 
Matrix4d_size(gint a,gint b,gint c,gint d,gsize cell)128 gsize Matrix4d_size(gint a, gint b, gint c, gint d, gsize cell){
129     register gulong primary_index_size = a * sizeof(gpointer),
130                     secondary_index_size = b * sizeof(gpointer),
131                     tertiary_index_size = c * sizeof(gpointer),
132                     row_size  = d * cell,
133                     block_size = tertiary_index_size
134                                + (c * row_size),
135                     sheet_size, total_size;
136     register gdouble check_primary_index_size = a * sizeof(gpointer),
137                      check_secondary_index_size = b * sizeof(gpointer),
138                      check_tertiary_index_size = c * sizeof(gpointer),
139                      check_row_size  = d * cell,
140                      check_block_size = check_tertiary_index_size
141                                       + (c * check_row_size),
142                      check_sheet_size, check_total_size;
143     g_assert(a > 0);
144     g_assert(b > 0);
145     g_assert(c > 0);
146     g_assert(d > 0);
147     g_assert(cell > 0);
148     block_size += (block_size % sizeof(gpointer)); /* Pad */
149     check_block_size += (block_size % sizeof(gpointer)); /* Pad */
150     sheet_size = secondary_index_size + (b * block_size),
151     check_sheet_size = check_secondary_index_size
152                      + (b * check_block_size),
153     sheet_size += (sheet_size % sizeof(gpointer)); /* Pad */
154     check_sheet_size += (sheet_size % sizeof(gpointer)); /* Pad */
155     total_size = primary_index_size + (a * sheet_size);
156     check_total_size = check_primary_index_size
157                      + (a * check_sheet_size);
158     if((check_total_size - total_size) > 1) /* overflow */
159         return 0;
160     return total_size;
161     }
162 
Matrix4d_create(gint a,gint b,gint c,gint d,gsize cell)163 gpointer ***Matrix4d_create(gint a, gint b, gint c, gint d, gsize cell){
164     register gint i, j;
165     register gchar ***m;
166     register gpointer *ptr;
167     register gulong primary_index_size = a * sizeof(gpointer),
168                     secondary_index_size = b * sizeof(gpointer),
169                     tertiary_index_size = c * sizeof(gpointer),
170                     row_size  = d * cell,
171                     block_size = tertiary_index_size
172                                + (c * row_size),
173                     sheet_size, total_size;
174     g_assert(a > 0);
175     g_assert(b > 0);
176     g_assert(c > 0);
177     g_assert(d > 0);
178     g_assert(cell > 0);
179     g_assert(Matrix4d_size(a, b, c, d, cell));
180     block_size += (block_size % sizeof(gpointer)); /* Pad */
181     sheet_size = secondary_index_size + (b * block_size),
182     sheet_size += (sheet_size % sizeof(gpointer)); /* Pad */
183     total_size = primary_index_size + (a * sheet_size);
184     m = g_malloc0(total_size);
185     Matrix_layout((gpointer*)m, a, (gchar*)&m[a], sheet_size);
186     for(i = 0; i < a; i++){
187         ptr = (gpointer*)m[i];
188         Matrix_layout(ptr, b,
189                       (gchar*)ptr+secondary_index_size, block_size);
190         for(j = 0; j < b; j++){
191             Matrix_layout((gpointer*)ptr[j], c,
192                           (gchar*)ptr[j]+tertiary_index_size, row_size);
193             }
194         }
195     return (gpointer***)m;
196     }
197 
198 /* FIXME: tidy and reduce redundancy between create and size functions
199  */
200 
201