1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
|
#ifndef WP_PARSER_Y_H_
#define WP_PARSER_Y_H_
#include <AMReX_GpuQualifiers.H>
#include <AMReX_GpuPrint.H>
#include <AMReX_REAL.H>
#include <AMReX_Math.H>
#include <AMReX_Print.H>
#include <cmath>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <type_traits>
enum wp_f1_t { // Built-in functions with one argument
WP_SQRT = 1,
WP_EXP,
WP_LOG,
WP_LOG10,
WP_SIN,
WP_COS,
WP_TAN,
WP_ASIN,
WP_ACOS,
WP_ATAN,
WP_SINH,
WP_COSH,
WP_TANH,
WP_ABS,
WP_POW_M3,
WP_POW_M2,
WP_POW_M1,
WP_POW_P1,
WP_POW_P2,
WP_POW_P3
};
enum wp_f2_t { // Built-in functions with two arguments
WP_POW = 1,
WP_GT,
WP_LT,
WP_GEQ,
WP_LEQ,
WP_EQ,
WP_NEQ,
WP_AND,
WP_OR,
WP_HEAVISIDE,
WP_JN,
WP_MIN,
WP_MAX
};
enum wp_node_t {
WP_NUMBER = 1,
WP_SYMBOL,
WP_ADD,
WP_SUB,
WP_MUL,
WP_DIV,
WP_NEG,
WP_F1,
WP_F2,
WP_ADD_VP, /* types below are generated by optimization */
WP_ADD_PP,
WP_SUB_VP,
WP_SUB_PP,
WP_MUL_VP,
WP_MUL_PP,
WP_DIV_VP,
WP_DIV_PP,
WP_NEG_P
};
/* In C, the address of the first member of a struct is the same as
* the address of the struct itself. Because of this, all struct wp_*
* pointers can be passed around as struct wp_node pointer and enum
* wp_node_t type can be safely checked to determine their real type.
*/
union wp_ip {
int i;
amrex_real* p;
};
union wp_vp {
amrex_real v;
union wp_ip ip;
};
struct wp_node {
enum wp_node_t type;
struct wp_node* l;
struct wp_node* r;
union wp_vp lvp; // After optimization, this may store left value/pointer.
union wp_ip rip; // this may store right pointer.
};
struct wp_number {
enum wp_node_t type;
amrex_real value;
};
struct wp_symbol {
enum wp_node_t type;
char* name;
union wp_ip ip;
};
struct wp_f1 { /* Builtin functions with one argument */
enum wp_node_t type;
struct wp_node* l;
enum wp_f1_t ftype;
};
struct wp_f2 { /* Builtin functions with two arguments */
enum wp_node_t type;
struct wp_node* l;
struct wp_node* r;
enum wp_f2_t ftype;
};
/*******************************************************************/
/* These functions are used in bison rules to generate the original
* AST. */
void wp_defexpr (struct wp_node* body);
struct wp_node* wp_newnumber (amrex_real d);
struct wp_symbol* wp_makesymbol (char* name);
struct wp_node* wp_newsymbol (struct wp_symbol* sym);
struct wp_node* wp_newnode (enum wp_node_t type, struct wp_node* l,
struct wp_node* r);
struct wp_node* wp_newf1 (enum wp_f1_t ftype, struct wp_node* l);
struct wp_node* wp_newf2 (enum wp_f2_t ftype, struct wp_node* l,
struct wp_node* r);
void wxparsererror (char const *s, ...);
/*******************************************************************/
/* This is our struct for storing AST in a more packed way. The whole
* tree is stored in a contiguous chunk of memory starting from void*
* p_root with a size of sz_mempool.
*/
struct wp_parser {
void* p_root;
void* p_free;
struct wp_node* ast;
size_t sz_mempool;
};
struct wp_parser* wp_parser_new (void);
void wp_parser_delete (struct wp_parser* parser);
struct wp_parser* wp_parser_dup (struct wp_parser* source);
struct wp_node* wp_parser_ast_dup (struct wp_parser* parser, struct wp_node* src, int move);
void wp_parser_regvar (struct wp_parser* parser, char const* name, amrex_real* p);
void wp_parser_regvar_gpu (struct wp_parser* parser, char const* name, int i);
void wp_parser_setconst (struct wp_parser* parser, char const* name, amrex_real c);
/* We need to walk the tree in these functions */
void wp_ast_optimize (struct wp_node* node);
size_t wp_ast_size (struct wp_node* node);
void wp_ast_print (struct wp_node* node);
void wp_ast_depth (struct wp_node* node, int* n);
void wp_ast_regvar (struct wp_node* node, char const* name, amrex_real* p);
void wp_ast_regvar_gpu (struct wp_node* node, char const* name, int i);
void wp_ast_setconst (struct wp_node* node, char const* name, amrex_real c);
template <typename T, std::enable_if_t<std::is_floating_point<T>::value,int> = 0>
AMREX_GPU_HOST_DEVICE
#ifdef AMREX_USE_GPU
AMREX_NO_INLINE
#endif
T
wp_call_f1 (enum wp_f1_t type, T a)
{
switch (type) {
case WP_SQRT: return std::sqrt(a);
case WP_EXP: return std::exp(a);
case WP_LOG: return std::log(a);
case WP_LOG10: return std::log10(a);
case WP_SIN: return std::sin(a);
case WP_COS: return std::cos(a);
case WP_TAN: return std::tan(a);
case WP_ASIN: return std::asin(a);
case WP_ACOS: return std::acos(a);
case WP_ATAN: return std::atan(a);
case WP_SINH: return std::sinh(a);
case WP_COSH: return std::cosh(a);
case WP_TANH: return std::tanh(a);
case WP_ABS: return amrex::Math::abs(a);
case WP_POW_M3: return amrex::Real(1.0)/(a*a*a);
case WP_POW_M2: return amrex::Real(1.0)/(a*a);
case WP_POW_M1: return amrex::Real(1.0)/a;
case WP_POW_P1: return a;
case WP_POW_P2: return a*a;
case WP_POW_P3: return a*a*a;
default:
#if AMREX_DEVICE_COMPILE
AMREX_DEVICE_PRINTF("wp_call_f1: Unknown function %d\n", type);
#else
amrex::AllPrint() << "wp_call_f1: Unknown function " << type << "\n";
#endif
return 0.0;
}
}
template <typename T, std::enable_if_t<std::is_floating_point<T>::value,int> = 0>
AMREX_GPU_HOST_DEVICE
#ifdef AMREX_USE_GPU
AMREX_NO_INLINE
#endif
T
wp_call_f2 (enum wp_f2_t type, T a, T b)
{
switch (type) {
case WP_POW:
return std::pow(a,b);
case WP_GT:
return (a > b) ? 1.0 : 0.0;
case WP_LT:
return (a < b) ? 1.0 : 0.0;
case WP_GEQ:
return (a >= b) ? 1.0 : 0.0;
case WP_LEQ:
return (a <= b) ? 1.0 : 0.0;
case WP_EQ:
return (a == b) ? 1.0 : 0.0;
case WP_NEQ:
return (a != b) ? 1.0 : 0.0;
case WP_AND:
return ((a != T(0)) && (b != T(0))) ? 1.0 : 0.0;
case WP_OR:
return ((a != T(0)) || (b != T(0))) ? 1.0 : 0.0;
case WP_HEAVISIDE:
return (a < 0.0) ? amrex::Real(0.0) : ((a > 0.0) ? amrex::Real(1.0) : b);
case WP_JN:
#ifdef AMREX_USE_DPCPP
// neither jn(f) nor std::cyl_bessel_j work yet
// https://github.com/oneapi-src/oneAPI-spec/issues/308
AMREX_DEVICE_PRINTF("wp_call_f2: Parser does not implement jn (%d) for SYCL/DPC++ yet\n", type);
amrex::Abort();
return 0.0;
#else
# if defined(AMREX_USE_FLOAT) && !defined(__APPLE__)
return jnf(a, b);
# else
return jn(a, b);
# endif
#endif
case WP_MIN:
return (a < b) ? a : b;
case WP_MAX:
return (a > b) ? a : b;
default:
#if AMREX_DEVICE_COMPILE
AMREX_DEVICE_PRINTF("wp_call_f2: Unknown function %d\n", type);
#else
amrex::AllPrint() << "wp_call_f2: Unknown function " << type << "\n";
#endif
amrex::Abort();
return 0.0;
}
}
#endif
|