1 /*
2 This file is part of CDO. CDO is a collection of Operators to manipulate and analyse Climate model Data.
3
4 Author: Uwe Schulzweida
5
6 */
7
8 #include <cstdlib>
9 #include <cassert>
10 #include <cdi.h>
11
12 #include "cdo_options.h"
13 #include "dmemory.h"
14 #include "process_int.h"
15 #include "field.h"
16 #include "expr.h"
17 #include "expr_fun.h"
18 #include "expr_yacc.h"
19 #include "cdo_zaxis.h"
20
21 static const char *const ExIn[] = { "expr", "init" };
22 static const char *const tmpvnm = "_tmp_";
23 static int pointID = -1;
24 static int zonalID = -1;
25 static int surfaceID = -1;
26
27 enum
28 {
29 FT_STD,
30 FT_CONST,
31 FT_FLD,
32 FT_ZON,
33 FT_VERT,
34 FT_COORD,
35 FT_1C,
36 FT_2C,
37 FT_0
38 };
39
40 // clang-format off
41 auto expr_func_con_var = [](auto hasMissvals, auto n, auto mv, const auto cVal, const auto &vIn, auto &vOut, auto binray_operator)
__anona30997820202(auto hasMissvals, auto n, auto mv, const auto cVal, const auto &vIn, auto &vOut, auto binray_operator) 42 {
43 if (hasMissvals)
44 {
45 if (std::isnan(mv))
46 for (size_t i = 0; i < n; ++i) vOut[i] = dbl_is_equal(vIn[i], mv) ? mv : binray_operator(cVal, vIn[i]);
47 else
48 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(vIn[i], mv) ? mv : binray_operator(cVal, vIn[i]);
49 }
50 else
51 {
52 for (size_t i = 0; i < n; ++i) vOut[i] = binray_operator(cVal, vIn[i]);
53 }
54 };
55
56 auto expr_mul_con_var = [](auto hasMissvals, auto n, auto mv, const auto cVal, const auto &vIn, auto &vOut)
__anona30997820302(auto hasMissvals, auto n, auto mv, const auto cVal, const auto &vIn, auto &vOut) 57 {
58 if (hasMissvals)
59 {
60 if (std::isnan(mv))
61 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(cVal, 0.0) ? 0.0 : dbl_is_equal(vIn[i], mv) ? mv : binary_op_MUL(cVal, vIn[i]);
62 else
63 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(cVal, 0.0) ? 0.0 : is_equal(vIn[i], mv) ? mv : binary_op_MUL(cVal, vIn[i]);
64 }
65 else
66 {
67 for (size_t i = 0; i < n; ++i) vOut[i] = binary_op_MUL(cVal, vIn[i]);
68 }
69 };
70
71 auto expr_div_con_var = [](auto hasMissvals, auto n, auto mv, const auto cVal, const auto &vIn, auto &vOut)
__anona30997820402(auto hasMissvals, auto n, auto mv, const auto cVal, const auto &vIn, auto &vOut) 72 {
73 if (hasMissvals)
74 {
75 if (std::isnan(mv))
76 for (size_t i = 0; i < n; ++i) vOut[i] = (dbl_is_equal(vIn[i], mv) || dbl_is_equal(vIn[i], 0.0)) ? mv : binary_op_DIV(cVal, vIn[i]);
77 else
78 for (size_t i = 0; i < n; ++i) vOut[i] = (is_equal(vIn[i], mv) || is_equal(vIn[i], 0.0)) ? mv : binary_op_DIV(cVal, vIn[i]);
79 }
80 else
81 {
82 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(vIn[i], 0.0) ? mv : binary_op_DIV(cVal, vIn[i]);
83 }
84 };
85
86 auto expr_func_var_con = [](auto hasMissvals, auto n, auto mv, const auto &vIn, const auto cVal, auto &vOut, auto binray_operator)
__anona30997820502(auto hasMissvals, auto n, auto mv, const auto &vIn, const auto cVal, auto &vOut, auto binray_operator) 87 {
88 if (hasMissvals)
89 {
90 if (std::isnan(mv))
91 for (size_t i = 0; i < n; ++i) vOut[i] = dbl_is_equal(vIn[i], mv) ? mv : binray_operator(vIn[i], cVal);
92 else
93 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(vIn[i], mv) ? mv : binray_operator(vIn[i], cVal);
94 }
95 else
96 {
97 for (size_t i = 0; i < n; ++i) vOut[i] = binray_operator(vIn[i], cVal);
98 }
99 };
100
101 auto expr_mul_var_con = [](auto hasMissvals, auto n, auto mv, const auto &vIn, const auto cVal, auto &vOut)
__anona30997820602(auto hasMissvals, auto n, auto mv, const auto &vIn, const auto cVal, auto &vOut) 102 {
103 if (hasMissvals)
104 {
105 if (std::isnan(mv))
106 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(cVal, 0.0) ? 0.0 : dbl_is_equal(vIn[i], mv) ? mv : binary_op_MUL(vIn[i], cVal);
107 else
108 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(cVal, 0.0) ? 0.0 : is_equal(vIn[i], mv) ? mv : binary_op_MUL(vIn[i], cVal);
109 }
110 else
111 {
112 for (size_t i = 0; i < n; ++i) vOut[i] = binary_op_MUL(vIn[i], cVal);
113 }
114 };
115
116 auto expr_div_var_con = [](auto hasMissvals, auto n, auto mv, const auto &vIn, const auto cVal, auto &vOut)
__anona30997820702(auto hasMissvals, auto n, auto mv, const auto &vIn, const auto cVal, auto &vOut) 117 {
118 if (hasMissvals)
119 {
120 if (std::isnan(mv))
121 for (size_t i = 0; i < n; ++i) vOut[i] = (dbl_is_equal(vIn[i], mv) || dbl_is_equal(cVal, 0.0)) ? mv : binary_op_DIV(vIn[i], cVal);
122 else
123 for (size_t i = 0; i < n; ++i) vOut[i] = (is_equal(vIn[i], mv) || is_equal(cVal, 0.0)) ? mv : binary_op_DIV(vIn[i], cVal);
124 }
125 else
126 {
127 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(cVal, 0.0) ? mv : binary_op_DIV(vIn[i], cVal);
128 }
129 };
130
131 auto expr_func_var_var = [](auto hasMissvals, auto n, auto mv1, auto mv2, const auto &vIn1, const auto &vIn2, auto &vOut, auto binray_operator)
__anona30997820802(auto hasMissvals, auto n, auto mv1, auto mv2, const auto &vIn1, const auto &vIn2, auto &vOut, auto binray_operator) 132 {
133 if (hasMissvals)
134 {
135 if (std::isnan(mv1) || std::isnan(mv2))
136 for (size_t i = 0; i < n; ++i) vOut[i] = (dbl_is_equal(vIn1[i], mv1) || dbl_is_equal(vIn2[i], mv2)) ? mv1 : binray_operator(vIn1[i], vIn2[i]);
137 else
138 for (size_t i = 0; i < n; ++i) vOut[i] = (is_equal(vIn1[i], mv1) || is_equal(vIn2[i], mv2)) ? mv1 : binray_operator(vIn1[i], vIn2[i]);
139 }
140 else
141 {
142 for (size_t i = 0; i < n; ++i) vOut[i] = binray_operator(vIn1[i], vIn2[i]);
143 }
144 };
145
146 auto expr_mul_var_var = [](auto hasMissvals, auto n, auto mv1, auto mv2, const auto &vIn1, const auto &vIn2, auto &vOut)
__anona30997820902(auto hasMissvals, auto n, auto mv1, auto mv2, const auto &vIn1, const auto &vIn2, auto &vOut) 147 {
148 if (hasMissvals)
149 {
150 if (std::isnan(mv1) || std::isnan(mv2))
151 for (size_t i = 0; i < n; ++i)
152 vOut[i] = (dbl_is_equal(vIn1[i], 0.0) || dbl_is_equal(vIn2[i], 0.0)) ? 0.0 : (dbl_is_equal(vIn1[i], mv1) || dbl_is_equal(vIn2[i], mv2)) ? mv1 : binary_op_MUL(vIn1[i], vIn2[i]);
153 else
154 for (size_t i = 0; i < n; ++i)
155 vOut[i] = (is_equal(vIn1[i], 0.0) || is_equal(vIn2[i], 0.0)) ? 0.0 : (is_equal(vIn1[i], mv1) || is_equal(vIn2[i], mv2)) ? mv1 : binary_op_MUL(vIn1[i], vIn2[i]);
156 }
157 else
158 {
159 for (size_t i = 0; i < n; ++i) vOut[i] = binary_op_MUL(vIn1[i], vIn2[i]);
160 }
161 };
162
163 auto expr_div_var_var = [](auto hasMissvals, auto n, auto mv1, auto mv2, const auto &vIn1, const auto &vIn2, auto &vOut)
__anona30997820a02(auto hasMissvals, auto n, auto mv1, auto mv2, const auto &vIn1, const auto &vIn2, auto &vOut) 164 {
165 if (hasMissvals)
166 {
167 if (std::isnan(mv1) || std::isnan(mv2))
168 for (size_t i = 0; i < n; ++i) vOut[i] = (dbl_is_equal(vIn1[i], mv1) || dbl_is_equal(vIn2[i], mv2) || dbl_is_equal(vIn2[i], 0.0)) ? mv1 : binary_op_DIV(vIn1[i], vIn2[i]);
169 else
170 for (size_t i = 0; i < n; ++i) vOut[i] = (is_equal(vIn1[i], mv1) || is_equal(vIn2[i], mv2) || is_equal(vIn2[i], 0.0)) ? mv1 : binary_op_DIV(vIn1[i], vIn2[i]);
171 }
172 else
173 {
174 for (size_t i = 0; i < n; ++i) vOut[i] = is_equal(vIn2[i], 0.0) ? mv1 : binary_op_DIV(vIn1[i], vIn2[i]);
175 }
176 };
177 // clang-format on
178
179 // clang-format off
f_float(const double x)180 static double f_float(const double x) { return (float) (x); }
f_int(const double x)181 static double f_int(const double x) { return (int) (x); }
f_nint(const double x)182 static double f_nint(const double x) { return std::round(x); }
f_rand(const double x)183 static double f_rand(const double x) { (void)x; return ((double) std::rand()) / ((double) RAND_MAX); }
f_sqr(const double x)184 static double f_sqr(const double x) { return x * x; }
f_rad(const double x)185 static double f_rad(const double x) { return x * M_PI / 180.0; }
f_deg(const double x)186 static double f_deg(const double x) { return x * 180.0 / M_PI; }
f_isMissval(const double x)187 static double f_isMissval(const double x) { (void)x; return 0.0; }
188
pt_ngp(const paramType * const p)189 static double pt_ngp(const paramType *const p) { return p->ngp; }
pt_nlev(const paramType * const p)190 static double pt_nlev(const paramType *const p) { return p->nlev; }
pt_size(const paramType * const p)191 static double pt_size(const paramType *const p) { return p->ngp * p->nlev; }
pt_missval(const paramType * const p)192 static double pt_missval(const paramType *const p) { return p->missval; }
ts_ctimestep(const double * const data)193 static double ts_ctimestep(const double *const data) { return std::lround(data[CTIMESTEP]); }
ts_cdate(const double * const data)194 static double ts_cdate(const double *const data) { return std::lround(data[CDATE]); }
ts_ctime(const double * const data)195 static double ts_ctime(const double *const data) { return std::lround(data[CTIME]); }
ts_cdeltat(const double * const data)196 static double ts_cdeltat(const double *const data) { return data[CDELTAT]; }
ts_cday(const double * const data)197 static double ts_cday(const double *const data) { return data[CDAY]; }
ts_cmonth(const double * const data)198 static double ts_cmonth(const double *const data) { return data[CMONTH]; }
ts_cyear(const double * const data)199 static double ts_cyear(const double *const data) { return data[CYEAR]; }
ts_csecond(const double * const data)200 static double ts_csecond(const double *const data) { return data[CSECOND]; }
ts_cminute(const double * const data)201 static double ts_cminute(const double *const data) { return data[CMINUTE]; }
ts_chour(const double * const data)202 static double ts_chour(const double *const data) { return data[CHOUR]; }
203 // clang-format on
204
205 struct func_t
206 {
207 int type;
208 int flag;
209 const char *name; // function name
210 void (*func)(void); // pointer to function
211 };
212
213 // clang-format off
214 static const func_t fun_sym_tbl[] = {
215 // scalar functions
216 { FT_STD, 0, "abs", (void (*)(void))((double (*)(double)) fabs) }, // math functions could be inlined
217 { FT_STD, 0, "floor", (void (*)(void))((double (*)(double)) floor) },
218 { FT_STD, 0, "ceil", (void (*)(void))((double (*)(double)) ceil) },
219 { FT_STD, 0, "sqrt", (void (*)(void))((double (*)(double)) sqrt) },
220 { FT_STD, 0, "exp", (void (*)(void))((double (*)(double)) exp) },
221 { FT_STD, 0, "erf", (void (*)(void))((double (*)(double)) erf) },
222 { FT_STD, 0, "log", (void (*)(void))((double (*)(double)) log) },
223 { FT_STD, 0, "ln", (void (*)(void))((double (*)(double)) log) },
224 { FT_STD, 0, "log10", (void (*)(void))((double (*)(double)) log10) },
225 { FT_STD, 0, "sin", (void (*)(void))((double (*)(double)) sin) },
226 { FT_STD, 0, "cos", (void (*)(void))((double (*)(double)) cos) },
227 { FT_STD, 0, "tan", (void (*)(void))((double (*)(double)) tan) },
228 { FT_STD, 0, "sinh", (void (*)(void))((double (*)(double)) sinh) },
229 { FT_STD, 0, "cosh", (void (*)(void))((double (*)(double)) cosh) },
230 { FT_STD, 0, "tanh", (void (*)(void))((double (*)(double)) tanh) },
231 { FT_STD, 0, "asin", (void (*)(void))((double (*)(double)) asin) },
232 { FT_STD, 0, "acos", (void (*)(void))((double (*)(double)) acos) },
233 { FT_STD, 0, "atan", (void (*)(void))((double (*)(double)) atan) },
234 { FT_STD, 0, "asinh", (void (*)(void))((double (*)(double)) asinh) },
235 { FT_STD, 0, "acosh", (void (*)(void))((double (*)(double)) acosh) },
236 { FT_STD, 0, "atanh", (void (*)(void))((double (*)(double)) atanh) },
237 { FT_STD, 0, "gamma", (void (*)(void))((double (*)(double)) tgamma) },
238 { FT_STD, 0, "float", reinterpret_cast<void (*)(void)>(&f_float) },
239 { FT_STD, 0, "int", reinterpret_cast<void (*)(void)>(&f_int) },
240 { FT_STD, 0, "nint", reinterpret_cast<void (*)(void)>(&f_nint) },
241 { FT_STD, 0, "rand", reinterpret_cast<void (*)(void)>(&f_rand) },
242 { FT_STD, 0, "sqr", reinterpret_cast<void (*)(void)>(&f_sqr) },
243 { FT_STD, 0, "rad", reinterpret_cast<void (*)(void)>(&f_rad) },
244 { FT_STD, 0, "deg", reinterpret_cast<void (*)(void)>(&f_deg) },
245 { FT_STD, 0, "isMissval", reinterpret_cast<void (*)(void)>(&f_isMissval) },
246
247 // constant functions
248 { FT_CONST, 0, "ngp", reinterpret_cast<void (*)(void)>(&pt_ngp) }, // number of horizontal grid points
249 { FT_CONST, 0, "nlev", reinterpret_cast<void (*)(void)>(&pt_nlev) }, // number of vertical levels
250 { FT_CONST, 0, "size", reinterpret_cast<void (*)(void)>(&pt_size) }, // ngp*nlev
251 { FT_CONST, 0, "missval", reinterpret_cast<void (*)(void)>(&pt_missval) }, // Returns the missing value of a variable
252
253 // CDO field functions (Reduce grid to point)
254 { FT_FLD, 0, "fldmin", reinterpret_cast<void (*)(void)>(&field_min) },
255 { FT_FLD, 0, "fldmax", reinterpret_cast<void (*)(void)>(&field_max) },
256 { FT_FLD, 0, "fldsum", reinterpret_cast<void (*)(void)>(&field_sum) },
257 { FT_FLD, 1, "fldmean", reinterpret_cast<void (*)(void)>(&field_meanw) },
258 { FT_FLD, 1, "fldavg", reinterpret_cast<void (*)(void)>(&field_avgw) },
259 { FT_FLD, 1, "fldstd", reinterpret_cast<void (*)(void)>(&field_stdw) },
260 { FT_FLD, 1, "fldstd1", reinterpret_cast<void (*)(void)>(&field_std1w) },
261 { FT_FLD, 1, "fldvar", reinterpret_cast<void (*)(void)>(&field_varw) },
262 { FT_FLD, 1, "fldvar1", reinterpret_cast<void (*)(void)>(&field_var1w) },
263
264 // CDO zonal functions (Reduce grid to point)
265 { FT_ZON, 0, "zonmin", reinterpret_cast<void (*)(void)>(&zonal_min) },
266 { FT_ZON, 0, "zonmax", reinterpret_cast<void (*)(void)>(&zonal_max) },
267 { FT_ZON, 0, "zonsum", reinterpret_cast<void (*)(void)>(&zonal_sum) },
268 { FT_ZON, 0, "zonmean", reinterpret_cast<void (*)(void)>(&zonal_mean) },
269 { FT_ZON, 0, "zonavg", reinterpret_cast<void (*)(void)>(&zonal_avg) },
270 { FT_ZON, 0, "zonstd", reinterpret_cast<void (*)(void)>(&zonal_std) },
271 { FT_ZON, 0, "zonstd1", reinterpret_cast<void (*)(void)>(&zonal_std1) },
272 { FT_ZON, 0, "zonvar", reinterpret_cast<void (*)(void)>(&zonal_var) },
273 { FT_ZON, 0, "zonvar1", reinterpret_cast<void (*)(void)>(&zonal_var1) },
274
275 // CDO field functions (Reduce level to point)
276 { FT_VERT, 0, "vertmin", reinterpret_cast<void (*)(void)>(&field_min) },
277 { FT_VERT, 0, "vertmax", reinterpret_cast<void (*)(void)>(&field_max) },
278 { FT_VERT, 0, "vertsum", reinterpret_cast<void (*)(void)>(&field_sum) },
279 { FT_VERT, 1, "vertmean", reinterpret_cast<void (*)(void)>(&field_meanw) },
280 { FT_VERT, 1, "vertavg", reinterpret_cast<void (*)(void)>(&field_avgw) },
281 { FT_VERT, 1, "vertstd", reinterpret_cast<void (*)(void)>(&field_stdw) },
282 { FT_VERT, 1, "vertstd1", reinterpret_cast<void (*)(void)>(&field_std1w) },
283 { FT_VERT, 1, "vertvar", reinterpret_cast<void (*)(void)>(&field_varw) },
284 { FT_VERT, 1, "vertvar1", reinterpret_cast<void (*)(void)>(&field_var1w) },
285
286 { FT_COORD, 0, "clon", nullptr },
287 { FT_COORD, 0, "clat", nullptr },
288 { FT_COORD, 0, "clev", nullptr },
289 { FT_COORD, 0, "cdeltaz", nullptr },
290 { FT_COORD, 0, "gridarea", nullptr },
291 { FT_COORD, 0, "gridweight", nullptr },
292
293 { FT_0, 0, "ctimestep", reinterpret_cast<void (*)(void)>(&ts_ctimestep) },
294 { FT_0, 0, "cdate", reinterpret_cast<void (*)(void)>(&ts_cdate) },
295 { FT_0, 0, "ctime", reinterpret_cast<void (*)(void)>(&ts_ctime) },
296 { FT_0, 0, "cdeltat", reinterpret_cast<void (*)(void)>(&ts_cdeltat) },
297 { FT_0, 0, "cday", reinterpret_cast<void (*)(void)>(&ts_cday) },
298 { FT_0, 0, "cmonth", reinterpret_cast<void (*)(void)>(&ts_cmonth) },
299 { FT_0, 0, "cyear", reinterpret_cast<void (*)(void)>(&ts_cyear) },
300 { FT_0, 0, "csecond", reinterpret_cast<void (*)(void)>(&ts_csecond) },
301 { FT_0, 0, "cminute", reinterpret_cast<void (*)(void)>(&ts_cminute) },
302 { FT_0, 0, "chour", reinterpret_cast<void (*)(void)>(&ts_chour) },
303
304 { FT_1C, 0, "sellevel", nullptr },
305 { FT_1C, 0, "sellevidx", nullptr },
306 { FT_2C, 0, "sellevelrange", nullptr },
307 { FT_2C, 0, "sellevidxrange", nullptr },
308 // {FT_1C, 0, "gridindex", nullptr},
309 };
310 // clang-format on
311
312 static const int NumFunc = sizeof(fun_sym_tbl) / sizeof(fun_sym_tbl[0]);
313
314 static void
node_data_delete(nodeType * p)315 node_data_delete(nodeType *p)
316 {
317 if (p)
318 {
319 if (p->param.data)
320 {
321 Free(p->param.data);
322 p->param.data = nullptr;
323 }
324 }
325 }
326
327 static void
node_delete(nodeType * p)328 node_delete(nodeType *p)
329 {
330 if (p)
331 {
332 if (p->type == typeVar) node_data_delete(p);
333 Free(p);
334 }
335 }
336
337 static int
get_funcID(const char * fun)338 get_funcID(const char *fun)
339 {
340 int funcID = -1;
341 for (int i = 0; i < NumFunc; i++)
342 if (cdo_cmpstr(fun, fun_sym_tbl[i].name))
343 {
344 funcID = i;
345 break;
346 }
347
348 if (funcID == -1) cdo_abort("Function >%s< not available!", fun);
349
350 return funcID;
351 }
352
353 static constexpr bool
isCompare(const int oper)354 isCompare(const int oper) noexcept
355 {
356 return (oper == LEG || oper == GE || oper == LE || oper == EQ || oper == NE || oper == GT || oper == LT);
357 }
358
359 static void
param_meta_copy(paramType & out,const paramType & in)360 param_meta_copy(paramType &out, const paramType &in)
361 {
362 out.type = in.type;
363 out.gridID = in.gridID;
364 out.zaxisID = in.zaxisID;
365 out.datatype = in.datatype;
366 out.steptype = in.steptype;
367 out.ngp = in.ngp;
368 out.nlat = in.nlat;
369 out.nlev = in.nlev;
370 out.missval = in.missval;
371 out.nmiss = 0;
372 out.coord = 0;
373 out.hasMissvals = true;
374 out.name = nullptr;
375 out.longname = nullptr;
376 out.units = nullptr;
377 out.data = nullptr;
378 }
379
380 static nodeType *
expr_con_con(const int oper,const nodeType * p1,const nodeType * p2)381 expr_con_con(const int oper, const nodeType *p1, const nodeType *p2)
382 {
383 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
384
385 p->type = typeCon;
386 p->ltmpobj = true;
387
388 auto cval1 = p1->u.con.value;
389 const auto cval2 = p2->u.con.value;
390
391 // clang-format off
392 switch (oper)
393 {
394 case LT: cval1 = binary_op_LT(cval1, cval2); break;
395 case GT: cval1 = binary_op_GT(cval1, cval2); break;
396 case LE: cval1 = binary_op_LE(cval1, cval2); break;
397 case GE: cval1 = binary_op_GE(cval1, cval2); break;
398 case NE: cval1 = binary_op_NE(cval1, cval2); break;
399 case EQ: cval1 = binary_op_EQ(cval1, cval2); break;
400 case LEG: cval1 = binary_op_LEG(cval1, cval2); break;
401 case AND: cval1 = binary_op_AND(cval1, cval2); break;
402 case OR: cval1 = binary_op_OR(cval1, cval2); break;
403 case '^': cval1 = binary_op_POW(cval1, cval2); break;
404 case '+': cval1 = binary_op_ADD(cval1, cval2); break;
405 case '-': cval1 = binary_op_SUB(cval1, cval2); break;
406 case '*': cval1 = binary_op_MUL(cval1, cval2); break;
407 case '/': cval1 = binary_op_DIV(cval1, cval2); break;
408 default: cdo_abort("%s: operator %d unsupported!", __func__, oper); break;
409 }
410 // clang-format on
411
412 p->u.con.value = cval1;
413
414 return p;
415 }
416
417 static void
oper_expr_con_var(const int oper,const bool hasMissvals,const size_t n,const double mv,double * odat,const double cval,const double * idat)418 oper_expr_con_var(const int oper, const bool hasMissvals, const size_t n, const double mv, double *odat,
419 const double cval, const double *idat)
420 {
421 // clang-format off
422 switch (oper)
423 {
424 case LT: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_LT); break;
425 case GT: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_GT); break;
426 case LE: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_LE); break;
427 case GE: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_GE); break;
428 case NE: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_NE); break;
429 case EQ: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_EQ); break;
430 case LEG: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_LEG); break;
431 case AND: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_AND); break;
432 case OR: expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_OR); break;
433 case '^': expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_POW); break;
434 case '+': expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_ADD); break;
435 case '-': expr_func_con_var(hasMissvals, n, mv, cval, idat, odat, binary_op_SUB); break;
436 case '*': expr_mul_con_var(hasMissvals, n, mv, cval, idat, odat); break;
437 case '/': expr_div_con_var(hasMissvals, n, mv, cval, idat, odat); break;
438 default: cdo_abort("%s: operator %d unsupported!", __func__, oper); break;
439 }
440 // clang-format on
441 }
442
443 static void
oper_expr_var_con(const int oper,const bool hasMissvals,const size_t n,const double mv,double * odat,const double * idat,const double cval)444 oper_expr_var_con(const int oper, const bool hasMissvals, const size_t n, const double mv,
445 double *odat, const double *idat, const double cval)
446 {
447 // clang-format off
448 switch (oper)
449 {
450 case LT: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_LT); break;
451 case GT: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_GT); break;
452 case LE: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_LE); break;
453 case GE: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_GE); break;
454 case NE: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_NE); break;
455 case EQ: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_EQ); break;
456 case LEG: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_LEG); break;
457 case AND: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_AND); break;
458 case OR: expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_OR); break;
459 case '^': expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_POW); break;
460 case '+': expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_ADD); break;
461 case '-': expr_func_var_con(hasMissvals, n, mv, idat, cval, odat, binary_op_SUB); break;
462 case '*': expr_mul_var_con(hasMissvals, n, mv, idat, cval, odat); break;
463 case '/': expr_div_var_con(hasMissvals, n, mv, idat, cval, odat); break;
464 default: cdo_abort("%s: operator %d unsupported!", __func__, oper); break;
465 }
466 // clang-format on
467 }
468
469 static void
oper_expr_var_var(const int oper,const bool hasMissvals,const size_t n,const double mv1,const double mv2,double * odat,const double * idat1,const double * idat2)470 oper_expr_var_var(const int oper, const bool hasMissvals, const size_t n, const double mv1, const double mv2,
471 double *odat, const double *idat1, const double *idat2)
472 {
473 // clang-format off
474 switch (oper)
475 {
476 case LT: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_LT); break;
477 case GT: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_GT); break;
478 case LE: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_LE); break;
479 case GE: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_GE); break;
480 case NE: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_NE); break;
481 case EQ: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_EQ); break;
482 case LEG: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_LEG); break;
483 case AND: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_AND); break;
484 case OR: expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_OR); break;
485 case '^': expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_POW); break;
486 case '+': expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_ADD); break;
487 case '-': expr_func_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat, binary_op_SUB); break;
488 case '*': expr_mul_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat); break;
489 case '/': expr_div_var_var(hasMissvals, n, mv1, mv2, idat1, idat2, odat); break;
490 default: cdo_abort("%s: operator %d unsupported!", __func__, oper); break;
491 }
492 // clang-format on
493 }
494
495 static nodeType *
expr_con_var(const int init,const int oper,const nodeType * p1,const nodeType * p2)496 expr_con_var(const int init, const int oper, const nodeType *p1, const nodeType *p2)
497 {
498 const auto ngp = (p2->param.ngp > 0) ? p2->param.ngp : 1;
499 const auto nlev = (p2->param.nlev > 0) ? p2->param.nlev : 1;
500 const auto nmiss = p2->param.nmiss;
501 const auto datatype = p2->param.datatype;
502 const auto missval2 = p2->param.missval;
503
504 const auto n = ngp * nlev;
505
506 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
507
508 p->type = typeVar;
509 p->ltmpobj = true;
510 p->u.var.nm = strdup(tmpvnm);
511 param_meta_copy(p->param, p2->param);
512 p->param.name = p->u.var.nm;
513
514 if (!init)
515 {
516 p->param.data = (double *) Malloc(n * sizeof(double));
517 auto odat = p->param.data;
518 const auto idat = p2->param.data;
519 auto cval = p1->u.con.value;
520 if (datatype == CDI_DATATYPE_FLT32 && isCompare(oper)) cval = (float) cval;
521
522 oper_expr_con_var(oper, nmiss, n, missval2, odat, cval, idat);
523
524 p->param.nmiss = array_num_mv(n, odat, missval2);
525 }
526
527 return p;
528 }
529
530 static nodeType *
expr_var_con(const int init,const int oper,const nodeType * p1,const nodeType * p2)531 expr_var_con(const int init, const int oper, const nodeType *p1, const nodeType *p2)
532 {
533 const auto ngp = (p1->param.ngp > 0) ? p1->param.ngp : 1;
534 const auto nlev = (p1->param.nlev > 0) ? p1->param.nlev : 1;
535 const auto nmiss = p1->param.nmiss;
536 const auto datatype = p1->param.datatype;
537 const auto missval1 = p1->param.missval;
538
539 const auto n = ngp * nlev;
540
541 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
542
543 p->type = typeVar;
544 p->ltmpobj = true;
545 p->u.var.nm = strdup(tmpvnm);
546 param_meta_copy(p->param, p1->param);
547 p->param.name = p->u.var.nm;
548
549 if (!init)
550 {
551 p->param.data = (double *) Malloc(n * sizeof(double));
552 auto odat = p->param.data;
553 const auto idat = p1->param.data;
554 auto cval = p2->u.con.value;
555 if (datatype == CDI_DATATYPE_FLT32 && isCompare(oper)) cval = (float) cval;
556
557 oper_expr_var_con(oper, nmiss, n, missval1, odat, idat, cval);
558
559 p->param.nmiss = array_num_mv(n, odat, missval1);
560 }
561
562 return p;
563 }
564
565 static nodeType *
expr_var_var(int init,int oper,nodeType * p1,nodeType * p2)566 expr_var_var(int init, int oper, nodeType *p1, nodeType *p2)
567 {
568 auto px = p1;
569 const auto nmiss1 = p1->param.nmiss;
570 const auto nmiss2 = p2->param.nmiss;
571 const auto missval1 = p1->param.missval;
572 const auto missval2 = p2->param.missval;
573
574 const auto ngp1 = (p1->param.ngp > 0) ? p1->param.ngp : 1;
575 const auto ngp2 = (p2->param.ngp > 0) ? p2->param.ngp : 1;
576 auto ngp = ngp1;
577
578 const auto nlat1 = p1->param.nlat;
579 const auto nlat2 = p2->param.nlat;
580 auto lzonal = false;
581
582 if (ngp1 != ngp2)
583 {
584 if (ngp1 == 1 || ngp2 == 1)
585 {
586 if (ngp1 == 1)
587 {
588 ngp = ngp2;
589 px = p2;
590 }
591 }
592 else if (nlat1 == nlat2 && ngp1 > ngp2)
593 {
594 lzonal = true;
595 }
596 else
597 {
598 cdo_abort("%s: Number of grid points differ (%s[%zu] <-> %s[%zu])", __func__, p1->param.name, ngp1, p2->param.name, ngp2);
599 }
600 }
601
602 const auto nlev1 = (p1->param.nlev > 0) ? p1->param.nlev : 1;
603 const auto nlev2 = (p2->param.nlev > 0) ? p2->param.nlev : 1;
604
605 auto nlev = nlev1;
606 if (nlev1 != nlev2)
607 {
608 if (nlev1 == 1 || nlev2 == 1)
609 {
610 if (nlev1 == 1)
611 {
612 nlev = nlev2;
613 px = p2;
614 }
615 }
616 else
617 {
618 cdo_abort("%s: Number of levels differ (%s[%zu] <-> %s[%zu])", __func__, p1->param.name, nlev1, p2->param.name, nlev2);
619 }
620 }
621
622 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
623
624 p->type = typeVar;
625 p->ltmpobj = true;
626 p->u.var.nm = strdup(tmpvnm);
627
628 param_meta_copy(p->param, px->param);
629
630 if (p->param.steptype == TIME_CONSTANT)
631 {
632 const auto steptype1 = p1->param.steptype;
633 const auto steptype2 = p2->param.steptype;
634 if (steptype1 != TIME_CONSTANT)
635 p->param.steptype = steptype1;
636 else if (steptype2 != TIME_CONSTANT)
637 p->param.steptype = steptype2;
638 }
639
640 p->param.name = p->u.var.nm;
641 // printf("%s %s nmiss %zu %zu\n", p->u.var.nm, px->param.name, nmiss1, nmiss2);
642
643 if (!init)
644 {
645 p->param.data = (double *) Malloc(ngp * nlev * sizeof(double));
646
647 for (size_t k = 0; k < nlev; k++)
648 {
649 const auto loff = k * ngp;
650 const size_t loff1 = (nlev1 > 1) ? k * ngp1 : 0;
651 const size_t loff2 = (nlev2 > 1) ? k * ngp2 : 0;
652
653 const auto idat1 = p1->param.data + loff1;
654 const auto idat2 = p2->param.data + loff2;
655 auto odat = p->param.data + loff;
656 const size_t nmiss = (nmiss1 || nmiss2);
657
658 if (ngp1 != ngp2)
659 {
660 if (lzonal)
661 {
662 const auto nlon = ngp1 / nlat1;
663 for (size_t j = 0; j < nlat1; ++j)
664 oper_expr_var_con(oper, nmiss, nlon, missval1, odat + j * nlon, idat1 + j * nlon, idat2[j]);
665 }
666 else
667 {
668 if (ngp2 == 1)
669 oper_expr_var_con(oper, nmiss, ngp, missval1, odat, idat1, idat2[0]);
670 else
671 oper_expr_con_var(oper, nmiss, ngp, missval2, odat, idat1[0], idat2);
672 }
673 }
674 else
675 {
676 oper_expr_var_var(oper, nmiss, ngp, missval1, missval2, odat, idat1, idat2);
677 }
678 }
679
680 p->param.nmiss = array_num_mv(ngp * nlev, p->param.data, missval1);
681 }
682
683 return p;
684 }
685
686 static void
ex_copy_var(int init,nodeType * p2,const nodeType * p1)687 ex_copy_var(int init, nodeType *p2, const nodeType *p1)
688 {
689 const auto copyConstValue1 = (p1->param.ngp == 0 && p1->param.nlev == 0);
690 const auto ngp1 = (p1->param.ngp > 0) ? p1->param.ngp : 1;
691 const auto nlev1 = (p1->param.nlev > 0) ? p1->param.nlev : 1;
692
693 if (Options::cdoVerbose)
694 {
695 if (copyConstValue1)
696 cdo_print("\t%s\tcopy\t%s[N%zu][L%zu] = %s", ExIn[init], p2->param.name, p2->param.ngp, p2->param.nlev, p1->param.name);
697 else
698 cdo_print("\t%s\tcopy\t%s[N%zu][L%zu] = %s[N%zu][L%zu]", ExIn[init], p2->param.name, p2->param.ngp, p2->param.nlev,
699 p1->param.name, p1->param.ngp, p1->param.nlev);
700 }
701
702 const auto ngp2 = (p2->param.ngp > 0) ? p2->param.ngp : 1;
703 const auto nlev2 = (p2->param.nlev > 0) ? p2->param.nlev : 1;
704
705 if (!copyConstValue1 && ngp2 != ngp1)
706 cdo_abort("%s: Number of grid points differ (%s[N%zu] = %s[N%zu])", __func__, p2->param.name, ngp2, p1->param.name, ngp1);
707
708 if (!copyConstValue1 && nlev2 != nlev1)
709 cdo_abort("%s: Number of levels differ (%s[L%zu] = %s[L%zu])", __func__, p2->param.name, nlev2, p1->param.name, nlev1);
710
711 if (!init)
712 {
713 if (copyConstValue1)
714 {
715 varray_fill(ngp2 * nlev2, p2->param.data, p1->param.data[0]);
716 }
717 else
718 {
719 array_copy(ngp2 * nlev2, p1->param.data, p2->param.data);
720 p2->param.missval = p1->param.missval;
721 p2->param.nmiss = p1->param.nmiss;
722 }
723 }
724 }
725
726 static void
ex_copy_con(int init,nodeType * p2,const nodeType * p1)727 ex_copy_con(int init, nodeType *p2, const nodeType *p1)
728 {
729 const auto cval = p1->u.con.value;
730
731 auto ngp = p2->param.ngp;
732 auto nlev = p2->param.nlev;
733
734 if (Options::cdoVerbose)
735 {
736 if (ngp == 0 && nlev == 0)
737 cdo_print("\t%s\tcopy\t%s = %g", ExIn[init], p2->param.name, cval);
738 else
739 cdo_print("\t%s\tcopy\t%s[N%zu][L%zu] = %g", ExIn[init], p2->param.name, ngp, nlev, cval);
740 }
741
742 if (ngp == 0 && nlev == 0)
743 {
744 ngp = 1;
745 nlev = 1;
746 }
747
748 assert(ngp > 0);
749 assert(nlev > 0);
750
751 if (!init)
752 {
753 assert(p2->param.data != nullptr);
754 varray_fill(ngp * nlev, p2->param.data, cval);
755 }
756 }
757
758 static void
ex_copy(int init,nodeType * p2,const nodeType * p1)759 ex_copy(int init, nodeType *p2, const nodeType *p1)
760 {
761 if (p1->type == typeCon)
762 ex_copy_con(init, p2, p1);
763 else
764 ex_copy_var(init, p2, p1);
765 }
766
767 static nodeType *
expr(const int init,const int oper,nodeType * p1,nodeType * p2)768 expr(const int init, const int oper, nodeType *p1, nodeType *p2)
769 {
770 if (p1 == nullptr || p2 == nullptr) return nullptr;
771
772 const char *coper = "???";
773
774 if (Options::cdoVerbose)
775 {
776 switch (oper)
777 {
778 case LT: coper = "<"; break;
779 case GT: coper = ">"; break;
780 case LE: coper = "<="; break;
781 case GE: coper = ">="; break;
782 case NE: coper = "!="; break;
783 case EQ: coper = "=="; break;
784 case LEG: coper = "<=>"; break;
785 case AND: coper = "&&"; break;
786 case OR: coper = "||"; break;
787 case '^': coper = "^"; break;
788 case '+': coper = "+"; break;
789 case '-': coper = "-"; break;
790 case '*': coper = "*"; break;
791 case '/': coper = "/"; break;
792 default: cdo_abort("Internal error, expr operator %d not implemented!\n", oper);
793 }
794 }
795
796 nodeType *p = nullptr;
797
798 if (p1->type == typeVar && p2->type == typeVar)
799 {
800 p = expr_var_var(init, oper, p1, p2);
801 if (Options::cdoVerbose)
802 cdo_print("\t%s\tarith\t%s[N%zu][L%zu] = %s %s %s", ExIn[init], p->u.var.nm, p->param.ngp, p->param.nlev, p1->u.var.nm,
803 coper, p2->u.var.nm);
804 }
805 else if (p1->type == typeVar && p2->type == typeCon)
806 {
807 p = expr_var_con(init, oper, p1, p2);
808 if (Options::cdoVerbose)
809 cdo_print("\t%s\tarith\t%s[N%zu][L%zu] = %s %s %g", ExIn[init], p->u.var.nm, p->param.ngp, p->param.nlev, p1->u.var.nm,
810 coper, p2->u.con.value);
811 }
812 else if (p1->type == typeCon && p2->type == typeVar)
813 {
814 p = expr_con_var(init, oper, p1, p2);
815 if (Options::cdoVerbose)
816 cdo_print("\t%s\tarith\t%s[N%zu][L%zu] = %g %s %s", ExIn[init], p->u.var.nm, p->param.ngp, p->param.nlev, p1->u.con.value,
817 coper, p2->u.var.nm);
818 }
819 else if (p1->type == typeCon && p2->type == typeCon)
820 {
821 p = expr_con_con(oper, p1, p2);
822 if (Options::cdoVerbose)
823 cdo_print("\t%s\tarith\t%g = %g %s %g", ExIn[init], p->u.con.value, p1->u.con.value, coper, p2->u.con.value);
824 }
825 else
826 cdo_abort("Internal problem!");
827
828 if (p1->ltmpobj) node_delete(p1);
829 if (p2->ltmpobj) node_delete(p2);
830
831 return p;
832 }
833
834 static nodeType *
ex_fun0_con(const int init,const int funcID,double * data)835 ex_fun0_con(const int init, const int funcID, double *data)
836 {
837 auto functype = fun_sym_tbl[funcID].type;
838 if (functype != FT_0) cdo_abort("Function %s not available for constant values!", fun_sym_tbl[funcID].name);
839
840 if (Options::cdoVerbose) cdo_print("\t%s\tfunc\t%s", ExIn[init], fun_sym_tbl[funcID].name);
841
842 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
843
844 p->type = typeCon;
845 p->ltmpobj = true;
846
847 if (!init)
848 {
849 double (*exprfunc)(const double *) = (double (*)(const double *)) fun_sym_tbl[funcID].func;
850 p->u.con.value = exprfunc(data);
851 }
852
853 return p;
854 }
855
856 static nodeType *
ex_fun_con(const int funcID,nodeType * p1)857 ex_fun_con(const int funcID, nodeType *p1)
858 {
859 const auto functype = fun_sym_tbl[funcID].type;
860 if (functype != FT_STD) cdo_abort("Function %s not available for constant values!", fun_sym_tbl[funcID].name);
861
862 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
863
864 p->type = typeCon;
865 p->ltmpobj = true;
866
867 double (*exprfunc)(double) = (double (*)(double)) fun_sym_tbl[funcID].func;
868 p->u.con.value = exprfunc(p1->u.con.value);
869
870 if (p1->ltmpobj)
871 node_delete(p1);
872 else
873 Free(p1);
874
875 return p;
876 }
877
878 static void
ex_fun_std(const int funcID,size_t ngp,size_t nlev,size_t nmiss,double missval,double * p1data,double * pdata)879 ex_fun_std(const int funcID, size_t ngp, size_t nlev, size_t nmiss, double missval, double *p1data, double *pdata)
880 {
881 double (*exprfunc)(double) = (double (*)(double)) fun_sym_tbl[funcID].func;
882 if (nmiss)
883 {
884 if (cdo_cmpstr(fun_sym_tbl[funcID].name, "isMissval"))
885 {
886 for (size_t i = 0; i < ngp * nlev; i++)
887 {
888 pdata[i] = DBL_IS_EQUAL(p1data[i], missval);
889 }
890 }
891 else
892 {
893 for (size_t i = 0; i < ngp * nlev; i++)
894 {
895 errno = -1;
896 pdata[i] = DBL_IS_EQUAL(p1data[i], missval) ? missval : exprfunc(p1data[i]);
897 if (errno == EDOM || errno == ERANGE || std::isnan(pdata[i])) pdata[i] = missval;
898 }
899 }
900 }
901 else
902 {
903 for (size_t i = 0; i < ngp * nlev; i++)
904 {
905 errno = -1;
906 pdata[i] = exprfunc(p1data[i]);
907 if (errno == EDOM || errno == ERANGE || std::isnan(pdata[i])) pdata[i] = missval;
908 }
909 }
910 }
911
912 static nodeType *
ex_fun_var(const int init,const int funcID,nodeType * p1)913 ex_fun_var(const int init, const int funcID, nodeType *p1)
914 {
915 const auto funcname = fun_sym_tbl[funcID].name;
916 const auto functype = fun_sym_tbl[funcID].type;
917 const auto funcflag = fun_sym_tbl[funcID].flag;
918
919 const auto gridID = p1->param.gridID;
920 const auto ngp = (p1->param.ngp > 0) ? p1->param.ngp : 1;
921 const auto nlev = (p1->param.nlev > 0) ? p1->param.nlev : 1;
922 const auto nlat = p1->param.nlat;
923 const auto nmiss = p1->param.nmiss;
924 const auto missval = p1->param.missval;
925
926 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
927
928 p->type = typeVar;
929 p->ltmpobj = true;
930 p->u.var.nm = strdup(tmpvnm);
931
932 param_meta_copy(p->param, p1->param);
933
934 if (functype == FT_CONST)
935 {
936 p->type = typeCon;
937 double (*exprfunc)(const paramType *) = (double (*)(const paramType *)) fun_sym_tbl[funcID].func;
938 p->u.con.value = exprfunc(&p1->param);
939 }
940 else if (functype == FT_FLD)
941 {
942 p->param.gridID = pointID;
943 p->param.ngp = 1;
944 }
945 else if (functype == FT_ZON)
946 {
947 if (zonalID == -1) cdo_abort("Function %s() is only available for regular 2D grids!", fun_sym_tbl[funcID].name);
948 p->param.gridID = zonalID;
949 p->param.ngp = nlat;
950 }
951 else if (functype == FT_VERT)
952 {
953 p->param.zaxisID = surfaceID;
954 p->param.nlev = 1;
955 }
956
957 if (!init)
958 {
959 p->param.data = (double *) Malloc(p->param.ngp * p->param.nlev * sizeof(double));
960 double *pdata = p->param.data;
961 double *p1data = p1->param.data;
962
963 if (functype == FT_STD)
964 {
965 ex_fun_std(funcID, ngp, nlev, nmiss, missval, p1data, pdata);
966 }
967 else if (functype == FT_FLD)
968 {
969 Field field;
970 field.resize(ngp);
971 if (funcflag == 1)
972 {
973 assert(p1->param.weight != nullptr);
974 field.weightv.resize(ngp);
975 }
976
977 double (*exprfunc)(const Field &) = (double (*)(const Field &)) fun_sym_tbl[funcID].func;
978 for (size_t k = 0; k < nlev; k++)
979 {
980 fld_field_init(field, nmiss, missval, ngp, p1data + k * ngp, p1->param.weight);
981 pdata[k] = exprfunc(field);
982 }
983 }
984 else if (functype == FT_ZON)
985 {
986 Field field1, field2;
987 field1.resize(ngp);
988 field2.resize(nlat);
989 void (*exprfunc)(const Field &, Field &) = (void (*)(const Field &, Field &)) fun_sym_tbl[funcID].func;
990 for (size_t k = 0; k < nlev; k++)
991 {
992 fld_field_init(field1, nmiss, missval, ngp, &p1data[k * ngp], nullptr);
993 field1.grid = gridID;
994 fld_field_init(field2, nmiss, missval, nlat, &pdata[k * nlat], nullptr);
995 exprfunc(field1, field2);
996 array_copy(nlat, field2.vec_d.data(), &pdata[k * nlat]);
997 }
998 }
999 else if (functype == FT_VERT)
1000 {
1001 Field field;
1002 field.resize(nlev);
1003 if (funcflag == 1) vert_weights(p1->param.zaxisID, nlev, field.weightv);
1004 double (*exprfunc)(const Field &) = (double (*)(const Field &)) fun_sym_tbl[funcID].func;
1005 for (size_t i = 0; i < ngp; i++)
1006 {
1007 for (size_t k = 0; k < nlev; k++) field.vec_d[k] = p1data[k * ngp + i];
1008 fld_field_init(field, nmiss, missval, nlev, nullptr, nullptr);
1009 pdata[i] = exprfunc(field);
1010 }
1011 }
1012 else if (functype == FT_CONST)
1013 {
1014 }
1015 else
1016 cdo_abort("Intermal error, wrong function type (%d) for %s()!", functype, funcname);
1017
1018 p->param.nmiss = array_num_mv(p->param.ngp * p->param.nlev, pdata, missval);
1019 }
1020
1021 if (p1->ltmpobj)
1022 node_delete(p1);
1023 else
1024 Free(p1);
1025
1026 return p;
1027 }
1028
1029 static nodeType *
ex_fun(const int init,const int funcID,nodeType * p1)1030 ex_fun(const int init, const int funcID, nodeType *p1)
1031 {
1032 nodeType *p = nullptr;
1033
1034 if (p1->type == typeVar)
1035 {
1036 if (Options::cdoVerbose) cdo_print("\t%s\tfunc\t%s (%s)", ExIn[init], fun_sym_tbl[funcID].name, p1->u.var.nm);
1037 p = ex_fun_var(init, funcID, p1);
1038 }
1039 else if (p1->type == typeCon)
1040 {
1041 if (Options::cdoVerbose) cdo_print("\t%s\tfunc\t%s (%g)", ExIn[init], fun_sym_tbl[funcID].name, p1->u.con.value);
1042 p = ex_fun_con(funcID, p1);
1043 }
1044 else
1045 cdo_abort("Internal problem!");
1046
1047 return p;
1048 }
1049
1050 static size_t
get_levidx(const size_t nlev,const double * data,const double value,const char * funcname)1051 get_levidx(const size_t nlev, const double *data, const double value, const char *funcname)
1052 {
1053 size_t levidx;
1054
1055 for (levidx = 0; levidx < nlev; ++levidx)
1056 if (IS_EQUAL(data[levidx], value)) break;
1057 if (levidx == nlev) cdo_abort("%s(): level %g not found!", funcname, value);
1058
1059 return levidx;
1060 }
1061
1062 static void
get_levidxrange(size_t nlev,const double * data,double value1,double value2,const char * funcname,size_t & levidx1,size_t & levidx2)1063 get_levidxrange(size_t nlev, const double *data, double value1, double value2, const char *funcname, size_t &levidx1,
1064 size_t &levidx2)
1065 {
1066 long i, n = nlev;
1067 if (data[0] <= data[nlev - 1])
1068 {
1069 for (i = 0; i < n; ++i)
1070 if (data[i] >= value1) break;
1071 if (i == n) cdo_abort("%s(): lower level %g not found!", funcname, value1);
1072 levidx1 = i;
1073
1074 for (i = n - 1; i >= 0; --i)
1075 if (data[i] <= value2) break;
1076 if (i < 0) cdo_abort("%s(): upper level %g not found!", funcname, value2);
1077 if (i < (long) levidx1) cdo_abort("%s(): level range %g to %g not found!", funcname, value1, value2);
1078 levidx2 = i;
1079 }
1080 else
1081 {
1082 for (i = 0; i < n; ++i)
1083 if (data[i] <= value2) break;
1084 if (i == n) cdo_abort("%s(): upper level %g not found!", funcname, value1);
1085 levidx1 = i;
1086
1087 for (i = n - 1; i >= 0; --i)
1088 if (data[i] >= value1) break;
1089 if (i < 0) cdo_abort("%s(): lower level %g not found!", funcname, value2);
1090 if (i < (long) levidx1) cdo_abort("%s(): level range %g to %g not found!", funcname, value1, value2);
1091 levidx2 = i;
1092 }
1093 }
1094
1095 static nodeType *
fun1c(int init,int funcID,nodeType * p1,double value,parseParamType * parse_arg)1096 fun1c(int init, int funcID, nodeType *p1, double value, parseParamType *parse_arg)
1097 {
1098 const auto funcname = fun_sym_tbl[funcID].name;
1099 if (p1->type != typeVar) cdo_abort("Parameter of function %s() needs to be a variable!", funcname);
1100 if (p1->ltmpobj) cdo_abort("Temporary objects not allowed in function %s()!", funcname);
1101
1102 if (parse_arg->debug)
1103 cdo_print("\t%s\tfunc\t%s=%s(%s[N%zu][L%zu], %g)", ExIn[init], tmpvnm, funcname, p1->param.name, p1->param.ngp, p1->param.nlev,
1104 value);
1105
1106 const auto ngp = (p1->param.ngp > 0) ? p1->param.ngp : 1;
1107 const auto nlev = (p1->param.nlev > 0) ? p1->param.nlev : 1;
1108 auto nmiss = p1->param.nmiss;
1109 const auto missval = p1->param.missval;
1110
1111 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1112
1113 p->type = typeVar;
1114 p->ltmpobj = true;
1115 p->u.var.nm = strdup(tmpvnm);
1116 param_meta_copy(p->param, p1->param);
1117 p->param.name = p->u.var.nm;
1118
1119 if (init)
1120 {
1121 if (p1->param.longname) p->param.longname = strdup(p1->param.longname);
1122 if (p1->param.units) p->param.units = strdup(p1->param.units);
1123 }
1124
1125 p->param.nlev = 1;
1126
1127 const auto zaxisID = p1->param.zaxisID;
1128 const auto coordID = params_get_coord_ID(parse_arg, 'z', zaxisID);
1129
1130 std::vector<double> data;
1131 double *pdata = nullptr;
1132
1133 if (init)
1134 {
1135 parse_arg->coords[coordID].needed = true;
1136
1137 data.resize(nlev);
1138 pdata = data.data();
1139 cdo_zaxis_inq_levels(zaxisID, pdata);
1140 }
1141 else
1142 {
1143 pdata = parse_arg->coords[coordID].data.data();
1144 }
1145
1146 size_t levidx = 0;
1147 if (cdo_cmpstr(funcname, "sellevidx"))
1148 {
1149 const auto ilevidx = std::lround(value);
1150 if (ilevidx < 1 || ilevidx > (long) nlev)
1151 cdo_abort("%s(): level index %ld out of range (range: 1-%zu)!", funcname, ilevidx, nlev);
1152 levidx = (size_t) ilevidx - 1;
1153 }
1154 else if (cdo_cmpstr(funcname, "sellevel"))
1155 {
1156 levidx = get_levidx(nlev, pdata, value, funcname);
1157 }
1158 else
1159 cdo_abort("Function %s() not implemented!", funcname);
1160
1161 if (init)
1162 {
1163 const auto level = data[levidx];
1164 const auto zaxisID2 = zaxisCreate(zaxisInqType(zaxisID), 1);
1165 zaxisDefLevels(zaxisID2, &level);
1166 p->param.zaxisID = zaxisID2;
1167 }
1168
1169 if (!init)
1170 {
1171 p->param.data = (double *) Malloc(ngp * sizeof(double));
1172 pdata = p->param.data;
1173 const auto p1data = p1->param.data + ngp * levidx;
1174 array_copy(ngp, p1data, pdata);
1175 if (nmiss) nmiss = array_num_mv(ngp, pdata, missval);
1176 p->param.nmiss = nmiss;
1177 }
1178
1179 if (p1->ltmpobj) node_delete(p1);
1180
1181 return p;
1182 }
1183
1184 static nodeType *
fun2c(int init,int funcID,nodeType * p1,double value1,double value2,parseParamType * parse_arg)1185 fun2c(int init, int funcID, nodeType *p1, double value1, double value2, parseParamType *parse_arg)
1186 {
1187 const auto funcname = fun_sym_tbl[funcID].name;
1188 if (p1->type != typeVar) cdo_abort("Parameter of function %s() needs to be a variable!", funcname);
1189 if (p1->ltmpobj) cdo_abort("Temporary objects not allowed in function %s()!", funcname);
1190
1191 if (parse_arg->debug)
1192 cdo_print("\t%s\tfunc\t%s=%s(%s[N%zu][L%zu], %g, %g)", ExIn[init], tmpvnm, funcname, p1->param.name, p1->param.ngp,
1193 p1->param.nlev, value1, value2);
1194
1195 const auto ngp = (p1->param.ngp > 0) ? p1->param.ngp : 1;
1196 const auto nlev = (p1->param.nlev > 0) ? p1->param.nlev : 1;
1197 auto nmiss = p1->param.nmiss;
1198 const auto missval = p1->param.missval;
1199
1200 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1201
1202 p->type = typeVar;
1203 p->ltmpobj = true;
1204 p->u.var.nm = strdup(tmpvnm);
1205 param_meta_copy(p->param, p1->param);
1206 p->param.name = p->u.var.nm;
1207
1208 if (init)
1209 {
1210 if (p1->param.longname) p->param.longname = strdup(p1->param.longname);
1211 if (p1->param.units) p->param.units = strdup(p1->param.units);
1212 }
1213
1214 const auto zaxisID = p1->param.zaxisID;
1215 const auto coordID = params_get_coord_ID(parse_arg, 'z', zaxisID);
1216 size_t levidx1 = 0;
1217 size_t levidx2 = 0;
1218
1219 double *data = nullptr;
1220 if (init)
1221 {
1222 parse_arg->coords[coordID].needed = true;
1223
1224 data = (double *) Malloc(nlev * sizeof(double));
1225 cdo_zaxis_inq_levels(zaxisID, data);
1226 }
1227 else
1228 {
1229 data = parse_arg->coords[coordID].data.data();
1230 }
1231
1232 if (cdo_cmpstr(funcname, "sellevidxrange"))
1233 {
1234 if (value2 < value1) cdo_abort("%s(): first level index is greater than last level index!", funcname);
1235 const auto ilevidx1 = std::lround(value1);
1236 if (ilevidx1 < 1 || ilevidx1 > (long) nlev)
1237 cdo_abort("%s(): level index1 %ld out of range (range: 1-%zu)!", funcname, ilevidx1, nlev);
1238 levidx1 = (size_t) ilevidx1 - 1;
1239 const auto ilevidx2 = std::lround(value2);
1240 if (ilevidx2 < 1 || ilevidx2 > (long) nlev)
1241 cdo_abort("%s(): level index2 %ld out of range (range: 1-%zu)!", funcname, ilevidx2, nlev);
1242 levidx2 = (size_t) ilevidx2 - 1;
1243 }
1244 else if (cdo_cmpstr(funcname, "sellevelrange"))
1245 {
1246 if (value2 < value1) cdo_abort("%s(): first level is greater than last level!", funcname);
1247 get_levidxrange(nlev, data, value1, value2, funcname, levidx1, levidx2);
1248 }
1249 else
1250 cdo_abort("Function %s() not implemented!", funcname);
1251
1252 const int nlevout = levidx2 - levidx1 + 1;
1253 p->param.nlev = nlevout;
1254
1255 if (init)
1256 {
1257 const auto zaxisID2 = zaxisCreate(zaxisInqType(zaxisID), nlevout);
1258 zaxisDefLevels(zaxisID2, &data[levidx1]);
1259 if (zaxisInqLbounds(zaxisID, nullptr) && zaxisInqUbounds(zaxisID, nullptr))
1260 {
1261 std::vector<double> bounds(nlev);
1262 zaxisInqLbounds(zaxisID, bounds.data());
1263 zaxisDefLbounds(zaxisID2, &bounds[levidx1]);
1264 zaxisInqUbounds(zaxisID, bounds.data());
1265 zaxisDefUbounds(zaxisID2, &bounds[levidx1]);
1266 }
1267 p->param.zaxisID = zaxisID2;
1268 }
1269
1270 if (init) Free(data);
1271
1272 if (!init)
1273 {
1274 p->param.data = (double *) Malloc(ngp * nlevout * sizeof(double));
1275 auto pdata = p->param.data;
1276 const auto p1data = p1->param.data + ngp * levidx1;
1277 array_copy(ngp * nlevout, p1data, pdata);
1278 if (nmiss) nmiss = array_num_mv(ngp * nlevout, pdata, missval);
1279 p->param.nmiss = nmiss;
1280 }
1281
1282 if (p1->ltmpobj) node_delete(p1);
1283
1284 return p;
1285 }
1286
1287 static nodeType *
coord_fun(const int init,const int funcID,nodeType * p1,parseParamType * parse_arg)1288 coord_fun(const int init, const int funcID, nodeType *p1, parseParamType *parse_arg)
1289 {
1290 const auto funcname = fun_sym_tbl[funcID].name;
1291 if (p1->type != typeVar) cdo_abort("Parameter of function %s() needs to be a variable!", funcname);
1292 if (p1->ltmpobj) cdo_abort("Temporary objects not allowed in function %s()!", funcname);
1293
1294 const auto len = 3 + strlen(p1->u.var.nm);
1295 auto cname = (char *) Calloc(len, 1);
1296 strcpy(cname, p1->u.var.nm);
1297
1298 // clang-format off
1299 if (cdo_cmpstr(funcname, "clon")) strcat(cname, ".x");
1300 else if (cdo_cmpstr(funcname, "clat")) strcat(cname, ".y");
1301 else if (cdo_cmpstr(funcname, "clev")) strcat(cname, ".z");
1302 else if (cdo_cmpstr(funcname, "cdeltaz")) strcat(cname, ".d");
1303 else if (cdo_cmpstr(funcname, "gridarea")) strcat(cname, ".a");
1304 else if (cdo_cmpstr(funcname, "gridweight")) strcat(cname, ".w");
1305 else cdo_abort("Implementation missing for function %s!", funcname);
1306 // clang-format on
1307
1308 Free(p1->u.var.nm);
1309 p1->u.var.nm = cname;
1310
1311 auto p = expr_run(p1, parse_arg);
1312 p->param.hasMissvals = false;
1313
1314 if (!init)
1315 {
1316 /*
1317 size_t ngp = p1->param.ngp;
1318 size_t nlev = p1->param.nlev;
1319 p->param.data = (double*) Malloc(ngp*nlev*sizeof(double));
1320 double *pdata = p->param.data;
1321 double *p1data = p1->param.data;
1322
1323 for (size_t i = 0; i < ngp*nlev; i++) pdata[i] = p1data[i];
1324 */
1325 }
1326 /*
1327 Free(cname);
1328 Free(p1);
1329 */
1330 return p;
1331 }
1332
1333 static nodeType *
ex_uminus_var(const int init,nodeType * p1)1334 ex_uminus_var(const int init, nodeType *p1)
1335 {
1336 const auto ngp = (p1->param.ngp > 0) ? p1->param.ngp : 1;
1337 const auto nlev = (p1->param.nlev > 0) ? p1->param.nlev : 1;
1338 const auto nmiss = p1->param.nmiss;
1339 const auto missval = p1->param.missval;
1340
1341 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1342
1343 p->type = typeVar;
1344 p->ltmpobj = true;
1345 p->u.var.nm = strdup(tmpvnm);
1346 param_meta_copy(p->param, p1->param);
1347 p->param.name = p->u.var.nm;
1348
1349 if (!init)
1350 {
1351 p->param.data = (double *) Malloc(ngp * nlev * sizeof(double));
1352 double *pdata = p->param.data;
1353 const double *p1data = p1->param.data;
1354
1355 if (nmiss)
1356 {
1357 for (size_t i = 0; i < ngp * nlev; ++i) pdata[i] = DBL_IS_EQUAL(p1data[i], missval) ? missval : -(p1data[i]);
1358 }
1359 else
1360 {
1361 for (size_t i = 0; i < ngp * nlev; ++i) pdata[i] = -(p1data[i]);
1362 }
1363
1364 p->param.nmiss = nmiss;
1365 }
1366
1367 if (p1->ltmpobj) node_delete(p1);
1368
1369 return p;
1370 }
1371
1372 static nodeType *
ex_uminus_con(nodeType * p1)1373 ex_uminus_con(nodeType *p1)
1374 {
1375 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1376
1377 p->type = typeCon;
1378 p->ltmpobj = true;
1379
1380 p->u.con.value = -(p1->u.con.value);
1381
1382 return p;
1383 }
1384
1385 static nodeType *
ex_uminus(const int init,nodeType * p1)1386 ex_uminus(const int init, nodeType *p1)
1387 {
1388 nodeType *p = nullptr;
1389
1390 if (p1->type == typeVar)
1391 {
1392 if (Options::cdoVerbose) cdo_print("\t%s\tneg\t- (%s)", ExIn[init], p1->u.var.nm);
1393 p = ex_uminus_var(init, p1);
1394 }
1395 else if (p1->type == typeCon)
1396 {
1397 if (Options::cdoVerbose) cdo_print("\t%s\tneg\t- (%g)", ExIn[init], p1->u.con.value);
1398 p = ex_uminus_con(p1);
1399 }
1400 else
1401 cdo_abort("Internal problem!");
1402
1403 return p;
1404 }
1405
1406 static nodeType *
ex_not_var(const int init,nodeType * p1)1407 ex_not_var(const int init, nodeType *p1)
1408 {
1409 const auto ngp = (p1->param.ngp > 0) ? p1->param.ngp : 1;
1410 const auto nlev = (p1->param.nlev > 0) ? p1->param.nlev : 1;
1411 const auto nmiss = p1->param.nmiss;
1412 const auto missval = p1->param.missval;
1413
1414 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1415
1416 p->type = typeVar;
1417 p->ltmpobj = true;
1418 p->u.var.nm = strdup(tmpvnm);
1419 param_meta_copy(p->param, p1->param);
1420 p->param.name = p->u.var.nm;
1421
1422 if (!init)
1423 {
1424 p->param.data = (double *) Malloc(ngp * nlev * sizeof(double));
1425 double *pdata = p->param.data;
1426 const double *p1data = p1->param.data;
1427
1428 if (nmiss)
1429 {
1430 for (size_t i = 0; i < ngp * nlev; ++i) pdata[i] = DBL_IS_EQUAL(p1data[i], missval) ? missval : unary_op_not(p1data[i]);
1431 }
1432 else
1433 {
1434 for (size_t i = 0; i < ngp * nlev; ++i) pdata[i] = unary_op_not(p1data[i]);
1435 }
1436
1437 p->param.nmiss = nmiss;
1438 }
1439
1440 if (p1->ltmpobj) node_delete(p1);
1441
1442 return p;
1443 }
1444
1445 static nodeType *
ex_not_con(const nodeType * p1)1446 ex_not_con(const nodeType *p1)
1447 {
1448 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1449
1450 p->type = typeCon;
1451 p->ltmpobj = true;
1452
1453 p->u.con.value = unary_op_not(p1->u.con.value);
1454
1455 return p;
1456 }
1457
1458 static nodeType *
ex_not(const int init,nodeType * p1)1459 ex_not(const int init, nodeType *p1)
1460 {
1461 nodeType *p = nullptr;
1462
1463 if (p1->type == typeVar)
1464 {
1465 if (Options::cdoVerbose) cdo_print("\t%s\tnot\t! (%s)", ExIn[init], p1->u.var.nm);
1466 p = ex_not_var(init, p1);
1467 }
1468 else if (p1->type == typeCon)
1469 {
1470 if (Options::cdoVerbose) cdo_print("\t%s\tnot\t! (%g)", ExIn[init], p1->u.con.value);
1471 p = ex_not_con(p1);
1472 }
1473 else
1474 cdo_abort("Internal problem!");
1475
1476 return p;
1477 }
1478
1479 static void
strAddNodeInfo(char * string,size_t stringlen,nodeType * p,const char * ext)1480 strAddNodeInfo(char *string, size_t stringlen, nodeType *p, const char *ext)
1481 {
1482 const auto len = strlen(string);
1483 if (p->type == typeCon)
1484 snprintf(string + len, stringlen - len, "%g%s", p->u.con.value, ext);
1485 else
1486 snprintf(string + len, stringlen - len, "%s[N%zu][L%zu]%s", p->u.var.nm, p->param.ngp, p->param.nlev, ext);
1487 }
1488
1489 static nodeType *
ex_ifelse(const int init,nodeType * p1,nodeType * p2,nodeType * p3)1490 ex_ifelse(const int init, nodeType *p1, nodeType *p2, nodeType *p3)
1491 {
1492 if (Options::cdoVerbose)
1493 {
1494 char strbuffer[1024];
1495 snprintf(strbuffer, sizeof(strbuffer), "\t%s\tifelse\t", ExIn[init]);
1496 strAddNodeInfo(strbuffer, sizeof(strbuffer), p1, " ? ");
1497 strAddNodeInfo(strbuffer, sizeof(strbuffer), p2, " : ");
1498 strAddNodeInfo(strbuffer, sizeof(strbuffer), p3, "");
1499 cdo_print(strbuffer);
1500 }
1501
1502 nodeType *p0 = nullptr;
1503 nodeType *pnodes[3] = { p1, p2, p3 };
1504 for (unsigned i = 0; i < 3; ++i)
1505 if (pnodes[i]->type != typeCon)
1506 {
1507 p0 = pnodes[i];
1508 break;
1509 }
1510
1511 if (p0 == nullptr) cdo_abort("expr?expr:expr: no data variable found!");
1512
1513 auto missval = p0->param.missval;
1514 auto ngp = (p0->param.ngp > 0) ? p0->param.ngp : 1;
1515 auto nlev = (p0->param.nlev > 0) ? p0->param.nlev : 1;
1516 auto px = p0;
1517
1518 size_t nmiss1 = 0;
1519 auto missval1 = missval;
1520 double *pdata1 = nullptr;
1521 size_t ngp1 = 1;
1522 size_t nlev1 = 1;
1523
1524 if (p1->type == typeCon)
1525 {
1526 pdata1 = &p1->u.con.value;
1527 }
1528 else
1529 {
1530 nmiss1 = p1->param.nmiss;
1531 ngp1 = (p1->param.ngp > 0) ? p1->param.ngp : 1;
1532 nlev1 = (p1->param.nlev > 0) ? p1->param.nlev : 1;
1533 missval1 = p1->param.missval;
1534 pdata1 = p1->param.data;
1535
1536 if (ngp1 > 1 && ngp1 != ngp)
1537 {
1538 if (ngp != 1) cdo_abort("expr?expr:expr: Number of grid points differ (ngp = %zu, ngp1 = %zu)", ngp, ngp1);
1539
1540 ngp = ngp1;
1541 px = p1;
1542 }
1543
1544 if (nlev1 > 1 && nlev1 != nlev)
1545 {
1546 if (nlev != 1) cdo_abort("expr?expr:expr: Number of levels differ (nlev = %zu, nlev1 = %zu)", nlev, nlev1);
1547
1548 nlev = nlev1;
1549 px = p1;
1550 }
1551 }
1552
1553 auto missval2 = missval1;
1554 double *pdata2 = nullptr;
1555 size_t ngp2 = 1;
1556 size_t nlev2 = 1;
1557
1558 if (p2->type == typeCon)
1559 {
1560 pdata2 = &p2->u.con.value;
1561 }
1562 else
1563 {
1564 ngp2 = (p2->param.ngp > 0) ? p2->param.ngp : 1;
1565 nlev2 = (p2->param.nlev > 0) ? p2->param.nlev : 1;
1566 missval2 = p2->param.missval;
1567 pdata2 = p2->param.data;
1568
1569 if (ngp2 > 1 && ngp2 != ngp)
1570 {
1571 if (ngp != 1) cdo_abort("expr?expr:expr: Number of grid points differ (ngp = %zu, ngp2 = %zu)", ngp, ngp2);
1572
1573 ngp = ngp2;
1574 px = p2;
1575 }
1576
1577 if (nlev2 > 1 && nlev2 != nlev)
1578 {
1579 if (nlev != 1) cdo_abort("expr?expr:expr: Number of levels differ (nlev = %zu, nlev2 = %zu)", nlev, nlev2);
1580
1581 nlev = nlev2;
1582 px = p2;
1583 }
1584 }
1585
1586 auto missval3 = missval1;
1587 double *pdata3 = nullptr;
1588 size_t ngp3 = 1;
1589 size_t nlev3 = 1;
1590
1591 if (p3->type == typeCon)
1592 {
1593 pdata3 = &p3->u.con.value;
1594 }
1595 else
1596 {
1597 ngp3 = (p3->param.ngp > 0) ? p3->param.ngp : 1;
1598 nlev3 = (p3->param.nlev > 0) ? p3->param.nlev : 1;
1599 missval3 = p3->param.missval;
1600 pdata3 = p3->param.data;
1601
1602 if (ngp3 > 1 && ngp3 != ngp)
1603 {
1604 if (ngp != 1) cdo_abort("expr?expr:expr: Number of grid points differ (ngp = %zu, ngp3 = %zu)", ngp, ngp3);
1605
1606 ngp = ngp3;
1607 px = p3;
1608 }
1609
1610 if (nlev3 > 1 && nlev3 != nlev)
1611 {
1612 if (nlev != 1) cdo_abort("expr?expr:expr: Number of levels differ (nlev = %zu, nlev3 = %zu)", nlev, nlev3);
1613
1614 nlev = nlev3;
1615 px = p3;
1616 }
1617 }
1618
1619 auto p = (nodeType *) Calloc(1, sizeof(nodeType));
1620
1621 p->type = typeVar;
1622 p->ltmpobj = true;
1623 p->u.var.nm = strdup(tmpvnm);
1624
1625 param_meta_copy(p->param, px->param);
1626 p->param.name = p->u.var.nm;
1627
1628 if (!init)
1629 {
1630 size_t nmiss = 0;
1631
1632 p->param.data = (double *) Malloc(ngp * nlev * sizeof(double));
1633
1634 for (size_t k = 0; k < nlev; ++k)
1635 {
1636 const size_t loff1 = (nlev1 == 1) ? 0 : k * ngp1;
1637 const size_t loff = k * ngp;
1638 const size_t loff2 = (nlev2 == 1) ? 0 : loff;
1639 const size_t loff3 = (nlev3 == 1) ? 0 : loff;
1640
1641 const auto idat1 = pdata1 + loff1;
1642 const auto idat2 = pdata2 + loff2;
1643 const auto idat3 = pdata3 + loff3;
1644 auto odat = p->param.data + loff;
1645
1646 for (size_t i = 0; i < ngp; ++i)
1647 {
1648 const auto ival1 = idat1[(ngp1 > 1) ? i : 0];
1649 const auto ival2 = idat2[(ngp2 > 1) ? i : 0];
1650 const auto ival3 = idat3[(ngp3 > 1) ? i : 0];
1651
1652 if (nmiss1 && DBL_IS_EQUAL(ival1, missval1))
1653 odat[i] = missval1;
1654 else if (IS_NOT_EQUAL(ival1, 0.0))
1655 odat[i] = DBL_IS_EQUAL(ival2, missval2) ? missval1 : ival2;
1656 else
1657 odat[i] = DBL_IS_EQUAL(ival3, missval3) ? missval1 : ival3;
1658 }
1659
1660 nmiss += array_num_mv(ngp, odat, missval1);
1661 }
1662
1663 p->param.nmiss = nmiss;
1664 }
1665
1666 if (p1->ltmpobj) node_delete(p1);
1667 if (p2->ltmpobj) node_delete(p2);
1668 if (p3->ltmpobj) node_delete(p3);
1669
1670 return p;
1671 }
1672 /*
1673 static int
1674 exNode(nodeType *p, parseParamType *parse_arg)
1675 {
1676 if (!p) return 0;
1677
1678 // node is leaf
1679 if (p->type == typeCon || p->type == typeVar || p->u.opr.nops == 0) return 0;
1680
1681 // node has children
1682 for (int k = 0; k < p->u.opr.nops; k++) exNode(p->u.opr.op[k], parse_arg);
1683
1684 return 0;
1685 }
1686 */
1687
1688 static int
param_search_name(const int nparam,const std::vector<paramType> & params,const char * name)1689 param_search_name(const int nparam, const std::vector<paramType> ¶ms, const char *name)
1690 {
1691 for (int varID = 0; varID < nparam; ++varID)
1692 {
1693 if (params[varID].isValid && cdo_cmpstr(params[varID].name, name)) return varID;
1694 }
1695
1696 return -1;
1697 }
1698
1699 static int
param_search_name_size(const int nparam,std::vector<paramType> & params,const char * name,size_t ngp,size_t nlev)1700 param_search_name_size(const int nparam, std::vector<paramType> ¶ms, const char *name, size_t ngp, size_t nlev)
1701 {
1702 for (int varID = 0; varID < nparam; ++varID)
1703 {
1704 if (cdo_cmpstr(params[varID].name, name))
1705 {
1706 if (ngp == params[varID].ngp && nlev == params[varID].nlev)
1707 return varID;
1708 else if (ngp == 0 && nlev == 0)
1709 return varID;
1710 else
1711 params[varID].isValid = false;
1712 }
1713 }
1714
1715 return -1;
1716 }
1717
1718 static void
param_print(const char * vname,const paramType & param,const long tsID)1719 param_print(const char *vname, const paramType ¶m, const long tsID)
1720 {
1721 constexpr size_t maxout = 100;
1722 const auto data = param.data;
1723 for (size_t k = 0; k < param.nlev; ++k)
1724 for (size_t i = 0; i < param.ngp; ++i)
1725 {
1726 if (i < maxout || (param.ngp > maxout && i >= (param.ngp - maxout)))
1727 {
1728 if (param.steptype == TIME_CONSTANT)
1729 fprintf(stdout, " %s[lev=%zu:gp=%zu] = %g\n", vname, k + 1, i + 1, data[k * param.ngp + i]);
1730 else
1731 fprintf(stdout, " %s[ts=%ld:lev=%zu:gp=%zu] = %g\n", vname, tsID, k + 1, i + 1, data[k * param.ngp + i]);
1732 }
1733 else if (i == maxout)
1734 {
1735 fprintf(stdout, " .......\n");
1736 }
1737 }
1738 }
1739
1740 static void
add_new_constant(const char * varname,parseParamType * parse_arg,std::vector<paramType> & params,const paramType & param)1741 add_new_constant(const char *varname, parseParamType *parse_arg, std::vector<paramType> ¶ms, const paramType ¶m)
1742 {
1743 const auto varID = parse_arg->nparams;
1744 if (varID >= parse_arg->maxparams) cdo_abort("Too many parameter (limit=%d)", parse_arg->maxparams);
1745
1746 param_meta_copy(params[varID], param);
1747 params[varID].type = PARAM_CONST;
1748 params[varID].isValid = true;
1749 params[varID].ngp = 0;
1750 params[varID].nlat = 0;
1751 params[varID].nlev = 0;
1752 params[varID].missval = -9.e33;
1753 params[varID].nmiss = 0;
1754 params[varID].name = strdup(varname);
1755 parse_arg->nparams++;
1756 parse_arg->cnparams++;
1757 }
1758
1759 static void
add_new_param(const char * varname,parseParamType * parse_arg,std::vector<paramType> & params,const paramType & param)1760 add_new_param(const char *varname, parseParamType *parse_arg, std::vector<paramType> ¶ms, const paramType ¶m)
1761 {
1762 const auto varID = parse_arg->nparams;
1763 if (varID >= parse_arg->maxparams) cdo_abort("Too many parameter (limit=%d)", parse_arg->maxparams);
1764
1765 param_meta_copy(params[varID], param);
1766 params[varID].isValid = true;
1767 params[varID].hasMissvals = param.hasMissvals;
1768 params[varID].name = strdup(varname);
1769 params[varID].nmiss = param.nmiss;
1770 if (param.units) params[varID].units = strdup(param.units);
1771 if (param.longname) params[varID].longname = strdup(param.longname);
1772 parse_arg->nparams++;
1773 parse_arg->cnparams++;
1774 }
1775
1776 static nodeType *
expr_run_type_com(nodeType * p,parseParamType * parse_arg)1777 expr_run_type_com(nodeType *p, parseParamType *parse_arg)
1778 {
1779 const auto init = parse_arg->init;
1780 auto ¶ms = parse_arg->params;
1781
1782 const auto cname = p->u.com.cname;
1783 const auto vname = p->u.com.vname;
1784 if (parse_arg->debug) cdo_print("\tstatement\t\t%s(%s)", cname, vname);
1785
1786 auto varID = param_search_name(parse_arg->nparams, params, vname);
1787 if (varID == -1) cdo_abort("Variable %s not found, needed for statement %s(%s)!", vname, cname, vname);
1788
1789 if (init)
1790 {
1791 if (cdo_cmpstr(cname, "remove")) params[varID].remove = true;
1792 }
1793 else
1794 {
1795 if (cdo_cmpstr(cname, "print")) param_print(vname, params[varID], std::lround(params[parse_arg->tsID].data[0]));
1796 }
1797
1798 return nullptr;
1799 }
1800
1801 static nodeType *
expr_run_type_con(nodeType * p,parseParamType * parse_arg)1802 expr_run_type_con(nodeType *p, parseParamType *parse_arg)
1803 {
1804 if (parse_arg->debug) cdo_print("\tpush\tconst\t%g", p->u.con.value);
1805 return p;
1806 }
1807
1808 static int
expr_run_type_var_grid(const char * vnm,int coord,parseParamType * parse_arg)1809 expr_run_type_var_grid(const char *vnm, int coord, parseParamType *parse_arg)
1810 {
1811 auto ¶ms = parse_arg->params;
1812
1813 const auto len = strlen(vnm);
1814 auto varname = strdup(vnm);
1815 varname[len - 2] = 0;
1816 const auto varID = param_search_name(parse_arg->nparams, params, varname);
1817 if (varID == -1) cdo_abort("Coordinate %c: variable >%s< not found!", coord, varname);
1818
1819 const auto nvarID = parse_arg->nparams;
1820 if (nvarID >= parse_arg->maxparams) cdo_abort("Too many parameter (limit=%d)", parse_arg->maxparams);
1821
1822 const auto coordID = params_get_coord_ID(parse_arg, coord, params[varID].gridID);
1823 parse_arg->coords[coordID].needed = true;
1824 const auto units = parse_arg->coords[coordID].units.data();
1825 const auto longname = parse_arg->coords[coordID].longname.data();
1826
1827 params[nvarID].isValid = true;
1828 params[nvarID].coord = coord;
1829 params[nvarID].hasMissvals = false;
1830 params[nvarID].name = strdup(vnm);
1831 params[nvarID].missval = params[varID].missval;
1832 params[nvarID].gridID = params[varID].gridID;
1833 params[nvarID].zaxisID = parse_arg->surfaceID;
1834 params[nvarID].steptype = TIME_CONSTANT;
1835 params[nvarID].ngp = params[varID].ngp;
1836 params[nvarID].nlat = params[varID].nlat;
1837 params[nvarID].nlev = 1;
1838 if (units) params[nvarID].units = strdup(units);
1839 if (longname) params[nvarID].longname = strdup(longname);
1840 parse_arg->nparams++;
1841 parse_arg->cnparams++;
1842
1843 free(varname);
1844
1845 return nvarID;
1846 }
1847
1848 static int
expr_run_type_var_zaxis(const char * vnm,int coord,parseParamType * parse_arg)1849 expr_run_type_var_zaxis(const char *vnm, int coord, parseParamType *parse_arg)
1850 {
1851 auto ¶ms = parse_arg->params;
1852
1853 const auto len = strlen(vnm);
1854 auto varname = strdup(vnm);
1855 varname[len - 2] = 0;
1856 const auto varID = param_search_name(parse_arg->nparams, params, varname);
1857 if (varID == -1) cdo_abort("Coordinate %c: variable >%s< not found!", coord, varname);
1858
1859 const auto nvarID = parse_arg->nparams;
1860 if (nvarID >= parse_arg->maxparams) cdo_abort("Too many parameter (limit=%d)", parse_arg->maxparams);
1861
1862 const auto coordID = params_get_coord_ID(parse_arg, coord, params[varID].zaxisID);
1863 parse_arg->coords[coordID].needed = true;
1864 const auto units = parse_arg->coords[coordID].units.data();
1865 const auto longname = parse_arg->coords[coordID].longname.data();
1866
1867 params[nvarID].isValid = true;
1868 params[nvarID].coord = coord;
1869 params[nvarID].hasMissvals = false;
1870 params[nvarID].name = strdup(vnm);
1871 params[nvarID].missval = params[varID].missval;
1872 params[nvarID].gridID = parse_arg->pointID;
1873 params[nvarID].zaxisID = params[varID].zaxisID;
1874 params[nvarID].steptype = TIME_CONSTANT;
1875 params[nvarID].ngp = 1;
1876 params[nvarID].nlev = params[varID].nlev;
1877 if (units) params[nvarID].units = strdup(units);
1878 if (longname) params[nvarID].longname = strdup(longname);
1879 parse_arg->nparams++;
1880 parse_arg->cnparams++;
1881
1882 free(varname);
1883
1884 return nvarID;
1885 }
1886
1887 static nodeType *
expr_run_type_var(nodeType * p,parseParamType * parse_arg)1888 expr_run_type_var(nodeType *p, parseParamType *parse_arg)
1889 {
1890 const auto init = parse_arg->init;
1891 const auto ¶ms = parse_arg->params;
1892
1893 const auto vnm = p->u.var.nm;
1894 auto varID = param_search_name(parse_arg->nparams, params, vnm);
1895 if (varID == -1 && init)
1896 {
1897 const auto len = strlen(vnm);
1898 if (len > 2 && vnm[len - 2] == '.')
1899 {
1900 const auto coord = vnm[len - 1];
1901 if (coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w')
1902 {
1903 varID = expr_run_type_var_grid(vnm, coord, parse_arg);
1904 }
1905 else if (coord == 'z' || coord == 'd')
1906 {
1907 varID = expr_run_type_var_zaxis(vnm, coord, parse_arg);
1908 }
1909 }
1910 }
1911
1912 if (varID == -1)
1913 {
1914 cdo_abort("Variable >%s< not found!", vnm);
1915 }
1916 else if (init)
1917 {
1918 if (varID < parse_arg->nvars1 && !parse_arg->needed[varID]) parse_arg->needed[varID] = true;
1919 }
1920
1921 param_meta_copy(p->param, params[varID]);
1922 p->param.coord = params[varID].coord;
1923 p->param.hasMissvals = params[varID].hasMissvals;
1924 p->param.name = params[varID].name;
1925 p->param.longname = params[varID].longname;
1926 p->param.units = params[varID].units;
1927 p->ltmpobj = false;
1928
1929 if (!init)
1930 {
1931 p->param.data = params[varID].data;
1932 p->param.nmiss = params[varID].nmiss;
1933 }
1934
1935 if (parse_arg->debug)
1936 {
1937 if (p->param.ngp == 0 && p->param.nlev == 0)
1938 cdo_print("\tpush\tvar\t%s", vnm);
1939 else
1940 cdo_print("\tpush\tvar\t%s[N%zu][L%zu]", vnm, p->param.ngp, p->param.nlev);
1941 }
1942
1943 return p;
1944 }
1945
1946 static nodeType *
expr_run_type_fun1c(nodeType * p,parseParamType * parse_arg)1947 expr_run_type_fun1c(nodeType *p, parseParamType *parse_arg)
1948 {
1949 const auto init = parse_arg->init;
1950
1951 const auto funcID = get_funcID(p->u.fun1c.name);
1952 const auto functype = fun_sym_tbl[funcID].type;
1953
1954 if (functype == FT_1C)
1955 {
1956 auto fnode = expr_run(p->u.fun1c.op, parse_arg);
1957 const auto value = p->u.fun1c.value;
1958 return fun1c(init, funcID, fnode, value, parse_arg);
1959 }
1960 else
1961 {
1962 cdo_abort("Syntax error in call to %s(), check number of parameter!\n", p->u.fun1c.name);
1963 }
1964
1965 return nullptr;
1966 }
1967
1968 static nodeType *
expr_run_type_fun2c(nodeType * p,parseParamType * parse_arg)1969 expr_run_type_fun2c(nodeType *p, parseParamType *parse_arg)
1970 {
1971 const auto init = parse_arg->init;
1972
1973 const auto funcID = get_funcID(p->u.fun2c.name);
1974 const auto functype = fun_sym_tbl[funcID].type;
1975
1976 if (functype == FT_2C)
1977 {
1978 auto fnode = expr_run(p->u.fun2c.op, parse_arg);
1979 const auto value1 = p->u.fun2c.value1;
1980 const auto value2 = p->u.fun2c.value2;
1981 return fun2c(init, funcID, fnode, value1, value2, parse_arg);
1982 }
1983 else
1984 {
1985 cdo_abort("Syntax error in call to %s(), check number of parameter!\n", p->u.fun2c.name);
1986 }
1987
1988 return nullptr;
1989 }
1990
1991 static nodeType *
expr_run_type_fun(nodeType * p,parseParamType * parse_arg)1992 expr_run_type_fun(nodeType *p, parseParamType *parse_arg)
1993 {
1994 const auto init = parse_arg->init;
1995 const auto ¶ms = parse_arg->params;
1996
1997 const auto funcID = get_funcID(p->u.fun.name);
1998 auto functype = fun_sym_tbl[funcID].type;
1999
2000 auto fnode = expr_run(p->u.fun.op, parse_arg);
2001
2002 if (functype == FT_COORD)
2003 {
2004 return coord_fun(init, funcID, fnode, parse_arg);
2005 }
2006 else if (functype == FT_0)
2007 {
2008 const auto vartsID = parse_arg->tsID;
2009 return ex_fun0_con(init, funcID, params[vartsID].data);
2010 }
2011 else
2012 {
2013 functype = fun_sym_tbl[funcID].type;
2014 const auto funcflag = fun_sym_tbl[funcID].flag;
2015 if (functype == FT_FLD && funcflag == 1)
2016 {
2017 const auto coordID = params_get_coord_ID(parse_arg, 'w', fnode->param.gridID);
2018 if (init)
2019 parse_arg->coords[coordID].needed = true;
2020 else
2021 fnode->param.weight = parse_arg->coords[coordID].data.data();
2022 }
2023 auto rnode = ex_fun(init, funcID, fnode);
2024 // if (fnode->ltmpobj) node_delete(fnode);
2025 // Free(fnode);
2026 return rnode;
2027 }
2028 }
2029
2030 static nodeType *
expr_run_type_opr(nodeType * p,parseParamType * parse_arg)2031 expr_run_type_opr(nodeType *p, parseParamType *parse_arg)
2032 {
2033 const auto init = parse_arg->init;
2034 auto ¶ms = parse_arg->params;
2035
2036 // clang-format off
2037 switch (p->u.opr.oper)
2038 {
2039 case '=':
2040 {
2041 auto rnode = expr_run(p->u.opr.op[1], parse_arg);
2042
2043 const auto varname2 = p->u.opr.op[0]->u.var.nm;
2044
2045 if (parse_arg->debug)
2046 {
2047 if (rnode && rnode->type == typeVar && rnode->param.ngp > 0 && rnode->param.nlev > 0)
2048 cdo_print("\tpop\tvar\t%s[N%zu][L%zu]", varname2, rnode->param.ngp, rnode->param.nlev);
2049 else
2050 cdo_print("\tpop\tconst\t%s", varname2);
2051 }
2052
2053 // auto varID = param_search_name(parse_arg->nparams, params, varname2);
2054 auto varID = param_search_name_size(parse_arg->nparams, params, varname2, rnode->param.ngp, rnode->param.nlev);
2055 if (init)
2056 {
2057 if (varID >= 0)
2058 {
2059 // printf(" found %s\n", varname2);
2060 if (varID < parse_arg->nvars1)
2061 {
2062 if (rnode->param.nlev > 0 && params[varID].nlev != rnode->param.nlev)
2063 cdo_abort("The number of layers must not change (name=%s layers: in=%zu out=%zu)!", params[varID].name,
2064 params[varID].nlev, rnode->param.nlev);
2065
2066 params[varID].select = true;
2067 parse_arg->needed[varID] = true;
2068 }
2069 else if (params[varID].coord)
2070 cdo_abort("Coordinate variable %s is read only!", varname2);
2071 /*
2072 else
2073 cdo_warning("Variable %s already defined!", varname2);
2074 */
2075 }
2076 else if (rnode && rnode->type == typeCon)
2077 {
2078 add_new_constant(varname2, parse_arg, params, rnode->param);
2079 }
2080 else if (p->u.opr.op[1]->type != typeCon)
2081 {
2082 add_new_param(varname2, parse_arg, params, rnode->param);
2083 }
2084 }
2085 else
2086 {
2087 if (varID < 0) cdo_abort("Variable >%s< not found!", varname2);
2088
2089 if (params[varID].coord) cdo_abort("Coordinate variable %s is read only!", varname2);
2090 param_meta_copy(p->param, params[varID]);
2091 p->param.name = params[varID].name;
2092 p->param.data = params[varID].data;
2093 p->ltmpobj = false;
2094
2095 ex_copy(init, p, rnode);
2096 params[varID].nmiss = p->param.nmiss;
2097 }
2098
2099 if (rnode && rnode->ltmpobj)
2100 {
2101 node_delete(rnode);
2102 rnode = nullptr;
2103 }
2104 // else Free(rnode);
2105 break;
2106 }
2107 case UMINUS: return ex_uminus(init, expr_run(p->u.opr.op[0], parse_arg));
2108 case NOT: return ex_not(init, expr_run(p->u.opr.op[0], parse_arg));
2109 case '?': return ex_ifelse(init, expr_run(p->u.opr.op[0], parse_arg), expr_run(p->u.opr.op[1], parse_arg),
2110 expr_run(p->u.opr.op[2], parse_arg));
2111 default: return expr(init, p->u.opr.oper, expr_run(p->u.opr.op[0], parse_arg), expr_run(p->u.opr.op[1], parse_arg));
2112 }
2113 // clang-format on
2114
2115 return nullptr;
2116 }
2117
2118 nodeType *
expr_run(nodeType * p,parseParamType * parse_arg)2119 expr_run(nodeType *p, parseParamType *parse_arg)
2120 {
2121 pointID = parse_arg->pointID;
2122 zonalID = parse_arg->zonalID;
2123 surfaceID = parse_arg->surfaceID;
2124
2125 if (!p) return nullptr;
2126
2127 // clang-format off
2128 switch (p->type)
2129 {
2130 case typeCom: return expr_run_type_com(p, parse_arg);
2131 case typeCon: return expr_run_type_con(p, parse_arg);
2132 case typeVar: return expr_run_type_var(p, parse_arg);
2133 case typeFun1c: return expr_run_type_fun1c(p, parse_arg);
2134 case typeFun2c: return expr_run_type_fun2c(p, parse_arg);
2135 case typeFun: return expr_run_type_fun(p, parse_arg);
2136 case typeOpr: return expr_run_type_opr(p, parse_arg);
2137 }
2138 // clang-format on
2139
2140 return nullptr;
2141 }
2142