epanet-plus 0.0.1__cp313-cp313-macosx_11_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of epanet-plus might be problematic. Click here for more details.

Files changed (105) hide show
  1. docs/conf.py +67 -0
  2. epanet-msx-src/dispersion.h +27 -0
  3. epanet-msx-src/hash.c +107 -0
  4. epanet-msx-src/hash.h +28 -0
  5. epanet-msx-src/include/epanetmsx.h +104 -0
  6. epanet-msx-src/include/epanetmsx_export.h +42 -0
  7. epanet-msx-src/mathexpr.c +937 -0
  8. epanet-msx-src/mathexpr.h +39 -0
  9. epanet-msx-src/mempool.c +204 -0
  10. epanet-msx-src/mempool.h +24 -0
  11. epanet-msx-src/msxchem.c +1285 -0
  12. epanet-msx-src/msxcompiler.c +368 -0
  13. epanet-msx-src/msxdict.h +42 -0
  14. epanet-msx-src/msxdispersion.c +586 -0
  15. epanet-msx-src/msxerr.c +116 -0
  16. epanet-msx-src/msxfile.c +260 -0
  17. epanet-msx-src/msxfuncs.c +175 -0
  18. epanet-msx-src/msxfuncs.h +35 -0
  19. epanet-msx-src/msxinp.c +1504 -0
  20. epanet-msx-src/msxout.c +398 -0
  21. epanet-msx-src/msxproj.c +791 -0
  22. epanet-msx-src/msxqual.c +2011 -0
  23. epanet-msx-src/msxrpt.c +400 -0
  24. epanet-msx-src/msxtank.c +422 -0
  25. epanet-msx-src/msxtoolkit.c +1164 -0
  26. epanet-msx-src/msxtypes.h +551 -0
  27. epanet-msx-src/msxutils.c +524 -0
  28. epanet-msx-src/msxutils.h +56 -0
  29. epanet-msx-src/newton.c +158 -0
  30. epanet-msx-src/newton.h +34 -0
  31. epanet-msx-src/rk5.c +287 -0
  32. epanet-msx-src/rk5.h +39 -0
  33. epanet-msx-src/ros2.c +293 -0
  34. epanet-msx-src/ros2.h +35 -0
  35. epanet-msx-src/smatrix.c +816 -0
  36. epanet-msx-src/smatrix.h +29 -0
  37. epanet-src/AUTHORS +60 -0
  38. epanet-src/LICENSE +21 -0
  39. epanet-src/enumstxt.h +151 -0
  40. epanet-src/epanet.c +5937 -0
  41. epanet-src/epanet2.c +961 -0
  42. epanet-src/epanet2.def +131 -0
  43. epanet-src/errors.dat +79 -0
  44. epanet-src/flowbalance.c +186 -0
  45. epanet-src/funcs.h +219 -0
  46. epanet-src/genmmd.c +1000 -0
  47. epanet-src/hash.c +177 -0
  48. epanet-src/hash.h +28 -0
  49. epanet-src/hydcoeffs.c +1303 -0
  50. epanet-src/hydraul.c +1164 -0
  51. epanet-src/hydsolver.c +781 -0
  52. epanet-src/hydstatus.c +442 -0
  53. epanet-src/include/epanet2.h +466 -0
  54. epanet-src/include/epanet2_2.h +1962 -0
  55. epanet-src/include/epanet2_enums.h +518 -0
  56. epanet-src/inpfile.c +884 -0
  57. epanet-src/input1.c +672 -0
  58. epanet-src/input2.c +970 -0
  59. epanet-src/input3.c +2265 -0
  60. epanet-src/leakage.c +527 -0
  61. epanet-src/mempool.c +146 -0
  62. epanet-src/mempool.h +24 -0
  63. epanet-src/output.c +853 -0
  64. epanet-src/project.c +1691 -0
  65. epanet-src/quality.c +695 -0
  66. epanet-src/qualreact.c +800 -0
  67. epanet-src/qualroute.c +696 -0
  68. epanet-src/report.c +1559 -0
  69. epanet-src/rules.c +1500 -0
  70. epanet-src/smatrix.c +871 -0
  71. epanet-src/text.h +508 -0
  72. epanet-src/types.h +928 -0
  73. epanet-src/util/cstr_helper.c +59 -0
  74. epanet-src/util/cstr_helper.h +38 -0
  75. epanet-src/util/errormanager.c +92 -0
  76. epanet-src/util/errormanager.h +39 -0
  77. epanet-src/util/filemanager.c +212 -0
  78. epanet-src/util/filemanager.h +81 -0
  79. epanet-src/validate.c +408 -0
  80. epanet.cpython-313-darwin.so +0 -0
  81. epanet_plus/VERSION +1 -0
  82. epanet_plus/__init__.py +8 -0
  83. epanet_plus/epanet_plus.c +118 -0
  84. epanet_plus/epanet_toolkit.py +2730 -0
  85. epanet_plus/epanet_wrapper.py +2414 -0
  86. epanet_plus/include/epanet_plus.h +9 -0
  87. epanet_plus-0.0.1.dist-info/METADATA +152 -0
  88. epanet_plus-0.0.1.dist-info/RECORD +105 -0
  89. epanet_plus-0.0.1.dist-info/WHEEL +6 -0
  90. epanet_plus-0.0.1.dist-info/licenses/LICENSE +21 -0
  91. epanet_plus-0.0.1.dist-info/top_level.txt +11 -0
  92. examples/basic_usage.py +35 -0
  93. python-extension/ext.c +344 -0
  94. python-extension/pyepanet.c +2133 -0
  95. python-extension/pyepanet.h +143 -0
  96. python-extension/pyepanet2.c +1823 -0
  97. python-extension/pyepanet2.h +141 -0
  98. python-extension/pyepanet_plus.c +37 -0
  99. python-extension/pyepanet_plus.h +4 -0
  100. python-extension/pyepanetmsx.c +388 -0
  101. python-extension/pyepanetmsx.h +35 -0
  102. tests/test_epanet.py +16 -0
  103. tests/test_epanetmsx.py +36 -0
  104. tests/test_epyt.py +114 -0
  105. tests/test_load_inp_from_buffer.py +18 -0
@@ -0,0 +1,937 @@
1
+ /******************************************************************************
2
+ ** MODULE: MATHEXPR.C
3
+ ** PROJECT: EPANET-MSX
4
+ ** DESCRIPTION: Evaluates symbolic mathematical expression consisting
5
+ ** of numbers, variable names, math functions & arithmetic
6
+ ** operators.
7
+ ** AUTHORS: see AUTHORS
8
+ ** Copyright: see AUTHORS
9
+ ** License: see LICENSE
10
+ ** VERSION: 2.0.00
11
+ ** LAST UPDATE: 09/02/2022
12
+ ******************************************************************************/
13
+ /*
14
+ ** Operand codes:
15
+ ** 1 = (
16
+ ** 2 = )
17
+ ** 3 = +
18
+ ** 4 = - (subtraction)
19
+ ** 5 = *
20
+ ** 6 = /
21
+ ** 7 = number
22
+ ** 8 = user-defined variable
23
+ ** 9 = - (negative)
24
+ ** 10 = cos
25
+ ** 11 = sin
26
+ ** 12 = tan
27
+ ** 13 = cot
28
+ ** 14 = abs
29
+ ** 15 = sgn
30
+ ** 16 = sqrt
31
+ ** 17 = log
32
+ ** 18 = exp
33
+ ** 19 = asin
34
+ ** 20 = acos
35
+ ** 21 = atan
36
+ ** 22 = acot
37
+ ** 23 = sinh
38
+ ** 24 = cosh
39
+ ** 25 = tanh
40
+ ** 26 = coth
41
+ ** 27 = log10
42
+ ** 28 = step (x<=0 ? 0 : 1)
43
+ ** 31 = ^
44
+ ******************************************************************************/
45
+ #define _CRT_SECURE_NO_WARNINGS
46
+
47
+ #include <ctype.h>
48
+ #include <string.h>
49
+ #include <stdlib.h>
50
+ #include <stdio.h>
51
+ #include <math.h>
52
+
53
+ #include "mathexpr.h"
54
+
55
+ #define MAX_STACK_SIZE 1024
56
+
57
+ //***************************************************
58
+ #define MAX_TERM_SIZE 1024
59
+ struct MathTerm
60
+ {
61
+ char s[MAX_TERM_SIZE];
62
+ };
63
+ typedef struct MathTerm Term;
64
+ //***************************************************
65
+
66
+
67
+ // Local declarations
68
+ //--------------------
69
+ // Structure for binary tree representation of math expression
70
+ struct TreeNode
71
+ {
72
+ int opcode; // operator code
73
+ int ivar; // variable index
74
+ double fvalue; // numerical value
75
+ struct TreeNode* left; // left sub-tree of tokenized formula
76
+ struct TreeNode* right; // right sub-tree of tokenized formula
77
+ };
78
+ typedef struct TreeNode ExprTree;
79
+
80
+ // Local variables
81
+ //----------------
82
+ static int Err;
83
+ static int Bc;
84
+ static int PrevLex, CurLex;
85
+ static int Len, Pos;
86
+ static char* S;
87
+ static char Token[255];
88
+ static int Ivar;
89
+ static double Fvalue;
90
+
91
+ // math function names
92
+ char* MathFunc[] = { "COS", "SIN", "TAN", "COT", "ABS", "SGN",
93
+ "SQRT", "LOG", "EXP", "ASIN", "ACOS", "ATAN",
94
+ "ACOT", "SINH", "COSH", "TANH", "COTH", "LOG10",
95
+ "STEP", NULL };
96
+
97
+ // Local functions
98
+ //----------------
99
+ static int sametext(char*, char*);
100
+ static int isDigit(char);
101
+ static int isLetter(char);
102
+ static void getToken(void);
103
+ static int getMathFunc(void);
104
+ static int getVariable(void);
105
+ static int getOperand(void);
106
+ static int getLex(void);
107
+ static double getNumber(void);
108
+ static ExprTree* newNode(void);
109
+ static ExprTree* getSingleOp(int*);
110
+ static ExprTree* getOp(int*);
111
+ static ExprTree* getTree(void);
112
+ static void traverseTree(ExprTree*, MathExpr**);
113
+ static void deleteTree(ExprTree*);
114
+
115
+ // Callback functions
116
+ static int (*getVariableIndex) (char*); // return index of named variable
117
+ static double (*getVariableValue) (int); // return value of indexed variable
118
+
119
+ //=============================================================================
120
+
121
+ int sametext(char* s1, char* s2)
122
+ /*
123
+ ** Purpose:
124
+ ** performs case insensitive comparison of two strings.
125
+ **
126
+ ** Input:
127
+ ** s1 = character string
128
+ ** s2 = character string.
129
+ **
130
+ ** Returns:
131
+ ** 1 if strings are the same, 0 otherwise.
132
+ */
133
+ {
134
+ int i;
135
+ for (i = 0; toupper(s1[i]) == toupper(s2[i]); i++)
136
+ if (!s1[i + 1] && !s2[i + 1]) return(1);
137
+ return(0);
138
+ }
139
+
140
+ //=============================================================================
141
+
142
+ int isDigit(char c)
143
+ {
144
+ if (c >= '1' && c <= '9') return 1;
145
+ if (c == '0') return 1;
146
+ return 0;
147
+ }
148
+
149
+ //=============================================================================
150
+
151
+ int isLetter(char c)
152
+ {
153
+ if (c >= 'a' && c <= 'z') return 1;
154
+ if (c >= 'A' && c <= 'Z') return 1;
155
+ if (c == '_') return 1;
156
+ return 0;
157
+ }
158
+
159
+ //=============================================================================
160
+
161
+ void getToken()
162
+ {
163
+ char c[] = " ";
164
+ Token[0] = '\0';
165
+ while (Pos <= Len &&
166
+ (isLetter(S[Pos]) || isDigit(S[Pos])))
167
+ {
168
+ c[0] = S[Pos];
169
+ strcat(Token, c);
170
+ Pos++;
171
+ }
172
+ Pos--;
173
+ }
174
+
175
+ //=============================================================================
176
+
177
+ int getMathFunc()
178
+ {
179
+ int i = 0;
180
+ while (MathFunc[i] != NULL)
181
+ {
182
+ if (sametext(MathFunc[i], Token)) return i + 10;
183
+ i++;
184
+ }
185
+ return(0);
186
+ }
187
+
188
+ //=============================================================================
189
+
190
+ int getVariable()
191
+ {
192
+ if (!getVariableIndex) return 0;
193
+ Ivar = getVariableIndex(Token);
194
+ if (Ivar >= 0) return 8;
195
+ return 0;
196
+ }
197
+
198
+ //=============================================================================
199
+
200
+ double getNumber()
201
+ {
202
+ char c[] = " ";
203
+ char sNumber[255];
204
+ int errflag = 0;
205
+ int decimalCount = 0;
206
+
207
+ /* --- get whole number portion of number */
208
+ sNumber[0] = '\0';
209
+ while (Pos < Len && isDigit(S[Pos]))
210
+ {
211
+ c[0] = S[Pos];
212
+ strcat(sNumber, c);
213
+ Pos++;
214
+ }
215
+
216
+ /* --- get fractional portion of number */
217
+ if (Pos < Len)
218
+ {
219
+ if (S[Pos] == '.')
220
+ {
221
+ decimalCount++;
222
+ if (decimalCount > 1) Err = 1;
223
+ strcat(sNumber, ".");
224
+ Pos++;
225
+ while (Pos < Len && isDigit(S[Pos]))
226
+ {
227
+ c[0] = S[Pos];
228
+ strcat(sNumber, c);
229
+ Pos++;
230
+ }
231
+ }
232
+
233
+ /* --- get exponent */
234
+ if (Pos < Len && (S[Pos] == 'e' || S[Pos] == 'E'))
235
+ {
236
+ strcat(sNumber, "E");
237
+ Pos++;
238
+ if (Pos >= Len) errflag = 1;
239
+ else
240
+ {
241
+ if (S[Pos] == '-' || S[Pos] == '+')
242
+ {
243
+ c[0] = S[Pos];
244
+ strcat(sNumber, c);
245
+ Pos++;
246
+ }
247
+ if (Pos >= Len || !isDigit(S[Pos])) errflag = 1;
248
+ else while (Pos < Len && isDigit(S[Pos]))
249
+ {
250
+ c[0] = S[Pos];
251
+ strcat(sNumber, c);
252
+ Pos++;
253
+ }
254
+ }
255
+ }
256
+ }
257
+ Pos--;
258
+ if (errflag) return 0;
259
+ else return atof(sNumber);
260
+ }
261
+
262
+ //=============================================================================
263
+
264
+ int getOperand()
265
+ {
266
+ int code;
267
+ switch (S[Pos])
268
+ {
269
+ case '(': code = 1; break;
270
+ case ')': code = 2; break;
271
+ case '+': code = 3; break;
272
+ case '-': code = 4;
273
+ if (Pos < Len - 1 &&
274
+ isDigit(S[Pos + 1]) &&
275
+ (CurLex <= 6 || CurLex == 31))
276
+ {
277
+ Pos++;
278
+ Fvalue = -getNumber();
279
+ code = 7;
280
+ }
281
+ break;
282
+ case '*': code = 5; break;
283
+ case '/': code = 6; break;
284
+ case '^': code = 31; break;
285
+ default: code = 0;
286
+ }
287
+ return code;
288
+ }
289
+
290
+ //=============================================================================
291
+
292
+ int getLex()
293
+ {
294
+ int n;
295
+
296
+ /* --- skip spaces */
297
+ while (Pos < Len && S[Pos] == ' ') Pos++;
298
+ if (Pos >= Len) return 0;
299
+
300
+ /* --- check for operand */
301
+ n = getOperand();
302
+
303
+ /* --- check for function/variable/number */
304
+ if (n == 0)
305
+ {
306
+ if (isLetter(S[Pos]))
307
+ {
308
+ getToken();
309
+ n = getMathFunc();
310
+ if (n == 0) n = getVariable();
311
+ }
312
+ else if (S[Pos] == '.' || isDigit(S[Pos]))
313
+ {
314
+ n = 7;
315
+ Fvalue = getNumber();
316
+ }
317
+ }
318
+ Pos++;
319
+ PrevLex = CurLex;
320
+ CurLex = n;
321
+ return n;
322
+ }
323
+
324
+ //=============================================================================
325
+
326
+ ExprTree* newNode()
327
+ {
328
+ ExprTree* node;
329
+ node = (ExprTree*)malloc(sizeof(ExprTree));
330
+ if (!node) Err = 2;
331
+ else
332
+ {
333
+ node->opcode = 0;
334
+ node->ivar = -1;
335
+ node->fvalue = 0.;
336
+ node->left = NULL;
337
+ node->right = NULL;
338
+ }
339
+ return node;
340
+ }
341
+
342
+ //=============================================================================
343
+
344
+ ExprTree* getSingleOp(int* lex)
345
+ {
346
+ int opcode;
347
+ ExprTree* left;
348
+ ExprTree* node;
349
+
350
+ /* --- open parenthesis, so continue to grow the tree */
351
+ if (*lex == 1)
352
+ {
353
+ Bc++;
354
+ left = getTree();
355
+ }
356
+
357
+ else
358
+ {
359
+ /* --- Error if not a singleton operand */
360
+ if (*lex < 7 || *lex == 9 || *lex > 30)
361
+ {
362
+ Err = 1;
363
+ return NULL;
364
+ }
365
+
366
+ opcode = *lex;
367
+
368
+ /* --- simple number or variable name */
369
+ if (*lex == 7 || *lex == 8)
370
+ {
371
+ left = newNode();
372
+ left->opcode = opcode;
373
+ if (*lex == 7) left->fvalue = Fvalue;
374
+ if (*lex == 8) left->ivar = Ivar;
375
+ }
376
+
377
+ /* --- function which must have a '(' after it */
378
+ else
379
+ {
380
+ *lex = getLex();
381
+ if (*lex != 1)
382
+ {
383
+ Err = 1;
384
+ return NULL;
385
+ }
386
+ Bc++;
387
+ left = newNode();
388
+ left->left = getTree();
389
+ left->opcode = opcode;
390
+ }
391
+ }
392
+ *lex = getLex();
393
+
394
+ /* --- exponentiation */
395
+ if (*lex == 31)
396
+ {
397
+ node = newNode();
398
+ node->left = left;
399
+ node->opcode = *lex;
400
+ *lex = getLex();
401
+ node->right = getSingleOp(lex);
402
+ left = node;
403
+ }
404
+ return left;
405
+ }
406
+
407
+ //=============================================================================
408
+
409
+ ExprTree* getOp(int* lex)
410
+ {
411
+ int opcode;
412
+ ExprTree* left;
413
+ ExprTree* right;
414
+ ExprTree* node;
415
+ int neg = 0;
416
+
417
+ *lex = getLex();
418
+ if (PrevLex == 0 || PrevLex == 1)
419
+ {
420
+ if (*lex == 4)
421
+ {
422
+ neg = 1;
423
+ *lex = getLex();
424
+ }
425
+ else if (*lex == 3) *lex = getLex();
426
+ }
427
+ left = getSingleOp(lex);
428
+ while (*lex == 5 || *lex == 6)
429
+ {
430
+ opcode = *lex;
431
+ *lex = getLex();
432
+ right = getSingleOp(lex);
433
+ node = newNode();
434
+ if (Err) return NULL;
435
+ node->left = left;
436
+ node->right = right;
437
+ node->opcode = opcode;
438
+ left = node;
439
+ }
440
+ if (neg)
441
+ {
442
+ node = newNode();
443
+ if (Err) return NULL;
444
+ node->left = left;
445
+ node->right = NULL;
446
+ node->opcode = 9;
447
+ left = node;
448
+ }
449
+ return left;
450
+ }
451
+
452
+ //=============================================================================
453
+
454
+ ExprTree* getTree()
455
+ {
456
+ int lex;
457
+ int opcode;
458
+ ExprTree* left;
459
+ ExprTree* right;
460
+ ExprTree* node;
461
+
462
+ left = getOp(&lex);
463
+ for (;;)
464
+ {
465
+ if (lex == 0 || lex == 2)
466
+ {
467
+ if (lex == 2) Bc--;
468
+ break;
469
+ }
470
+
471
+ if (lex != 3 && lex != 4)
472
+ {
473
+ Err = 1;
474
+ break;
475
+ }
476
+
477
+ opcode = lex;
478
+ right = getOp(&lex);
479
+ node = newNode();
480
+ if (Err) break;
481
+ node->left = left;
482
+ node->right = right;
483
+ node->opcode = opcode;
484
+ left = node;
485
+ }
486
+ return left;
487
+ }
488
+
489
+ //=============================================================================
490
+
491
+ void traverseTree(ExprTree* tree, MathExpr** expr)
492
+ // Converts binary tree to linked list (postfix format)
493
+ {
494
+ MathExpr* node;
495
+ if (tree == NULL) return;
496
+ traverseTree(tree->left, expr);
497
+ traverseTree(tree->right, expr);
498
+ node = (MathExpr*)malloc(sizeof(MathExpr));
499
+ if (node)
500
+ {
501
+ node->fvalue = tree->fvalue;
502
+ node->opcode = tree->opcode;
503
+ node->ivar = tree->ivar;
504
+ node->next = NULL;
505
+ node->prev = (*expr);
506
+ }
507
+ if (*expr) (*expr)->next = node;
508
+ (*expr) = node;
509
+ }
510
+
511
+ //=============================================================================
512
+
513
+ void deleteTree(ExprTree* tree)
514
+ {
515
+ if (tree)
516
+ {
517
+ if (tree->left) deleteTree(tree->left);
518
+ if (tree->right) deleteTree(tree->right);
519
+ free(tree);
520
+ }
521
+ }
522
+
523
+ //=============================================================================
524
+
525
+ // Turn on "precise" floating point option
526
+ #pragma float_control(precise, on, push)
527
+
528
+ double mathexpr_eval(MathExpr* expr, double (*getVariableValue) (int))
529
+ // Mathematica expression evaluation using a stack
530
+ {
531
+
532
+ // --- Note: the exprStack array must be declared locally and not globally
533
+ // since this function can be called recursively.
534
+
535
+ double exprStack[MAX_STACK_SIZE];
536
+ MathExpr* node = expr;
537
+ double r1, r2;
538
+ int stackindex = 0;
539
+
540
+ exprStack[0] = 0.0;
541
+ while (node != NULL)
542
+ {
543
+ switch (node->opcode)
544
+ {
545
+ case 3:
546
+ r1 = exprStack[stackindex];
547
+ stackindex--;
548
+ r2 = exprStack[stackindex];
549
+ exprStack[stackindex] = r2 + r1;
550
+ break;
551
+
552
+ case 4:
553
+ r1 = exprStack[stackindex];
554
+ stackindex--;
555
+ r2 = exprStack[stackindex];
556
+ exprStack[stackindex] = r2 - r1;
557
+ break;
558
+
559
+ case 5:
560
+ r1 = exprStack[stackindex];
561
+ stackindex--;
562
+ r2 = exprStack[stackindex];
563
+ exprStack[stackindex] = r2 * r1;
564
+ break;
565
+
566
+ case 6:
567
+ r1 = exprStack[stackindex];
568
+ stackindex--;
569
+ r2 = exprStack[stackindex];
570
+ exprStack[stackindex] = r2 / r1;
571
+ break;
572
+
573
+ case 7:
574
+ stackindex++;
575
+ exprStack[stackindex] = node->fvalue;
576
+ break;
577
+
578
+ case 8:
579
+ if (getVariableValue != NULL)
580
+ r1 = getVariableValue(node->ivar);
581
+ else r1 = 0.0;
582
+ stackindex++;
583
+ exprStack[stackindex] = r1;
584
+ break;
585
+
586
+ case 9:
587
+ exprStack[stackindex] = -exprStack[stackindex];
588
+ break;
589
+
590
+ case 10:
591
+ r1 = exprStack[stackindex];
592
+ r2 = cos(r1);
593
+ exprStack[stackindex] = r2;
594
+ break;
595
+
596
+ case 11:
597
+ r1 = exprStack[stackindex];
598
+ r2 = sin(r1);
599
+ exprStack[stackindex] = r2;
600
+ break;
601
+
602
+ case 12:
603
+ r1 = exprStack[stackindex];
604
+ r2 = tan(r1);
605
+ exprStack[stackindex] = r2;
606
+ break;
607
+
608
+ case 13:
609
+ r1 = exprStack[stackindex];
610
+ r2 = 1.0 / tan(r1);
611
+ exprStack[stackindex] = r2;
612
+ break;
613
+
614
+ case 14:
615
+ r1 = exprStack[stackindex];
616
+ r2 = fabs(r1);
617
+ exprStack[stackindex] = r2;
618
+ break;
619
+
620
+ case 15:
621
+ r1 = exprStack[stackindex];
622
+ if (r1 < 0.0) r2 = -1.0;
623
+ else if (r1 > 0.0) r2 = 1.0;
624
+ else r2 = 0.0;
625
+ exprStack[stackindex] = r2;
626
+ break;
627
+
628
+ case 16:
629
+ r1 = exprStack[stackindex];
630
+ r2 = sqrt(r1);
631
+ exprStack[stackindex] = r2;
632
+ break;
633
+
634
+ case 17:
635
+ r1 = exprStack[stackindex];
636
+ r2 = log(r1);
637
+ exprStack[stackindex] = r2;
638
+ break;
639
+
640
+ case 18:
641
+ r1 = exprStack[stackindex];
642
+ r2 = exp(r1);
643
+ exprStack[stackindex] = r2;
644
+ break;
645
+
646
+ case 19:
647
+ r1 = exprStack[stackindex];
648
+ r2 = asin(r1);
649
+ exprStack[stackindex] = r2;
650
+ break;
651
+
652
+ case 20:
653
+ r1 = exprStack[stackindex];
654
+ r2 = acos(r1);
655
+ exprStack[stackindex] = r2;
656
+ break;
657
+
658
+ case 21:
659
+ r1 = exprStack[stackindex];
660
+ r2 = atan(r1);
661
+ exprStack[stackindex] = r2;
662
+ break;
663
+
664
+ case 22:
665
+ r1 = exprStack[stackindex];
666
+ r2 = 1.57079632679489661923 - atan(r1);
667
+ exprStack[stackindex] = r2;
668
+ break;
669
+
670
+ case 23:
671
+ r1 = exprStack[stackindex];
672
+ r2 = (exp(r1) - exp(-r1)) / 2.0;
673
+ exprStack[stackindex] = r2;
674
+ break;
675
+
676
+ case 24:
677
+ r1 = exprStack[stackindex];
678
+ r2 = (exp(r1) + exp(-r1)) / 2.0;
679
+ exprStack[stackindex] = r2;
680
+ break;
681
+
682
+ case 25:
683
+ r1 = exprStack[stackindex];
684
+ r2 = (exp(r1) - exp(-r1)) / (exp(r1) + exp(-r1));
685
+ exprStack[stackindex] = r2;
686
+ break;
687
+
688
+ case 26:
689
+ r1 = exprStack[stackindex];
690
+ r2 = (exp(r1) + exp(-r1)) / (exp(r1) - exp(-r1));
691
+ exprStack[stackindex] = r2;
692
+ break;
693
+
694
+ case 27:
695
+ r1 = exprStack[stackindex];
696
+ r2 = log10(r1);
697
+ exprStack[stackindex] = r2;
698
+ break;
699
+
700
+ case 28:
701
+ r1 = exprStack[stackindex];
702
+ if (r1 <= 0.0) r2 = 0.0;
703
+ else r2 = 1.0;
704
+ exprStack[stackindex] = r2;
705
+ break;
706
+
707
+ case 31:
708
+ r1 = exprStack[stackindex];
709
+ stackindex--;
710
+ if (stackindex < 0) break;
711
+ r2 = exprStack[stackindex];
712
+ if (r2 <= 0.0) r2 = 0.0;
713
+ else r2 = pow(r2, r1);
714
+ exprStack[stackindex] = r2;
715
+ break;
716
+ }
717
+ node = node->next;
718
+ }
719
+ if (stackindex >= 0)
720
+ r1 = exprStack[stackindex];
721
+ else
722
+ r1 = 0.0;
723
+
724
+ // Set result to 0 if it is NaN due to an illegal math op
725
+ if (r1 != r1) r1 = 0.0;
726
+
727
+ return r1;
728
+ }
729
+
730
+ // Turn off "precise" floating point option
731
+ #pragma float_control(pop)
732
+
733
+ //=============================================================================
734
+
735
+ void mathexpr_delete(MathExpr* expr)
736
+ {
737
+ if (expr) mathexpr_delete(expr->next);
738
+ free(expr);
739
+ }
740
+
741
+ //=============================================================================
742
+
743
+ MathExpr* mathexpr_create(char* formula, int (*getVar) (char*))
744
+ {
745
+ ExprTree* tree;
746
+ MathExpr* expr = NULL;
747
+ MathExpr* result = NULL;
748
+ getVariableIndex = getVar;
749
+ Err = 0;
750
+ PrevLex = 0;
751
+ CurLex = 0;
752
+ S = formula;
753
+ Len = (int)strlen(S);
754
+ Pos = 0;
755
+ Bc = 0;
756
+ tree = getTree();
757
+ if (Bc == 0 && Err == 0)
758
+ {
759
+ traverseTree(tree, &expr);
760
+ while (expr)
761
+ {
762
+ result = expr;
763
+ expr = expr->prev;
764
+ }
765
+ }
766
+ deleteTree(tree);
767
+ return result;
768
+ }
769
+
770
+
771
+ //=============================================================================
772
+
773
+ char* mathexpr_getStr(MathExpr* expr, char* exprStr,
774
+ char* (*getVariableStr) (int, char*))
775
+ {
776
+ Term TermStack[50];
777
+ MathExpr* node = expr;
778
+ char r1[MAX_TERM_SIZE], r2[MAX_TERM_SIZE];
779
+ int stackindex = 0;
780
+
781
+ strcpy(TermStack[0].s, "");
782
+ while (node != NULL)
783
+ {
784
+ switch (node->opcode)
785
+ {
786
+ case 3:
787
+ strcpy(r1, TermStack[stackindex].s);
788
+ stackindex--;
789
+ strcpy(r2, TermStack[stackindex].s);
790
+ sprintf(TermStack[stackindex].s, "(%s) + (%s)", r2, r1);
791
+ break;
792
+
793
+ case 4:
794
+ strcpy(r1, TermStack[stackindex].s);
795
+ stackindex--;
796
+ strcpy(r2, TermStack[stackindex].s);
797
+ sprintf(TermStack[stackindex].s, "(%s) - (%s)", r2, r1);
798
+ break;
799
+
800
+ case 5:
801
+ strcpy(r1, TermStack[stackindex].s);
802
+ stackindex--;
803
+ strcpy(r2, TermStack[stackindex].s);
804
+ sprintf(TermStack[stackindex].s, "(%s) * (%s)", r2, r1);
805
+ break;
806
+
807
+ case 6:
808
+ strcpy(r1, TermStack[stackindex].s);
809
+ stackindex--;
810
+ strcpy(r2, TermStack[stackindex].s);
811
+ sprintf(TermStack[stackindex].s, "(%s) / (%s)", r2, r1);
812
+ break;
813
+
814
+ case 7:
815
+ stackindex++;
816
+ sprintf(TermStack[stackindex].s, "%.6g", node->fvalue);
817
+ break;
818
+
819
+ case 8:
820
+ if (getVariableStr != NULL)strcpy(r1, getVariableStr(node->ivar, r2));
821
+ else strcpy(r1, "");
822
+ stackindex++;
823
+ strcpy(TermStack[stackindex].s, r1);
824
+ break;
825
+
826
+ case 9:
827
+ strcpy(r1, TermStack[stackindex].s);
828
+ sprintf(TermStack[stackindex].s, "-(%s)", r1);
829
+ break;
830
+
831
+ case 10:
832
+ strcpy(r1, TermStack[stackindex].s);
833
+ sprintf(TermStack[stackindex].s, "cos(%s)", r1);
834
+ break;
835
+
836
+ case 11:
837
+ strcpy(r1, TermStack[stackindex].s);
838
+ sprintf(TermStack[stackindex].s, "sin(%s)", r1);
839
+ break;
840
+
841
+ case 12:
842
+ strcpy(r1, TermStack[stackindex].s);
843
+ sprintf(TermStack[stackindex].s, "tan(%s)", r1);
844
+ break;
845
+
846
+ case 13:
847
+ strcpy(r1, TermStack[stackindex].s);
848
+ sprintf(TermStack[stackindex].s, "cot(%s)", r1);
849
+ break;
850
+
851
+ case 14:
852
+ strcpy(r1, TermStack[stackindex].s);
853
+ sprintf(TermStack[stackindex].s, "abs(%s)", r1);
854
+ break;
855
+
856
+ case 15:
857
+ strcpy(r1, TermStack[stackindex].s);
858
+ sprintf(TermStack[stackindex].s, "sgn(%s)", r1);
859
+ break;
860
+
861
+ case 16:
862
+ strcpy(r1, TermStack[stackindex].s);
863
+ sprintf(TermStack[stackindex].s, "sqrt(%s)", r1);
864
+ break;
865
+
866
+ case 17:
867
+ strcpy(r1, TermStack[stackindex].s);
868
+ sprintf(TermStack[stackindex].s, "log(%s)", r1);
869
+ break;
870
+
871
+ case 18:
872
+ strcpy(r1, TermStack[stackindex].s);
873
+ sprintf(TermStack[stackindex].s, "exp(%s)", r1);
874
+ break;
875
+
876
+ case 19:
877
+ strcpy(r1, TermStack[stackindex].s);
878
+ sprintf(TermStack[stackindex].s, "asin(%s)", r1);
879
+ break;
880
+
881
+ case 20:
882
+ strcpy(r1, TermStack[stackindex].s);
883
+ sprintf(TermStack[stackindex].s, "acos(%s)", r1);
884
+ break;
885
+
886
+ case 21:
887
+ strcpy(r1, TermStack[stackindex].s);
888
+ sprintf(TermStack[stackindex].s, "atan(%s)", r1);
889
+ break;
890
+
891
+ case 22:
892
+ strcpy(r1, TermStack[stackindex].s);
893
+ sprintf(TermStack[stackindex].s, "acot(%s)", r1);
894
+ break;
895
+
896
+ case 23:
897
+ strcpy(r1, TermStack[stackindex].s);
898
+ sprintf(TermStack[stackindex].s, "sinh(%s)", r1);
899
+ break;
900
+
901
+ case 24:
902
+ strcpy(r1, TermStack[stackindex].s);
903
+ sprintf(TermStack[stackindex].s, "cosh(%s)", r1);
904
+ break;
905
+
906
+ case 25:
907
+ strcpy(r1, TermStack[stackindex].s);
908
+ sprintf(TermStack[stackindex].s, "tanh(%s)", r1);
909
+ break;
910
+
911
+ case 26:
912
+ strcpy(r1, TermStack[stackindex].s);
913
+ sprintf(TermStack[stackindex].s, "coth(%s)", r1);
914
+ break;
915
+
916
+ case 27:
917
+ strcpy(r1, TermStack[stackindex].s);
918
+ sprintf(TermStack[stackindex].s, "log10(%s)", r1);
919
+ break;
920
+
921
+ case 28:
922
+ strcpy(r1, TermStack[stackindex].s);
923
+ sprintf(TermStack[stackindex].s, "step(%s)", r1);
924
+ break;
925
+
926
+ case 31:
927
+ strcpy(r1, TermStack[stackindex].s);
928
+ strcpy(r2, TermStack[stackindex - 1].s);
929
+ sprintf(TermStack[stackindex - 1].s, "pow(%s,%s)", r2, r1);
930
+ stackindex--;
931
+ break;
932
+ }
933
+ node = node->next;
934
+ }
935
+ strcpy(exprStr, TermStack[stackindex].s);
936
+ return exprStr;
937
+ }