Orbiter 2022
Combinatorial Objects
function_polish.cpp
Go to the documentation of this file.
1/*
2 * function_polish.cpp
3 *
4 * Created on: Apr 18, 2020
5 * Author: betten
6 */
7
8
9
10
11#include "foundations.h"
12
13
14using namespace std;
15
16
17namespace orbiter {
18namespace layer1_foundations {
19
20
22{
23 Descr = NULL;
24}
25
27{
28}
29
30
33 int verbose_level)
34{
35 int f_v = (verbose_level >= 1);
36 double val;
37 int entry, len;
38 int i;
40
41
42 if (f_v) {
43 cout << "function_polish::init" << endl;
44 cout << "function_polish::nb_variables = " << Descr->nb_variables << endl;
45 cout << "function_polish::nb_constants = " << Descr->nb_constants << endl;
46 cout << "function_polish::nb_commands = " << Descr->code_sz << endl;
47 cout << "variables:" << endl;
48 for (i = 0; i < Descr->nb_variables; i++) {
49 cout << i << " : " << Descr->variable_names[i] << endl;
50 }
51 cout << "constants:" << endl;
52 for (i = 0; i < Descr->nb_constants; i++) {
53 cout << i << " : " << Descr->const_names[i] << " = " << Descr->const_values[i] << endl;
54 }
55 cout << "commands:" << endl;
56 for (i = 0; i < Descr->code_sz; i++) {
57 cout << i << " : " << Descr->code[i] << endl;
58 }
59 }
60
61 for (i = 0; i < Descr->nb_variables; i++) {
62 string S(Descr->variable_names[i]);
63 Variables.push_back(S);
64 }
65
66 for (i = 0; i < Descr->nb_constants; i++) {
67 double f;
68
69 f = ST.strtof(Descr->const_values[i]);
70 pair<string, double> P(Descr->const_names[i], f);
71 Constants.push_back(P);
72 }
73
74
75 if (f_v) {
76 cout << "function_polish::init start parsing" << endl;
77 }
78 entry = 0;
79 len = 0;
80 for (i = 0; i < Descr->code_sz; i++) {
82
83 len++;
84
85 if (ST.stringcmp(Descr->code[i], "push") == 0) {
86
87 string S(Descr->code[++i]);
88
89 int j;
90
91 for (j = 0; j < (int) Variables.size(); j++) {
92 if (strcmp(Variables[j].c_str(), S.c_str()) == 0) {
93 break;
94 }
95 }
96 if (j < (int) Variables.size()) {
97 cmd.init_with_argument(3, j);
98 if (f_v) {
99 cout << "push variable " << S << " (= " << j << ")" << endl;
100 }
101 }
102 else {
103 for (j = 0; j < (int) Constants.size(); j++) {
104
105 if (strcmp(Constants[j].first.c_str(), S.c_str()) == 0) {
106 break;
107 }
108 }
109 if (j < (int) Constants.size()) {
110 cmd.init_with_argument(1, j);
111 if (f_v) {
112 cout << "push constant " << S << " (= " << j << ")" << endl;
113 }
114 }
115 else {
116 val = atof(S.c_str());
118 if (f_v) {
119 cout << "push immediate " << val << endl;
120 }
121 //cout << "function_polish::init unknown label " << S << endl;
122 //exit(1);
123 }
124 }
125 }
126 else if (ST.stringcmp(Descr->code[i], "store") == 0) {
127 int j;
128 string S(Descr->code[++i]);
129
130 for (j = 0; j < (int) Variables.size(); j++) {
131 if (strcmp(Variables[j].c_str(), S.c_str()) == 0) {
132 break;
133 }
134 }
135 if (j < (int) Variables.size()) {
136 cmd.init_with_argument(4, j);
137 if (f_v) {
138 cout << "store " << S << " (= " << j << ")" << endl;
139 }
140 }
141 else {
142 cout << "store command, cannot find variable with label " << S << endl;
143 }
144 }
145 else if (ST.stringcmp(Descr->code[i], "mult") == 0) {
146 cmd.init_simple(5);
147 if (f_v) {
148 cout << "mult" << endl;
149 }
150 }
151 else if (ST.stringcmp(Descr->code[i], "add") == 0) {
152 cmd.init_simple(6);
153 if (f_v) {
154 cout << "add" << endl;
155 }
156 }
157 else if (ST.stringcmp(Descr->code[i], "cos") == 0) {
158 cmd.init_simple(7);
159 }
160 else if (ST.stringcmp(Descr->code[i], "sin") == 0) {
161 cmd.init_simple(8);
162 if (f_v) {
163 cout << "cos" << endl;
164 }
165 }
166 else if (ST.stringcmp(Descr->code[i], "sqrt") == 0) {
167 cmd.init_simple(10);
168 if (f_v) {
169 cout << "sqrt" << endl;
170 }
171 }
172 else if (ST.stringcmp(Descr->code[i], "return") == 0) {
173 cmd.init_simple(9);
174 if (f_v) {
175 cout << "return" << endl;
176 }
177 Entry.push_back(entry);
178 Len.push_back(len);
179 entry = Code.size() + 1; // next entry point
180 len = 0;
181 }
182 else {
183 cout << "unrecognized command " << Descr->code[i] << endl;
184 exit(1);
185 }
186 Code.push_back(cmd);
187 }
188
189 if (f_v) {
190 cout << "function_polish::init Parsed " << Entry.size() << " functions" << endl;
191
192 print_code_complete(verbose_level);
193
194 }
195
196
197 if (f_v) {
198 cout << "function_polish::init done" << endl;
199 }
200}
201
203 int verbose_level)
204{
205 int f_v = (verbose_level >= 1);
206
207 if (f_v) {
208 cout << "function_polish::print_code_complete" << endl;
209 }
210
211 int h, i0, len;
212
213 for (h = 0; h < Entry.size(); h++) {
214 i0 = Entry[h];
215 len = Len[h];
216 cout << "subroutine " << h << " starts at " << i0 << " and has length " << len << ":" << endl;
217 print_code(i0, len, verbose_level);
218 }
219}
220
222 int i0, int len,
223 int verbose_level)
224{
225 int i, j, t;
226 double f;
227
228 for (j = 0; j < len; j++) {
229 i = i0 + j;
230 if (i >= Code.size()) {
231 break;
232 }
233 t = Code[i].type;
234 if (t == 1) {
235 // push a labeled constant
236 cout << i << " : push " << Constants[Code[i].arg].first << endl;
237 }
238 else if (t == 2) {
239 // push a immediate constant
240 f = Code[i].val;
241 cout << i << " : push " << f << endl;
242 }
243 else if (t == 3) {
244 // push a variable
245 cout << i << " : push " << Variables[Code[i].arg] << endl;
246 }
247 else if (t == 4) {
248 // store to a variable, pop the stack
249 cout << i << " : store " << Variables[Code[i].arg] << endl;
250 }
251 else if (t == 5) {
252 // mult
253 cout << i << " : mult" << endl;
254 }
255 else if (t == 6) {
256 // add
257 cout << i << " : add" << endl;
258 }
259 else if (t == 7) {
260 // cos
261 cout << i << " : cos" << endl;
262 }
263 else if (t == 8) {
264 // sin
265 cout << i << " : sin" << endl;
266 }
267 else if (t == 10) {
268 // sqrt
269 cout << i << " : sqrt" << endl;
270 }
271 else if (t == 9) {
272 cout << i << " : return" << endl;
273 }
274 else {
275 cout << "unknown type, error. t = " << t << endl;
276 exit(1);
277 }
278 } //next j
279}
280
282 double *variable_values,
283 double *output_values,
284 int verbose_level)
285{
286 int f_v = (verbose_level >= 1);
287 vector<double > Stack;
288 int h, fst, len, i, j, t;
289 double f, a, b;
290
291 if (f_v) {
292 cout << "function_polish::evaluate" << endl;
293 }
294 for (h = 0; h < (int) Entry.size(); h++) {
295 fst = Entry[h];
296 len = Len[h];
297 if (f_v) {
298 cout << "function_polish::evaluate evaluation function " << h << " / " << Entry.size() << endl;
299 cout << "function_polish::evaluate fst=" << fst << endl;
300 cout << "function_polish::evaluate len=" << len << endl;
301 }
302 if (Stack.size() != 0) {
303 cout << "stack must be empty before we start" << endl;
304 exit(1);
305 }
306 for (j = 0; j < len; j++) {
307 if (f_v) {
308 cout << "h=" << h << " j=" << j << " : ";
309 }
310 i = fst + j;
311 t = Code[i].type;
312 if (t == 1) {
313 // push a labeled constant
314 f = Constants[Code[i].arg].second;
315 if (f_v) {
316 cout << "pushing constant " << f << " from constant " << Code[i].arg << endl;
317 }
318 Stack.push_back(f);
319 }
320 else if (t == 2) {
321 // push a immediate constant
322 f = Code[i].val;
323 if (f_v) {
324 cout << "pushing immediate constant " << f << endl;
325 }
326 Stack.push_back(f);
327 }
328 else if (t == 3) {
329 // push a variable
330 f = variable_values[Code[i].arg];
331 if (f_v) {
332 cout << "pushing variable " << f << " from variable " << Code[i].arg << endl;
333 }
334 Stack.push_back(f);
335 }
336 else if (t == 4) {
337 // store to a variable, pop the stack
338 f = Stack[Stack.size() - 1];
339 variable_values[Code[i].arg] = f;
340 Stack.pop_back();
341 if (f_v || TRUE) {
342 cout << "storing value " << f << " to variable " << Variables[Code[i].arg] << " : stacksize = " << Stack.size() << endl;
343 }
344 }
345 else if (t == 5) {
346 // mult
347 if (Stack.size() < 2) {
348 cout << "multiplication needs at least two elements on the stack; stack size = " << Stack.size() << endl;
349 print_code(fst + j, 20, verbose_level);
350 exit(1);
351 }
352 a = Stack[Stack.size() - 1];
353 Stack.pop_back();
354 b = Stack[Stack.size() - 1];
355 Stack.pop_back();
356 f = a * b;
357 if (f_v) {
358 cout << "mult: " << a << " * " << b << " = " << f << endl;
359 }
360 Stack.push_back(f);
361 }
362 else if (t == 6) {
363 // add
364 if (Stack.size() < 2) {
365 cout << "addition needs at least two elements on the stack; stack size = " << Stack.size() << endl;
366 print_code(fst + j, 20, verbose_level);
367 exit(1);
368 }
369 a = Stack[Stack.size() - 1];
370 Stack.pop_back();
371 b = Stack[Stack.size() - 1];
372 Stack.pop_back();
373 f = a + b;
374 if (f_v) {
375 cout << "add: " << a << " + " << b << " = " << f << endl;
376 }
377 Stack.push_back(f);
378 }
379 else if (t == 7) {
380 // cos
381 if (Stack.size() < 1) {
382 cout << "cos needs at least one element on the stack; stack size = " << Stack.size() << endl;
383 print_code(fst + j, 20, verbose_level);
384 exit(1);
385 }
386 a = Stack[Stack.size() - 1];
387 f = cos(a);
388 if (f_v) {
389 cout << "cos " << a << " = " << f << endl;
390 }
391 Stack[Stack.size() - 1] = f;
392 }
393 else if (t == 8) {
394 // sin
395 if (Stack.size() < 1) {
396 cout << "sin needs at least one element on the stack; stack size = " << Stack.size() << endl;
397 print_code(fst + j, 20, verbose_level);
398 exit(1);
399 }
400 a = Stack[Stack.size() - 1];
401 f = sin(a);
402 if (f_v) {
403 cout << "sin " << a << " = " << f << endl;
404 }
405 Stack[Stack.size() - 1] = f;
406 }
407 else if (t == 10) {
408 // sqrt
409 if (Stack.size() < 1) {
410 cout << "sin needs at least one element on the stack; stack size = " << Stack.size() << endl;
411 print_code(fst + j, 20, verbose_level);
412 exit(1);
413 }
414 a = Stack[Stack.size() - 1];
415 if (a < 0) {
416 cout << "sqrt: the argument is negative, a = " << a << endl;
417 print_code(fst + j, 20, verbose_level);
418 exit(1);
419 }
420 f = sqrt(a);
421 if (f_v) {
422 cout << "sqrt " << a << " = " << f << endl;
423 }
424 Stack[Stack.size() - 1] = f;
425 }
426 else if (t == 9) {
427 if (f_v) {
428 cout << "return, stacksize = " << Stack.size() << endl;
429 }
430 if (Stack.size() != 1) {
431 cout << "Stack size is not 1 at the end of the execution of function " << h << endl;
432 exit(1);
433 }
434 output_values[h] = Stack[0];
435 Stack.pop_back();
436 break;
437 }
438 else {
439 cout << "unknown type, error. t = " << t << endl;
440 exit(1);
441 }
442 } //next j
443 if (f_v) {
444 cout << "function_polish::evaluate function " << h << " / " << Entry.size()
445 << " evaluates to " << output_values[h] << endl;
446 }
447 } // next h
448
449 if (f_v) {
450 for (h = 0; h < (int) Entry.size(); h++) {
451 cout << "function " << h << " evaluates to " << output_values[h] << endl;
452 }
453 }
454 if (f_v) {
455 cout << "function_polish::evaluate done" << endl;
456 }
457}
458
459}}
functions related to strings and character arrays
an individual command which is part of a function expressed in reverse polish notation
Definition: globals.h:27
description of a function in reverse polish notation from the command line
Definition: globals.h:61
function_polish_description * Descr
Definition: globals.h:90
void print_code(int i0, int len, int verbose_level)
std::vector< std::pair< std::string, double > > Constants
Definition: globals.h:94
std::vector< std::string > Variables
Definition: globals.h:92
void init(function_polish_description *Descr, int verbose_level)
void evaluate(double *variable_values, double *output_values, int verbose_level)
std::vector< function_command > Code
Definition: globals.h:99
#define TRUE
Definition: foundations.h:231
the orbiter library for the classification of combinatorial objects