1 /*
2 * vec_h.c -- vec.h generator.
3 *
4 * Outputs a file containing vector macros for dimensions 2..maxdim,
5 * where maxdim is specified on the command line.
6 *
7 * Usage: vec_h <maxdim>
8 */
9
10 static const char *intro[] = {
11 " vec.h -- Vector macros for %2..d-1, and %d dimensions,",
12 " for any combination of C scalar types.",
13 "",
14 " Author: Don Hatch (hatch@hadron.org)",
15 " Last modified: Tue Apr 13 21:58:39 PDT 1999",
16 "",
17 " General description:",
18 "",
19 " The macro name describes its arguments; e.g.",
20 " MXS3 is \"matrix times scalar in 3 dimensions\";",
21 " VMV2 is \"vector minus vector in 2 dimensions\".",
22 "",
23 " If the result of an operation is a scalar, then the macro \"returns\"",
24 " the value; e.g.",
25 " result = DOT3(v,w);",
26 " result = DET4(m);",
27 "",
28 " If the result of an operation is a vector or matrix, then",
29 " the first argument is the destination; e.g.",
30 " SET2(tovec, fromvec);",
31 " MXM3(result, m1, m2);",
32 "",
33 " WARNING: For the operations that are not done \"componentwise\"",
34 " (e.g. vector cross products and matrix multiplies)",
35 " the destination should not be either of the arguments,",
36 " for obvious reasons. For example, the following is wrong:",
37 " VXM2(v,v,m);",
38 " For such \"unsafe\" macros, there are safe versions provided,",
39 " but you have to specify a type for the temporary",
40 " result vector or matrix. For example, the safe versions",
41 " of VXM2 are:",
42 " VXM2d(v,v,m) if v's scalar type is double or float",
43 " VXM2f(v,v,m) if v's scalar type is float",
44 " VXM2i(v,v,m) if v's scalar type is int or char",
45 " VXM2l(v,v,m) if v's scalar type is long",
46 " VXM2r(v,v,m) if v's scalar type is real",
47 " VXM2safe(type,v,v,m) for other scalar types.",
48 "",
49 " These \"safe\" macros and INVERTMAT do not evaluate to C expressions",
50 " (so, for example, they can't be used inside the parentheses of",
51 " a for(...)).",
52 "",
53 " Specific descriptions:",
54 "",
55 " The \"?\"'s in the following can be 2, 3, or 4.",
56 "",
57 " EXPAND?(v) comma-separated list of elements of v",
58 "",
59 " SET?(to,from) to = from",
60 " SETMAT?(to,from) to = from",
61 " ROUNDVEC?(to,from) to = from with entries rounded",
62 " to nearest integer",
63 " ROUNDMAT?(to,from) to = from with entries rounded",
64 " to nearest integer",
65 " FILLVEC?(v,s) set each entry of vector v to be s",
66 " FILLMAT?(m,s) set each entry of matrix m to be s",
67 " ZEROVEC?(v) v = 0",
68 " ISZEROVEC?(v) v == 0",
69 " EQVEC?(v,w) v == w",
70 " EQMAT?(m1,m2) m1 == m2",
71 " ZEROMAT?(m) m = 0",
72 " IDENTMAT?(m) m = 1",
73 " TRANSPOSE?(to,from) (matrix to) = (transpose of matrix from)",
74 " ADJOINT?(to,from) (matrix to) = (adjoint of matrix from)",
75 " i.e. its determinant times its inverse",
76 " INVERTMAT?{d,f,i,l,r}(to,from) (matrix to) = (inverse of matrix from)",
77 " with temp adjoint and determinant type",
78 " double, float, int, long, or real respectively",
79 "",
80 " V{P,M}V?(to,v,w) to = v {+,-} w",
81 " M{P,M}M?(to,m1,m2) to = m1 {+,-} m2",
82 " SX{V,M}?(to,s,from) to = s * from",
83 " VPSXV?(to,v,s,w) to = v + s*w",
84 " VPVXS?(to,v,w,s) to = v + w*s",
85 " M{V,M}?(to,from) to = -from",
86 " {V,M}{X,D}S?(to,from,s) to = from {*,/} s",
87 " MXM?(to,m1,m2) to = m1 * m2",
88 " VXM?(to,v,m) (row vec to) = (row vec v) * m",
89 " MXV?(to,m,v) (column vec to) = m * (column vec v)",
90 " VMODS?(to,v,s) to = v mod s (always >= 0)",
91 " VMODV?(to,v0,v1) to = v0 mod v1 componentwise",
92 " VDIVS?(to,v,s) to = (v-(v mod s))/s",
93 " VDIVV?(to,v0,v1) to = (v0-(v0 mod v1))/v1 componentwise",
94 " V{MIN,MAX}S?(to,v,s) to = {MIN,MAX}(v, s)",
95 " V{MIN,MAX}V?(to,v0,v1) to = {MIN,MAX}(v0, v1)",
96 " LERP?(to,v0,v1,t) to = v0 + t*(v1-v0)",
97 "",
98 " DET?(m) determinant of m",
99 " TRACE?(m) trace (sum of diagonal entries) of m",
100 " DOT?(v,w) dot (scalar) product of v and w",
101 " NORMSQRD?(v) square of |v|",
102 " DISTSQRD?(v,w) square of |v-w|",
103 "",
104 " XV2(to,v) to = v rotated by 90 degrees",
105 " VXV3(to,v1,v2) to = cross (vector) product of v1 and v2",
106 " VXVXV4(to,v1,v2,v3) to = 4-dimensional vector cross product",
107 " of v1,v2,v3 (a vector orthogonal to",
108 " v1,v2,v3 whose length equals the",
109 " volume of the spanned parallelotope)",
110 " VXV2(v0,v1) determinant of matrix with rows v0,v1",
111 " VXVXV3(v0,v1,v2) determinant of matrix with rows v0,v1,v2",
112 " VXVXVXV4(v0,v1,v2,v3) determinant of matrix with rows v0,..,v3",
113 "",
114 " The following macros mix objects from different dimensions.",
115 " For example, V3XM4 would be used to apply a composite",
116 " 4x4 rotation-and-translation matrix to a 3d vector.",
117 "",
118 " SET3from2(to,from,pad) (3d vec to) = (2d vec from) with pad",
119 " SET4from3(to,from,pad) (4d vec to) = (3d vec from) with pad",
120 " SETMAT3from2(to,from,pad0,pad1) (3x3 mat to) = (2x2 mat from)",
121 " padded with pad0 on the sides",
122 " and pad1 in the corner",
123 " SETMAT4from3(to,from,pad0,pad1) (4x4 mat to) = (3x3 mat from)",
124 " padded with pad0 on the sides",
125 " and pad1 in the corner",
126 " V2XM3(to2,v2,m3) (2d row vec to2) = (2d row vec v2) * (3x3 mat m3)",
127 " V3XM4(to3,v3,m4) (3d row vec to3) = (3d row vec v2) * (4x4 mat m4)",
128 " M3XV2(to2,m3,v2) (2d col vec to2) = (3x3 mat m3) * (2d col vec v2)",
129 " M4XV3(to3,m4,v3) (3d col vec to3) = (4x4 mat m4) * (3d col vec v3)",
130 " M2XM3(to3,m2,m3) (3x3 mat to3) = (2x2 mat m2) * (3x3 mat m3)",
131 " M3XM4(to4,m3,m4) (4x4 mat to4) = (3x3 mat m3) * (4x4 mat m4)",
132 " M3XM2(to3,m3,m2) (3x3 mat to3) = (3x3 mat m3) * (2x2 mat m2)",
133 " M4XM3(to4,m4,m3) (4x4 mat to4) = (4x4 mat m4) * (3x3 mat m3)",
134 "",
135 "",
136 " This file is machine-generated and can be regenerated",
137 " for any number of dimensions.",
138 " The program that generated it is available upon request.",
139 0
140 };
141
142 static struct {
143 const char *abbr, *full;
144 } types[] = {
145 {"d", "double"},
146 {"f", "float"},
147 {"i", "int"},
148 {"l", "long"},
149 {"r", "real"},
150 };
151
152 static struct definition {
153 int safety; /* 0 means already safe, i.e. returns a scalar or is done
154 "componentwise". 1 means unsafe and returns a vector.
155 2 means unsafe and returns a matrix. */
156 const char *name_and_args, *all_but_last, *sep, *last;
157 } defs[] = {
158 {0, "SET%d(to,from)", "(to)[%i] = (from)[%i]", ","},
159 {0, "SETMAT%d(to,from)", "SET%d((to)[%i], (from)[%i])", ","},
160 {0, "ROUNDVEC%d(to,from)","(to)[%i] = (int)floor((from)[%i]+.5)", ","},
161 {0, "ROUNDMAT%d(to,from)","ROUNDVEC%d((to)[%i], (from)[%i])", ","},
162 {0, "FILLVEC%d(v,s)", "(v)[%i] = (s)", ","},
163 {0, "FILLMAT%d(m,s)", "FILLVEC%d((m)[%i], s)", ","},
164 {0, "ZEROVEC%d(v)", "(v)[%i] = 0", ","},
165 {0, "ISZEROVEC%d(v)", "(v)[%i] == 0", " &&"},
166 {0, "EQVEC%d(v,w)", "(v)[%i] == (w)[%i]", " &&"},
167 {0, "EQMAT%d(m1,m2)", "EQVEC%d((m1)[%i], (m2)[%i])", " &&"},
168 {0, "ZEROMAT%d(m)", "ZEROVEC%d((m)[%i])", ","},
169 {0, "IDENTMAT%d(m)", "ZEROVEC%d((m)[%i]), (m)[%i][%i]=1", ","},
170 {2, "TRANSPOSE%d(to,from)", "_SETcol%d((to)[%i], from, %i)", ","},
171 {0, "VPSXV%d(to,v,s,w)", "(to)[%i] = (v)[%i] + (s) * (w)[%i]", ","},
172 {0, "VPVXS%d(to,v,w,s)", "(to)[%i] = (v)[%i] + (w)[%i] * (s)", ","},
173 {0, "VPV%d(to,v,w)", "(to)[%i] = (v)[%i] + (w)[%i]", ","},
174 {0, "VMV%d(to,v,w)", "(to)[%i] = (v)[%i] - (w)[%i]", ","},
175 {0, "MPM%d(to,m1,m2)", "VPV%d((to)[%i], (m1)[%i], (m2)[%i])", ","},
176 {0, "MMM%d(to,m1,m2)", "VMV%d((to)[%i], (m1)[%i], (m2)[%i])", ","},
177 {0, "SXV%d(to,s,from)", "(to)[%i] = (s) * (from)[%i]", ","},
178 {0, "SXM%d(to,s,from)", "SXV%d((to)[%i], s, (from)[%i])", ","},
179 {0, "MV%d(to,from)", "(to)[%i] = -(from)[%i]", ","},
180 {0, "MM%d(to,from)", "MV%d((to)[%i], (from)[%i])", ","},
181 {0, "VXS%d(to,from,s)", "(to)[%i] = (from)[%i] * (s)", ","},
182 {0, "VDS%d(to,from,s)", "(to)[%i] = (from)[%i] / (s)", ","},
183 {0, "MXS%d(to,from,s)", "VXS%d((to)[%i], (from)[%i], s)", ","},
184 {0, "MDS%d(to,from,s)", "VDS%d((to)[%i], (from)[%i], s)", ","},
185 {2, "MXM%d(to,m1,m2)", "VXM%d((to)[%i], (m1)[%i], m2)", ","},
186 {1, "VXM%d(to,v,m)", "(to)[%i] = _DOTcol%d(v, m, %i)", ","},
187 {1, "MXV%d(to,m,v)", "(to)[%i] = DOT%d((m)[%i], v)", ","},
188 {0, "VMODS%d(to,v,s)", "(to)[%i] = SMODS1((v)[%i], s)", ","},
189 {0, "VMODV%d(to,v0,v1)", "(to)[%i] = SMODS1((v0)[%i], (v1)[%i])", ","},
190 {0, "VDIVS%d(to,v,s)", "(to)[%i] = SDIVS1((v)[%i], s)", ","},
191 {0, "VDIVV%d(to,v0,v1)", "(to)[%i] = SDIVS1((v0)[%i], (v1)[%i])", ","},
192 {0, "VMINS%d(to,v,s)", "(to)[%i] = SMINS1((v)[%i], s)", ","},
193 {0, "VMINV%d(to,v0,v1)", "(to)[%i] = SMINS1((v0)[%i], (v1)[%i])", ","},
194 {0, "VMAXS%d(to,v,s)", "(to)[%i] = SMAXS1((v)[%i], s)", ","},
195 {0, "VMAXV%d(to,v0,v1)", "(to)[%i] = SMAXS1((v0)[%i], (v1)[%i])", ","},
196 {0, "LERP%d(to,v0,v1,t)", "(to)[%i]=(v0)[%i]+(t)*((v1)[%i]-(v0)[%i])", ","},
197 {0, "TRACE%d(m)", "(m)[%i][%i]", " +"},
198 {0, "DOT%d(v,w)", "(v)[%i] * (w)[%i]", " +"},
199 {0, "NORMSQRD%d(v)", "(v)[%i] * (v)[%i]", " +"},
200 {0, "DISTSQRD%d(v,w)", "((v)[%i]-(w)[%i])*((v)[%i]-(w)[%i])", " +"},
201 {0, "_DOTcol%d(v,m,j)", "(v)[%i] * (m)[%i][j]", " +"},
202 /* following two aren't really "safe", but shouldn't be used anyway */
203 {0, "_SETcol%d(v,m,j)", "(v)[%i] = (m)[%i][j]", ","},
204 {0, "_MXVcol%d(to,m,M,j)","(to)[%i][j] = _DOTcol%d((m)[%i],M,j)", ","},
205 {0, "_DET%d(v%0..d-1,i%0..d-1)","(v0)[i%i]*%-_DET%d-1(v%1..d-1,i%~i)"," +"},
206 {1, "%XV%d(to,v%1..d-1)", "(to)[%i] = %-%-_DET%d-1(v%1..d-1, %~i)",","},
207 /* careful! don't use v%0..d-1 for the above or the hack utility routines
208 for making "safe" macros won't be able to find the first arg. */
209
210 /*
211 * dimension-mixing macros for which d (= the dimension of the destination)
212 * is the larger of the two dimensions. This is deduced from
213 * the fact that the macro name contains %d-1.
214 */
215 {0, "SET%dfrom%d-1(to,from,pad)", "(to)[%i] = (from)[%i]", ",",
216 "(to)[%i] = (pad)"},
217 {0, "SETMAT%dfrom%d-1(to,from,pad0,pad1)",
218 "SET%dfrom%d-1((to)[%i], (from)[%i], pad0)", ",",
219 "FILLVEC%d-1((to)[%i], (pad0)), (to)[%i][%i] = (pad1)"},
220 {2, "M%d-1XM%d(to%d,m%d-1,m%d)",
221 "_MXVcol%d-1(to%d,m%d-1,m%d,%i), (to%d)[%d-1][%i]=(m%d)[%d-1][%i]", ","},
222 {2, "M%dXM%d-1(to%d,m%d,m%d-1)",
223 "VXM%d-1((to%d)[%i],(m%d)[%i],m%d-1), (to%d)[%i][%d-1]=(m%d)[%i][%d-1]", ","},
224
225 /*
226 * dimension-mixing macros for which d (= the dimension of the destination)
227 * is the smaller of the two dimensions. This is deduced from
228 * the fact that the macro name contains %d+1.
229 */
230 {1, "V%dXM%d+1(to%d,v%d,m%d+1)",
231 "(to%d)[%i] = _DOTcol%d(v%d,m%d+1,%i) + (m%d+1)[%d][%i]", ","},
232 {1, "M%d+1XV%d(to%d,m%d+1,v%d)",
233 "(to%d)[%i] = DOT%d((m%d+1)[%i],v%d) + (m%d+1)[%i][%d]", ","},
234
235 /*
236 * definitions that don't get vector-expanded.
237 * This is deduced from the fact that the "sep" field is empty.
238 */
239 {0, "_DET1(v0,i0)", "(v0)[i0]"},
240 {0, "%VXV%d(v%0..d-1)", "_DET%d(v%0..d-1,%0..d-1)"},
241 {0, "DET%d(m)", "%VXV%d((m)[%0..d-1])"},
242 {0, "SMODS1(a,b)", "(((a)%%(b)+(b))%%(b))"},
243 {0, "SDIVS1(a,b)", "(((a)-SMODS1(a,b))/(b))"},
244 {0, "SMINS1(a,b)", "((a) < (b) ? (a) : (b))"},
245 {0, "SMAXS1(a,b)", "((a) > (b) ? (a) : (b))"},
246
247 /*
248 * New adjoint stuff.
249 */
250 {2, "ADJOINT%d(to,m)", "%__ADJOINTcol%d(to,%i,m,%~i)", ","},
251 {0, "_ADJOINTcol%d(to,col,m,i%1..d-1)",
252 "(to)[%i][col] = %-_DET%d-1((m)[i%1..d-1], %~i)", ","},
253 {0, "__ADJOINTcol%d(to,col,m,i%1..d-1)",
254 "(to)[%i][col] = %--_DET%d-1((m)[i%1..d-1], %~i)", ","},
255 /*
256 * Inverse-- completely special case, defined in terms of adjoint and det
257 */
258 {2, "INVERTMAT%d(to,from)"}
259 };
260
261 #include <stdio.h>
262 #include <stdlib.h>
263 #include <assert.h>
264 #include <ctype.h>
265 #include <string.h>
266 #define MIN(a,b) ((a)<(b)?(a):(b))
267 #define MAX(a,b) ((a)>(b)?(a):(b))
268 #define numberof(sextoys) (sizeof(sextoys) / sizeof(*(sextoys)))
269
isprefix(const char * pre,const char * s)270 static int isprefix(const char *pre, const char *s)
271 {
272 return strncmp(pre, s, strlen(pre)) == 0;
273 }
274
275 /*
276 * s is pointing to the last char of the prefix;
277 * to a space, ',' or a '(', taking into account nesting parens
278 */
getprefix(const char * s)279 static const char *getprefix(const char *s)
280 {
281 static char buf[100];
282 char *bufptr = buf + sizeof(buf);
283 int i, nest = 0;
284 *--bufptr = 0;
285 for (i = 0; nest || !strchr(" ,(", s[i]); --i) {
286 nest += (s[i] == ')') - (s[i] == '(');
287 *--bufptr = s[i];
288 }
289 return bufptr;
290 }
291
292 /*
293 * s is pointing to the beginning of the suffix;
294 * get the suffix up to but not including a space, ',' or ')'.
295 */
getsuffix(const char * s)296 static const char *getsuffix(const char *s)
297 {
298 static char buf[100];
299 int i;
300 for (i = 0; !strchr(" ,)", s[i]); ++i)
301 buf[i] = s[i];
302 buf[i] = 0;
303 return buf;
304 }
305
306 /*
307 * Print the string s with the following substitutions:
308 * %d turns into d
309 * %i turns into i
310 * %- turns into "-" if i is odd, " " otherwise
311 * %-- turns into "-" if i is even, " " otherwise
312 * %_ turns into "_" if i is odd, " " otherwise
313 * %-%- turns into "-" if d+i is even, " " otherwise (sorry this is stupid)
314 * %i+1 turns into (i+1)%d etc.
315 * %d-1 turns into d-1 etc.
316 * %% turns into %
317 * blah%0..d-1bleh turns into blah0bleh,blah1bleh,...,blahd-1bleh
318 * blah%~ibleh is same as blah%0..d-1bleh but excluding i
319 * %XV turns into VXVX...XV with d-1 V's (or XV if d==2)
320 * %VXV turns into VXVX...XV with d V's
321 */
printformatted_to(const char * s,const char * tochars,int d,int i)322 static void printformatted_to(const char *s, const char *tochars, int d, int i)
323 {
324 const char *prefix, *suffix;
325 int num, j, lastj;
326
327 for (; *s && !strchr(tochars, *s); s++) {
328 if (*s == '%') {
329 ++s;
330
331 prefix = NULL;
332 if (isdigit(*s) && !strncmp(s+1, "..d-1", 5)) {
333 prefix = getprefix(s-2); /* one char before the % */
334 suffix = getsuffix(s+6);
335 } else if (!strncmp(s, "~i", 2)) {
336 prefix = getprefix(s-2); /* one char before the % */
337 suffix = getsuffix(s+2);
338 }
339 if (prefix) {
340 lastj = d-1 - (*s == '~');
341 for (j = atoi(s); j <= lastj; ++j) {
342 printf("%d", j + (*s == '~' && j >= i));
343 printf("%s", suffix);
344 if (j < lastj)
345 printf(",%s", prefix);
346 }
347 s += (*s == '~' ? 2 : 6) + strlen(suffix) - 1;
348 } else {
349 switch(*s) {
350 case '-': case '_':
351 if (!strncmp(s, "-%-", 3)) {
352 printf("%c", (i+d)%2==0 ? *s : ' ');
353 s += 2;
354 } else if (!strncmp(s, "--", 2)) {
355 printf("%c", i%2==0 ? *s : ' ');
356 s++;
357 } else {
358 printf("%c", i%2==1 ? *s : ' ');
359 }
360 break;
361 case 'i': case 'd':
362 num = (*s == 'i' ? i : d);
363 if (strchr("+-", s[1])) {
364 num += (s[1] == '-' ? -1 : 1) * atoi(s+2);
365 if (*s == 'i')
366 num = (num+d) % d;
367 s += 2;
368 /* s is now pointing to the first digit */
369 while (isdigit(s[1]))
370 s++;
371 /* s is now pointing to the last digit */
372 }
373 printf("%d", num);
374 break;
375 case 'X': case 'V':
376 if (*s == 'X' && d == 2)
377 printf("X");
378 for (j = 0; j < d-2; ++j)
379 printf("VX");
380 if (*s == 'V')
381 printf("V");
382 break;
383 case '%':
384 printf("%%");
385 break;
386 default:
387 assert(0);
388 }
389 }
390 } else
391 putchar(*s);
392 }
393 }
394
printformatted(const char * s,int d,int i)395 static void printformatted(const char *s, int d, int i)
396 {
397 printformatted_to(s, "", d, i);
398 }
399
define(int d,const char * name_and_args,const char * all_but_last,const char * sep,const char * last)400 static void define(int d, const char *name_and_args, const char *all_but_last, const char *sep, const char *last)
401 {
402 int i;
403
404 printf("#define ");
405 printformatted(name_and_args, d, 0);
406 printf("\t\\\n\t\t");
407 printf("(");
408
409 if (sep)
410 for (i = 0; i < d-1; ++i) { /* loop for all but last */
411 printformatted(all_but_last, d, i);
412 printformatted(sep, d, i);
413 printf(" \\\n\t\t ");
414 }
415 printformatted(last, d, i);
416
417 printf(")\n");
418 }
419
is_substring(const char * a,const char * b)420 static int is_substring(const char *a, const char *b)
421 {
422 for (; *b; b++)
423 if (strncmp(a, b, strlen(a)) == 0)
424 return 1;
425 return 0;
426 }
427
428
429 /*
430 * Hack utility routines...
431 */
print_name_and_args_with_stuff_inserted(const char * name_and_arg,const char * suff,const char * arg0,int d)432 static void print_name_and_args_with_stuff_inserted(const char *name_and_arg, const char *suff, const char *arg0, int d)
433 {
434 printformatted_to(name_and_arg, "(", d, 0);
435 printformatted(suff, d, 0);
436 printf("(");
437 if (arg0) {
438 printformatted(arg0, d, 0);
439 printf(",");
440 }
441 printformatted(strchr(name_and_arg, '(' /*)*/ ) + 1, d, 0);
442 }
443
print_name_and_args_with_first_arg_changed(const char * name_and_arg,const char * arg0,int d)444 static void print_name_and_args_with_first_arg_changed(const char *name_and_arg, const char *arg0, int d)
445 {
446 printformatted_to(name_and_arg, "(", d, 0);
447 printf("(");
448 printformatted(arg0, d, 0);
449 printformatted(strchr(name_and_arg, ','), d, 0);
450 }
451
print_first_arg(const char * name_and_arg,int d)452 static void print_first_arg(const char *name_and_arg, int d)
453 {
454 printformatted_to(strchr(name_and_arg, '(' /*)*/ ) + 1, ",)", d, 0);
455 }
456
print_second_arg(const char * name_and_arg,int d)457 static void print_second_arg(const char *name_and_arg, int d)
458 {
459 printformatted_to(strchr(name_and_arg, ',') + 1, ",)", d, 0);
460 }
461
462
463 #define MINDIM 2
464
main(int argc,char ** argv)465 main(int argc, char **argv)
466 {
467 int i, d, maxdim;
468
469 if (argc != 2 || ! (maxdim = atoi(argv[argc-1])))
470 fprintf(stderr, "Usage: %s [<maxdim>]\n", argv[0]), exit(1);
471
472
473 printf("/*\n");
474 for (i = 0; intro[i]; ++i) {
475 printf(" *");
476 printformatted(intro[i], maxdim, 0);
477 printf("\n");
478 }
479 printf(" */\n\n");
480
481 printf("#ifndef VEC_H\n");
482 printf("#define VEC_H %d\n", maxdim);
483 printf("\n");
484 printf("#undef TRACE2\n");
485 printf("#undef TRACE3\n");
486 printf("\n");
487 printf("#include <math.h> /* for definition of floor() */\n");
488 printf("\n");
489
490 for (d = MINDIM; d <= maxdim; ++d) {
491 printf("#define EXPAND%d(v) ", d);
492 for (i = 0; i < d; ++i)
493 printf("%s(v)[%d]", i==0 ? "" : ", ", i);
494 printf("\n");
495 }
496 for (d = MINDIM; d <= maxdim; ++d)
497 for (i = 0; i < numberof(defs); ++i) {
498 if (is_substring("%d-1", defs[i].name_and_args) && d-1 < MINDIM
499 || is_substring("%d+1", defs[i].name_and_args) && d+1 > maxdim)
500 continue;
501 if (!is_substring("%d", defs[i].name_and_args) && d != MINDIM)
502 continue; /* don't redefine if it's the same */
503 if (!defs[i].all_but_last)
504 continue; /* no definition here */
505 define(d, defs[i].name_and_args,
506 defs[i].all_but_last,
507 defs[i].sep,
508 defs[i].last ? defs[i].last : defs[i].all_but_last);
509 }
510 for (d = MINDIM; d <= maxdim; ++d)
511 for (i = 0; i < numberof(defs); ++i) {
512 if (is_substring("%d-1", defs[i].name_and_args) && d-1 < MINDIM
513 || is_substring("%d+1", defs[i].name_and_args) && d+1 > maxdim)
514 continue;
515 if (!is_substring("%d", defs[i].name_and_args) && d != MINDIM)
516 continue; /* don't redefine if it's the same */
517 if (defs[i].safety > 0) {
518 int t;
519 printf("#define ");
520 print_name_and_args_with_stuff_inserted(defs[i].name_and_args,
521 "safe", "type", d);
522 printf(" \\\n\t\t");
523 printformatted("do {type _vec_h_temp_[%d]", d, 0);
524 if (defs[i].safety > 1)
525 printformatted("[%d]", d, 0);
526 printf("; \\\n\t\t ");
527
528 if (isprefix("INVERTMAT", defs[i].name_and_args)) {
529 printf("type _vec_h_temp_invdet_;\\\n\t\t ");
530 printformatted("ADJOINT%d(_vec_h_temp_, ", d, 0);
531 print_second_arg(defs[i].name_and_args, d);
532 printf("); \\\n\t\t ");
533 printformatted("_vec_h_temp_invdet_ = (type)1/(type)DET%d(from); \\\n\t\t ", d, 0);
534 printformatted("SXM%d(", d, 0);
535 print_first_arg(defs[i].name_and_args, d);
536 printf(", _vec_h_temp_invdet_");
537 } else {
538 print_name_and_args_with_first_arg_changed(
539 defs[i].name_and_args, "_vec_h_temp_", d);
540 printf("; \\\n\t\t ");
541
542 if (defs[i].safety > 1)
543 printformatted("SETMAT%d(", d, 0);
544 else
545 printformatted("SET%d(", d, 0);
546 print_first_arg(defs[i].name_and_args, d);
547 }
548 printf(", _vec_h_temp_); \\\n\t\t} while (0)\n");
549
550 for (t = 0; t < numberof(types); ++t) {
551 printf("#define ");
552 print_name_and_args_with_stuff_inserted(
553 defs[i].name_and_args, types[t].abbr, (char *)NULL, d);
554 printf(" ");
555 print_name_and_args_with_stuff_inserted(
556 defs[i].name_and_args, "safe", types[t].full, d);
557 printf("\n");
558 }
559 }
560 }
561 printf("#endif /* VEC_H */\n");
562
563 return 0;
564 }
565
566