initial setup of thesis repository
[cluster_expansion_thesis.git] / little_helpers / tikz / sketch-0.2.161 / expr.c
blob6d78c523ea02bf30681b7e8b3e70974a0dabe214
1 /* expr.c
2 Copyright (C) 2005,2006,2007,2008 Eugene K. Ressler, Jr.
4 This file is part of Sketch, a small, simple system for making
5 3d drawings with LaTeX and the PSTricks or TikZ package.
7 Sketch is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 Sketch is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with Sketch; see the file COPYING.txt. If not, see
19 http://www.gnu.org/copyleft */
21 #include <stdio.h>
22 #include <math.h>
23 #include "expr.h"
24 #include "error.h"
26 #define F "%.3f"
28 char *expr_val_type_str[] = {
29 "float",
30 "point",
31 "vector",
32 "transform",
35 // set expression value to given type and value
36 void
37 set_float (EXPR_VAL * r, FLOAT val)
39 r->tag = E_FLOAT;
40 r->val.flt = val;
43 void
44 print_float (FILE * f, EXPR_VAL * val)
46 fprintf (f, F, val->val.flt);
49 void
50 set_point (EXPR_VAL * r, POINT_3D val)
52 r->tag = E_POINT;
53 copy_pt_3d (r->val.pt, val);
56 void
57 print_point (FILE * f, EXPR_VAL * val)
59 FLOAT *p = val->val.pt;
60 fprintf (f, "(" F "," F "," F ")", p[X], p[Y], p[Z]);
63 void
64 set_vector (EXPR_VAL * r, VECTOR_3D val)
66 r->tag = E_VECTOR;
67 copy_vec_3d (r->val.vec, val);
70 void
71 print_vector (FILE * f, EXPR_VAL * val)
73 FLOAT *v = val->val.vec;
74 fprintf (f, "[" F "," F "," F "]", v[X], v[Y], v[Z]);
77 void
78 set_transform (EXPR_VAL * r, TRANSFORM val)
80 r->tag = E_TRANSFORM;
81 copy_transform (r->val.xf, val);
84 void
85 print_transform (FILE * f, EXPR_VAL * val)
87 FLOAT *xf = val->val.xf;
88 int i, j;
90 fprintf (f, "[");
91 for (i = 0; i < 4; i++)
93 fprintf (f, "[");
94 for (j = 0; j < 16; j += 4)
95 fprintf (f, "%s" F, (j == 0) ? "" : ",", xf[i + j]);
96 fprintf (f, "]");
98 fprintf (f, "]");
101 // coerce an expression value to given type
102 // generate error message if it can't be done
103 void
104 coerce_to_float (EXPR_VAL * r, FLOAT * val, SRC_LINE line)
106 if (r->tag == E_FLOAT)
108 *val = r->val.flt;
110 else
112 *val = 0;
113 err (line, "expected float, found %s", expr_val_type_str[r->tag]);
117 void
118 coerce_to_point (EXPR_VAL * r, POINT_3D val, SRC_LINE line)
120 if (r->tag == E_POINT)
122 copy_pt_3d (val, r->val.pt);
124 else
126 val[X] = val[Y] = val[Z] = 0;
127 err (line, "expected point, found %s", expr_val_type_str[r->tag]);
131 void
132 coerce_to_vector (EXPR_VAL * r, VECTOR_3D val, SRC_LINE line)
134 if (r->tag == E_VECTOR)
136 copy_vec_3d (val, r->val.vec);
138 else
140 val[X] = val[Y] = val[Z] = 0;
141 err (line, "expected vector, found %s", expr_val_type_str[r->tag]);
145 void
146 coerce_to_transform (EXPR_VAL * r, TRANSFORM val, SRC_LINE line)
148 if (r->tag == E_TRANSFORM)
150 copy_transform (val, r->val.xf);
152 else
154 set_ident (val);
155 err (line, "expected transform, found %s", expr_val_type_str[r->tag]);
159 typedef void (*PRINT_FUNC) (FILE *, EXPR_VAL *);
161 static PRINT_FUNC print_expr_val_tbl[] = {
162 print_float,
163 print_point,
164 print_vector,
165 print_transform,
168 void
169 print_expr_val (FILE * f, EXPR_VAL * r)
171 (*print_expr_val_tbl[r->tag]) (f, r);
174 #define HASH(A, B) (((A) << 2) | (B))
176 void
177 do_add (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
179 switch (HASH (a->tag, b->tag))
181 case HASH (E_FLOAT, E_FLOAT):
182 set_float (r, a->val.flt + b->val.flt);
183 break;
184 case HASH (E_POINT, E_VECTOR):
185 r->tag = E_POINT;
186 add_vec_to_pt_3d (r->val.pt, a->val.pt, b->val.vec);
187 break;
188 case HASH (E_VECTOR, E_POINT):
189 r->tag = E_POINT;
190 add_vec_to_pt_3d (r->val.pt, b->val.pt, a->val.vec);
191 break;
192 case HASH (E_VECTOR, E_VECTOR):
193 r->tag = E_VECTOR;
194 add_vecs_3d (r->val.vec, a->val.vec, b->val.vec);
195 break;
196 default:
197 err (line, "operands of + (types %s and %s) cannot be added",
198 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
199 set_float (r, 0);
200 break;
204 void
205 do_sub (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
207 switch (HASH (a->tag, b->tag))
209 case HASH (E_FLOAT, E_FLOAT):
210 set_float (r, a->val.flt - b->val.flt);
211 break;
212 case HASH (E_POINT, E_POINT):
213 r->tag = E_VECTOR;
214 sub_pts_3d (r->val.vec, a->val.pt, b->val.pt);
215 break;
216 case HASH (E_POINT, E_VECTOR):
217 r->tag = E_POINT;
218 add_scaled_vec_to_pt_3d (r->val.pt, a->val.pt, b->val.vec, -1);
219 break;
220 case HASH (E_VECTOR, E_VECTOR):
221 r->tag = E_VECTOR;
222 sub_vecs_3d (r->val.vec, a->val.vec, b->val.vec);
223 break;
224 default:
225 err (line, "operands of - (types %s and %s) cannot be subtracted",
226 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
227 set_float (r, 0);
228 break;
232 void
233 do_mul (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
235 switch (HASH (a->tag, b->tag))
237 case HASH (E_FLOAT, E_FLOAT):
238 set_float (r, a->val.flt * b->val.flt);
239 break;
240 case HASH (E_VECTOR, E_FLOAT):
241 r->tag = E_VECTOR;
242 scale_vec_3d (r->val.vec, a->val.vec, b->val.flt);
243 break;
244 case HASH (E_FLOAT, E_VECTOR):
245 r->tag = E_VECTOR;
246 scale_vec_3d (r->val.vec, b->val.vec, a->val.flt);
247 break;
248 case HASH (E_VECTOR, E_VECTOR):
249 r->tag = E_VECTOR;
250 cross (r->val.vec, a->val.vec, b->val.vec);
251 break;
252 case HASH (E_TRANSFORM, E_TRANSFORM):
253 r->tag = E_TRANSFORM;
254 compose (r->val.xf, a->val.xf, b->val.xf);
255 break;
256 case HASH (E_TRANSFORM, E_POINT):
257 r->tag = E_POINT;
258 transform_pt_3d (r->val.pt, a->val.xf, b->val.pt);
259 break;
260 case HASH (E_TRANSFORM, E_VECTOR):
261 r->tag = E_VECTOR;
262 transform_vec_3d (r->val.vec, a->val.xf, b->val.vec);
263 break;
264 default:
265 err (line, "operands of * (types %s and %s) cannot be multiplied",
266 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
267 set_float (r, 0);
268 break;
272 void
273 do_thn (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
275 switch (HASH (a->tag, b->tag))
277 case HASH (E_TRANSFORM, E_TRANSFORM):
278 r->tag = E_TRANSFORM;
279 compose (r->val.xf, b->val.xf, a->val.xf);
280 break;
281 case HASH (E_POINT, E_TRANSFORM):
282 r->tag = E_POINT;
283 transform_pt_3d (r->val.pt, b->val.xf, a->val.pt);
284 break;
285 case HASH (E_VECTOR, E_TRANSFORM):
286 r->tag = E_VECTOR;
287 transform_vec_3d (r->val.vec, b->val.xf, a->val.vec);
288 break;
289 default:
290 err (line,
291 "operands of 'then' (types %s and %s) cannot be multiplied",
292 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
293 set_float (r, 0);
294 break;
298 static FLOAT
299 safe_dvd (FLOAT a, FLOAT b, SRC_LINE line)
301 if (-FLOAT_EPS < b && b < FLOAT_EPS)
303 err (line, "attempt to divide " F " by zero", a);
304 return 0;
306 return a / b;
309 void
310 do_dvd (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
312 switch (HASH (a->tag, b->tag))
314 case HASH (E_FLOAT, E_FLOAT):
315 set_float (r, safe_dvd (a->val.flt, b->val.flt, line));
316 break;
317 case HASH (E_VECTOR, E_FLOAT):
318 r->tag = E_VECTOR;
319 scale_vec_3d (r->val.vec, a->val.vec, safe_dvd (1, b->val.flt, line));
320 break;
321 case HASH (E_FLOAT, E_VECTOR):
322 r->tag = E_VECTOR;
323 scale_vec_3d (r->val.vec, b->val.vec, safe_dvd (1, a->val.flt, line));
324 break;
325 default:
326 err (line, "operands of / (types %s and %s) cannot be divided",
327 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
328 set_float (r, 0);
329 break;
333 void
334 do_dot (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
336 switch (HASH (a->tag, b->tag))
338 case HASH (E_VECTOR, E_VECTOR):
339 r->tag = E_FLOAT;
340 r->val.flt = dot_3d (a->val.vec, b->val.vec);
341 break;
342 case HASH (E_FLOAT, E_FLOAT):
343 case HASH (E_VECTOR, E_FLOAT):
344 case HASH (E_FLOAT, E_VECTOR):
345 case HASH (E_TRANSFORM, E_TRANSFORM):
346 case HASH (E_TRANSFORM, E_POINT):
347 case HASH (E_TRANSFORM, E_VECTOR):
348 do_mul (r, a, b, line);
349 break;
350 default:
351 err (line, "operands of dot (types %s and %s) cannot be multiplied",
352 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
353 set_float (r, 0);
354 break;
358 void
359 do_index (EXPR_VAL * r, EXPR_VAL * a, int index, SRC_LINE line)
361 switch (a->tag)
363 case E_VECTOR:
364 set_float (r, a->val.vec[index]);
365 break;
366 case E_POINT:
367 set_float (r, a->val.pt[index]);
368 break;
369 default:
370 err (line,
371 "operand of 'index is a %s and should be a point or a vector",
372 expr_val_type_str[a->tag]);
373 set_float (r, 0);
374 break;
378 void
379 do_inverse (TRANSFORM inv, TRANSFORM xf, SRC_LINE line)
381 FLOAT det;
382 invert (inv, &det, xf, 1e-4);
383 if (det == 0)
385 err (line, "inverse of singular transform");
386 set_ident (inv);
390 // put a^n into r; r and a can't both be the same storage
391 // exploits a^(2n) = (a^n)^2 to reduce work
392 void
393 do_transform_power (TRANSFORM r, TRANSFORM a, int n, SRC_LINE line)
395 if (n < 0)
397 TRANSFORM inv;
398 do_inverse (inv, a, line);
399 do_transform_power (r, inv, -n, line);
401 else if (n == 0)
403 set_ident (r);
405 else
407 int m = (int) bit (30);
408 while ((m & n) == 0)
409 m >>= 1;
410 copy_transform (r, a);
411 for (m >>= 1; m; m >>= 1)
413 compose (r, r, r);
414 if (m & n)
415 compose (r, r, a);
421 to_integer (FLOAT x, int *n)
423 double frac_part, int_part;
425 frac_part = modf (x, &int_part);
426 if (-1e9 <= int_part && int_part <= 1e9)
428 *n = (int) int_part;
429 return 1;
431 return 0;
434 void
435 do_pwr (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
437 TRANSFORM xf_pwr;
438 int n;
440 switch (HASH (a->tag, b->tag))
442 case HASH (E_FLOAT, E_FLOAT):
443 set_float (r, pow (a->val.flt, b->val.flt));
444 break;
445 case HASH (E_TRANSFORM, E_FLOAT):
446 if (to_integer (b->val.flt, &n))
448 do_transform_power (xf_pwr, a->val.xf, n, line);
450 else
452 err (line, "transform power out of domain (integer -1e9..1e9)");
453 set_ident (xf_pwr);
455 set_transform (r, xf_pwr);
456 break;
457 default:
458 err (line, "operands of ^ (types %s and %s) must be type float",
459 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
460 set_float (r, 0);
461 break;
465 void
466 do_mag (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
468 switch (a->tag)
470 case E_FLOAT:
471 set_float (r, a->val.flt >= 0 ? a->val.flt : -a->val.flt);
472 break;
473 case E_VECTOR:
474 set_float (r, length_vec_3d (a->val.vec));
475 break;
476 default:
477 err (line, "operand of magnitude operator (type %s) must be vector",
478 expr_val_type_str[a->tag]);
479 *r = *a;
480 break;
484 void
485 do_neg (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
487 switch (a->tag)
489 case E_FLOAT:
490 set_float (r, -a->val.flt);
491 break;
492 case E_VECTOR:
493 r->tag = E_VECTOR;
494 negate_vec_3d (r->val.vec, a->val.vec);
495 break;
496 default:
497 err (line, "operand of unary minus (type %s) cannot be negated",
498 expr_val_type_str[a->tag]);
499 *r = *a;
500 break;
504 void
505 do_unit (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
507 if (a->tag == E_VECTOR)
509 r->tag = E_VECTOR;
510 find_unit_vec_3d (r->val.vec, a->val.vec);
512 else
514 static VECTOR_3D k = { 0, 0, 1 };
515 err (line, "operand of unit operator (type %s) must be vector",
516 expr_val_type_str[a->tag]);
517 set_vector (r, k);
521 void
522 do_sqrt (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
524 switch (a->tag)
526 case E_FLOAT:
527 if (a->val.flt < 0)
528 err (line, "square root of negative number");
529 set_float (r, sqrt (a->val.flt));
530 break;
531 default:
532 err (line, "operand of sqrt (type %s) must be float",
533 expr_val_type_str[a->tag]);
534 break;
538 void
539 do_sin (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
541 switch (a->tag)
543 case E_FLOAT:
544 set_float (r, sin ((PI / 180) * a->val.flt));
545 break;
546 default:
547 err (line, "operand of sin (type %s) must be float",
548 expr_val_type_str[a->tag]);
549 break;
553 void
554 do_cos (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
556 switch (a->tag)
558 case E_FLOAT:
559 set_float (r, cos ((PI / 180) * a->val.flt));
560 break;
561 default:
562 err (line, "operand of cos (type %s) must be float",
563 expr_val_type_str[a->tag]);
564 break;
568 void
569 do_atan2 (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
571 switch (HASH (a->tag, b->tag))
573 case HASH (E_FLOAT, E_FLOAT):
574 set_float (r, (180 / PI) * atan2 (a->val.flt, b->val.flt));
575 break;
576 default:
577 err (line, "operands of atan2 (types %s, %s) must be float",
578 expr_val_type_str[a->tag], expr_val_type_str[b->tag]);
579 break;