MIDAS
Loading...
Searching...
No Matches
tinyexpr.c File Reference
#include "tinyexpr.h"
#include <ctype.h>
#include <limits.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Include dependency graph for tinyexpr.c:

Go to the source code of this file.

Classes

struct  state
 

Macros

#define NAN   (0.0 / 0.0)
 
#define INFINITY   (1.0 / 0.0)
 
#define TYPE_MASK(TYPE)   ((TYPE) &0x0000001F)
 
#define IS_PURE(TYPE)   (((TYPE) &TE_FLAG_PURE) != 0)
 
#define IS_FUNCTION(TYPE)   (((TYPE) &TE_FUNCTION0) != 0)
 
#define IS_CLOSURE(TYPE)   (((TYPE) &TE_CLOSURE0) != 0)
 
#define ARITY(TYPE)   (((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) &0x00000007) : 0)
 
#define NEW_EXPR(type, ...)   new_expr((type), (const te_expr *[]){__VA_ARGS__})
 
#define TE_FUN(...)   ((double (*)(__VA_ARGS__)) n->function)
 
#define M(e)   te_eval(n->parameters[e])
 

Typedefs

typedef double(* te_fun2) (double, double)
 
typedef struct state state
 

Enumerations

enum  {
  TOK_NULL = TE_CLOSURE7 + 1 , TOK_ERROR , TOK_END , TOK_SEP ,
  TOK_OPEN , TOK_CLOSE , TOK_NUMBER , TOK_VARIABLE ,
  TOK_INFIX
}
 
enum  { TE_CONSTANT = 1 }
 

Functions

static te_exprnew_expr (const int type, const te_expr *parameters[])
 
void te_free_parameters (te_expr *n)
 
void te_free (te_expr *n)
 
static double pi (void)
 
static double e (void)
 
static double fac (double a)
 
static double ncr (double n, double r)
 
static double npr (double n, double r)
 
static const te_variablefind_builtin (const char *name, int len)
 
static const te_variablefind_lookup (const state *s, const char *name, int len)
 
static double add (double a, double b)
 
static double sub (double a, double b)
 
static double mul (double a, double b)
 
static double divide (double a, double b)
 
static double negate (double a)
 
static double comma (double a, double b)
 
void next_token (state *s)
 
static te_exprlist (state *s)
 
static te_exprexpr (state *s)
 
static te_exprpower (state *s)
 
static te_exprbase (state *s)
 
static te_exprfactor (state *s)
 
static te_exprterm (state *s)
 
double te_eval (const te_expr *n)
 
static void optimize (te_expr *n)
 
te_exprte_compile (const char *expression, const te_variable *variables, int var_count, int *error)
 
double te_interp (const char *expression, int *error)
 
static void pn (const te_expr *n, int depth)
 
void te_print (const te_expr *n)
 

Variables

static const te_variable functions []
 

Macro Definition Documentation

◆ ARITY

#define ARITY (   TYPE)    (((TYPE) & (TE_FUNCTION0 | TE_CLOSURE0)) ? ((TYPE) &0x00000007) : 0)

Definition at line 90 of file tinyexpr.c.

◆ INFINITY

#define INFINITY   (1.0 / 0.0)

Definition at line 51 of file tinyexpr.c.

◆ IS_CLOSURE

#define IS_CLOSURE (   TYPE)    (((TYPE) &TE_CLOSURE0) != 0)

Definition at line 89 of file tinyexpr.c.

◆ IS_FUNCTION

#define IS_FUNCTION (   TYPE)    (((TYPE) &TE_FUNCTION0) != 0)

Definition at line 88 of file tinyexpr.c.

◆ IS_PURE

#define IS_PURE (   TYPE)    (((TYPE) &TE_FLAG_PURE) != 0)

Definition at line 87 of file tinyexpr.c.

◆ M

#define M (   e)    te_eval(n->parameters[e])

Definition at line 581 of file tinyexpr.c.

◆ NAN

#define NAN   (0.0 / 0.0)

Definition at line 47 of file tinyexpr.c.

◆ NEW_EXPR

#define NEW_EXPR (   type,
  ... 
)    new_expr((type), (const te_expr *[]){__VA_ARGS__})

Definition at line 91 of file tinyexpr.c.

◆ TE_FUN

#define TE_FUN (   ...)    ((double (*)(__VA_ARGS__)) n->function)

Definition at line 580 of file tinyexpr.c.

◆ TYPE_MASK

#define TYPE_MASK (   TYPE)    ((TYPE) &0x0000001F)

Definition at line 85 of file tinyexpr.c.

Typedef Documentation

◆ state

◆ te_fun2

typedef double(* te_fun2) (double, double)

Definition at line 54 of file tinyexpr.c.

Enumeration Type Documentation

◆ anonymous enum

Enumerator
TOK_NULL 
TOK_ERROR 
TOK_END 
TOK_SEP 
TOK_OPEN 
TOK_CLOSE 
TOK_NUMBER 
TOK_VARIABLE 
TOK_INFIX 

Definition at line 56 of file tinyexpr.c.

56 {
59 TOK_END,
60 TOK_SEP,
66};
@ TOK_VARIABLE
Definition tinyexpr.c:64
@ TOK_NULL
Definition tinyexpr.c:57
@ TOK_ERROR
Definition tinyexpr.c:58
@ TOK_SEP
Definition tinyexpr.c:60
@ TOK_OPEN
Definition tinyexpr.c:61
@ TOK_INFIX
Definition tinyexpr.c:65
@ TOK_NUMBER
Definition tinyexpr.c:63
@ TOK_CLOSE
Definition tinyexpr.c:62
@ TOK_END
Definition tinyexpr.c:59
@ TE_CLOSURE7
Definition tinyexpr.h:62

◆ anonymous enum

Enumerator
TE_CONSTANT 

Definition at line 68 of file tinyexpr.c.

68{ TE_CONSTANT = 1 };
@ TE_CONSTANT
Definition tinyexpr.c:68

Function Documentation

◆ add()

static double add ( double  a,
double  b 
)
static

Definition at line 243 of file tinyexpr.c.

243{ return a + b; }

◆ base()

static te_expr * base ( state s)
static

Definition at line 357 of file tinyexpr.c.

357 {
358 /* <base> = <constant> | <variable> | <function-0> {"(" ")"} | <function-1> <power> | <function-X> "(" <expr> {"," <expr>} ")" | "(" <list> ")" */
359 te_expr *ret;
360 int arity;
361
362 switch (TYPE_MASK(s->type)) {
363 case TOK_NUMBER:
364 ret = new_expr(TE_CONSTANT, 0);
365 ret->value = s->value;
366 next_token(s);
367 break;
368
369 case TOK_VARIABLE:
370 ret = new_expr(TE_VARIABLE, 0);
371 ret->bound = s->bound;
372 next_token(s);
373 break;
374
375 case TE_FUNCTION0:
376 case TE_CLOSURE0:
377 ret = new_expr(s->type, 0);
378 ret->function = s->function;
379 if (IS_CLOSURE(s->type))
380 ret->parameters[0] = s->context;
381 next_token(s);
382 if (s->type == TOK_OPEN) {
383 next_token(s);
384 if (s->type != TOK_CLOSE) {
385 s->type = TOK_ERROR;
386 } else {
387 next_token(s);
388 }
389 }
390 break;
391
392 case TE_FUNCTION1:
393 case TE_CLOSURE1:
394 ret = new_expr(s->type, 0);
395 ret->function = s->function;
396 if (IS_CLOSURE(s->type))
397 ret->parameters[1] = s->context;
398 next_token(s);
399 ret->parameters[0] = power(s);
400 break;
401
402 case TE_FUNCTION2:
403 case TE_FUNCTION3:
404 case TE_FUNCTION4:
405 case TE_FUNCTION5:
406 case TE_FUNCTION6:
407 case TE_FUNCTION7:
408 case TE_CLOSURE2:
409 case TE_CLOSURE3:
410 case TE_CLOSURE4:
411 case TE_CLOSURE5:
412 case TE_CLOSURE6:
413 case TE_CLOSURE7:
414 arity = ARITY(s->type);
415
416 ret = new_expr(s->type, 0);
417 ret->function = s->function;
418 if (IS_CLOSURE(s->type))
419 ret->parameters[arity] = s->context;
420 next_token(s);
421
422 if (s->type != TOK_OPEN) {
423 s->type = TOK_ERROR;
424 } else {
425 int i;
426 for (i = 0; i < arity; i++) {
427 next_token(s);
428 ret->parameters[i] = expr(s);
429 if (s->type != TOK_SEP) {
430 break;
431 }
432 }
433 if (s->type != TOK_CLOSE || i != arity - 1) {
434 s->type = TOK_ERROR;
435 } else {
436 next_token(s);
437 }
438 }
439
440 break;
441
442 case TOK_OPEN:
443 next_token(s);
444 ret = list(s);
445 if (s->type != TOK_CLOSE) {
446 s->type = TOK_ERROR;
447 } else {
448 next_token(s);
449 }
450 break;
451
452 default:
453 ret = new_expr(0, 0);
454 s->type = TOK_ERROR;
455 ret->value = NAN;
456 break;
457 }
458
459 return ret;
460}
INT i
Definition mdump.cxx:32
TH1X EXPRT * h1_book(const char *name, const char *title, int bins, double min, double max)
Definition rmidas.h:24
void * context
Definition tinyexpr.c:79
const double * bound
Definition tinyexpr.c:76
int type
Definition tinyexpr.c:73
double value
Definition tinyexpr.c:75
const void * function
Definition tinyexpr.c:77
double value
Definition tinyexpr.h:36
const double * bound
Definition tinyexpr.h:37
const void * function
Definition tinyexpr.h:38
void * parameters[1]
Definition tinyexpr.h:40
static te_expr * expr(state *s)
Definition tinyexpr.c:553
#define TYPE_MASK(TYPE)
Definition tinyexpr.c:85
#define IS_CLOSURE(TYPE)
Definition tinyexpr.c:89
static te_expr * power(state *s)
Definition tinyexpr.c:462
void next_token(state *s)
Definition tinyexpr.c:253
#define NAN
Definition tinyexpr.c:47
static te_expr * new_expr(const int type, const te_expr *parameters[])
Definition tinyexpr.c:93
#define ARITY(TYPE)
Definition tinyexpr.c:90
static te_expr * list(state *s)
Definition tinyexpr.c:567
@ TE_CLOSURE6
Definition tinyexpr.h:61
@ TE_FUNCTION2
Definition tinyexpr.h:48
@ TE_FUNCTION1
Definition tinyexpr.h:47
@ TE_FUNCTION6
Definition tinyexpr.h:52
@ TE_FUNCTION4
Definition tinyexpr.h:50
@ TE_CLOSURE2
Definition tinyexpr.h:57
@ TE_FUNCTION5
Definition tinyexpr.h:51
@ TE_FUNCTION0
Definition tinyexpr.h:46
@ TE_CLOSURE5
Definition tinyexpr.h:60
@ TE_FUNCTION7
Definition tinyexpr.h:53
@ TE_FUNCTION3
Definition tinyexpr.h:49
@ TE_CLOSURE4
Definition tinyexpr.h:59
@ TE_CLOSURE0
Definition tinyexpr.h:55
@ TE_CLOSURE3
Definition tinyexpr.h:58
@ TE_CLOSURE1
Definition tinyexpr.h:56
@ TE_VARIABLE
Definition tinyexpr.h:44
Here is the call graph for this function:
Here is the caller graph for this function:

◆ comma()

static double comma ( double  a,
double  b 
)
static

Definition at line 248 of file tinyexpr.c.

248 {
249 (void) a;
250 return b;
251}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ divide()

static double divide ( double  a,
double  b 
)
static

Definition at line 246 of file tinyexpr.c.

246{ return a / b; }
Here is the caller graph for this function:

◆ e()

static double e ( void  )
static

Definition at line 136 of file tinyexpr.c.

136{ return 2.71828182845904523536; }
Here is the caller graph for this function:

◆ expr()

static te_expr * expr ( state s)
static

Definition at line 553 of file tinyexpr.c.

553 {
554 /* <expr> = <term> {("+" | "-") <term>} */
555 te_expr *ret = term(s);
556
557 while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
558 te_fun2 t = s->function;
559 next_token(s);
560 ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, term(s));
561 ret->function = t;
562 }
563
564 return ret;
565}
INT add
Definition odbhist.cxx:40
static te_expr * term(state *s)
Definition tinyexpr.c:539
static double sub(double a, double b)
Definition tinyexpr.c:244
double(* te_fun2)(double, double)
Definition tinyexpr.c:54
#define NEW_EXPR(type,...)
Definition tinyexpr.c:91
@ TE_FLAG_PURE
Definition tinyexpr.h:64
Here is the call graph for this function:
Here is the caller graph for this function:

◆ fac()

static double fac ( double  a)
static

Definition at line 137 of file tinyexpr.c.

137 { /* simplest version of fac */
138 if (a < 0.0)
139 return NAN;
140 if (a > UINT_MAX)
141 return INFINITY;
142 unsigned int ua = (unsigned int) (a);
143 unsigned long int result = 1, i;
144 for (i = 1; i <= ua; i++) {
145 if (i > ULONG_MAX / result)
146 return INFINITY;
147 result *= i;
148 }
149 return (double) result;
150}
#define INFINITY
Definition tinyexpr.c:51
Here is the call graph for this function:
Here is the caller graph for this function:

◆ factor()

static te_expr * factor ( state s)
static

Definition at line 524 of file tinyexpr.c.

524 {
525 /* <factor> = <power> {"^" <power>} */
526 te_expr *ret = power(s);
527
528 while (s->type == TOK_INFIX && (s->function == pow)) {
529 te_fun2 t = s->function;
530 next_token(s);
531 ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, power(s));
532 ret->function = t;
533 }
534
535 return ret;
536}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_builtin()

static const te_variable * find_builtin ( const char name,
int  len 
)
static

Definition at line 207 of file tinyexpr.c.

207 {
208 int imin = 0;
209 int imax = sizeof(functions) / sizeof(te_variable) - 2;
210
211 /*Binary search.*/
212 while (imax >= imin) {
213 const int i = (imin + ((imax - imin) / 2));
214 int c = strncmp(name, functions[i].name, len);
215 if (!c)
216 c = '\0' - functions[i].name[len];
217 if (c == 0) {
218 return functions + i;
219 } else if (c > 0) {
220 imin = i + 1;
221 } else {
222 imax = i - 1;
223 }
224 }
225
226 return 0;
227}
#define name(x)
Definition midas_macro.h:24
const char * name
Definition tinyexpr.h:68
char c
Definition system.cxx:1310
static const te_variable functions[]
Definition tinyexpr.c:175
Here is the call graph for this function:
Here is the caller graph for this function:

◆ find_lookup()

static const te_variable * find_lookup ( const state s,
const char name,
int  len 
)
static

Definition at line 229 of file tinyexpr.c.

229 {
230 int iters;
231 const te_variable *var;
232 if (!s->lookup)
233 return 0;
234
235 for (var = s->lookup, iters = s->lookup_len; iters; ++var, --iters) {
236 if (strncmp(name, var->name, len) == 0 && var->name[len] == '\0') {
237 return var;
238 }
239 }
240 return 0;
241}
int lookup_len
Definition tinyexpr.c:82
const te_variable * lookup
Definition tinyexpr.c:81
Here is the call graph for this function:
Here is the caller graph for this function:

◆ list()

static te_expr * list ( state s)
static

Definition at line 567 of file tinyexpr.c.

567 {
568 /* <list> = <expr> {"," <expr>} */
569 te_expr *ret = expr(s);
570
571 while (s->type == TOK_SEP) {
572 next_token(s);
573 ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, expr(s));
574 ret->function = comma;
575 }
576
577 return ret;
578}
static double comma(double a, double b)
Definition tinyexpr.c:248
Here is the call graph for this function:
Here is the caller graph for this function:

◆ mul()

static double mul ( double  a,
double  b 
)
static

Definition at line 245 of file tinyexpr.c.

245{ return a * b; }
Here is the caller graph for this function:

◆ ncr()

static double ncr ( double  n,
double  r 
)
static

Definition at line 151 of file tinyexpr.c.

151 {
152 if (n < 0.0 || r < 0.0 || n < r)
153 return NAN;
154 if (n > UINT_MAX || r > UINT_MAX)
155 return INFINITY;
156 unsigned long int un = (unsigned int) (n), ur = (unsigned int) (r), i;
157 unsigned long int result = 1;
158 if (ur > un / 2)
159 ur = un - ur;
160 for (i = 1; i <= ur; i++) {
161 if (result > ULONG_MAX / (un - ur + i))
162 return INFINITY;
163 result *= un - ur + i;
164 result /= i;
165 }
166 return result;
167}
DWORD n[4]
Definition mana.cxx:247
Here is the call graph for this function:
Here is the caller graph for this function:

◆ negate()

static double negate ( double  a)
static

Definition at line 247 of file tinyexpr.c.

247{ return -a; }
Here is the caller graph for this function:

◆ new_expr()

static te_expr * new_expr ( const int  type,
const te_expr parameters[] 
)
static

Definition at line 93 of file tinyexpr.c.

93 {
94 const int arity = ARITY(type);
95 const int psize = sizeof(void *) * arity;
96 const int size = (sizeof(te_expr) /* - sizeof(void *) */) + psize + (IS_CLOSURE(type) ? sizeof(void *) : 0);
97 te_expr *ret = malloc(size);
98 memset(ret, 0, size);
99 if (arity && parameters) {
100 memcpy(ret->parameters, parameters, psize);
101 }
102 ret->type = type;
103 ret->bound = 0;
104 return ret;
105}
INT type
Definition mana.cxx:269
int type
Definition tinyexpr.h:34
Here is the call graph for this function:
Here is the caller graph for this function:

◆ next_token()

void next_token ( state s)

Definition at line 253 of file tinyexpr.c.

253 {
254 s->type = TOK_NULL;
255
256 do {
257
258 if (!*s->next) {
259 s->type = TOK_END;
260 return;
261 }
262
263 /* Try reading a number. */
264 if ((s->next[0] >= '0' && s->next[0] <= '9') || s->next[0] == '.') {
265 s->value = strtod(s->next, (char **) &s->next);
266 s->type = TOK_NUMBER;
267 } else {
268 /* Look for a variable or builtin function call. */
269 if (isalpha(s->next[0])) {
270 const char *start;
271 start = s->next;
272 while (isalpha(s->next[0]) || isdigit(s->next[0]) || (s->next[0] == '_'))
273 s->next++;
274
275 const te_variable *var = find_lookup(s, start, s->next - start);
276 if (!var)
277 var = find_builtin(start, s->next - start);
278
279 if (!var) {
280 s->type = TOK_ERROR;
281 } else {
282 switch (TYPE_MASK(var->type)) {
283 case TE_VARIABLE:
284 s->type = TOK_VARIABLE;
285 s->bound = var->address;
286 break;
287
288 case TE_CLOSURE0:
289 case TE_CLOSURE1:
290 case TE_CLOSURE2:
291 case TE_CLOSURE3: /* Falls through. */
292 case TE_CLOSURE4:
293 case TE_CLOSURE5:
294 case TE_CLOSURE6:
295 case TE_CLOSURE7: /* Falls through. */
296 s->context = var->context; /* Falls through. */
297
298 case TE_FUNCTION0:
299 case TE_FUNCTION1:
300 case TE_FUNCTION2:
301 case TE_FUNCTION3: /* Falls through. */
302 case TE_FUNCTION4:
303 case TE_FUNCTION5:
304 case TE_FUNCTION6:
305 case TE_FUNCTION7: /* Falls through. */
306 s->type = var->type;
307 s->function = var->address;
308 break;
309 }
310 }
311
312 } else {
313 /* Look for an operator or special character. */
314 switch (s->next++[0]) {
315 case '+':
316 s->type = TOK_INFIX;
317 s->function = add;
318 break;
319 case '-':
320 s->type = TOK_INFIX;
321 s->function = sub;
322 break;
323 case '*':
324 s->type = TOK_INFIX;
325 s->function = mul;
326 break;
327 case '/':
328 s->type = TOK_INFIX;
329 s->function = divide;
330 break;
331 case '^':
332 s->type = TOK_INFIX;
333 s->function = pow;
334 break;
335 case '%':
336 s->type = TOK_INFIX;
337 s->function = fmod;
338 break;
339 case '(': s->type = TOK_OPEN; break;
340 case ')': s->type = TOK_CLOSE; break;
341 case ',': s->type = TOK_SEP; break;
342 case ' ':
343 case '\t':
344 case '\n':
345 case '\r': break;
346 default: s->type = TOK_ERROR; break;
347 }
348 }
349 }
350 } while (s->type == TOK_NULL);
351}
const char * next
Definition tinyexpr.c:72
static const te_variable * find_builtin(const char *name, int len)
Definition tinyexpr.c:207
static const te_variable * find_lookup(const state *s, const char *name, int len)
Definition tinyexpr.c:229
static double mul(double a, double b)
Definition tinyexpr.c:245
static double divide(double a, double b)
Definition tinyexpr.c:246
Here is the call graph for this function:
Here is the caller graph for this function:

◆ npr()

static double npr ( double  n,
double  r 
)
static

Definition at line 168 of file tinyexpr.c.

168{ return ncr(n, r) * fac(r); }
static double ncr(double n, double r)
Definition tinyexpr.c:151
static double fac(double a)
Definition tinyexpr.c:137
Here is the call graph for this function:

◆ optimize()

static void optimize ( te_expr n)
static

Definition at line 638 of file tinyexpr.c.

638 {
639 /* Evaluates as much as possible. */
640 if (n->type == TE_CONSTANT)
641 return;
642 if (n->type == TE_VARIABLE)
643 return;
644
645 /* Only optimize out functions flagged as pure. */
646 if (IS_PURE(n->type)) {
647 const int arity = ARITY(n->type);
648 int known = 1;
649 int i;
650 for (i = 0; i < arity; ++i) {
651 optimize(n->parameters[i]);
652 if (((te_expr *) (n->parameters[i]))->type != TE_CONSTANT) {
653 known = 0;
654 }
655 }
656 if (known) {
657 const double value = te_eval(n);
659 n->type = TE_CONSTANT;
660 n->value = value;
661 }
662 }
663}
INT optimize
Definition mfe.cxx:48
double value[100]
Definition odbhist.cxx:42
double te_eval(const te_expr *n)
Definition tinyexpr.c:583
#define IS_PURE(TYPE)
Definition tinyexpr.c:87
void te_free_parameters(te_expr *n)
Definition tinyexpr.c:107
Here is the call graph for this function:

◆ pi()

static double pi ( void  )
static

Definition at line 135 of file tinyexpr.c.

135{ return 3.14159265358979323846; }
Here is the caller graph for this function:

◆ pn()

static void pn ( const te_expr n,
int  depth 
)
static

Definition at line 702 of file tinyexpr.c.

702 {
703 int i, arity;
704 printf("%*s", depth, "");
705
706 switch (TYPE_MASK(n->type)) {
707 case TE_CONSTANT: printf("%f\n", n->value); break;
708 case TE_VARIABLE: printf("bound %p\n", n->bound); break;
709
710 case TE_FUNCTION0:
711 case TE_FUNCTION1:
712 case TE_FUNCTION2:
713 case TE_FUNCTION3:
714 case TE_FUNCTION4:
715 case TE_FUNCTION5:
716 case TE_FUNCTION6:
717 case TE_FUNCTION7:
718 case TE_CLOSURE0:
719 case TE_CLOSURE1:
720 case TE_CLOSURE2:
721 case TE_CLOSURE3:
722 case TE_CLOSURE4:
723 case TE_CLOSURE5:
724 case TE_CLOSURE6:
725 case TE_CLOSURE7:
726 arity = ARITY(n->type);
727 printf("f%d", arity);
728 for (i = 0; i < arity; i++) {
729 printf(" %p", n->parameters[i]);
730 }
731 printf("\n");
732 for (i = 0; i < arity; i++) {
733 pn(n->parameters[i], depth + 1);
734 }
735 break;
736 }
737}
static void pn(const te_expr *n, int depth)
Definition tinyexpr.c:702
Here is the call graph for this function:
Here is the caller graph for this function:

◆ power()

static te_expr * power ( state s)
static

Definition at line 462 of file tinyexpr.c.

462 {
463 /* <power> = {("-" | "+")} <base> */
464 int sign = 1;
465 while (s->type == TOK_INFIX && (s->function == add || s->function == sub)) {
466 if (s->function == sub)
467 sign = -sign;
468 next_token(s);
469 }
470
471 te_expr *ret;
472
473 if (sign == 1) {
474 ret = base(s);
475 } else {
477 ret->function = negate;
478 }
479
480 return ret;
481}
static double negate(double a)
Definition tinyexpr.c:247
static te_expr * base(state *s)
Definition tinyexpr.c:357
Here is the call graph for this function:
Here is the caller graph for this function:

◆ sub()

static double sub ( double  a,
double  b 
)
static

Definition at line 244 of file tinyexpr.c.

244{ return a - b; }
Here is the caller graph for this function:

◆ te_compile()

te_expr * te_compile ( const char expression,
const te_variable variables,
int  var_count,
int error 
)

Definition at line 665 of file tinyexpr.c.

665 {
666 state s;
667 s.start = s.next = expression;
668 s.lookup = variables;
670
671 next_token(&s);
672 te_expr *root = list(&s);
673
674 if (s.type != TOK_END) {
675 te_free(root);
676 if (error) {
677 *error = (s.next - s.start);
678 if (*error == 0)
679 *error = 1;
680 }
681 return 0;
682 } else {
683 optimize(root);
684 if (error)
685 *error = 0;
686 return root;
687 }
688}
const char * start
Definition tinyexpr.c:71
void te_free(te_expr *n)
Definition tinyexpr.c:128
Here is the call graph for this function:
Here is the caller graph for this function:

◆ te_eval()

double te_eval ( const te_expr n)

Definition at line 583 of file tinyexpr.c.

583 {
584 if (!n)
585 return NAN;
586
587 switch (TYPE_MASK(n->type)) {
588 case TE_CONSTANT: return n->value;
589 case TE_VARIABLE: return *n->bound;
590
591 case TE_FUNCTION0:
592 case TE_FUNCTION1:
593 case TE_FUNCTION2:
594 case TE_FUNCTION3:
595 case TE_FUNCTION4:
596 case TE_FUNCTION5:
597 case TE_FUNCTION6:
598 case TE_FUNCTION7:
599 switch (ARITY(n->type)) {
600 case 0: return TE_FUN(void)();
601 case 1: return TE_FUN(double)(M(0));
602 case 2: return TE_FUN(double, double)(M(0), M(1));
603 case 3: return TE_FUN(double, double, double)(M(0), M(1), M(2));
604 case 4: return TE_FUN(double, double, double, double)(M(0), M(1), M(2), M(3));
605 case 5: return TE_FUN(double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4));
606 case 6: return TE_FUN(double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5));
607 case 7: return TE_FUN(double, double, double, double, double, double, double)(M(0), M(1), M(2), M(3), M(4), M(5), M(6));
608 default: return NAN;
609 }
610
611 case TE_CLOSURE0:
612 case TE_CLOSURE1:
613 case TE_CLOSURE2:
614 case TE_CLOSURE3:
615 case TE_CLOSURE4:
616 case TE_CLOSURE5:
617 case TE_CLOSURE6:
618 case TE_CLOSURE7:
619 switch (ARITY(n->type)) {
620 case 0: return TE_FUN(void *)(n->parameters[0]);
621 case 1: return TE_FUN(void *, double)(n->parameters[1], M(0));
622 case 2: return TE_FUN(void *, double, double)(n->parameters[2], M(0), M(1));
623 case 3: return TE_FUN(void *, double, double, double)(n->parameters[3], M(0), M(1), M(2));
624 case 4: return TE_FUN(void *, double, double, double, double)(n->parameters[4], M(0), M(1), M(2), M(3));
625 case 5: return TE_FUN(void *, double, double, double, double, double)(n->parameters[5], M(0), M(1), M(2), M(3), M(4));
626 case 6: return TE_FUN(void *, double, double, double, double, double, double)(n->parameters[6], M(0), M(1), M(2), M(3), M(4), M(5));
627 case 7: return TE_FUN(void *, double, double, double, double, double, double, double)(n->parameters[7], M(0), M(1), M(2), M(3), M(4), M(5), M(6));
628 default: return NAN;
629 }
630
631 default: return NAN;
632 }
633}
#define TE_FUN(...)
Definition tinyexpr.c:580
#define M(e)
Definition tinyexpr.c:581
Here is the caller graph for this function:

◆ te_free()

void te_free ( te_expr n)

Definition at line 128 of file tinyexpr.c.

128 {
129 if (!n)
130 return;
132 free(n);
133}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ te_free_parameters()

void te_free_parameters ( te_expr n)

Definition at line 107 of file tinyexpr.c.

107 {
108 if (!n)
109 return;
110 switch (TYPE_MASK(n->type)) {
111 case TE_FUNCTION7:
112 case TE_CLOSURE7: te_free(n->parameters[6]); /* Falls through. */
113 case TE_FUNCTION6:
114 case TE_CLOSURE6: te_free(n->parameters[5]); /* Falls through. */
115 case TE_FUNCTION5:
116 case TE_CLOSURE5: te_free(n->parameters[4]); /* Falls through. */
117 case TE_FUNCTION4:
118 case TE_CLOSURE4: te_free(n->parameters[3]); /* Falls through. */
119 case TE_FUNCTION3:
120 case TE_CLOSURE3: te_free(n->parameters[2]); /* Falls through. */
121 case TE_FUNCTION2:
122 case TE_CLOSURE2: te_free(n->parameters[1]); /* Falls through. */
123 case TE_FUNCTION1:
124 case TE_CLOSURE1: te_free(n->parameters[0]);
125 }
126}
Here is the call graph for this function:
Here is the caller graph for this function:

◆ te_interp()

double te_interp ( const char expression,
int error 
)

Definition at line 690 of file tinyexpr.c.

690 {
691 te_expr *n = te_compile(expression, 0, 0, error);
692 double ret;
693 if (n) {
694 ret = te_eval(n);
695 te_free(n);
696 } else {
697 ret = NAN;
698 }
699 return ret;
700}
te_expr * te_compile(const char *expression, const te_variable *variables, int var_count, int *error)
Definition tinyexpr.c:665
Here is the call graph for this function:
Here is the caller graph for this function:

◆ te_print()

void te_print ( const te_expr n)

Definition at line 739 of file tinyexpr.c.

739 {
740 pn(n, 0);
741}
Here is the call graph for this function:

◆ term()

static te_expr * term ( state s)
static

Definition at line 539 of file tinyexpr.c.

539 {
540 /* <term> = <factor> {("*" | "/" | "%") <factor>} */
541 te_expr *ret = factor(s);
542
543 while (s->type == TOK_INFIX && (s->function == mul || s->function == divide || s->function == fmod)) {
544 te_fun2 t = s->function;
545 next_token(s);
546 ret = NEW_EXPR(TE_FUNCTION2 | TE_FLAG_PURE, ret, factor(s));
547 ret->function = t;
548 }
549
550 return ret;
551}
static te_expr * factor(state *s)
Definition tinyexpr.c:524
Here is the call graph for this function:
Here is the caller graph for this function:

Variable Documentation

◆ functions

const te_variable functions[]
static

Definition at line 175 of file tinyexpr.c.

175 {
176 /* must be in alphabetical order */
177 {"abs", fabs, TE_FUNCTION1 | TE_FLAG_PURE, 0},
178 {"acos", acos, TE_FUNCTION1 | TE_FLAG_PURE, 0},
179 {"asin", asin, TE_FUNCTION1 | TE_FLAG_PURE, 0},
180 {"atan", atan, TE_FUNCTION1 | TE_FLAG_PURE, 0},
181 {"atan2", atan2, TE_FUNCTION2 | TE_FLAG_PURE, 0},
182 {"ceil", ceil, TE_FUNCTION1 | TE_FLAG_PURE, 0},
183 {"cos", cos, TE_FUNCTION1 | TE_FLAG_PURE, 0},
184 {"cosh", cosh, TE_FUNCTION1 | TE_FLAG_PURE, 0},
185 {"e", e, TE_FUNCTION0 | TE_FLAG_PURE, 0},
186 {"exp", exp, TE_FUNCTION1 | TE_FLAG_PURE, 0},
187 {"fac", fac, TE_FUNCTION1 | TE_FLAG_PURE, 0},
188 {"floor", floor, TE_FUNCTION1 | TE_FLAG_PURE, 0},
189 {"ln", log, TE_FUNCTION1 | TE_FLAG_PURE, 0},
190#ifdef TE_NAT_LOG
191 {"log", log, TE_FUNCTION1 | TE_FLAG_PURE, 0},
192#else
193 {"log", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},
194#endif
195 {"log10", log10, TE_FUNCTION1 | TE_FLAG_PURE, 0},
196 {"ncr", ncr, TE_FUNCTION2 | TE_FLAG_PURE, 0},
197 {"npr", npr, TE_FUNCTION2 | TE_FLAG_PURE, 0},
198 {"pi", pi, TE_FUNCTION0 | TE_FLAG_PURE, 0},
199 {"pow", pow, TE_FUNCTION2 | TE_FLAG_PURE, 0},
200 {"sin", sin, TE_FUNCTION1 | TE_FLAG_PURE, 0},
201 {"sinh", sinh, TE_FUNCTION1 | TE_FLAG_PURE, 0},
202 {"sqrt", sqrt, TE_FUNCTION1 | TE_FLAG_PURE, 0},
203 {"tan", tan, TE_FUNCTION1 | TE_FLAG_PURE, 0},
204 {"tanh", tanh, TE_FUNCTION1 | TE_FLAG_PURE, 0},
205 {0, 0, 0, 0}};
static double npr(double n, double r)
Definition tinyexpr.c:168
static double e(void)
Definition tinyexpr.c:136
static double pi(void)
Definition tinyexpr.c:135