From: Laurent Mazet Date: Thu, 29 Dec 2022 09:37:30 +0000 (+0100) Subject: evaluation function X-Git-Tag: v0.8~62 X-Git-Url: https://secure.softndesign.org/git/?a=commitdiff_plain;h=f29271085277e2cfe75796b4156c8339a901211d;p=calc.git evaluation function --- diff --git a/calc.c b/calc.c index b83bbd6..945bddd 100644 --- a/calc.c +++ b/calc.c @@ -1,6 +1,6 @@ /* depend: */ /* cflags: */ -/* linker: atoi.o debug.o fdprintf.o parser.o */ +/* linker: atoi.o debug.o fdprintf.o parser.o -lm */ //#include #include @@ -103,7 +103,8 @@ int main (int argc, char *argv[]) VERBOSE (WARNING, PRINTOUT ("error while parsing: %s\n", buffer)); ret = 1; } else { - print_element (element, 0); + VERBOSE (INFO, print_element (element, 0)); + PRINTOUT ("=> %f\n", evaluate_element (element)); ret = 0; } //fsync (stdfdout); @@ -130,33 +131,33 @@ int main (int argc, char *argv[]) // test: calc.exe -h | awk '/usage:/ { rc=1 } END { exit (1-rc) }' // test: calc.exe -_ 2> /dev/null | awk 'END { if (NR == 0) { exit(0) } else exit (1) }' // test: calc.exe -_ 2>&1 | awk '/usage:/ { rc=1 } END { exit (1-rc) }' -// test: echo "1 + 2" | calc.exe -// test: echo "1 - 2" | calc.exe -// test: echo "1 * 2" | calc.exe -// test: echo "1 / 2" | calc.exe -// test: echo "2 ^ 3" | calc.exe -// test: echo "1e-1 + 2.34e5" | calc.exe -// test: echo "sqrt (2)" | calc.exe -// test: echo "pow (2, 3)" | calc.exe -// test: echo "cos (2)" | calc.exe -// test: echo "sin (2)" | calc.exe -// test: echo "atan (2)" | calc.exe -// test: echo "exp (2)" | calc.exe -// test: echo "log (2)" | calc.exe -// test: echo "1 + 2 - 3" | calc.exe -// test: echo "1 + cos (2 - 3)" | calc.exe -// test: echo "cos (1 / 2) * 3" | calc.exe -// test: echo "1 + 4 * (2 - 3)" | calc.exe -// test: echo "(2 - 3) / 4" | calc.exe -// test: echo "pow (2 - 3, 8 / 3)" | calc.exe -// test: echo "1 + -2" | calc.exe -// test: echo "1 - +2" | calc.exe -// test: echo "-1 + +2" | calc.exe -// test: echo "-1+2" | calc.exe -// test: echo "1-2" | calc.exe -// test: echo "1 * 2 / 3 + 4" | calc.exe -// test: echo "2 ^ 3 * 4 + 5" | calc.exe -// test: echo "2 + 3 * 4 ^ 5" | calc.exe -// test: echo "2 ^ 3 * 4 + cos(5/6)" | calc.exe +// test: echo "1 + 2" | calc.exe | grep -q '=> 3' +// test: echo "1 - 2" | calc.exe | grep -q '=> -1' +// test: echo "2 * 3" | calc.exe | grep -q '=> 6' +// test: echo "1 / 2" | calc.exe | grep -q '=> 5e-1' +// test: echo "2 ^ 3" | calc.exe | grep -q '=> 8' +// test: echo "1e-1 + 2.34e3" | calc.exe | grep -q '=> 2.3401' +// test: echo "sqrt (2)" | calc.exe | grep -q '=> 1.414213' +// test: echo "pow (2, 3)" | calc.exe | grep -q '=> 8' +// test: echo "cos (2)" | calc.exe | grep -q '=> -4.161468e-1' +// test: echo "sin (2)" | calc.exe | grep -q '=> 9.092974e-1' +// test: echo "atan (2)" | calc.exe | grep -q '=> 1.107148' +// test: echo "exp (2)" | calc.exe | grep -q '=> 7.389056' +// test: echo "log (2)" | calc.exe | grep -q '=> 6.931471e-1' +// test: echo "2 + 3 - 4" | calc.exe | grep -q '=> 1' +// test: echo "1 + cos (2 - 3)" | calc.exe | grep -q '=> 1.54030' +// test: echo "cos (1 / 2) * 3" | calc.exe | grep -q '=> 2.63274' +// test: echo "1 + 4 * (2 - 3)" | calc.exe | grep -q '=> -3' +// test: echo "(2 - 3) / 4" | calc.exe | grep -q '=> -2.5e-1' +// test: echo "pow (8 - 3, 4 / 3)" | calc.exe | grep -q '=> 8.549879' +// test: echo "1 + -2" | calc.exe | grep -q '=> -1' +// test: echo "1 - +2" | calc.exe | grep -q '=> -1' +// test: echo "-1 + +2" | calc.exe | grep -q '=> 1' +// test: echo "-1+2" | calc.exe | grep -q '=> 1' +// test: echo "1-2" | calc.exe | grep -q '=> -1' +// test: echo "1 * 2 / 3 + 4" | calc.exe | grep -q '=> 4.666666' +// test: echo "2 ^ 3 * 4 + 5" | calc.exe | grep -q '=> 3.7e1' +// test: echo "2 + 3 * 4 ^ 5" | calc.exe | grep -q '=> 3.074e3' +// test: echo "2 ^ 3 * 4 + cos(5/6)" | calc.exe | grep -q '=> 3.267241e1' /* vim: set ts=4 sw=4 et: */ diff --git a/parser.c b/parser.c index 0caa750..0244307 100644 --- a/parser.c +++ b/parser.c @@ -1,4 +1,5 @@ #include +#include #include #include "debug.h" @@ -270,7 +271,6 @@ void print_element (element_t *root, int level) switch (root->func) { case Val: func = "Value"; break; - case Set: func = "Set"; break; case Add: func = "Addition"; break; case Sub: func = "Subtraction"; break; case Mul: func = "Multiplication"; break; @@ -298,4 +298,67 @@ void print_element (element_t *root, int level) } } +/* evaluate element tree */ + +double evaluate_element (element_t *root) +{ + double op0 = 0, op1 = 0; + + if ((root == NULL) || (root == ERROR_OP)) { + VERBOSE (WARNING, PRINTOUT ("error while evaluating\n")); + return 0; + } + + switch (root->func) { + case Val: + if (root->ops[0]) { + return evaluate_element (root->ops[0]); + } else { + return root->value; + } + break; + case Add: + case Sub: + case Mul: + case Div: + case Pow: + if (root->ops[1]) { + op1 = evaluate_element (root->ops[1]); + } else { + VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[1])\n")); + return 0; + } + /* fallthrough */ + case Sqr: + case Cos: + case Sin: + case Atn: + case Log: + case Exp: + if (root->ops[0]) { + op0 = evaluate_element (root->ops[0]); + } else { + VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[0])\n")); + return 0; + } + } + + switch (root->func) { + case Add: return op0 + op1; + case Sub: return op0 - op1; + case Mul: return op0 * op1; + case Div: return op0 / op1; + case Pow: return pow (op0, op1); + case Sqr: return sqrt (op0); + case Cos: return cos (op0); + case Sin: return sin (op0); + case Atn: return atan (op0); + case Log: return log (op0); + case Exp: return exp (op0); + default: break; + } + + return 0; +} + /* vim: set ts=4 sw=4 et: */ diff --git a/parser.h b/parser.h index 767fcf0..ed17452 100644 --- a/parser.h +++ b/parser.h @@ -4,7 +4,7 @@ /* function type */ typedef enum { - Val = 0, Set, + Val = 0, Add, Sub, Mul, Div, Pow, Sqr, @@ -41,6 +41,8 @@ element_t *parser (char *str, char **next, int prio); void print_element (element_t *root, int level); +double evaluate_element (element_t *root); + #endif /* __PARSER_H__ */ /* vim: set ts=4 sw=4 et: */