GCC Code Coverage Report


Directory: src/solver/
Coverage: low: ≥ 0% medium: ≥ 75.0% high: ≥ 90.0%
Coverage Exec / Excl / Total
Lines: 93.4% 369 / 0 / 395
Functions: 100.0% 18 / 0 / 18
Branches: 74.6% 182 / 0 / 244

mathexpr.c
Line Branch Exec Source
1 /******************************************************************************
2 ** MODULE: MATHEXPR.C
3 ** PROJECT: EPA SWMM5
4 ** DESCRIPTION: Evaluates symbolic mathematical expression consisting
5 ** of numbers, variable names, math functions & arithmetic
6 ** operators.
7 ** AUTHORS: L. Rossman, US EPA - NRMRL
8 ** F. Shang, University of Cincinnati
9 ** VERSION: 5.2.2
10 ** LAST UPDATE: 09/02/2022
11 ** BUG FIXES: Problems related to '^' operator (F. Shang, 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_DEPRECATE
46
47 #include <ctype.h>
48 #include <stdlib.h>
49 #include <string.h>
50 #include <stdlib.h>
51 #include <math.h>
52 #include "mathexpr.h"
53
54 #define MAX_STACK_SIZE 1024
55
56 // Local declarations
57 //--------------------
58 // Structure for binary tree representation of math expression
59 struct TreeNode
60 {
61 int opcode; // operator code
62 int ivar; // variable index
63 double fvalue; // numerical value
64 struct TreeNode *left; // left sub-tree of tokenized formula
65 struct TreeNode *right; // right sub-tree of tokenized formula
66 };
67 typedef struct TreeNode ExprTree;
68
69 // Local variables
70 //----------------
71 static int Err;
72 static int Bc;
73 static int PrevLex, CurLex;
74 static int Len, Pos;
75 static char *S;
76 static char Token[255];
77 static int Ivar;
78 static double Fvalue;
79
80 // math function names
81 char *MathFunc[] = {"COS", "SIN", "TAN", "COT", "ABS", "SGN",
82 "SQRT", "LOG", "EXP", "ASIN", "ACOS", "ATAN",
83 "ACOT", "SINH", "COSH", "TANH", "COTH", "LOG10",
84 "STEP", NULL};
85
86 // Local functions
87 //----------------
88 static int sametext(char *, char *);
89 static int isDigit(char);
90 static int isLetter(char);
91 static void getToken(void);
92 static int getMathFunc(void);
93 static int getVariable(void);
94 static int getOperand(void);
95 static int getLex(void);
96 static double getNumber(void);
97 static ExprTree * newNode(void);
98 static ExprTree * getSingleOp(int *);
99 static ExprTree * getOp(int *);
100 static ExprTree * getTree(void);
101 static void traverseTree(ExprTree *, MathExpr **);
102 static void deleteTree(ExprTree *);
103
104 // Callback functions
105 static int (*getVariableIndex) (char *); // return index of named variable
106
107 //=============================================================================
108
109 1558 int sametext(char *s1, char *s2)
110 /*
111 ** Purpose:
112 ** performs case insensitive comparison of two strings.
113 **
114 ** Input:
115 ** s1 = character string
116 ** s2 = character string.
117 **
118 ** Returns:
119 ** 1 if strings are the same, 0 otherwise.
120 */
121 {
122 int i;
123
2/2
✓ Branch 0 taken 168 times.
✓ Branch 1 taken 1539 times.
1707 for (i=0; toupper(s1[i]) == toupper(s2[i]); i++)
124
4/4
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 144 times.
✓ Branch 2 taken 19 times.
✓ Branch 3 taken 5 times.
168 if (!s1[i+1] && !s2[i+1]) return(1);
125 1539 return(0);
126 }
127
128 //=============================================================================
129
130 435 int isDigit(char c)
131 {
132
4/4
✓ Branch 0 taken 98 times.
✓ Branch 1 taken 337 times.
✓ Branch 2 taken 94 times.
✓ Branch 3 taken 4 times.
435 if (c >= '1' && c <= '9') return 1;
133
2/2
✓ Branch 0 taken 130 times.
✓ Branch 1 taken 211 times.
341 if (c == '0') return 1;
134 211 return 0;
135 }
136
137 //=============================================================================
138
139 789 int isLetter(char c)
140 {
141
3/4
✓ Branch 0 taken 56 times.
✓ Branch 1 taken 733 times.
✓ Branch 2 taken 56 times.
✗ Branch 3 not taken.
789 if (c >= 'a' && c <= 'z') return 1;
142
4/4
✓ Branch 0 taken 579 times.
✓ Branch 1 taken 154 times.
✓ Branch 2 taken 547 times.
✓ Branch 3 taken 32 times.
733 if (c >= 'A' && c <= 'Z') return 1;
143
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 156 times.
186 if (c == '_') return 1;
144 156 return 0;
145 }
146
147 //=============================================================================
148
149 91 void getToken()
150 {
151 91 char c[] = " ";
152 91 Token[0] = '\0';
153
3/4
✓ Branch 0 taken 637 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 542 times.
✓ Branch 3 taken 95 times.
1274 while ( Pos <= Len &&
154
2/2
✓ Branch 2 taken 4 times.
✓ Branch 3 taken 91 times.
732 ( isLetter(S[Pos]) || isDigit(S[Pos]) ) )
155 {
156 546 c[0] = S[Pos];
157 546 strcat(Token, c);
158 546 Pos++;
159 }
160 91 Pos--;
161 91 }
162
163 //=============================================================================
164
165 91 int getMathFunc()
166 {
167 91 int i = 0;
168
2/2
✓ Branch 0 taken 1558 times.
✓ Branch 1 taken 72 times.
1630 while (MathFunc[i] != NULL)
169 {
170
2/2
✓ Branch 1 taken 19 times.
✓ Branch 2 taken 1539 times.
1558 if (sametext(MathFunc[i], Token)) return i+10;
171 1539 i++;
172 }
173 72 return(0);
174 }
175
176 //=============================================================================
177
178 72 int getVariable()
179 {
180
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 72 times.
72 if ( !getVariableIndex ) return 0;
181 72 Ivar = getVariableIndex(Token);
182
1/2
✓ Branch 0 taken 72 times.
✗ Branch 1 not taken.
72 if (Ivar >= 0) return 8;
183 return 0;
184 }
185
186 //=============================================================================
187
188 61 double getNumber()
189 {
190 61 char c[] = " ";
191 char sNumber[255];
192 61 int errflag = 0;
193 61 int decimalCount = 0;
194
195 /* --- get whole number portion of number */
196 61 sNumber[0] = '\0';
197
4/4
✓ Branch 0 taken 122 times.
✓ Branch 1 taken 1 time.
✓ Branch 3 taken 62 times.
✓ Branch 4 taken 60 times.
123 while (Pos < Len && isDigit(S[Pos]))
198 {
199 62 c[0] = S[Pos];
200 62 strcat(sNumber, c);
201 62 Pos++;
202 }
203
204 /* --- get fractional portion of number */
205
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 1 time.
61 if (Pos < Len)
206 {
207
1/2
✓ Branch 0 taken 60 times.
✗ Branch 1 not taken.
60 if (S[Pos] == '.')
208 {
209 60 decimalCount++;
210
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 60 times.
60 if (decimalCount > 1) Err = 1;
211 60 strcat(sNumber, ".");
212 60 Pos++;
213
4/4
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 5 times.
✓ Branch 3 taken 97 times.
✓ Branch 4 taken 55 times.
157 while (Pos < Len && isDigit(S[Pos]))
214 {
215 97 c[0] = S[Pos];
216 97 strcat(sNumber, c);
217 97 Pos++;
218 }
219 }
220
221 /* --- get exponent */
222
4/6
✓ Branch 0 taken 55 times.
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 55 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 55 times.
60 if (Pos < Len && (S[Pos] == 'e' || S[Pos] == 'E'))
223 {
224 strcat(sNumber, "E");
225 Pos++;
226 if (Pos >= Len) errflag = 1;
227 else
228 {
229 if (S[Pos] == '-' || S[Pos] == '+')
230 {
231 c[0] = S[Pos];
232 strcat(sNumber, c);
233 Pos++;
234 }
235 if (Pos >= Len || !isDigit(S[Pos])) errflag = 1;
236 else while ( Pos < Len && isDigit(S[Pos]))
237 {
238 c[0] = S[Pos];
239 strcat(sNumber, c);
240 Pos++;
241 }
242 }
243 }
244 }
245 61 Pos--;
246
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 61 times.
61 if (errflag) return 0;
247 61 else return atof(sNumber);
248 }
249
250 //=============================================================================
251
252 306 int getOperand()
253 {
254 int code;
255
8/8
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 24 times.
✓ Branch 2 taken 32 times.
✓ Branch 3 taken 5 times.
✓ Branch 4 taken 45 times.
✓ Branch 5 taken 21 times.
✓ Branch 6 taken 3 times.
✓ Branch 7 taken 152 times.
306 switch(S[Pos])
256 {
257 24 case '(': code = 1; break;
258 24 case ')': code = 2; break;
259 32 case '+': code = 3; break;
260 5 case '-': code = 4;
261
2/4
✓ Branch 0 taken 5 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 5 times.
10 if (Pos < Len-1 &&
262 5 isDigit(S[Pos+1]) &&
263 (CurLex <= 6 || CurLex == 31))
264 {
265 Pos++;
266 Fvalue = -getNumber();
267 code = 7;
268 }
269 5 break;
270 45 case '*': code = 5; break;
271 21 case '/': code = 6; break;
272 3 case '^': code = 31; break;
273 152 default: code = 0;
274 }
275 306 return code;
276 }
277
278 //=============================================================================
279
280 335 int getLex()
281 {
282 int n;
283
284 /* --- skip spaces */
285
4/4
✓ Branch 0 taken 462 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 156 times.
✓ Branch 3 taken 306 times.
491 while ( Pos < Len && S[Pos] == ' ' ) Pos++;
286
2/2
✓ Branch 0 taken 29 times.
✓ Branch 1 taken 306 times.
335 if ( Pos >= Len ) return 0;
287
288 /* --- check for operand */
289 306 n = getOperand();
290
291 /* --- check for function/variable/number */
292
2/2
✓ Branch 0 taken 152 times.
✓ Branch 1 taken 154 times.
306 if ( n == 0 )
293 {
294
2/2
✓ Branch 1 taken 91 times.
✓ Branch 2 taken 61 times.
152 if ( isLetter(S[Pos]) )
295 {
296 91 getToken();
297 91 n = getMathFunc();
298
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 19 times.
91 if ( n == 0 ) n = getVariable();
299 }
300
2/4
✓ Branch 0 taken 61 times.
✗ Branch 1 not taken.
✓ Branch 3 taken 61 times.
✗ Branch 4 not taken.
61 else if ( S[Pos] == '.' || isDigit(S[Pos]) )
301 {
302 61 n = 7;
303 61 Fvalue = getNumber();
304 }
305 }
306 306 Pos++;
307 306 PrevLex = CurLex;
308 306 CurLex = n;
309 306 return n;
310 }
311
312 //=============================================================================
313
314 258 ExprTree * newNode()
315 {
316 ExprTree *node;
317 258 node = (ExprTree *) malloc(sizeof(ExprTree));
318
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 258 times.
258 if (!node) Err = 2;
319 else
320 {
321 258 node->opcode = 0;
322 258 node->ivar = -1;
323 258 node->fvalue = 0.;
324 258 node->left = NULL;
325 258 node->right = NULL;
326 }
327 258 return node;
328 }
329
330 //=============================================================================
331
332 157 ExprTree * getSingleOp(int *lex)
333 {
334 int opcode;
335 ExprTree *left;
336 ExprTree *node;
337
338 /* --- open parenthesis, so continue to grow the tree */
339
2/2
✓ Branch 0 taken 5 times.
✓ Branch 1 taken 152 times.
157 if ( *lex == 1 )
340 {
341 5 Bc++;
342 5 left = getTree();
343 }
344
345 else
346 {
347 /* --- Error if not a singleton operand */
348
3/6
✓ Branch 0 taken 152 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 152 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 152 times.
152 if ( *lex < 7 || *lex == 9 || *lex > 30)
349 {
350 Err = 1;
351 return NULL;
352 }
353
354 152 opcode = *lex;
355
356 /* --- simple number or variable name */
357
4/4
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 61 times.
✓ Branch 2 taken 72 times.
✓ Branch 3 taken 19 times.
152 if ( *lex == 7 || *lex == 8 )
358 {
359 133 left = newNode();
360 133 left->opcode = opcode;
361
2/2
✓ Branch 0 taken 61 times.
✓ Branch 1 taken 72 times.
133 if ( *lex == 7 ) left->fvalue = Fvalue;
362
2/2
✓ Branch 0 taken 72 times.
✓ Branch 1 taken 61 times.
133 if ( *lex == 8 ) left->ivar = Ivar;
363 }
364
365 /* --- function which must have a '(' after it */
366 else
367 {
368 19 *lex = getLex();
369
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 19 times.
19 if ( *lex != 1 )
370 {
371 Err = 1;
372 return NULL;
373 }
374 19 Bc++;
375 19 left = newNode();
376 19 left->left = getTree();
377 19 left->opcode = opcode;
378 }
379 }
380 157 *lex = getLex();
381
382 /* --- exponentiation */
383
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 154 times.
157 if (*lex == 31)
384 {
385 3 node = newNode();
386 3 node->left = left;
387 3 node->opcode = *lex;
388 3 *lex = getLex();
389 3 node->right = getSingleOp(lex);
390 3 left = node;
391 }
392 157 return left;
393 }
394
395 //=============================================================================
396
397 88 ExprTree * getOp(int *lex)
398 {
399 int opcode;
400 ExprTree *left;
401 ExprTree *right;
402 ExprTree *node;
403 88 int neg = 0;
404
405 88 *lex = getLex();
406
4/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 35 times.
88 if (PrevLex == 0 || PrevLex == 1)
407 {
408
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 51 times.
53 if ( *lex == 4 )
409 {
410 2 neg = 1;
411 2 *lex = getLex();
412 }
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51 times.
51 else if ( *lex == 3) *lex = getLex();
414 }
415 88 left = getSingleOp(lex);
416
4/4
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 109 times.
✓ Branch 2 taken 21 times.
✓ Branch 3 taken 88 times.
154 while ( *lex == 5 || *lex == 6)
417 {
418 66 opcode = *lex;
419 66 *lex = getLex();
420 66 right = getSingleOp(lex);
421 66 node = newNode();
422
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 66 times.
66 if (Err) return NULL;
423 66 node->left = left;
424 66 node->right = right;
425 66 node->opcode = opcode;
426 66 left = node;
427 }
428
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 86 times.
88 if ( neg )
429 {
430 2 node = newNode();
431
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
2 if (Err) return NULL;
432 2 node->left = left;
433 2 node->right = NULL;
434 2 node->opcode = 9;
435 2 left = node;
436 }
437 88 return left;
438 }
439
440 //=============================================================================
441
442 53 ExprTree * getTree()
443 {
444 int lex;
445 int opcode;
446 ExprTree *left;
447 ExprTree *right;
448 ExprTree *node;
449
450 53 left = getOp(&lex);
451 for (;;)
452 {
453
4/4
✓ Branch 0 taken 59 times.
✓ Branch 1 taken 29 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 35 times.
88 if ( lex == 0 || lex == 2 )
454 {
455
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 29 times.
53 if ( lex == 2 ) Bc--;
456 53 break;
457 }
458
459
3/4
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 32 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 3 times.
35 if (lex != 3 && lex != 4 )
460 {
461 Err = 1;
462 break;
463 }
464
465 35 opcode = lex;
466 35 right = getOp(&lex);
467 35 node = newNode();
468
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35 times.
35 if (Err) break;
469 35 node->left = left;
470 35 node->right = right;
471 35 node->opcode = opcode;
472 35 left = node;
473 }
474 53 return left;
475 }
476
477 //=============================================================================
478
479 545 void traverseTree(ExprTree *tree, MathExpr **expr)
480 // Converts binary tree to linked list (postfix format)
481 {
482 MathExpr *node;
483
2/2
✓ Branch 0 taken 287 times.
✓ Branch 1 taken 258 times.
545 if ( tree == NULL) return;
484 258 traverseTree(tree->left, expr);
485 258 traverseTree(tree->right, expr);
486 258 node = (MathExpr *) malloc(sizeof(MathExpr));
487
1/2
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
258 if (node)
488 {
489 258 node->fvalue = tree->fvalue;
490 258 node->opcode = tree->opcode;
491 258 node->ivar = tree->ivar;
492 258 node->next = NULL;
493 258 node->prev = (*expr);
494 }
495
2/2
✓ Branch 0 taken 229 times.
✓ Branch 1 taken 29 times.
258 if (*expr) (*expr)->next = node;
496 258 (*expr) = node;
497 }
498
499 //=============================================================================
500
501 258 void deleteTree(ExprTree *tree)
502 {
503
1/2
✓ Branch 0 taken 258 times.
✗ Branch 1 not taken.
258 if (tree)
504 {
505
2/2
✓ Branch 0 taken 125 times.
✓ Branch 1 taken 133 times.
258 if (tree->left) deleteTree(tree->left);
506
2/2
✓ Branch 0 taken 104 times.
✓ Branch 1 taken 154 times.
258 if (tree->right) deleteTree(tree->right);
507 258 free(tree);
508 }
509 258 }
510
511 //=============================================================================
512
513 // Turn on "precise" floating point option
514 #pragma float_control(precise, on, push)
515
516 289812 double mathexpr_eval(MathExpr *expr, double (*getVariableValue) (int))
517 // Mathematica expression evaluation using a stack
518 {
519
520 // --- Note: the ExprStack array must be declared locally and not globally
521 // since this function can be called recursively.
522
523 double ExprStack[MAX_STACK_SIZE];
524 289812 MathExpr *node = expr;
525 double r1, r2;
526 289812 int stackindex = 0;
527
528 289812 ExprStack[0] = 0.0;
529
3/4
✓ Branch 0 taken 997352 times.
✓ Branch 1 taken 289812 times.
✓ Branch 2 taken 997352 times.
✗ Branch 3 not taken.
1287164 while(node != NULL && stackindex >= 0)
530 {
531
27/28
✓ Branch 0 taken 9130 times.
✓ Branch 1 taken 720 times.
✓ Branch 2 taken 175580 times.
✓ Branch 3 taken 164520 times.
✓ Branch 4 taken 140042 times.
✓ Branch 5 taken 501020 times.
✓ Branch 6 taken 480 times.
✓ Branch 7 taken 240 times.
✓ Branch 8 taken 240 times.
✓ Branch 9 taken 240 times.
✓ Branch 10 taken 240 times.
✓ Branch 11 taken 240 times.
✓ Branch 12 taken 240 times.
✓ Branch 13 taken 240 times.
✓ Branch 14 taken 240 times.
✓ Branch 15 taken 240 times.
✓ Branch 16 taken 240 times.
✓ Branch 17 taken 240 times.
✓ Branch 18 taken 240 times.
✓ Branch 19 taken 240 times.
✓ Branch 20 taken 240 times.
✓ Branch 21 taken 240 times.
✓ Branch 22 taken 240 times.
✓ Branch 23 taken 240 times.
✓ Branch 24 taken 240 times.
✓ Branch 25 taken 240 times.
✓ Branch 26 taken 1300 times.
✗ Branch 27 not taken.
997352 switch (node->opcode)
532 {
533 9130 case 3:
534 9130 r1 = ExprStack[stackindex];
535 9130 stackindex--;
536
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 9130 times.
9130 if (stackindex < 0) break;
537 9130 r2 = ExprStack[stackindex];
538 9130 ExprStack[stackindex] = r2 + r1;
539 9130 break;
540
541 720 case 4:
542 720 r1 = ExprStack[stackindex];
543 720 stackindex--;
544
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 720 times.
720 if (stackindex < 0) break;
545 720 r2 = ExprStack[stackindex];
546 720 ExprStack[stackindex] = r2 - r1;
547 720 break;
548
549 175580 case 5:
550 175580 r1 = ExprStack[stackindex];
551 175580 stackindex--;
552
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 175580 times.
175580 if (stackindex < 0) break;
553 175580 r2 = ExprStack[stackindex];
554 175580 ExprStack[stackindex] = r2 * r1;
555 175580 break;
556
557 164520 case 6:
558 164520 r1 = ExprStack[stackindex];
559 164520 stackindex--;
560
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 164520 times.
164520 if (stackindex < 0) break;
561 164520 r2 = ExprStack[stackindex];
562 164520 ExprStack[stackindex] = r2 / r1;
563 164520 break;
564
565 140042 case 7:
566 140042 stackindex++;
567
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140042 times.
140042 if (stackindex >= MAX_STACK_SIZE) break;
568 140042 ExprStack[stackindex] = node->fvalue;
569 140042 break;
570
571 501020 case 8:
572
1/2
✓ Branch 0 taken 501020 times.
✗ Branch 1 not taken.
501020 if (getVariableValue != NULL)
573 {
574 501020 r1 = getVariableValue(node->ivar);
575 }
576 else r1 = 0.0;
577 501020 stackindex++;
578
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 501020 times.
501020 if (stackindex >= MAX_STACK_SIZE) break;
579 501020 ExprStack[stackindex] = r1;
580 501020 break;
581
582 480 case 9:
583 480 ExprStack[stackindex] = -ExprStack[stackindex];
584 480 break;
585
586 240 case 10:
587 240 r1 = ExprStack[stackindex];
588 240 r2 = cos(r1);
589 240 ExprStack[stackindex] = r2;
590 240 break;
591
592 240 case 11:
593 240 r1 = ExprStack[stackindex];
594 240 r2 = sin(r1);
595 240 ExprStack[stackindex] = r2;
596 240 break;
597
598 240 case 12:
599 240 r1 = ExprStack[stackindex];
600 240 r2 = tan(r1);
601 240 ExprStack[stackindex] = r2;
602 240 break;
603
604 240 case 13:
605 240 r1 = ExprStack[stackindex];
606
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (r1 == 0.0) r2 = 0.0;
607 240 else r2 = 1.0/tan( r1 );
608 240 ExprStack[stackindex] = r2;
609 240 break;
610
611 240 case 14:
612 240 r1 = ExprStack[stackindex];
613 240 r2 = fabs( r1 );
614 240 ExprStack[stackindex] = r2;
615 240 break;
616
617 240 case 15:
618 240 r1 = ExprStack[stackindex];
619
2/2
✓ Branch 0 taken 92 times.
✓ Branch 1 taken 148 times.
240 if (r1 < 0.0) r2 = -1.0;
620
1/2
✓ Branch 0 taken 148 times.
✗ Branch 1 not taken.
148 else if (r1 > 0.0) r2 = 1.0;
621 else r2 = 0.0;
622 240 ExprStack[stackindex] = r2;
623 240 break;
624
625 240 case 16:
626 240 r1 = ExprStack[stackindex];
627
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (r1 < 0.0) r2 = 0.0;
628 240 else r2 = sqrt( r1 );
629 240 ExprStack[stackindex] = r2;
630 240 break;
631
632 240 case 17:
633 240 r1 = ExprStack[stackindex];
634
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (r1 <= 0) r2 = 0.0;
635 240 else r2 = log(r1);
636 240 ExprStack[stackindex] = r2;
637 240 break;
638
639 240 case 18:
640 240 r1 = ExprStack[stackindex];
641 240 r2 = exp(r1);
642 240 ExprStack[stackindex] = r2;
643 240 break;
644
645 240 case 19:
646 240 r1 = ExprStack[stackindex];
647 240 r2 = asin( r1 );
648 240 ExprStack[stackindex] = r2;
649 240 break;
650
651 240 case 20:
652 240 r1 = ExprStack[stackindex];
653 240 r2 = acos( r1 );
654 240 ExprStack[stackindex] = r2;
655 240 break;
656
657 240 case 21:
658 240 r1 = ExprStack[stackindex];
659 240 r2 = atan( r1 );
660 240 ExprStack[stackindex] = r2;
661 240 break;
662
663 240 case 22:
664 240 r1 = ExprStack[stackindex];
665 240 r2 = 1.57079632679489661923 - atan(r1);
666 240 ExprStack[stackindex] = r2;
667 240 break;
668
669 240 case 23:
670 240 r1 = ExprStack[stackindex];
671 240 r2 = (exp(r1)-exp(-r1))/2.0;
672 240 ExprStack[stackindex] = r2;
673 240 break;
674
675 240 case 24:
676 240 r1 = ExprStack[stackindex];
677 240 r2 = (exp(r1)+exp(-r1))/2.0;
678 240 ExprStack[stackindex] = r2;
679 240 break;
680
681 240 case 25:
682 240 r1 = ExprStack[stackindex];
683 240 r2 = (exp(r1)-exp(-r1))/(exp(r1)+exp(-r1));
684 240 ExprStack[stackindex] = r2;
685 240 break;
686
687 240 case 26:
688 240 r1 = ExprStack[stackindex];
689 240 r2 = (exp(r1)+exp(-r1))/(exp(r1)-exp(-r1));
690 240 ExprStack[stackindex] = r2;
691 240 break;
692
693 240 case 27:
694 240 r1 = ExprStack[stackindex];
695
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 240 times.
240 if (r1 == 0.0) r2 = 0.0;
696 240 else r2 = log10( r1 );
697 240 ExprStack[stackindex] = r2;
698 240 break;
699
700 240 case 28:
701 240 r1 = ExprStack[stackindex];
702
2/2
✓ Branch 0 taken 109 times.
✓ Branch 1 taken 131 times.
240 if (r1 <= 0.0) r2 = 0.0;
703 131 else r2 = 1.0;
704 240 ExprStack[stackindex] = r2;
705 240 break;
706
707 1300 case 31:
708 1300 r1 = ExprStack[stackindex];
709 1300 stackindex--;
710
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1300 times.
1300 if (stackindex < 0) break;
711 1300 r2 = ExprStack[stackindex];
712
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1298 times.
1300 if (r2 <= 0.0) r2 = 0.0;
713 1298 else r2 = pow(r2, r1);
714 1300 ExprStack[stackindex] = r2;
715 1300 break;
716 }
717 997352 node = node->next;
718 }
719
1/2
✓ Branch 0 taken 289812 times.
✗ Branch 1 not taken.
289812 if (stackindex >= 0)
720 289812 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
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 289812 times.
289812 if ( r1 != r1 ) r1 = 0.0;
726
727 289812 return r1;
728 }
729
730 // Turn off "precise" floating point option
731 #pragma float_control(pop)
732
733 //=============================================================================
734
735 5080 void mathexpr_delete(MathExpr *expr)
736 {
737
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 4822 times.
5080 if (expr) mathexpr_delete(expr->next);
738 5080 free(expr);
739 5080 }
740
741 //=============================================================================
742
743 29 MathExpr * mathexpr_create(char *formula, int (*getVar) (char *))
744 {
745 ExprTree *tree;
746 29 MathExpr *expr = NULL;
747 29 MathExpr *result = NULL;
748 29 getVariableIndex = getVar;
749 29 Err = 0;
750 29 PrevLex = 0;
751 29 CurLex = 0;
752 29 S = formula;
753 29 Len = (int)strlen(S);
754 29 Pos = 0;
755 29 Bc = 0;
756 29 tree = getTree();
757
2/4
✓ Branch 0 taken 29 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 29 times.
✗ Branch 3 not taken.
29 if (Bc == 0 && Err == 0)
758 {
759 29 traverseTree(tree, &expr);
760
2/2
✓ Branch 0 taken 258 times.
✓ Branch 1 taken 29 times.
287 while (expr)
761 {
762 258 result = expr;
763 258 expr = expr->prev;
764 }
765 }
766 29 deleteTree(tree);
767 29 return result;
768 }
769