Added option TE_POW_FROM_RIGHT

This commit is contained in:
Lewis Van Winkle
2016-08-22 21:20:28 -05:00
parent 52a46baabc
commit af6c47ef28
2 changed files with 102 additions and 0 deletions

51
test.c
View File

@@ -32,6 +32,10 @@ typedef struct {
double answer;
} test_case;
typedef struct {
const char *expr1;
const char *expr2;
} test_equ;
@@ -517,6 +521,52 @@ void test_optimize() {
}
}
void test_pow() {
#ifdef TE_POW_FROM_RIGHT
test_equ cases[] = {
{"2^3^4", "2^(3^4)"},
{"2^1.1^1.2^1.3", "2^(1.1^(1.2^1.3))"},
{"-a^b", "-(a^b)"},
{"-a^-b", "-(a^-b)"}
};
#else
test_equ cases[] = {
{"2^3^4", "(2^3)^4"},
{"2^1.1^1.2^1.3", "((2^1.1)^1.2)^1.3"},
{"-a^b", "(-a)^b"},
{"-a^-b", "(-a)^(-b)"}
};
#endif
double a = 2, b = 3;
te_variable lookup[] = {
{"a", &a},
{"b", &b}
};
int i;
for (i = 0; i < sizeof(cases) / sizeof(test_equ); ++i) {
const char *expr1 = cases[i].expr1;
const char *expr2 = cases[i].expr2;
te_expr *ex1 = te_compile(expr1, lookup, sizeof(lookup)/sizeof(te_variable), 0);
te_expr *ex2 = te_compile(expr2, lookup, sizeof(lookup)/sizeof(te_variable), 0);
lok(ex1);
lok(ex2);
double r1 = te_eval(ex1);
double r2 = te_eval(ex2);
fflush(stdout);
lfequal(r1, r2);
te_free(ex1);
te_free(ex2);
}
}
int main(int argc, char *argv[])
{
@@ -528,6 +578,7 @@ int main(int argc, char *argv[])
lrun("Dynamic", test_dynamic);
lrun("Closure", test_closure);
lrun("Optimize", test_optimize);
lrun("Pow", test_pow);
lresults();
return lfails != 0;

View File

@@ -22,6 +22,14 @@
* 3. This notice may not be removed or altered from any source distribution.
*/
/* COMPILE TIME OPTIONS */
/* Exponentiation associativity:
For a^b^c = (a^b)^c and -a^b = (-a)^b do nothing.
For a^b^c = a^(b^c) and -a^b = -(a^b) uncomment the next line.*/
/* #define TE_POW_FROM_RIGHT */
#include "tinyexpr.h"
#include <stdlib.h>
#include <math.h>
@@ -357,7 +365,48 @@ static te_expr *power(state *s) {
return ret;
}
#ifdef TE_POW_FROM_RIGHT
static te_expr *factor(state *s) {
/* <factor> = <power> {"^" <power>} */
te_expr *ret = power(s);
int neg = 0;
te_expr *insertion = 0;
if (ret->type == (TE_FUNCTION1 | TE_FLAG_PURE) && ret->function == negate) {
te_expr *se = ret->parameters[0];
if (se->type != TE_CONSTANT) {
free(ret);
ret = se;
neg = 1;
}
}
while (s->type == TOK_INFIX && (s->function == pow)) {
te_fun2 t = s->function;
next_token(s);
if (insertion) {
/* Make exponentiation go right-to-left. */
te_expr *insert = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, insertion->parameters[1], power(s));
insert->function = t;
insertion->parameters[1] = insert;
insertion = insert;
} else {
ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
ret->function = t;
insertion = ret;
}
}
if (neg) {
ret = NEW_EXPR(TE_FUNCTION1 | TE_FLAG_PURE, ret);
ret->function = negate;
}
return ret;
}
#else
static te_expr *factor(state *s) {
/* <factor> = <power> {"^" <power>} */
te_expr *ret = power(s);
@@ -371,6 +420,8 @@ static te_expr *factor(state *s) {
return ret;
}
#endif
static te_expr *term(state *s) {