ret = 1;
} else {
VERBOSE (INFO, print_element (element, 0));
- PRINTOUT ("=> %f\n", evaluate_element (element));
+ PRINTOUT ("=> %f\n", evaluate_element (element, 0));
ret = 0;
}
//fsync (stdfdout);
// 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'
// test: echo "95-6.3*15-1" | calc.exe | grep -q '=> -5.000028e-1'
+// test: echo "95 - 6.3 * 15 - 1" | calc.exe | grep -q '=> -5.000028e-1'
// test: echo "95-6.3+15" | calc.exe | grep -q '=> 1.037e2'
+// test: echo "-cos (0) + 1" | calc.exe | grep -q '=> 0'
/* vim: set ts=4 sw=4 et: */
if (new->ops[1] == ERROR_OP) {
return ERROR_OP;
}
- *proot = newelement (Val, 1, 4);
+ *proot = newelement (Val, 1, 5);
if (*proot == ERROR_OP) {
return ERROR_OP;
}
}
} while (*str == ',');
} else {
- root = newelement (Val, 1, 4);
+ root = newelement (Val, 1, 5);
if (root == NULL) {
return ERROR_OP;
}
if (subparser (&root, &str, operator->func, operator->nbops, operator->prio) == ERROR_OP) {
return ERROR_OP;
}
+ } else if (*str == '-') {
+ new = newelement (Sig, 1, 9);
+ if (new == NULL) {
+ return ERROR_OP;
+ }
+ root = new;
} else {
return ERROR_OP;
}
VERBOSE (INFO, PRINTOUT ("Value: %f\n", value));
if (str != pt) {
if (root == NULL) {
- new = newelement (Val, 1, 4);
+ new = newelement (Val, 1, 5);
if (new == NULL) {
return ERROR_OP;
}
case Atn: func = "Arc Tangent"; break;
case Log: func = "Logarithm"; break;
case Exp: func = "Exponantial"; break;
+ case Sig: func = "Sign"; break;
}
PRINTOUT ("Function: %s\n", func);
}
}
+#define MASK_SUB 0x1
+#define MASK_DIV 0x2
+
/* evaluate element tree */
-double evaluate_element (element_t *root)
+double evaluate_element (element_t *root, char mask)
{
double op0 = 0, op1 = 0;
+ char nextmask = mask;
if ((root == NULL) || (root == ERROR_OP)) {
VERBOSE (WARNING, PRINTOUT ("error while evaluating\n"));
return 0;
}
+ /* mask to manage sub operator sub and div */
+ switch (root->func) {
+ case Add:
+ nextmask &= ~MASK_SUB;
+ nextmask &= ~MASK_DIV;
+ break;
+ case Sub:
+ nextmask |= MASK_SUB;
+ nextmask &= ~MASK_DIV;
+ break;
+ case Mul:
+ nextmask &= ~MASK_DIV;
+ break;
+ case Div:
+ nextmask |= MASK_DIV;
+ break;
+ default:
+ nextmask = mask;
+ }
+
switch (root->func) {
case Val:
- if (root->ops[0]) {
- return evaluate_element (root->ops[0]);
- } else {
- return root->value;
- }
+ case Sig:
+ op0 = (root->ops[0]) ? evaluate_element (root->ops[0], nextmask) : root->value;
break;
case Add:
case Sub:
case Mod:
case Pow:
if (root->ops[1]) {
- op1 = evaluate_element (root->ops[1]);
+ op1 = evaluate_element (root->ops[1], nextmask);
} else {
VERBOSE (WARNING, PRINTOUT ("error while evaluating (op[1])\n"));
return 0;
case Log:
case Exp:
if (root->ops[0]) {
- op0 = evaluate_element (root->ops[0]);
+ op0 = evaluate_element (root->ops[0], 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 Val: return op0;
+ case Sig: return -op0;
+ case Add: return ((mask & MASK_SUB) == 0) ? op0 + op1 : op0 - op1;
+ case Sub: return ((mask & MASK_SUB) == 0) ? op0 - op1 : op0 + op1;
+ case Mul: return ((mask & MASK_DIV) == 0) ? op0 * op1 : op0 / op1;
+ case Div: return ((mask & MASK_DIV) == 0) ? op0 / op1 : op0 * op1;
case Mod: return fmod (op0, op1);
case Pow: return pow (op0, op1);
case Sqr: return sqrt (op0);
case Atn: return atan (op0);
case Log: return log (op0);
case Exp: return exp (op0);
- default: break;
}
return 0;