C   8

expr.c

Guest on 20th July 2021 03:07:44 PM

  1. /* expr.c
  2.    Copyright (C) 2005,2006,2007 Eugene K. Ressler, Jr.
  3.  
  4. This file is part of Sketch, a small, simple system for making
  5. 3d drawings with LaTeX and the PSTricks or TikZ package.
  6.  
  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.
  11.  
  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.
  16.  
  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 */
  20.  
  21. #include <stdio.h>
  22. #include <math.h>
  23. #include "expr.h"
  24. #include "error.h"
  25.  
  26. #define F "%.3f"
  27.  
  28. char *expr_val_type_str[] = {
  29.   "float",
  30.   "point",
  31.   "vector",
  32.   "transform",
  33. };
  34.  
  35. // set expression value to given type and value
  36. void
  37. set_float (EXPR_VAL * r, FLOAT val)
  38. {
  39.   r->tag = E_FLOAT;
  40.   r->val.flt = val;
  41. }
  42.  
  43. void
  44. print_float (FILE * f, EXPR_VAL * val)
  45. {
  46.   fprintf (f, F, val->val.flt);
  47. }
  48.  
  49. void
  50. set_point (EXPR_VAL * r, POINT_3D val)
  51. {
  52.   r->tag = E_POINT;
  53.   copy_pt_3d (r->val.pt, val);
  54. }
  55.  
  56. void
  57. print_point (FILE * f, EXPR_VAL * val)
  58. {
  59.   FLOAT *p = val->val.pt;
  60.   fprintf (f, "(" F "," F "," F ")", p[X], p[Y], p[Z]);
  61. }
  62.  
  63. void
  64. set_vector (EXPR_VAL * r, VECTOR_3D val)
  65. {
  66.   r->tag = E_VECTOR;
  67.   copy_vec_3d (r->val.vec, val);
  68. }
  69.  
  70. void
  71. print_vector (FILE * f, EXPR_VAL * val)
  72. {
  73.   FLOAT *v = val->val.vec;
  74.   fprintf (f, "[" F "," F "," F "]", v[X], v[Y], v[Z]);
  75. }
  76.  
  77. void
  78. set_transform (EXPR_VAL * r, TRANSFORM val)
  79. {
  80.   r->tag = E_TRANSFORM;
  81.   copy_transform (r->val.xf, val);
  82. }
  83.  
  84. void
  85. print_transform (FILE * f, EXPR_VAL * val)
  86. {
  87.   FLOAT *xf = val->val.xf;
  88.   int i, j;
  89.  
  90.   fprintf (f, "[");
  91.   for (i = 0; i < 4; i++)
  92.     {
  93.       fprintf (f, "[");
  94.       for (j = 0; j < 16; j += 4)
  95.         fprintf (f, "%s" F, (j == 0) ? "" : ",", xf[i + j]);
  96.       fprintf (f, "]");
  97.     }
  98.   fprintf (f, "]");
  99. }
  100.  
  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)
  105. {
  106.   if (r->tag == E_FLOAT)
  107.     {
  108.       *val = r->val.flt;
  109.     }
  110.   else
  111.     {
  112.       *val = 0;
  113.       err (line, "expected float, found %s", expr_val_type_str[r->tag]);
  114.     }
  115. }
  116.  
  117. void
  118. coerce_to_point (EXPR_VAL * r, POINT_3D val, SRC_LINE line)
  119. {
  120.   if (r->tag == E_POINT)
  121.     {
  122.       copy_pt_3d (val, r->val.pt);
  123.     }
  124.   else
  125.     {
  126.       val[X] = val[Y] = val[Z] = 0;
  127.       err (line, "expected point, found %s", expr_val_type_str[r->tag]);
  128.     }
  129. }
  130.  
  131. void
  132. coerce_to_vector (EXPR_VAL * r, VECTOR_3D val, SRC_LINE line)
  133. {
  134.   if (r->tag == E_VECTOR)
  135.     {
  136.       copy_vec_3d (val, r->val.vec);
  137.     }
  138.   else
  139.     {
  140.       val[X] = val[Y] = val[Z] = 0;
  141.       err (line, "expected vector, found %s", expr_val_type_str[r->tag]);
  142.     }
  143. }
  144.  
  145. void
  146. coerce_to_transform (EXPR_VAL * r, TRANSFORM val, SRC_LINE line)
  147. {
  148.   if (r->tag == E_TRANSFORM)
  149.     {
  150.       copy_transform (val, r->val.xf);
  151.     }
  152.   else
  153.     {
  154.       set_ident (val);
  155.       err (line, "expected transform, found %s", expr_val_type_str[r->tag]);
  156.     }
  157. }
  158.  
  159. typedef void (*PRINT_FUNC) (FILE *, EXPR_VAL *);
  160.  
  161. static PRINT_FUNC print_expr_val_tbl[] = {
  162.   print_float,
  163.   print_point,
  164.   print_vector,
  165.   print_transform,
  166. };
  167.  
  168. void
  169. print_expr_val (FILE * f, EXPR_VAL * r)
  170. {
  171.   (*print_expr_val_tbl[r->tag]) (f, r);
  172. }
  173.  
  174. #define HASH(A, B) (((A) << 2) | (B))
  175.  
  176. void
  177. do_add (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  178. {
  179.   switch (HASH (a->tag, b->tag))
  180.     {
  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;
  201.     }
  202. }
  203.  
  204. void
  205. do_sub (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  206. {
  207.   switch (HASH (a->tag, b->tag))
  208.     {
  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;
  229.     }
  230. }
  231.  
  232. void
  233. do_mul (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  234. {
  235.   switch (HASH (a->tag, b->tag))
  236.     {
  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;
  269.     }
  270. }
  271.  
  272. void
  273. do_thn (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  274. {
  275.   switch (HASH (a->tag, b->tag))
  276.     {
  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;
  295.     }
  296. }
  297.  
  298. static FLOAT
  299. safe_dvd (FLOAT a, FLOAT b, SRC_LINE line)
  300. {
  301.   if (-FLOAT_EPS < b && b < FLOAT_EPS)
  302.     {
  303.       err (line, "attempt to divide " F " by zero", a);
  304.       return 0;
  305.     }
  306.   return a / b;
  307. }
  308.  
  309. void
  310. do_dvd (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  311. {
  312.   switch (HASH (a->tag, b->tag))
  313.     {
  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;
  330.     }
  331. }
  332.  
  333. void
  334. do_dot (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  335. {
  336.   switch (HASH (a->tag, b->tag))
  337.     {
  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;
  355.     }
  356. }
  357.  
  358. void
  359. do_index (EXPR_VAL * r, EXPR_VAL * a, int index, SRC_LINE line)
  360. {
  361.   switch (a->tag)
  362.     {
  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;
  375.     }
  376. }
  377.  
  378. void
  379. do_inverse (TRANSFORM inv, TRANSFORM xf, SRC_LINE line)
  380. {
  381.   FLOAT det;
  382.   invert (inv, &det, xf, 1e-4);
  383.   if (det == 0)
  384.     {
  385.       err (line, "inverse of singular transform");
  386.       set_ident (inv);
  387.     }
  388. }
  389.  
  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)
  394. {
  395.   if (n < 0)
  396.     {
  397.       TRANSFORM inv;
  398.       do_inverse (inv, a, line);
  399.       do_transform_power (r, inv, -n, line);
  400.     }
  401.   else if (n == 0)
  402.     {
  403.       set_ident (r);
  404.     }
  405.   else
  406.     {
  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)
  412.         {
  413.           compose (r, r, r);
  414.           if (m & n)
  415.             compose (r, r, a);
  416.         }
  417.     }
  418. }
  419.  
  420. int
  421. to_integer (FLOAT x, int *n)
  422. {
  423.   double frac_part, int_part;
  424.  
  425.   frac_part = modf (x, &int_part);
  426.   if (-1e9 <= int_part && int_part <= 1e9)
  427.     {
  428.       *n = (int) int_part;
  429.       return 1;
  430.     }
  431.   return 0;
  432. }
  433.  
  434. void
  435. do_pwr (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  436. {
  437.   TRANSFORM xf_pwr;
  438.   int n;
  439.  
  440.   switch (HASH (a->tag, b->tag))
  441.     {
  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))
  447.         {
  448.           do_transform_power (xf_pwr, a->val.xf, n, line);
  449.         }
  450.       else
  451.         {
  452.           err (line, "transform power out of domain (integer -1e9..1e9)");
  453.           set_ident (xf_pwr);
  454.         }
  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;
  462.     }
  463. }
  464.  
  465. void
  466. do_mag (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
  467. {
  468.   switch (a->tag)
  469.     {
  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;
  481.     }
  482. }
  483.  
  484. void
  485. do_neg (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
  486. {
  487.   switch (a->tag)
  488.     {
  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;
  501.     }
  502. }
  503.  
  504. void
  505. do_unit (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
  506. {
  507.   if (a->tag == E_VECTOR)
  508.     {
  509.       r->tag = E_VECTOR;
  510.       find_unit_vec_3d (r->val.vec, a->val.vec);
  511.     }
  512.   else
  513.     {
  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);
  518.     }
  519. }
  520.  
  521. void
  522. do_sqrt (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
  523. {
  524.   switch (a->tag)
  525.     {
  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;
  535.     }
  536. }
  537.  
  538. void
  539. do_sin (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
  540. {
  541.   switch (a->tag)
  542.     {
  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;
  550.     }
  551. }
  552.  
  553. void
  554. do_cos (EXPR_VAL * r, EXPR_VAL * a, SRC_LINE line)
  555. {
  556.   switch (a->tag)
  557.     {
  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;
  565.     }
  566. }
  567.  
  568. void
  569. do_atan2 (EXPR_VAL * r, EXPR_VAL * a, EXPR_VAL * b, SRC_LINE line)
  570. {
  571.   switch (HASH (a->tag, b->tag))
  572.     {
  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;
  580.     }
  581. }

Raw Paste


Login or Register to edit or fork this paste. It's free.