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