1 
2 /******************************************************************************
3 * MODULE     : evaluate_numeric.cpp
4 * DESCRIPTION: numeric operations
5 * COPYRIGHT  : (C) 2006  Joris van der Hoeven
6 *******************************************************************************
7 * This software falls under the GNU general public license version 3 or later.
8 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
9 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
10 ******************************************************************************/
11 
12 #include "evaluate_main.hpp"
13 
14 /******************************************************************************
15 * Arithmetic operations
16 ******************************************************************************/
17 
18 tree
evaluate_plus_minus(tree t)19 evaluate_plus_minus (tree t) {
20   int i, n= N(t);
21   if (n==0) return evaluate_error ("bad plus/minus");
22   tree inc= evaluate (t[0]);
23   if (is_double (inc)) {
24     double acc= as_double (inc);
25     if ((n==1) && is_func (t, MINUS))
26       acc= -acc;
27     for (i=1; i<n; i++) {
28       tree inc= evaluate (t[i]);
29       if (!is_double (inc))
30 	return evaluate_error ("bad plus/minus");
31       if ((i == n-1) && is_func (t, MINUS))
32 	acc -= as_double (inc);
33       else acc += as_double (inc);
34     }
35     return as_string (acc);
36   }
37   else if (is_anylen (inc)) {
38     tree acc= as_tmlen (inc);
39     if ((n==1) && is_func (t, MINUS))
40       acc= tmlen_times (-1, acc);
41     for (i=1; i<n; i++) {
42       tree inc= evaluate (t[i]);
43       if (!is_anylen (inc))
44 	return evaluate_error ("bad plus/minus");
45       inc= as_tmlen (inc);
46       if ((i == n-1) && is_func (t, MINUS))
47 	inc= tmlen_times (-1, inc);
48       acc= tmlen_plus (acc, inc);
49     }
50     return acc;
51   }
52   else return evaluate_error ("bad plus/minus");
53 }
54 
55 tree
evaluate_times_over(tree t)56 evaluate_times_over (tree t) {
57   int i, n= N(t);
58   if (n==0) return evaluate_error ("bad times/over");
59   tree prod= evaluate (t[0]);
60   if (is_double (prod));
61   else if (is_anylen (prod)) prod= as_tmlen (prod);
62   else if (is_percentage (prod)) prod= as_tree (as_percentage (prod));
63   else return evaluate_error ("bad times/over");
64   if ((n==1) && is_func (t, OVER)) {
65     if (is_double (prod)) return as_string (1 / as_double (prod));
66     else return evaluate_error ("bad times/over");
67   }
68   // cout << t << "\n";
69   // cout << "  0\t" << prod << "\n";
70   for (i=1; i<n; i++) {
71     tree mul= evaluate (t[i]);
72     if (is_double (mul)) {
73       double _mul= as_double (mul);
74       if ((i == n-1) && is_func (t, OVER))
75 	_mul= 1 / _mul;
76       if (is_double (prod))
77 	prod= as_string (_mul * as_double (prod));
78       else prod= tmlen_times (_mul, prod);
79     }
80     else if (is_anylen (mul)) {
81       mul= as_tmlen (mul);
82       if ((i == n-1) && is_func (t, OVER)) {
83 	if (!is_func (prod, TMLEN))
84 	  return evaluate_error ("bad times/over");
85 	return tmlen_over (prod, mul);
86       }
87       if (is_double (prod))
88 	prod= tmlen_times (as_double (prod), mul);
89       else return evaluate_error ("bad times/over");
90     }
91     else if (is_percentage (mul)) {
92       double _mul= as_percentage (mul);
93       if (is_double (prod))
94 	prod= as_string (_mul * as_double (prod));
95       else prod= tmlen_times (_mul, prod);
96     }
97     else return evaluate_error ("bad times/over");
98     // cout << "  " << i << "\t" << prod << "\n";
99   }
100   return prod;
101 }
102 
103 tree
evaluate_divide(tree t)104 evaluate_divide (tree t) {
105   if (N(t) != 2) return evaluate_error ("bad divide");
106   tree t1= evaluate (t[0]);
107   tree t2= evaluate (t[1]);
108   if (is_compound (t1) || is_compound (t2))
109     return evaluate_error ("bad divide");
110   if (is_int (t1->label) && (is_int (t2->label))) {
111     int den= as_int (t2->label);
112     if (den == 0) return evaluate_error ("division by zero");
113     return as_string (as_int (t1->label) / den);
114   }
115   return evaluate_error ("bad divide");
116 }
117 
118 tree
evaluate_modulo(tree t)119 evaluate_modulo (tree t) {
120   if (N(t)!=2) return evaluate_error ("bad modulo");
121   tree t1= evaluate (t[0]);
122   tree t2= evaluate (t[1]);
123   if (is_compound (t1) || is_compound (t2))
124     return evaluate_error ("bad modulo");
125   if (is_int (t1->label) && (is_int (t2->label))) {
126     int den= as_int (t2->label);
127     if (den == 0) return evaluate_error ("modulo zero");
128     return as_string (as_int (t1->label) % den);
129   }
130   return evaluate_error ("bad modulo");
131 }
132 
133 /******************************************************************************
134 * Elementary functions
135 ******************************************************************************/
136 
137 tree
evaluate_math_sqrt(tree t)138 evaluate_math_sqrt (tree t) {
139   if (N(t)!=1) return evaluate_error ("bad sqrt");
140   tree t1= evaluate (t[0]);
141   if (is_double (t1))
142     return as_tree (sqrt (as_double (t1)));
143   return evaluate_error ("bad sqrt");
144 }
145 
146 tree
evaluate_exp(tree t)147 evaluate_exp (tree t) {
148   if (N(t)!=1) return evaluate_error ("bad exp");
149   tree t1= evaluate (t[0]);
150   if (is_double (t1))
151     return as_tree (exp (as_double (t1)));
152   return evaluate_error ("bad exp");
153 }
154 
155 tree
evaluate_log(tree t)156 evaluate_log (tree t) {
157   if (N(t)!=1) return evaluate_error ("bad log");
158   tree t1= evaluate (t[0]);
159   if (is_double (t1))
160     return as_tree (log (as_double (t1)));
161   return evaluate_error ("bad log");
162 }
163 
164 tree
evaluate_pow(tree t)165 evaluate_pow (tree t) {
166   if (N(t)!=2) return evaluate_error ("bad pow");
167   tree t1= evaluate (t[0]);
168   tree t2= evaluate (t[1]);
169   if (is_double (t1) && is_double (t2))
170     return as_tree (pow (as_double (t1), as_double (t2)));
171   return evaluate_error ("bad pow");
172 }
173 
174 tree
evaluate_cos(tree t)175 evaluate_cos (tree t) {
176   if (N(t)!=1) return evaluate_error ("bad cos");
177   tree t1= evaluate (t[0]);
178   if (is_double (t1))
179     return as_tree (cos (as_double (t1)));
180   return evaluate_error ("bad cos");
181 }
182 
183 tree
evaluate_sin(tree t)184 evaluate_sin (tree t) {
185   if (N(t)!=1) return evaluate_error ("bad sin");
186   tree t1= evaluate (t[0]);
187   if (is_double (t1))
188     return as_tree (sin (as_double (t1)));
189   return evaluate_error ("bad sin");
190 }
191 
192 tree
evaluate_tan(tree t)193 evaluate_tan (tree t) {
194   if (N(t)!=1) return evaluate_error ("bad tan");
195   tree t1= evaluate (t[0]);
196   if (is_double (t1))
197     return as_tree (tan (as_double (t1)));
198   return evaluate_error ("bad tan");
199 }
200 
201 /******************************************************************************
202 * Colors
203 ******************************************************************************/
204 
205 tree
evaluate_blend(tree t)206 evaluate_blend (tree t) {
207   if (N(t)!=2) return evaluate_error ("bad blend");
208   tree t1= evaluate (t[0]);
209   tree t2= evaluate (t[1]);
210   if (is_compound (t1) || is_compound (t2))
211     return evaluate_error ("bad blend");
212   string s1= t1->label;
213   string s2= t2->label;
214   if (is_color_name (s1) && (is_color_name (s2))) {
215     color c1= named_color (s1);
216     color c2= named_color (s2);
217     return get_hex_color (blend_colors (c1, c2));
218   }
219   return evaluate_error ("bad blend");
220 }
221