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