Line data Source code
1 : #ifndef AMREX_PARSER_EXE_H_
2 : #define AMREX_PARSER_EXE_H_
3 : #include <AMReX_Config.H>
4 :
5 : #include <AMReX_Parser_Y.H>
6 : #include <AMReX_Vector.H>
7 :
8 : #include <limits>
9 :
10 : #ifndef AMREX_PARSER_STACK_SIZE
11 : #define AMREX_PARSER_STACK_SIZE 16
12 : #endif
13 :
14 : #define AMREX_PARSER_LOCAL_IDX0 1000
15 : #define AMREX_PARSER_GET_DATA(i) ((i)<1000) ? x[i] : pstack[(i)-1000]
16 :
17 : namespace amrex {
18 :
19 : // N: node
20 : // P: pointer offset
21 : // V: value (i.e., double literal)
22 :
23 : enum parser_exe_t {
24 : PARSER_EXE_NULL = 0,
25 : PARSER_EXE_NUMBER,
26 : PARSER_EXE_SYMBOL,
27 : PARSER_EXE_ADD,
28 : PARSER_EXE_SUB_F,
29 : PARSER_EXE_SUB_B,
30 : PARSER_EXE_MUL,
31 : PARSER_EXE_DIV_F,
32 : PARSER_EXE_DIV_B,
33 : PARSER_EXE_F1,
34 : PARSER_EXE_F2_F,
35 : PARSER_EXE_F2_B,
36 : PARSER_EXE_ADD_VP,
37 : PARSER_EXE_SUB_VP,
38 : PARSER_EXE_MUL_VP,
39 : PARSER_EXE_DIV_VP,
40 : PARSER_EXE_ADD_PP,
41 : PARSER_EXE_SUB_PP,
42 : PARSER_EXE_MUL_PP,
43 : PARSER_EXE_DIV_PP,
44 : PARSER_EXE_ADD_VN,
45 : PARSER_EXE_SUB_VN,
46 : PARSER_EXE_MUL_VN,
47 : PARSER_EXE_DIV_VN,
48 : PARSER_EXE_ADD_PN,
49 : PARSER_EXE_SUB_PN,
50 : PARSER_EXE_MUL_PN,
51 : PARSER_EXE_DIV_PN,
52 : PARSER_EXE_SQUARE,
53 : PARSER_EXE_POWI,
54 : PARSER_EXE_IF,
55 : PARSER_EXE_JUMP
56 : };
57 :
58 : struct alignas(8) ParserExeNull {
59 : enum parser_exe_t type = PARSER_EXE_NULL;
60 : };
61 :
62 : struct alignas(8) ParserExeNumber {
63 : enum parser_exe_t type = PARSER_EXE_NUMBER;
64 : double v;
65 : };
66 :
67 : struct alignas(8) ParserExeSymbol {
68 : enum parser_exe_t type = PARSER_EXE_SYMBOL;
69 : int i;
70 : };
71 :
72 : struct alignas(8) ParserExeADD {
73 : enum parser_exe_t type = PARSER_EXE_ADD;
74 : };
75 :
76 : struct alignas(8) ParserExeSUB_F {
77 : enum parser_exe_t type = PARSER_EXE_SUB_F;
78 : };
79 :
80 : struct alignas(8) ParserExeSUB_B {
81 : enum parser_exe_t type = PARSER_EXE_SUB_B;
82 : };
83 :
84 : struct alignas(8) ParserExeMUL {
85 : enum parser_exe_t type = PARSER_EXE_MUL;
86 : };
87 :
88 : struct alignas(8) ParserExeDIV_F {
89 : enum parser_exe_t type = PARSER_EXE_DIV_F;
90 : };
91 :
92 : struct alignas(8) ParserExeDIV_B {
93 : enum parser_exe_t type = PARSER_EXE_DIV_B;
94 : };
95 :
96 : struct alignas(8) ParserExeF1 {
97 : enum parser_exe_t type = PARSER_EXE_F1;
98 : parser_f1_t ftype;
99 : };
100 :
101 : struct alignas(8) ParserExeF2_F {
102 : enum parser_exe_t type = PARSER_EXE_F2_F;
103 : parser_f2_t ftype;
104 : };
105 :
106 : struct alignas(8) ParserExeF2_B {
107 : enum parser_exe_t type = PARSER_EXE_F2_B;
108 : parser_f2_t ftype;
109 : };
110 :
111 : struct alignas(8) ParserExeADD_VP {
112 : enum parser_exe_t type = PARSER_EXE_ADD_VP;
113 : int i;
114 : double v;
115 : };
116 :
117 : struct alignas(8) ParserExeSUB_VP {
118 : enum parser_exe_t type = PARSER_EXE_SUB_VP;
119 : int i;
120 : double v;
121 : };
122 :
123 : struct alignas(8) ParserExeMUL_VP {
124 : enum parser_exe_t type = PARSER_EXE_MUL_VP;
125 : int i;
126 : double v;
127 : };
128 :
129 : struct alignas(8) ParserExeDIV_VP {
130 : enum parser_exe_t type = PARSER_EXE_DIV_VP;
131 : int i;
132 : double v;
133 : };
134 :
135 : struct alignas(8) ParserExeADD_PP {
136 : enum parser_exe_t type = PARSER_EXE_ADD_PP;
137 : int i1;
138 : int i2;
139 : };
140 :
141 : struct alignas(8) ParserExeSUB_PP {
142 : enum parser_exe_t type = PARSER_EXE_SUB_PP;
143 : int i1;
144 : int i2;
145 : };
146 :
147 : struct alignas(8) ParserExeMUL_PP {
148 : enum parser_exe_t type = PARSER_EXE_MUL_PP;
149 : int i1;
150 : int i2;
151 : };
152 :
153 : struct alignas(8) ParserExeDIV_PP {
154 : enum parser_exe_t type = PARSER_EXE_DIV_PP;
155 : int i1;
156 : int i2;
157 : };
158 :
159 : struct alignas(8) ParserExeADD_VN {
160 : enum parser_exe_t type = PARSER_EXE_ADD_VN;
161 : double v;
162 : };
163 :
164 : struct alignas(8) ParserExeSUB_VN {
165 : enum parser_exe_t type = PARSER_EXE_SUB_VN;
166 : double v;
167 : };
168 :
169 : struct alignas(8) ParserExeMUL_VN {
170 : enum parser_exe_t type = PARSER_EXE_MUL_VN;
171 : double v;
172 : };
173 :
174 : struct alignas(8) ParserExeDIV_VN {
175 : enum parser_exe_t type = PARSER_EXE_DIV_VN;
176 : double v;
177 : };
178 :
179 : struct alignas(8) ParserExeADD_PN {
180 : enum parser_exe_t type = PARSER_EXE_ADD_PN;
181 : int i;
182 : };
183 :
184 : struct alignas(8) ParserExeSUB_PN {
185 : enum parser_exe_t type = PARSER_EXE_SUB_PN;
186 : int i;
187 : double sign;
188 : };
189 :
190 : struct alignas(8) ParserExeMUL_PN {
191 : enum parser_exe_t type = PARSER_EXE_MUL_PN;
192 : int i;
193 : };
194 :
195 : struct alignas(8) ParserExeDIV_PN {
196 : enum parser_exe_t type = PARSER_EXE_DIV_PN;
197 : int i;
198 : bool reverse;
199 : };
200 :
201 : struct alignas(8) ParserExeSquare {
202 : enum parser_exe_t type = PARSER_EXE_SQUARE;
203 : };
204 :
205 : struct alignas(8) ParserExePOWI {
206 : enum parser_exe_t type = PARSER_EXE_POWI;
207 : int i;
208 : };
209 :
210 : struct alignas(8) ParserExeIF {
211 : enum parser_exe_t type = PARSER_EXE_IF;
212 : int offset;
213 : };
214 :
215 : struct alignas(8) ParserExeJUMP {
216 : enum parser_exe_t type = PARSER_EXE_JUMP;
217 : int offset;
218 : };
219 :
220 : template <int N>
221 : struct ParserStack
222 : {
223 : double m_data[N];
224 : int m_size = 0;
225 102654 : constexpr void push (double v) { m_data[m_size++] = v; }
226 73278 : constexpr void pop () { --m_size; }
227 : [[nodiscard]] constexpr double const& top () const { return m_data[m_size-1]; }
228 331818 : [[nodiscard]] constexpr double & top () { return m_data[m_size-1]; }
229 0 : [[nodiscard]] constexpr double operator[] (int i) const { return m_data[i]; }
230 : };
231 :
232 : AMREX_GPU_HOST_DEVICE AMREX_FORCE_INLINE
233 : double parser_exe_eval (const char* p, double const* x)
234 : {
235 29376 : if (p == nullptr) { return std::numeric_limits<double>::max(); }
236 :
237 29376 : ParserStack<AMREX_PARSER_STACK_SIZE> pstack;
238 332044 : while (*((parser_exe_t*)p) != PARSER_EXE_NULL) { // NOLINT
239 302668 : switch (*((parser_exe_t*)p))
240 : {
241 22290 : case PARSER_EXE_NUMBER:
242 : {
243 22290 : pstack.push(((ParserExeNumber*)p)->v);
244 22290 : p += sizeof(ParserExeNumber);
245 22290 : break;
246 : }
247 80304 : case PARSER_EXE_SYMBOL:
248 : {
249 80304 : int i = ((ParserExeSymbol*)p)->i;
250 80304 : double d = AMREX_PARSER_GET_DATA(i);
251 80304 : pstack.push(d);
252 80304 : p += sizeof(ParserExeSymbol);
253 80304 : break;
254 : }
255 51214 : case PARSER_EXE_ADD:
256 : {
257 51214 : double b = pstack.top(); // NOLINT
258 51214 : pstack.pop();
259 51214 : pstack.top() += b; // NOLINT
260 51214 : p += sizeof(ParserExeADD);
261 51214 : break;
262 : }
263 0 : case PARSER_EXE_SUB_F:
264 : {
265 0 : double b = pstack.top(); // NOLINT
266 0 : pstack.pop();
267 0 : pstack.top() -= b; // NOLINT
268 0 : p += sizeof(ParserExeSUB_F);
269 0 : break;
270 : }
271 0 : case PARSER_EXE_SUB_B:
272 : {
273 0 : double b = pstack.top(); // NOLINT
274 0 : pstack.pop();
275 0 : pstack.top() = b - pstack.top(); // NOLINT
276 0 : p += sizeof(ParserExeSUB_B);
277 0 : break;
278 : }
279 0 : case PARSER_EXE_MUL:
280 : {
281 0 : double b = pstack.top(); // NOLINT
282 0 : pstack.pop();
283 0 : pstack.top() *= b; // NOLINT
284 0 : p += sizeof(ParserExeMUL);
285 0 : break;
286 : }
287 0 : case PARSER_EXE_DIV_F:
288 : {
289 0 : double v = pstack.top(); // NOLINT
290 0 : pstack.pop();
291 0 : pstack.top() /= v; // NOLINT
292 0 : p += sizeof(ParserExeDIV_F);
293 0 : break;
294 : }
295 0 : case PARSER_EXE_DIV_B:
296 : {
297 0 : double v = pstack.top(); // NOLINT
298 0 : pstack.pop();
299 0 : pstack.top() = v / pstack.top(); // NOLINT
300 0 : p += sizeof(ParserExeDIV_B);
301 0 : break;
302 : }
303 7086 : case PARSER_EXE_F1:
304 : {
305 14172 : pstack.top() = parser_call_f1(((ParserExeF1*)p)->ftype, pstack.top()); // NOLINT
306 7086 : p += sizeof(ParserExeF1);
307 7086 : break;
308 : }
309 22064 : case PARSER_EXE_F2_F:
310 : {
311 22064 : double v = pstack.top(); // NOLINT
312 22064 : pstack.pop();
313 44128 : pstack.top() = parser_call_f2(((ParserExeF2_F*)p)->ftype, pstack.top(), v); // NOLINT
314 22064 : p += sizeof(ParserExeF2_F);
315 22064 : break;
316 : }
317 0 : case PARSER_EXE_F2_B:
318 : {
319 0 : double v = pstack.top(); // NOLINT
320 0 : pstack.pop();
321 0 : pstack.top() = parser_call_f2(((ParserExeF2_B*)p)->ftype, v, pstack.top()); // NOLINT
322 0 : p += sizeof(ParserExeF2_B);
323 0 : break;
324 : }
325 0 : case PARSER_EXE_ADD_VP:
326 : {
327 0 : int i = ((ParserExeADD_VP*)p)->i;
328 0 : double d = AMREX_PARSER_GET_DATA(i);
329 0 : pstack.push(((ParserExeADD_VP*)p)->v + d);
330 0 : p += sizeof(ParserExeADD_VP);
331 0 : break;
332 : }
333 0 : case PARSER_EXE_SUB_VP:
334 : {
335 0 : int i = ((ParserExeSUB_VP*)p)->i;
336 0 : double d = AMREX_PARSER_GET_DATA(i);
337 0 : pstack.push(((ParserExeSUB_VP*)p)->v - d);
338 0 : p += sizeof(ParserExeSUB_VP);
339 0 : break;
340 : }
341 0 : case PARSER_EXE_MUL_VP:
342 : {
343 0 : int i = ((ParserExeMUL_VP*)p)->i;
344 0 : double d = AMREX_PARSER_GET_DATA(i);
345 0 : pstack.push(((ParserExeMUL_VP*)p)->v * d);
346 0 : p += sizeof(ParserExeMUL_VP);
347 0 : break;
348 : }
349 0 : case PARSER_EXE_DIV_VP:
350 : {
351 0 : int i = ((ParserExeDIV_VP*)p)->i;
352 0 : double d = AMREX_PARSER_GET_DATA(i);
353 0 : pstack.push(((ParserExeDIV_VP*)p)->v / d);
354 0 : p += sizeof(ParserExeDIV_VP);
355 0 : break;
356 : }
357 0 : case PARSER_EXE_ADD_PP:
358 : {
359 0 : int i = ((ParserExeADD_PP*)p)->i1;
360 0 : double d1 = AMREX_PARSER_GET_DATA(i);
361 0 : i = ((ParserExeADD_PP*)p)->i2;
362 0 : double d2 = AMREX_PARSER_GET_DATA(i);
363 0 : pstack.push(d1+d2);
364 0 : p += sizeof(ParserExeADD_PP);
365 0 : break;
366 : }
367 30 : case PARSER_EXE_SUB_PP:
368 : {
369 30 : int i = ((ParserExeSUB_PP*)p)->i1;
370 30 : double d1 = AMREX_PARSER_GET_DATA(i);
371 30 : i = ((ParserExeSUB_PP*)p)->i2;
372 30 : double d2 = AMREX_PARSER_GET_DATA(i);
373 30 : pstack.push(d1-d2);
374 30 : p += sizeof(ParserExeSUB_PP);
375 30 : break;
376 : }
377 30 : case PARSER_EXE_MUL_PP:
378 : {
379 30 : int i = ((ParserExeMUL_PP*)p)->i1;
380 30 : double d1 = AMREX_PARSER_GET_DATA(i);
381 30 : i = ((ParserExeMUL_PP*)p)->i2;
382 30 : double d2 = AMREX_PARSER_GET_DATA(i);
383 30 : pstack.push(d1*d2);
384 30 : p += sizeof(ParserExeMUL_PP);
385 30 : break;
386 : }
387 0 : case PARSER_EXE_DIV_PP:
388 : {
389 0 : int i = ((ParserExeDIV_PP*)p)->i1;
390 0 : double d1 = AMREX_PARSER_GET_DATA(i);
391 0 : i = ((ParserExeDIV_PP*)p)->i2;
392 0 : double d2 = AMREX_PARSER_GET_DATA(i);
393 0 : pstack.push(d1/d2);
394 0 : p += sizeof(ParserExeDIV_PP);
395 0 : break;
396 : }
397 14112 : case PARSER_EXE_ADD_VN:
398 : {
399 14112 : pstack.top() += ((ParserExeADD_VN*)p)->v; // NOLINT
400 14112 : p += sizeof(ParserExeADD_VN);
401 14112 : break;
402 : }
403 0 : case PARSER_EXE_SUB_VN:
404 : {
405 0 : pstack.top() = ((ParserExeSUB_VN*)p)->v - pstack.top(); // NOLINT
406 0 : p += sizeof(ParserExeSUB_VN);
407 0 : break;
408 : }
409 25204 : case PARSER_EXE_MUL_VN:
410 : {
411 25204 : pstack.top() *= ((ParserExeMUL_VN*)p)->v; // NOLINT
412 25204 : p += sizeof(ParserExeMUL_VN);
413 25204 : break;
414 : }
415 0 : case PARSER_EXE_DIV_VN:
416 : {
417 0 : pstack.top() = ((ParserExeDIV_VN*)p)->v / pstack.top(); // NOLINT
418 0 : p += sizeof(ParserExeDIV_VN);
419 0 : break;
420 : }
421 0 : case PARSER_EXE_ADD_PN:
422 : {
423 0 : int i = ((ParserExeADD_PN*)p)->i;
424 0 : double d = AMREX_PARSER_GET_DATA(i);
425 0 : pstack.top() += d; // NOLINT
426 0 : p += sizeof(ParserExeADD_PN);
427 0 : break;
428 : }
429 0 : case PARSER_EXE_SUB_PN:
430 : {
431 0 : int i = ((ParserExeSUB_PN*)p)->i;
432 0 : double d = AMREX_PARSER_GET_DATA(i);
433 0 : pstack.top() = (d - pstack.top()) * (((ParserExeSUB_PN*)p)->sign); // NOLINT
434 0 : p += sizeof(ParserExeSUB_PN);
435 0 : break;
436 : }
437 0 : case PARSER_EXE_MUL_PN:
438 : {
439 0 : int i = ((ParserExeMUL_PN*)p)->i;
440 0 : double d = AMREX_PARSER_GET_DATA(i);
441 0 : pstack.top() *= d; // NOLINT
442 0 : p += sizeof(ParserExeMUL_PN);
443 0 : break;
444 : }
445 0 : case PARSER_EXE_DIV_PN:
446 : {
447 0 : int i = ((ParserExeDIV_PN*)p)->i;
448 0 : double d = AMREX_PARSER_GET_DATA(i);
449 0 : if (((ParserExeDIV_PN*)p)->reverse) {
450 0 : pstack.top() /= d; // NOLINT
451 : } else {
452 0 : pstack.top() = d / pstack.top(); // NOLINT
453 : }
454 0 : p += sizeof(ParserExeDIV_PN);
455 0 : break;
456 : }
457 80334 : case PARSER_EXE_SQUARE:
458 : {
459 80334 : double& d = pstack.top();
460 80334 : d *= d;
461 80334 : p += sizeof(ParserExeSquare);
462 80334 : break;
463 : }
464 0 : case PARSER_EXE_POWI:
465 : {
466 0 : double& d = pstack.top();
467 0 : int n = ((ParserExePOWI*)p)->i;
468 0 : if (n != 0) {
469 0 : if (n < 0) {
470 0 : d = 1.0/d;
471 0 : n = -n;
472 : }
473 0 : double y = 1.0;
474 0 : while (n > 1) {
475 0 : if (n % 2 == 0) {
476 0 : d *= d;
477 0 : n = n/2;
478 : } else {
479 0 : y *= d;
480 0 : d *= d;
481 0 : n = (n-1)/2;
482 : }
483 : }
484 0 : d *= y;
485 : } else {
486 0 : d = 1.0;
487 : }
488 0 : p += sizeof(ParserExePOWI);
489 0 : break;
490 : }
491 0 : case PARSER_EXE_IF:
492 : {
493 0 : double cond = pstack.top(); // NOLINT
494 0 : pstack.pop();
495 0 : if (cond == 0.0) { // false branch
496 0 : p += ((ParserExeIF*)p)->offset;
497 : }
498 0 : p += sizeof(ParserExeIF);
499 0 : break;
500 : }
501 0 : case PARSER_EXE_JUMP:
502 : {
503 0 : int offset = ((ParserExeJUMP*)p)->offset;
504 0 : p += sizeof(ParserExeJUMP) + offset;
505 0 : break;
506 : }
507 0 : default:
508 : AMREX_ALWAYS_ASSERT_WITH_MESSAGE(false,"parser_exe_eval: unknown node type");
509 : }
510 : }
511 29376 : return pstack.top(); // NOLINT
512 : }
513 :
514 : void parser_compile_exe_size (struct parser_node* node, char*& p, std::size_t& exe_size,
515 : int& max_stack_size, int& stack_size, Vector<char const*>& local_variables);
516 :
517 : inline std::size_t
518 19 : parser_exe_size (struct amrex_parser* parser, int& max_stack_size, int& stack_size)
519 : {
520 19 : parser_ast_sort(parser->ast);
521 19 : char* p = nullptr;
522 19 : std::size_t exe_size = 0;
523 19 : max_stack_size = 0;
524 19 : stack_size = 0;
525 19 : Vector<char const*> local_variables;
526 19 : parser_compile_exe_size(parser->ast, p, exe_size, max_stack_size, stack_size, local_variables);
527 19 : stack_size -= static_cast<int>(local_variables.size())+1;
528 38 : return exe_size+sizeof(ParserExeNull);
529 : }
530 :
531 : inline Vector<char const*>
532 19 : parser_compile (struct amrex_parser* parser, char* p)
533 : {
534 19 : std::size_t exe_size = 0;
535 19 : int max_stack_size = 0;
536 19 : int stack_size = 0;
537 19 : Vector<char const*> local_variables;
538 19 : parser_compile_exe_size(parser->ast, p, exe_size, max_stack_size, stack_size, local_variables);
539 19 : new(p) ParserExeNull;
540 38 : return local_variables;
541 : }
542 :
543 : void parser_exe_print(char const* parser, Vector<std::string> const& vars,
544 : Vector<char const*> const& locals);
545 :
546 : }
547 :
548 : #endif
|