diff options
Diffstat (limited to 'pd/extra/expr~')
-rw-r--r-- | pd/extra/expr~/README | 36 | ||||
-rw-r--r-- | pd/extra/expr~/help-expr.pd | 231 | ||||
-rw-r--r-- | pd/extra/expr~/makefile | 52 | ||||
-rw-r--r-- | pd/extra/expr~/vexp.c | 422 | ||||
-rw-r--r-- | pd/extra/expr~/vexp.h | 57 | ||||
-rw-r--r-- | pd/extra/expr~/vexp_fun.c | 611 | ||||
-rw-r--r-- | pd/extra/expr~/vexp_if.c | 420 |
7 files changed, 1309 insertions, 520 deletions
diff --git a/pd/extra/expr~/README b/pd/extra/expr~/README index 28fccf84..bf84f2ae 100644 --- a/pd/extra/expr~/README +++ b/pd/extra/expr~/README @@ -1,9 +1,38 @@ -You can get more inofrmation on the expr object at +You can get more information on the expr object at http://www.crca.ucsd.edu/~yadegari/expr.html ----------- +New if Version 0.4 + +-access to variables (made by value object) +-multiple expression separated by ; +-added the following shorthands: + $y or $y1 = $y1[-1] and $y2 = $y2[-1] +-new functions: + if - conditional evaluation + cbrt - cube root + erf - error function + erfc - complementary error function + expm1 - exponential minus 1, + log1p - logarithm of 1 plus + isinf - is the value infinite, + finite - is the value finite + isnan -- is the resut a nan (Not a number) + copysign - copy sign of a number + ldexp - multiply floating-point number by integral power of 2 + imodf - get signed integral value from floating-point number + modf - get signed fractional value from floating-point number + drem - floating-point remainder function + + Thanks to Orm Finnendahl for adding the following functions: + fmod - floating-point remainder function + ceil - ceiling function: smallest integral value not less than argument + floor - largest integral value not greater than argument + +------------ + New in Version 0.3 -Full function functionality @@ -57,11 +86,12 @@ $x#[n]: the sample from inlet # indexed by n, where n has to satisfy 0 => n >= -vector size, ($x# is a shorthand for $x#[0], specifying the current sample) -$y[n]: the output value indexed by n, where n has to +$y#[n]: the output value indexed by n, where n has to satisfy 0 > n >= -vector size, + $y[n] is a shorthand for $y1[n] I'll appreciate hearing about bugs, comments, suggestions, ... Shahrokh Yadegari (sdy@ucsd.edu) -1/29/02 +7/10/02 diff --git a/pd/extra/expr~/help-expr.pd b/pd/extra/expr~/help-expr.pd deleted file mode 100644 index 98ca696f..00000000 --- a/pd/extra/expr~/help-expr.pd +++ /dev/null @@ -1,231 +0,0 @@ -#N canvas 0 0 1024 745 10; -#X obj 75 416 expr 1; -#X floatatom 239 384 0 0 0; -#X floatatom 75 446 0 0 0; -#X msg 75 388 bang; -#X obj 143 414 expr 2 + 3; -#X msg 143 387 bang; -#X floatatom 143 442 0 0 0; -#X floatatom 238 442 0 0 0; -#X obj 238 414 expr 2+$f1; -#X floatatom 76 485 0 0 0; -#X floatatom 76 542 0 0 0; -#X obj 76 514 expr $f1 * $f2; -#X floatatom 155 485 0 0 0; -#N canvas 0 0 450 300 graph1 0; -#X coords 0 10 10 0 200 150 1; -#X array array1 10 float 0; -#X restore 472 362 graph; -#X floatatom 77 580 0 0 0; -#X floatatom 77 636 0 0 0; -#X floatatom 236 484 0 0 0; -#X floatatom 236 541 0 0 0; -#X obj 236 513 expr $s2[$f1]; -#X msg 309 485 symbol array1; -#X obj 77 608 expr sin(2 * 3.14159 * $f1 / 360); -#X msg 429 554 \; array1 1 4 2 8 5 6 1 4 2 8 5 6; -#X text 81 345 expr examples:; -#X text 66 10 expression evaluation family - expr \, expr~ \, fexpr~ -; -#X text 66 188 Syntyax:; -#X text 67 260 $f#: float input variable; -#X text 68 275 $s#: symbol input variable; -#X text -37 708 expr~ examples:; -#X obj 30 911 print~; -#X msg 67 890 bang; -#X obj 30 832 sig~ 440; -#X floatatom 103 849 0 0 0; -#X floatatom 30 809 0 0 0; -#X obj 30 872 expr~ $v1*$f2; -#X obj 139 912 print~; -#X msg 155 891 bang; -#X floatatom 139 824 0 0 0; -#X floatatom 212 826 0 0 0; -#X floatatom 411 847 0 0 0; -#X floatatom 298 823 0 0 0; -#X obj 298 850 osc~; -#X msg 526 670 \; pd dsp 0; -#X msg 448 672 \; pd dsp 1; -#X text 451 649 audio on; -#X text 534 648 audio off; -#X text 274 314 comment; -#X text 9 792 vector times scalar; -#X text 141 792 vector; -#X obj 297 910 dac~; -#X text 295 801 frequency; -#X text 427 829 amplitude; -#X text 497 116 Used for expr~ only:; -#X text 499 139 $v#: signal (vector) input (vector by vector evaluation) -; -#X text 494 172 Used for fexpr~ only:; -#X text 495 242 $y[n]: the output value indexed by n where n has to -satisfy 0 > n >= -vector size.; -#X text 489 282 (the vector size can be changed by the "block~" object.) -; -#X text 493 191 $x#[n]: the sample from inlet # indexed by n where -n has to satisfy 0 => n >= -vector size \, ($x# is a shorthand for -$x#[0] \, specifying the current sample); -#X floatatom 81 1300 0 0 0; -#X floatatom 214 1319 0 0 0; -#X msg 181 1279 -10; -#X text 8 1099 fexpr~ examples:; -#X obj 80 1567 print~; -#X msg 88 1547 bang; -#X floatatom 80 1471 0 0 0; -#X obj 80 1500 sig~ 1; -#X obj 81 1343 fexpr~ ($x1[$f2]+$x1)/2; -#X obj 80 1528 fexpr~ $x1+$y[-1]; -#X floatatom 590 1362 0 0 0; -#X floatatom 750 1383 0 0 0; -#X obj 585 1452 dac~; -#X obj 587 1403 fexpr~ ($x1[$f2/1000]+$x1)/2; -#X msg 819 1313 0 10000; -#X obj 750 1364 line 0; -#X msg 753 1314 -10000; -#X obj 75 1385 dac~; -#X text 51 1223 Simple FIR filter; -#X text 512 1130 Simple FIR filter using fractional offset; -#X msg 659 1314 -10000 10000; -#X obj 590 1383 osc~ 2205; -#X msg 599 1339 1102.5; -#X msg 817 1338 0 10000; -#X msg 751 1339 -20000; -#X msg 657 1339 -20000 10000; -#X msg 590 1314 2205; -#X text 88 1611 end; -#X msg 503 1308 start; -#X msg 505 1330 stop; -#X msg 12 1280 start; -#X msg 11 1305 stop; -#X msg 30 1465 start; -#X msg 29 1490 stop; -#X obj 446 1331 loadbang; -#X obj -27 1491 loadbang; -#X obj -44 1305 loadbang; -#X text 572 1287 frequency; -#X text 662 1296 of the simple filter; -#X msg 248 1278 -20; -#X obj 81 1321 osc~ 2205; -#X msg 111 1277 1102.5; -#X msg 65 1277 2205; -#X msg 215 1278 0; -#X text 78 1441 simple accumulator defined as and an IIR filter; -#X obj 139 871 expr~ $v1*$v2; -#X text 7 1144 NOTE: fexpr~ could use lots of CPU power \, by default -fexpr~ is on when it is loaded. In this page we are turning them off -with loadbang \, so to hear them you have to turn them on explicitly. -You can use the "start" and "stop" messages to start and stop fexpr~ -and expr~; -#X text 65 101 expr~ is used for expression evaluaion of signal data -on the vector by vector basis; -#X text 66 85 expr is used for expression evaluaion of control data -; -#X text 661 1284 index defining the frequency; -#X text 50 1236 -10 offset will fully filter audio frequency of 2205 -\, and -20 offset will filter audio at frequency of 1102.5; -#X text 514 1211 Thus \, the offset -10000 will filter audio at frequency -of 2205 and the offset value -20000 will filter the audio at frequency -of 1102.5.; -#X text 513 1157 When fractional offset is used \, fexpr~ determines -indexed by linear interpolation. In the following example the offset -value is divided by 1000 \, thus we can continuously change the offset -without an audible click in the output.; -#X text 243 1314 If you change this value you; -#X text 245 1326 hear a click; -#X text 77 670 make sure you turn on audio for the expr~ and fexpr~ -examples; -#X text 64 38 For a more detailed documentaion refer to http://www.crca.ucsd.edu/~yadegari/expr.html -; -#X text 67 203 The syntax is very close to how expressions are written -in C. Variables are specified as follows where the '#' stands for the -inlet number:; -#X text 68 246 $i#: integer input variable; -#X text 67 138 fexpr~ is used for expression evaluaion on sample level -data \; i.e. \, filter design. Warning: fexpr~ is very cpu intensive. -; -#X floatatom 792 826 5 0 0; -#X obj 545 875 tabsend~ a1; -#N canvas 0 0 450 300 graph4 0; -#X coords 0 1 63 -1 200 140 1; -#X array a1 64 float 0; -#X restore 546 897 graph; -#X obj 545 852 expr~ max(min($v1 \, $f2/10) \, -$f2/10); -#X obj 545 828 osc~ 4000; -#X text 13 730 NOTES: the first inlet of expr~ cannot be a $f1 or $i1 -\, this may change in later releases; -#X text 535 775 A simple limiter example; -#X text 718 800 Move the value below between 0 and 10 to change the -limiter threshold; -#X obj 410 714 vsl 15 128 0 127 0 0 empty empty empty 20 8 0 8 -262144 --1 -1 0 1; -#X obj 297 871 expr~ $v1*$f2/128; -#X text 641 12 updated for Pd 0.35-35 test 8 and expr* 0.3; -#X connect 0 0 2 0; -#X connect 1 0 8 0; -#X connect 3 0 0 0; -#X connect 4 0 6 0; -#X connect 5 0 4 0; -#X connect 8 0 7 0; -#X connect 9 0 11 0; -#X connect 11 0 10 0; -#X connect 12 0 11 1; -#X connect 14 0 20 0; -#X connect 16 0 18 0; -#X connect 18 0 17 0; -#X connect 19 0 18 1; -#X connect 20 0 15 0; -#X connect 29 0 28 0; -#X connect 30 0 33 0; -#X connect 31 0 33 1; -#X connect 32 0 30 0; -#X connect 33 0 28 0; -#X connect 35 0 34 0; -#X connect 36 0 102 0; -#X connect 37 0 102 1; -#X connect 38 0 126 1; -#X connect 39 0 40 0; -#X connect 40 0 126 0; -#X connect 57 0 97 0; -#X connect 58 0 65 1; -#X connect 59 0 58 0; -#X connect 62 0 61 0; -#X connect 63 0 64 0; -#X connect 64 0 66 0; -#X connect 65 0 74 0; -#X connect 65 0 74 1; -#X connect 66 0 61 0; -#X connect 67 0 78 0; -#X connect 68 0 70 1; -#X connect 70 0 69 0; -#X connect 70 0 69 1; -#X connect 71 0 72 0; -#X connect 72 0 68 0; -#X connect 73 0 72 0; -#X connect 77 0 72 0; -#X connect 78 0 70 0; -#X connect 79 0 67 0; -#X connect 80 0 72 0; -#X connect 81 0 72 0; -#X connect 82 0 72 0; -#X connect 83 0 67 0; -#X connect 85 0 70 0; -#X connect 86 0 70 0; -#X connect 87 0 65 0; -#X connect 88 0 65 0; -#X connect 89 0 66 0; -#X connect 90 0 66 0; -#X connect 91 0 86 0; -#X connect 92 0 90 0; -#X connect 93 0 88 0; -#X connect 96 0 58 0; -#X connect 97 0 65 0; -#X connect 98 0 57 0; -#X connect 99 0 57 0; -#X connect 100 0 58 0; -#X connect 102 0 34 0; -#X connect 117 0 120 1; -#X connect 120 0 118 0; -#X connect 121 0 120 0; -#X connect 125 0 38 0; -#X connect 126 0 48 0; -#X connect 126 0 48 1; diff --git a/pd/extra/expr~/makefile b/pd/extra/expr~/makefile index d0175a8a..b482f249 100644 --- a/pd/extra/expr~/makefile +++ b/pd/extra/expr~/makefile @@ -1,5 +1,6 @@ -current: expr.pd_linux expr~.pd_linux fexpr~.pd_linux +current: expr.pd_linux expr~.pd_linux fexpr~.pd_linux \ + ../expr.pd_linux ../expr~.pd_linux ../fexpr~.pd_linux install: install_linux @@ -18,20 +19,20 @@ NTOBJ = vexp.obj vexp_fun.obj vexp_if.obj PDNTCFLAGS = /W3 /WX /DNT /DPD /nologo VC="C:\Program Files\Microsoft Visual Studio\Vc98" -PDNTINCLUDE = /I. /I\tcl\include /I\ftp\pd\src /I$(VC)\include +PDNTINCLUDE = /I. /I..\..\src /I$(VC)\include PDNTLDIR = $(VC)\lib PDNTLIB = $(PDNTLDIR)\libc.lib \ $(PDNTLDIR)\oldnames.lib \ $(PDNTLDIR)\kernel32.lib \ - \ftp\pd\bin\pd.lib + ..\..\bin\pd.lib .c.obj: cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c expr.dll: $(NTOBJ) link /dll /export:expr_setup /export:expr_tilde_setup \ - /export:fexpr_tilde_setup $(NTOBJ) $(PDNTLIB) + /export:fexpr_tilde_setup $(NTOBJ) $(PDNTLIB) ren vexp.dll expr.dll copy expr.dll ..\expr.dll copy expr.dll ..\expr~.dll @@ -90,30 +91,36 @@ LINUXINCLUDE = -I../../src expr.pd_linux: $(LINUXOBJ) ld -export_dynamic -shared -o expr.pd_linux $(LINUXOBJ) -lc -lm strip --strip-unneeded expr.pd_linux - rm -f ../expr.pd_linux - ln -s expr~/expr.pd_linux .. expr~.pd_linux: expr.pd_linux - ln -s expr.pd_linux expr~.pd_linux - ln -s expr~/expr~.pd_linux .. - + -ln -s expr.pd_linux expr~.pd_linux + fexpr~.pd_linux: expr.pd_linux - ln -s expr.pd_linux fexpr~.pd_linux - ln -s expr~/fexpr~.pd_linux .. + -ln -s expr.pd_linux fexpr~.pd_linux + +../expr.pd_linux: expr.pd_linux + -ln -s expr~/expr.pd_linux ../expr.pd_linux + +../expr~.pd_linux: expr.pd_linux + -ln -s expr~/expr.pd_linux ../expr~.pd_linux + +../fexpr~.pd_linux: expr.pd_linux + -ln -s expr~/expr.pd_linux ../fexpr~.pd_linux install_linux: install expr.pd_linux $(PDEXTERN) rm -f $(PDEXTERN)/expr~.pd_linux rm -f $(PDEXTERN)/fexpr~.pd_linux cd $(PDEXTERN); \ - ln -s expr.pd_linux expr~.pd_linux; \ - ln -s expr.pd_linux fexpr~.pd_linux + -ln -s expr.pd_linux expr~.pd_linux + -ln -s expr.pd_linux fexpr~.pd_linux + linux_clean: rm -f *.pd_linux_o *.o linux_clobber: clean - rm -f expr.pd_linux expr.pd_irix6 + rm -f expr.pd_linux # ----------------------- MAC OSX ----------------------- @@ -133,28 +140,29 @@ expr.pd_darwin: $(MACOSXOBJ) cc -bundle -undefined suppress -flat_namespace \ -o expr.pd_darwin $(MACOSXOBJ) -lm rm -f ../expr.pd_darwin - ln -s expr~/expr.pd_darwin .. + -ln -s expr~/expr.pd_darwin .. expr~.pd_darwin: expr.pd_darwin - ln -s expr.pd_darwin expr~.pd_darwin + -ln -s expr.pd_darwin expr~.pd_darwin rm -f ../expr~.pd_darwin - ln -s expr~/expr~.pd_darwin .. + -ln -s expr~/expr~.pd_darwin .. fexpr~.pd_darwin: expr.pd_darwin - ln -s expr.pd_darwin fexpr~.pd_darwin + -ln -s expr.pd_darwin fexpr~.pd_darwin rm -f ../fexpr~.pd_darwin - ln -s expr~/fexpr~.pd_darwin .. + -ln -s expr~/fexpr~.pd_darwin .. install_darwin: install expr.pd_darwin $(PDEXTERN) rm -f $(PDEXTERN)/expr~.pd_darwin rm -f $(PDEXTERN)/fexpr~.pd_darwin cd $(PDEXTERN); \ - ln -s expr.pd_darwin expr~.pd_darwin; \ - ln -s expr.pd_darwin fexpr~.pd_darwin + -ln -s expr.pd_darwin expr~.pd_darwin; \ + -ln -s expr.pd_darwin fexpr~.pd_darwin darwin_clean: rm -f *.pd_darwin_o *.o darwin_clobber: clean - rm -f expr.pd_darwin expr.pd_irix6 + rm -f expr.pd_darwin + diff --git a/pd/extra/expr~/vexp.c b/pd/extra/expr~/vexp.c index dddf6efa..d75ab539 100644 --- a/pd/extra/expr~/vexp.c +++ b/pd/extra/expr~/vexp.c @@ -28,6 +28,19 @@ /* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */ /* + * Feb 2002 - added access to variables + * multiple expression support + * new short hand forms for fexpr~ + * now $y or $y1 = $y1[-1] and $y2 = $y2[-1] + * --sdy + * + * July 2002 + * fixed bugs introduced in last changes in store and ET_EQ + * --sdy + * + */ + +/* * vexp.c -- a variable expression evaluator * * This modules implements an expression evaluator using the @@ -56,17 +69,13 @@ #include <string.h> #include <stdlib.h> +#include <ctype.h> #include "vexp.h" - -#ifndef MSP -#ifndef MACOSX -/* - *stdlib.h produces a redefinition of _alloca() - * why, I do not know? - */ -#include "stdlib.h" -#endif +#ifdef MSP +#undef isdigit +#define isdigit(x) (x >= '0' && x <= '9') #endif + char *atoif(char *s, long int *value, long int *type); static struct ex_ex *ex_lex(struct expr *exp, long int *n); @@ -81,6 +90,10 @@ struct ex_ex *eval_func(struct expr *exp,struct ex_ex *eptr, struct ex_ex *optr, int i); struct ex_ex *eval_tab(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int i); +struct ex_ex *eval_var(struct expr *exp, struct ex_ex *eptr, + struct ex_ex *optr, int i); +struct ex_ex *eval_store(struct expr *exp, struct ex_ex *eptr, + struct ex_ex *optr, int i); struct ex_ex *eval_sigidx(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int i); static int cal_sigidx(struct ex_ex *optr, /* The output value */ @@ -192,6 +205,7 @@ expr_donew(struct expr *expr, int ac, t_atom *av) char *exp_string; int exp_strlen; t_binbuf *b; + int i; memset(expr->exp_var, 0, MAX_VARS * sizeof (*expr->exp_var)); #ifdef PD @@ -200,7 +214,7 @@ expr_donew(struct expr *expr, int ac, t_atom *av) binbuf_gettext(b, &exp_string, &exp_strlen); #else /* MSP */ -{ + { char *buf = getbytes(0), *newbuf; int length = 0; char string[250]; @@ -230,32 +244,45 @@ expr_donew(struct expr *expr, int ac, t_atom *av) } exp_string = buf; exp_strlen = length; -} + } #endif exp_string = (char *)t_resizebytes(exp_string, exp_strlen,exp_strlen+1); exp_string[exp_strlen] = 0; - set_tokens(exp_string); - list = ex_lex(expr, &max_node); - set_tokens((char *)0); - if (!list) { /* syntax error */ - return (1); - } - expr->exp_stack = (struct ex_ex *)fts_malloc(max_node * - sizeof (struct ex_ex)); - ret = ex_match(list, (long)0); - if (!ret) /* syntax error */ - goto error; - ret = ex_parse(expr, list, expr->exp_stack, (long *)0); - if (ret) { - *ret = nullex; - /* print the stack that been built */ - t_freebytes(exp_string, exp_strlen+1); - return (0); + expr->exp_string = exp_string; + expr->exp_str = exp_string; + expr->exp_nexpr = 0; + ret = (struct ex_ex *) 0; + /* + * if ret == 0 it means that we have no expression + * so we let the pass go through to build a single null stack + */ + while (*expr->exp_str || !ret) { + list = ex_lex(expr, &max_node); + if (!list) { /* syntax error */ + goto error; + } + expr->exp_stack[expr->exp_nexpr] = + (struct ex_ex *)fts_malloc(max_node * sizeof (struct ex_ex)); + expr->exp_nexpr++; + ret = ex_match(list, (long)0); + if (!ret) /* syntax error */ + goto error; + ret = ex_parse(expr, + list, expr->exp_stack[expr->exp_nexpr - 1], (long *)0); + if (!ret) + goto error; } + *ret = nullex; + t_freebytes(exp_string, exp_strlen+1); + return (0); error: - fts_free(expr->exp_stack); - expr->exp_stack = 0; - fts_free(list); + for (i = 0; i < expr->exp_nexpr; i++) { + fts_free(expr->exp_stack[i]); + expr->exp_stack[i] = 0; + } + expr->exp_nexpr = 0; + if (list) + fts_free(list); t_freebytes(exp_string, exp_strlen+1); return (1); } @@ -342,7 +369,10 @@ ex_match(struct ex_ex *eptr, long int op) case ET_VI: case ET_SYM: case ET_VSYM: - case ET_VO: + continue; + case ET_YO: + if (eptr[1].ex_type != ET_OP || eptr[1].ex_op != OP_LB) + eptr->ex_type = ET_YOM1; continue; case ET_XI: if (eptr[1].ex_type != ET_OP || eptr[1].ex_op != OP_LB) @@ -401,10 +431,6 @@ ex_match(struct ex_ex *eptr, long int op) } continue; case ET_STR: - if (eptr[1].ex_type != ET_OP) { - post("expr: syntax error: bad string '%s'\n", eptr->ex_ptr); - return (exNULL); - } if (eptr[1].ex_op == OP_LB) { char *tmp; @@ -426,8 +452,20 @@ ex_match(struct ex_ex *eptr, long int op) eptr->ex_type = ET_FUNC; eptr->ex_ptr = (char *) fun; } else { - post("expr: syntax error: bad string '%s'\n", eptr->ex_ptr); - return (exNULL); + char *tmp; + + if (eptr[1].ex_type && eptr[1].ex_type!=ET_OP){ + post("expr: syntax error: bad string '%s'\n", eptr->ex_ptr); + return (exNULL); + } + /* it is a variable */ + eptr->ex_type = ET_VAR; + tmp = eptr->ex_ptr; + if (ex_getsym(tmp, + (t_symbol **)&(eptr->ex_ptr))) { + post("expr: variable '%s' not found",tmp); + return (exNULL); + } } continue; default: @@ -490,14 +528,16 @@ ex_parse(struct expr *x, struct ex_ex *iptr, struct ex_ex *optr, long int *argc) case ET_II: case ET_FI: case ET_XI0: + case ET_YOM1: case ET_VI: + case ET_VAR: if (!count && !eptr[1].ex_type) { *optr++ = *eptr; return (optr); } break; case ET_XI: - case ET_VO: + case ET_YO: case ET_SI: case ET_TBL: if (eptr[1].ex_type != ET_LB) { @@ -1016,6 +1056,8 @@ abort(); } return(++eptr); case ET_XI0: + /* short hand for $x?[0] */ + /* SDY delete the following check */ if (!IS_FEXPR_TILDE(exp) || optr->ex_type==ET_VEC) { post("%d:exp->exp_flags = %d", __LINE__,exp->exp_flags); @@ -1024,7 +1066,21 @@ abort(); optr->ex_type = ET_FLT; optr->ex_flt = exp->exp_var[eptr->ex_int].ex_vec[idx]; return(++eptr); - case ET_VO: + case ET_YOM1: + /* + * short hand for $y?[-1] + * if we are calculating the first sample of the vector + * we need to look at the previous results buffer + */ + optr->ex_type = ET_FLT; + if (idx == 0) + optr->ex_flt = + exp->exp_p_res[eptr->ex_int][exp->exp_vsize - 1]; + else + optr->ex_flt=exp->exp_tmpres[eptr->ex_int][idx-1]; + return(++eptr); + + case ET_YO: case ET_XI: /* SDY delete the following */ if (!IS_FEXPR_TILDE(exp) || optr->ex_type==ET_VEC) { @@ -1038,6 +1094,8 @@ abort(); return (eval_tab(exp, eptr, optr, idx)); case ET_FUNC: return (eval_func(exp, eptr, optr, idx)); + case ET_VAR: + return (eval_var(exp, eptr, optr, idx)); case ET_OP: break; case ET_STR: @@ -1060,6 +1118,8 @@ abort(); } switch((eptr++)->ex_op) { + case OP_STORE: + return (eval_store(exp, eptr, optr, idx)); case OP_NOT: EVAL_UNARY(!, +); case OP_NEG: @@ -1130,12 +1190,6 @@ abort(); } -/* SDY -all the returns in the function need to be changed to come here -to make sure that we are freeing any allocated buffer pointed to -by left and right vectors -*/ - /* * the left and right nodes could have been transformed to vectors * down the chain @@ -1187,8 +1241,70 @@ eval_func(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) return (eptr); } + /* - * eval_tab -- + * eval_store -- evaluate the '=' operator, + * make sure the first operator is a legal left operator + * and call ex_eval on the right operator + */ +struct ex_ex * +eval_store(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +{ + struct ex_ex arg; + int isvalue; + char *tbl = (char *) 0; + char *var = (char *) 0; + int badleft = 0; + +post("store called\n"); +ex_print(eptr); +eptr = ex_eval(exp, ++eptr, optr, idx); +return (eptr); + +#ifdef notdef /* SDY */ + arg.ex_type = ET_INT; + arg.ex_int = 0; + if (eptr->ex_type == ET_VAR) { + var = (char *) eptr->ex_ptr; + + eptr = ex_eval(exp, ++eptr, &arg, idx); + (void)max_ex_var_store(exp, (t_symbol *)var, &arg, optr); + if (arg.ex_type == ET_VEC) + fts_free(arg.ex_vec); + } + + + if (eptr->ex_type == ET_SI) { + eptr++; + if (eptr->ex_type = + } + + /* the left operator should either be a value or a array member */ + switch (eptr->ex_type) { + case ET_SI: + if ((eptr + 1)->ex_type == OP_LB) { + } + if (!exp->exp_var[eptr->ex_int].ex_ptr) { + if (!(exp->exp_error & EE_NOTABLE)) { + post("expr: syntax error: no string for inlet %d", eptr->ex_int + 1); + post("expr: No more table errors will be reported"); + post("expr: till the next reset"); + exp->exp_error |= EE_NOTABLE; + } + badleft++; + } else + tbl = (char *) exp->exp_var[eptr->ex_int].ex_ptr; + break; + case ET_TBL: + } +#endif /* SDY */ +} + +/* + * eval_tab -- evaluate a table operation */ struct ex_ex * eval_tab(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) @@ -1230,10 +1346,55 @@ eval_tab(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) optr->ex_int = 0; if (!notable) (void)max_ex_tab(exp, (t_symbol *)tbl, &arg, optr); + if (arg.ex_type == ET_VEC) + fts_free(arg.ex_vec); return (eptr); } /* + * eval_var -- evaluate a variable + */ +struct ex_ex * +eval_var(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) +/* the expr object data pointer */ +/* the operation stack */ +/* the result pointer */ +{ + struct ex_ex arg; + char *var = (char *) 0; + int novar = 0; + + if (eptr->ex_type == ET_SI) { + if (!exp->exp_var[eptr->ex_int].ex_ptr) { +/* SDY post_error() does not work in MAX/MSP yet +post_error((fts_object_t *) exp, +"expr: syntax error: no string for inlet %d\n", eptr->ex_int + 1); +*/ + if (!(exp->exp_error & EE_NOVAR)) { + post("expr: syntax error: no string for inlet %d", eptr->ex_int + 1); + post("expr: No more table errors will be reported"); + post("expr: till the next reset"); + exp->exp_error |= EE_NOVAR; + } + novar++; + } else + var = (char *) exp->exp_var[eptr->ex_int].ex_ptr; + } else if (eptr->ex_type == ET_VAR) + var = (char *) eptr->ex_ptr; + else { + post_error((fts_object_t *) exp, "expr: eval_tbl: bad type %ld\n", eptr->ex_type); + novar++; + + } + + optr->ex_type = ET_INT; + optr->ex_int = 0; + if (!novar) + (void)max_ex_var(exp, (t_symbol *)var, optr); + return (++eptr); +} + +/* * eval_sigidx -- evaluate the value of an indexed signal for fexpr~ */ struct ex_ex * @@ -1298,7 +1459,7 @@ eval_sigidx(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) /* * indexing an output vector */ - } else if (eptr->ex_type == ET_VO) { + } else if (eptr->ex_type == ET_YO) { /* for output vectors index of zero is not legal */ if (fi >= 0) { if (!(exp->exp_error & EE_BI_OUTPUT)) { @@ -1308,10 +1469,17 @@ eval_sigidx(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int idx) post("fexpr~: no error report till next reset"); post("fexpr~: index assumed to be = -1"); } - i = 0; + i = -1; + } + if (eptr->ex_int >= exp->exp_nexpr) { + post("fexpr~: $y%d illegal: not that many exprs", + eptr->ex_int); + optr->ex_flt = 0; + return (reteptr); } if (cal_sigidx(optr, i, rem_i, idx, exp->exp_vsize, - exp->exp_tmpres, exp->exp_p_res)) { + exp->exp_tmpres[eptr->ex_int], + exp->exp_p_res[eptr->ex_int])) { if (!(exp->exp_error & EE_BI_OUTPUT)) { exp->exp_error |= EE_BI_OUTPUT; post("fexpr~: bad output index, (%f)", fi); @@ -1380,16 +1548,6 @@ cal_sigidx(struct ex_ex *optr, /* The output value */ return (1); } -static char *exp_str; -/* - * set_tokens -- set a new string for reading tokens - */ - -void -set_tokens(char *s) -{ - exp_str = s; -} /* * getoken -- return 1 on syntax error otherwise 0 */ @@ -1399,18 +1557,25 @@ getoken(struct expr *exp, struct ex_ex *eptr) char *p; long i; - if (!exp_str) { + + if (!exp->exp_str) { post("expr: getoken: expression string not set\n"); return (0); } retry: - if (!*exp_str) { + if (!*exp->exp_str) { + eptr->ex_type = 0; + eptr->ex_int = 0; + return (0); + } + if (*exp->exp_str == ';') { + exp->exp_str++; eptr->ex_type = 0; eptr->ex_int = 0; return (0); } eptr->ex_type = ET_OP; - switch (*exp_str++) { + switch (*exp->exp_str++) { case '\\': case ' ': case '\t': @@ -1456,21 +1621,21 @@ retry: eptr->ex_op = OP_LB; break; case '!': - if (*exp_str == '=') { + if (*exp->exp_str == '=') { eptr->ex_op = OP_NE; - exp_str++; + exp->exp_str++; } else eptr->ex_op = OP_NOT; break; case '<': - switch (*exp_str) { + switch (*exp->exp_str) { case '<': eptr->ex_op = OP_SL; - exp_str++; + exp->exp_str++; break; case '=': eptr->ex_op = OP_LE; - exp_str++; + exp->exp_str++; break; default: eptr->ex_op = OP_LT; @@ -1478,14 +1643,14 @@ retry: } break; case '>': - switch (*exp_str) { + switch (*exp->exp_str) { case '>': eptr->ex_op = OP_SR; - exp_str++; + exp->exp_str++; break; case '=': eptr->ex_op = OP_GE; - exp_str++; + exp->exp_str++; break; default: eptr->ex_op = OP_GT; @@ -1493,30 +1658,39 @@ retry: } break; case '=': - if (*exp_str++ != '=') { + if (*exp->exp_str++ != '=') { post("expr: syntax error: =\n"); return (1); } eptr->ex_op = OP_EQ; break; +/* do not allow the store till the function is fixed + if (*exp->exp_str != '=') + eptr->ex_op = OP_STORE; + else { + exp->exp_str++; + eptr->ex_op = OP_EQ; + } + break; +*/ case '&': - if (*exp_str == '&') { - exp_str++; + if (*exp->exp_str == '&') { + exp->exp_str++; eptr->ex_op = OP_LAND; } else eptr->ex_op = OP_AND; break; case '|': - if ((*exp_str == '|')) { - exp_str++; + if ((*exp->exp_str == '|')) { + exp->exp_str++; eptr->ex_op = OP_LOR; } else eptr->ex_op = OP_OR; break; case '$': - switch (*exp_str++) { + switch (*exp->exp_str++) { case 'I': case 'i': eptr->ex_type = ET_II; @@ -1536,36 +1710,44 @@ retry: break; } post("$v? works only for expr~"); - post("expr: syntax error: %s\n", &exp_str[-2]); + post("expr: syntax error: %s\n", &exp->exp_str[-2]); return (1); case 'X': case 'x': if (IS_FEXPR_TILDE(exp)) { eptr->ex_type = ET_XI; - break; + if (isdigit(*exp->exp_str)) + break; + /* for $x[] is a shorhand for $x1[] */ + eptr->ex_int = 0; + goto noinletnum; } post("$x? works only for fexpr~"); - post("expr: syntax error: %s\n", &exp_str[-2]); + post("expr: syntax error: %s\n", &exp->exp_str[-2]); return (1); case 'y': case 'Y': if (IS_FEXPR_TILDE(exp)) { - eptr->ex_type = ET_VO; + eptr->ex_type = ET_YO; /*$y takes no number */ + if (isdigit(*exp->exp_str)) + break; + /* for $y[] is a shorhand for $y1[] */ + eptr->ex_int = 0; goto noinletnum; } post("$y works only for fexpr~"); default: - post("expr: syntax error: %s\n", &exp_str[-2]); + post("expr: syntax error: %s\n", &exp->exp_str[-2]); return (1); } - p = atoif(exp_str, &eptr->ex_op, &i); + p = atoif(exp->exp_str, &eptr->ex_op, &i); if (!p) { - post("expr: syntax error: %s\n", &exp_str[-2]); + post("expr: syntax error: %s\n", &exp->exp_str[-2]); return (1); } if (i != ET_INT) { - post("expr: syntax error: %s\n", exp_str); + post("expr: syntax error: %s\n", exp->exp_str); return (1); } /* @@ -1573,39 +1755,46 @@ retry: * therefore we decrement the number that user has supplied */ if (!eptr->ex_op || (eptr->ex_op)-- > MAX_VARS) { - post("expr: syntax error: inlet out of range: %s\n", - exp_str); + post("expr: syntax error: inlet or outlet out of range: %s\n", + exp->exp_str); return (1); } -/* - * until we can change the input type of inlets on the fly (at pd_new() - * time) the first input to expr~ is always a vectore and $f1 or $i1 is - * illegal for fexr~ - */ -if (eptr->ex_op == 0 && - (IS_FEXPR_TILDE(exp) || IS_EXPR_TILDE(exp)) && - (eptr->ex_type==ET_II || eptr->ex_type==ET_FI || eptr->ex_type==ET_SI)) { - post("first inlet of expr~ for fexpr~ can only be a vector"); - return (1); -} - /* record the inlet type and check for consistency */ - if (!exp->exp_var[eptr->ex_op].ex_type) + /* + * until we can change the input type of inlets on + * the fly (at pd_new() + * time) the first input to expr~ is always a vectore + * and $f1 or $i1 is + * illegal for fexr~ + */ + if (eptr->ex_op == 0 && + (IS_FEXPR_TILDE(exp) || IS_EXPR_TILDE(exp)) && + (eptr->ex_type==ET_II || eptr->ex_type==ET_FI || + eptr->ex_type==ET_SI)) { + post("first inlet of expr~/fexpr~ can only be a vector"); + return (1); + } + /* record the inlet or outlet type and check for consistency */ + if (eptr->ex_type == ET_YO ) { + /* it is an outlet for fexpr~*/ + /* no need to do anything */ + ; + } else if (!exp->exp_var[eptr->ex_op].ex_type) exp->exp_var[eptr->ex_op].ex_type = eptr->ex_type; else if (exp->exp_var[eptr->ex_op].ex_type != eptr->ex_type) { - post("expr: syntax error: inlets can only have one type: %s\n", exp_str); + post("expr: syntax error: inlets can only have one type: %s\n", exp->exp_str); return (1); } - exp_str = p; + exp->exp_str = p; noinletnum: break; case '"': { struct ex_ex ex; - p = exp_str; - if (!*exp_str || *exp_str == '"') { - post("expr: syntax error: empty symbol: %s\n", --exp_str); + p = exp->exp_str; + if (!*exp->exp_str || *exp->exp_str == '"') { + post("expr: syntax error: empty symbol: %s\n", --exp->exp_str); return (1); } if (getoken(exp, &ex)) @@ -1626,7 +1815,7 @@ noinletnum: post("expr: syntax error: bad symbol name: %s\n", p); return (1); } - if (*exp_str++ != '"') { + if (*exp->exp_str++ != '"') { post("expr: syntax error: missing '\"'\n"); return (1); } @@ -1643,10 +1832,10 @@ noinletnum: case '7': case '8': case '9': - p = atoif(--exp_str, &eptr->ex_int, &eptr->ex_type); + p = atoif(--exp->exp_str, &eptr->ex_int, &eptr->ex_type); if (!p) return (1); - exp_str = p; + exp->exp_str = p; break; default: @@ -1654,17 +1843,17 @@ noinletnum: * has to be a string, it should either be a * function or a table */ - p = --exp_str; + p = --exp->exp_str; for (i = 0; name_ok(*p); i++) p++; if (!i) { - post("expr: syntax error: %s\n", exp_str); + post("expr: syntax error: %s\n", exp->exp_str); return (1); } eptr->ex_ptr = (char *)fts_malloc(i + 1); - strncpy(eptr->ex_ptr, exp_str, (int) i); + strncpy(eptr->ex_ptr, exp->exp_str, (int) i); (eptr->ex_ptr)[i] = 0; - exp_str = p; + exp->exp_str = p; /* * we mark this as a string and later we will change this * to either a function or a table @@ -1798,6 +1987,7 @@ ex_print(struct ex_ex *eptr) post("%s ", eptr->ex_ptr); break; case ET_TBL: + case ET_VAR: post("%s ", ex_symname((fts_symbol_t )eptr->ex_ptr)); break; case ET_SYM: @@ -1841,8 +2031,9 @@ ex_print(struct ex_ex *eptr) case ET_VEC: post("vec = %ld ", eptr->ex_vec); break; - case ET_VO: - post("$y"); + case ET_YOM1: + case ET_YO: + post("$y%d", eptr->ex_int + 1); break; case ET_XI: case ET_XI0: @@ -1907,6 +2098,9 @@ ex_print(struct ex_ex *eptr) case OP_EQ: post("%s", "=="); break; + case OP_STORE: + post("%s", "="); + break; case OP_NE: post("%s", "!="); break; diff --git a/pd/extra/expr~/vexp.h b/pd/extra/expr~/vexp.h index dd93d2b8..e90c8409 100644 --- a/pd/extra/expr~/vexp.h +++ b/pd/extra/expr~/vexp.h @@ -94,6 +94,7 @@ #define OP_LB ((long)(14<<16|25)) /* [ */ #define OP_RP ((long)(14<<16|26)) /* ) */ #define OP_LP ((long)(14<<16|27)) /* ( */ +#define OP_STORE ((long)(15<<16|28)) /* = */ #define HI_PRE ((long)(100<<16)) /* infinite precedence */ #define PRE_MASK ((long)0xffff0000) /* precedence level mask */ @@ -121,28 +122,30 @@ struct ex_ex { #define exNULL ((struct ex_ex *)0) /* defines for ex_type */ -#define ET_INT 0x1 /* an int */ -#define ET_FLT 0x2 /* a float */ -#define ET_OP 0x3 /* operator */ -#define ET_STR 0x4 /* string */ -#define ET_TBL 0x5 /* a table, the content is a pointer */ -#define ET_FUNC 0x6 /* a function */ -#define ET_SYM 0x7 /* symbol ("string") */ -#define ET_VSYM 0x8 /* variable symbol ("$s?") */ +#define ET_INT 1 /* an int */ +#define ET_FLT 2 /* a float */ +#define ET_OP 3 /* operator */ +#define ET_STR 4 /* string */ +#define ET_TBL 5 /* a table, the content is a pointer */ +#define ET_FUNC 6 /* a function */ +#define ET_SYM 7 /* symbol ("string") */ +#define ET_VSYM 8 /* variable symbol ("$s?") */ /* we treat parenthesis and brackets */ /* special to keep a pointer to their */ /* match in the content */ -#define ET_LP 0x9 /* left parenthesis */ -#define ET_LB 0x10 /* left bracket */ -#define ET_II 0x11 /* and integer inlet */ -#define ET_FI 0x12 /* float inlet */ -#define ET_SI 0x13 /* string inlet */ -#define ET_VI 0x14 /* signal inlet */ -#define ET_VEC 0x15 /* allocated signal vector */ +#define ET_LP 9 /* left parenthesis */ +#define ET_LB 10 /* left bracket */ +#define ET_II 11 /* and integer inlet */ +#define ET_FI 12 /* float inlet */ +#define ET_SI 13 /* string inlet */ +#define ET_VI 14 /* signal inlet */ +#define ET_VEC 15 /* allocated signal vector */ /* special types for fexpr~ */ -#define ET_VO 0x16 /* vector output for fexpr~ */ -#define ET_XI 0x17 /* vector input for fexpr~ */ -#define ET_XI0 0x18 /* shorthand for $x?[0] */ +#define ET_YO 16 /* vector output for fexpr~ */ +#define ET_YOM1 17 /* shorthand for $y?[-1] */ +#define ET_XI 18 /* vector input for fexpr~ */ +#define ET_XI0 20 /* shorthand for $x?[0] */ +#define ET_VAR 21 /* variable */ /* defines for ex_flags */ #define EF_TYPE_MASK 0x07 /* first three bits define the type of expr */ @@ -151,6 +154,7 @@ struct ex_ex { #define EF_FEXPR_TILDE 0x04 /* fexpr~ filter expression */ #define EF_STOP 0x08 /* is it stopped used for expr~ and fexpr~ */ +#define EF_VERBOSE 0x10 /* verbose mode */ #define IS_EXPR(x) ((((x)->exp_flags&EF_TYPE_MASK)|EF_EXPR) == EF_EXPR) #define IS_EXPR_TILDE(x) \ @@ -177,6 +181,7 @@ struct ex_ex { #define EE_BI_OUTPUT 0x02 /* Bad output index */ #define EE_BI_INPUT 0x04 /* Bad input index */ #define EE_NOTABLE 0x08 /* NO TABLE */ +#define EE_NOVAR 0x10 /* NO VARIABLE */ typedef struct expr { #ifdef PD @@ -186,19 +191,22 @@ typedef struct expr { #endif int exp_flags; /* are we expr~, fexpr~, or expr */ int exp_error; /* reported errors */ - t_outlet *exp_outlet; + int exp_nexpr; /* number of expressions */ + char *exp_string; /* the full expression string */ + char *exp_str; /* current parsing position */ + t_outlet *exp_outlet[MAX_VARS]; #ifdef PD struct _exprproxy *exp_proxy; #else /* MAX */ void *exp_proxy[MAX_VARS]; long exp_proxy_id; #endif - struct ex_ex *exp_stack; + struct ex_ex *exp_stack[MAX_VARS]; struct ex_ex exp_var[MAX_VARS]; - struct ex_ex exp_res; /* the evluation result */ + struct ex_ex exp_res[MAX_VARS]; /* the evluation result */ t_float *exp_p_var[MAX_VARS]; - t_float *exp_p_res; /* the previous evaluation result */ - t_float *exp_tmpres; /* temporty result for fexpr~ */ + t_float *exp_p_res[MAX_VARS]; /* the previous evaluation result */ + t_float *exp_tmpres[MAX_VARS]; /* temporty result for fexpr~ */ int exp_vsize; /* the size of the signal vector */ int exp_nivec; /* # of vector inlets */ float exp_f; /* control value to be transformed to signal */ @@ -214,6 +222,7 @@ typedef struct ex_funcs { /* function prototypes for pd-related functions called withing vexp.h */ extern int max_ex_tab(struct expr *expr, t_symbol *s, struct ex_ex *arg, struct ex_ex *optr); +extern int max_ex_var(struct expr *expr, t_symbol *s, struct ex_ex *optr); extern int ex_getsym(char *p, t_symbol **s); extern const char *ex_symname(t_symbol *s); void ex_mkvector(t_float *fp, t_float x, int size); @@ -225,6 +234,8 @@ extern void ex_avg(t_expr *expr, long int argc, struct ex_ex *argv, stru extern void ex_Avg(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); extern void ex_store(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +int value_getonly(t_symbol *s, t_float *f); + #ifdef NT #pragma warning (disable: 4305 4244) diff --git a/pd/extra/expr~/vexp_fun.c b/pd/extra/expr~/vexp_fun.c index 2879d96b..53e9092f 100644 --- a/pd/extra/expr~/vexp_fun.c +++ b/pd/extra/expr~/vexp_fun.c @@ -24,8 +24,42 @@ * */ -/* "expr" was written by Shahrokh Yadegari c. 1989. -msp */ -/* Nov. 2001 - conversion for expr~ --sdy */ +/* "expr" was written by Shahrokh Yadegari c. 1989. -msp + * + * Nov. 2001 --sdy + * conversion for expr~ + * + * Jan, 2002 --sdy + * added fmod() + * + * May 2002 + * added floor and ceil for expr -- Orm Finnendahl + * + * July 2002 --sdy + * added the following math funtions: + * cbrt - cube root + * erf - error function + * erfc - complementary error function + * expm1 - exponential minus 1, + * log1p - logarithm of 1 plus + * isinf - is the value infinite, + * finite - is the value finite + * isnan -- is the resut a nan (Not a number) + * copysign - copy sign of a number + * ldexp - multiply floating-point number by integral power of 2 + * imodf - get signed integral value from floating-point number + * modf - get signed fractional value from floating-point number + * drem - floating-point remainder function + * + * The following are done but not popular enough in math libss + * to be included yet + * hypoth - Euclidean distance function + * trunc + * round + * nearbyint - + */ + + /* * vexp_func.c -- this file include all the functions for vexp. @@ -45,6 +79,7 @@ */ #include <stdlib.h> +#include <string.h> #define __STRICT_BSD__ #include <math.h> @@ -81,6 +116,33 @@ static void ex_sqrt(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_e static void ex_fact(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); static void ex_random(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); static void ex_abs(t_expr *expr, long int argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_fmod(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_ceil(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_floor(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_if(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_ldexp(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_imodf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_modf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +#ifndef NT +static void ex_cbrt(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_erf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_erfc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_expm1(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_log1p(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_isinf(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_finite(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_isnan(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_copysign(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_drem(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +#endif +#ifdef notdef +/* the following will be added once they are more popular in math libraries */ +static void ex_round(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_trunc(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_nearbyint(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +static void ex_hypoth(t_expr *expr, long argc, struct ex_ex *argv, struct ex_ex *optr); +#endif + t_ex_func ex_funcs[] = { {"min", ex_min, 2}, @@ -88,6 +150,9 @@ t_ex_func ex_funcs[] = { {"int", ex_toint, 1}, {"rint", ex_rint, 1}, {"float", ex_tofloat, 1}, + {"fmod", ex_fmod, 2}, + {"floor", ex_floor, 2}, + {"ceil", ex_ceil, 2}, {"pow", ex_pow, 2}, {"sqrt", ex_sqrt, 1}, {"exp", ex_exp, 1}, @@ -107,7 +172,21 @@ t_ex_func ex_funcs[] = { {"fact", ex_fact, 1}, {"random", ex_random, 2}, /* random number */ {"abs", ex_abs, 1}, + {"if", ex_if, 3}, + {"ldexp ", ex_ldexp, 1}, + {"imodf ", ex_imodf, 1}, + {"modf", ex_modf, 1}, #ifndef NT + {"cbrt", ex_cbrt, 1}, + {"erf", ex_erf, 1}, + {"erfc", ex_erfc, 1}, + {"expm1", ex_expm1, 1}, + {"log1p", ex_log1p, 1}, + {"isinf", ex_isinf, 1}, + {"finite", ex_finite, 1}, + {"isnan", ex_isnan, 1}, + {"copysig", ex_copysign, 1}, + {"drem", ex_drem, 1}, {"asinh", ex_asinh, 1}, {"acosh", ex_acosh, 1}, {"atanh", ex_atanh, 1}, /* hyperbolic atan */ @@ -120,13 +199,22 @@ t_ex_func ex_funcs[] = { {"Avg", ex_Avg, 3}, {"store", ex_store, 3}, #endif +#ifdef notdef +/* the following will be added once they are more popular in math libraries */ + {"round", ex_round, 1}, + {"trunc", ex_trunc, 1}, + {"nearbyint", ex_nearbyint, 1}, + {"hypoth", ex_hypoth, 1}, +#endif {0, 0, 0} }; /* - * FUN_EVAL -- + * FUN_EVAL -- do type checking, evaluate a function, + * if fltret is set return float + * otherwise return value based on regular typechecking, */ -#define FUNC_EVAL(left, right, func, leftfuncast, rightfuncast, optr) \ +#define FUNC_EVAL(left, right, func, leftfuncast, rightfuncast, optr, fltret) \ switch (left->ex_type) { \ case ET_INT: \ switch(right->ex_type) { \ @@ -139,9 +227,15 @@ case ET_INT: \ while (j--) \ *op++ = scalar; \ } else { \ - optr->ex_type = ET_INT; \ - optr->ex_int = (int)func(leftfuncast left->ex_int, \ - rightfuncast right->ex_int); \ + if (fltret) { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (float)func(leftfuncast \ + left->ex_int, rightfuncast right->ex_int); \ + } else { \ + optr->ex_type = ET_INT; \ + optr->ex_int = (int)func(leftfuncast \ + left->ex_int, rightfuncast right->ex_int); \ + } \ } \ break; \ case ET_FLT: \ @@ -197,8 +291,8 @@ case ET_FLT: \ while (j--) \ *op++ = scalar; \ } else { \ - optr->ex_type = ET_INT; \ - optr->ex_int = (int)func(leftfuncast left->ex_flt, \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (float)func(leftfuncast left->ex_flt, \ rightfuncast right->ex_int); \ } \ break; \ @@ -306,9 +400,11 @@ default: \ } /* - * evaluate a unary operator, TYPE is applied to float operands + * FUNC_EVAL_UNARY - evaluate a unary function, + * if fltret is set return float + * otherwise return value based on regular typechecking, */ -#define FUNC_EVAL_UNARY(left, func, leftcast, optr) \ +#define FUNC_EVAL_UNARY(left, func, leftcast, optr, fltret) \ switch(left->ex_type) { \ case ET_INT: \ if (optr->ex_type == ET_VEC) { \ @@ -316,6 +412,11 @@ case ET_INT: \ (float)(func (leftcast left->ex_int)), e->exp_vsize);\ break; \ } \ + if (fltret) { \ + optr->ex_type = ET_FLT; \ + optr->ex_flt = (float) func(leftcast left->ex_int); \ + break; \ + } \ optr->ex_type = ET_INT; \ optr->ex_int = (int) func(leftcast left->ex_int); \ break; \ @@ -352,8 +453,39 @@ default: \ #define min(x,y) (x > y ? y : x) #define max(x,y) (x > y ? x : y) +#define FUNC_DEF(ex_func, func, castleft, castright, fltret); \ +static void \ +ex_func(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)\ +{ \ + struct ex_ex *left, *right; \ + float *op; /* output pointer */ \ + float *lp, *rp; /* left and right vector pointers */ \ + float scalar; \ + int j; \ + \ + left = argv++; \ + right = argv; \ + FUNC_EVAL(left, right, func, castleft, castright, optr, fltret); \ +} + + +#define FUNC_DEF_UNARY(ex_func, func, cast, fltret); \ +static void \ +ex_func(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr)\ +{ \ + struct ex_ex *left; \ + float *op; /* output pointer */ \ + float *lp, *rp; /* left and right vector pointers */ \ + float scalar; \ + int j; \ + \ + left = argv++; \ + \ + FUNC_EVAL_UNARY(left, func, cast, optr, fltret); \ +} + /* - * ex_min -- if any of the arfuments are or the output are vectors, a vector + * ex_min -- if any of the arguments are or the output are vectors, a vector * of floats is generated otherwise the type of the result is the * type of the smaller value */ @@ -369,12 +501,11 @@ ex_min(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; right = argv; - /* minimum needs no cast, as it is not a real function */ - FUNC_EVAL(left, right, min, (double), (double), optr); + FUNC_EVAL(left, right, min, (double), (double), optr, 0); } /* - * ex_max -- if any of the arfuments are or the output are vectors, a vector + * ex_max -- if any of the arguments are or the output are vectors, a vector * of floats is generated otherwise the type of the result is the * type of the larger value */ @@ -390,12 +521,9 @@ ex_max(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; right = argv; - /* minimum needs no cast, as it is not a real function */ - FUNC_EVAL(left, right, max, (double), (double), optr); + FUNC_EVAL(left, right, max, (double), (double), optr, 0); } -/* SDY changed to new form up to here */ - /* * ex_toint -- convert to integer */ @@ -411,8 +539,8 @@ ex_toint(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; #define toint(x) ((int)(x)) - FUNC_EVAL_UNARY(left, toint, (int), optr); -} + FUNC_EVAL_UNARY(left, toint, (int), optr, 0); + } #ifdef NT /* No rint in NT land ??? */ @@ -441,25 +569,7 @@ ex_rint(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, rint, (double), optr); - -#ifdef old - - if (argv->ex_type == ET_INT) - *optr = *argv; - else if (argv->ex_type == ET_FLT) { - optr->ex_type = ET_FLT; -#ifdef NT /* no rint() in NT??? */ - optr->ex_flt = floor(argv->ex_flt + 0.5); -#else - optr->ex_flt = rint(argv->ex_flt); -#endif - } else { -/* SDY what does this mean? this is wrong!!???? */ - optr->ex_type = ET_INT; - optr->ex_int = (int)argv->ex_ptr; - } -#endif + FUNC_EVAL_UNARY(left, rint, (double), optr, 1); } /* @@ -477,7 +587,7 @@ ex_tofloat(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; #define tofloat(x) ((float)(x)) - FUNC_EVAL_UNARY(left, toint, (int), optr); + FUNC_EVAL_UNARY(left, tofloat, (int), optr, 1); } @@ -495,7 +605,7 @@ ex_pow(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; right = argv; - FUNC_EVAL(left, right, pow, (double), (double), optr); + FUNC_EVAL(left, right, pow, (double), (double), optr, 1); } /* @@ -512,7 +622,7 @@ ex_sqrt(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, sqrt, (double), optr); + FUNC_EVAL_UNARY(left, sqrt, (double), optr, 1); } /* @@ -529,7 +639,7 @@ ex_exp(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, exp, (double), optr); + FUNC_EVAL_UNARY(left, exp, (double), optr, 1); } /* @@ -546,7 +656,7 @@ ex_log(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, log10, (double), optr); + FUNC_EVAL_UNARY(left, log10, (double), optr, 1); } /* @@ -563,7 +673,7 @@ ex_ln(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, log, (double), optr); + FUNC_EVAL_UNARY(left, log, (double), optr, 1); } static void @@ -577,7 +687,7 @@ ex_sin(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, sin, (double), optr); + FUNC_EVAL_UNARY(left, sin, (double), optr, 1); } static void @@ -591,7 +701,7 @@ ex_cos(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, cos, (double), optr); + FUNC_EVAL_UNARY(left, cos, (double), optr, 1); } @@ -606,7 +716,7 @@ ex_tan(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, tan, (double), optr); + FUNC_EVAL_UNARY(left, tan, (double), optr, 1); } static void @@ -620,7 +730,7 @@ ex_asin(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, asin, (double), optr); + FUNC_EVAL_UNARY(left, asin, (double), optr, 1); } static void @@ -634,7 +744,7 @@ ex_acos(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, acos, (double), optr); + FUNC_EVAL_UNARY(left, acos, (double), optr, 1); } @@ -649,7 +759,7 @@ ex_atan(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, atan, (double), optr); + FUNC_EVAL_UNARY(left, atan, (double), optr, 1); } /* @@ -666,9 +776,59 @@ ex_atan2(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; right = argv; - FUNC_EVAL(left, right, atan2, (double), (double), optr); + FUNC_EVAL(left, right, atan2, (double), (double), optr, 1); } +/* + * ex_fmod -- floating point modulo + */ +static void +ex_fmod(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right; + float *op; /* output pointer */ + float *lp, *rp; /* left and right vector pointers */ + float scalar; + int j; + + left = argv++; + right = argv; + FUNC_EVAL(left, right, fmod, (double), (double), optr, 1); +} + + +/* + * ex_floor -- floor + */ +static void +ex_floor(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + float *op; /* output pointer */ + float *lp, *rp; /* left and right vector pointers */ + float scalar; + int j; + + left = argv++; + FUNC_EVAL_UNARY(left, floor, (double), optr, 1); +} + + +/* + * ex_ceil -- ceil + */ +static void +ex_ceil(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left; + float *op; /* output pointer */ + float *lp, *rp; /* left and right vector pointers */ + float scalar; + int j; + + left = argv++; + FUNC_EVAL_UNARY(left, ceil, (double), optr, 1); +} static void ex_sinh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) @@ -681,7 +841,7 @@ ex_sinh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, sinh, (double), optr); + FUNC_EVAL_UNARY(left, sinh, (double), optr, 1); } static void @@ -695,7 +855,7 @@ ex_cosh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, cosh, (double), optr); + FUNC_EVAL_UNARY(left, cosh, (double), optr, 1); } @@ -710,7 +870,7 @@ ex_tanh(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, tanh, (double), optr); + FUNC_EVAL_UNARY(left, tanh, (double), optr, 1); } @@ -726,7 +886,7 @@ ex_asinh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, asinh, (double), optr); + FUNC_EVAL_UNARY(left, asinh, (double), optr, 1); } static void @@ -740,7 +900,7 @@ ex_acosh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, acosh, (double), optr); + FUNC_EVAL_UNARY(left, acosh, (double), optr, 1); } static void @@ -754,7 +914,7 @@ ex_atanh(t_expr *e, long argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, atanh, (double), optr); + FUNC_EVAL_UNARY(left, atanh, (double), optr, 1); } #endif @@ -786,7 +946,7 @@ ex_fact(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, ex_dofact, (int), optr); + FUNC_EVAL_UNARY(left, ex_dofact, (int), optr, 0); } static int @@ -808,7 +968,7 @@ ex_random(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; right = argv; - FUNC_EVAL(left, right, ex_dorandom, (int), (int), optr); + FUNC_EVAL(left, right, ex_dorandom, (int), (int), optr, 0); } @@ -823,6 +983,333 @@ ex_abs(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) left = argv++; - FUNC_EVAL_UNARY(left, fabs, (double), optr); + FUNC_EVAL_UNARY(left, fabs, (double), optr, 0); } +/* + *ex_if -- floating point modulo + */ +static void +ex_if(t_expr *e, long int argc, struct ex_ex *argv, struct ex_ex *optr) +{ + struct ex_ex *left, *right, *cond, *res; + float *op; /* output pointer */ + float *lp, *rp; /* left and right vector pointers */ + float *cp; /* condition pointer */ + float leftvalue, rightvalue; + int j; + + cond = argv++; + left = argv++; + right = argv; + + switch (cond->ex_type) { + case ET_VEC: + case ET_VI: + if (optr->ex_type != ET_VEC) { + if (optr->ex_type == ET_VI) { + /* SDY remove this test */ + post("expr~: Int. error %d", __LINE__); + return; + } + optr->ex_type = ET_VEC; + optr->ex_vec = (t_float *) + fts_malloc(sizeof (t_float) * e->exp_vsize); + } + op = optr->ex_vec; + j = e->exp_vsize; + cp = cond->ex_vec; + switch (left->ex_type) { + case ET_INT: + leftvalue = left->ex_int; + switch (right->ex_type) { + case ET_INT: + rightvalue = right->ex_int; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return; + case ET_FLT: + rightvalue = right->ex_flt; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return; + case ET_VEC: + case ET_VI: + rp = right->ex_vec; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = *rp; + rp++; + } + return; + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad right type %ld\n", + __LINE__, right->ex_type); + return; + } + case ET_FLT: + leftvalue = left->ex_flt; + switch (right->ex_type) { + case ET_INT: + rightvalue = right->ex_int; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return; + case ET_FLT: + rightvalue = right->ex_flt; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = rightvalue; + } + return; + case ET_VEC: + case ET_VI: + rp = right->ex_vec; + while (j--) { + if (*cp++) + *op++ = leftvalue; + else + *op++ = *rp; + rp++; + } + return; + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad right type %ld\n", + __LINE__, right->ex_type); + return; + } + case ET_VEC: + case ET_VI: + lp = left->ex_vec; + switch (right->ex_type) { + case ET_INT: + rightvalue = right->ex_int; + while (j--) { + if (*cp++) + *op++ = *lp; + else + *op++ = rightvalue; + lp++; + } + return; + case ET_FLT: + rightvalue = right->ex_flt; + while (j--) { + if (*cp++) + *op++ = *lp; + else + *op++ = rightvalue; + lp++; + } + return; + case ET_VEC: + case ET_VI: + rp = right->ex_vec; + while (j--) { + if (*cp++) + *op++ = *lp; + else + *op++ = *rp; + lp++; rp++; + } + return; + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad right type %ld\n", + __LINE__, right->ex_type); + return; + } + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad left type %ld\n", + __LINE__, left->ex_type); + return; + } + case ET_INT: + if (cond->ex_int) + res = left; + else + res = right; + break; + case ET_FLT: + if (cond->ex_flt) + res = left; + else + res = right; + break; + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad condition type %ld\n", + __LINE__, cond->ex_type); + return; + } + switch(res->ex_type) { + case ET_INT: + if (optr->ex_type == ET_VEC) { + ex_mkvector(optr->ex_vec, (float)res->ex_int, + e->exp_vsize); + return; + } + *optr = *res; + return; + case ET_FLT: + if (optr->ex_type == ET_VEC) { + ex_mkvector(optr->ex_vec, (float)res->ex_flt, + e->exp_vsize); + return; + } + *optr = *res; + return; + case ET_VEC: + case ET_VI: + if (optr->ex_type != ET_VEC) { + if (optr->ex_type == ET_VI) { + /* SDY remove this test */ + post("expr~: Int. error %d", __LINE__); + return; + } + optr->ex_type = ET_VEC; + optr->ex_vec = (t_float *) + fts_malloc(sizeof (t_float) * e->exp_vsize); + } + memcpy(optr->ex_vec, res->ex_vec, e->exp_vsize*sizeof(t_float)); + return; + case ET_SYM: + default: + post_error((fts_object_t *) e, + "expr: FUNC_EVAL(%d): bad res type %ld\n", + __LINE__, res->ex_type); + return; + } + +} + +/* + * ex_imodf - extract signed integral value from floating-point number + */ +static double +imodf(double x) +{ + double xx; + + modf(x, &xx); + return (xx); +} +FUNC_DEF_UNARY(ex_imodf, imodf, (double), 1); + +/* + * ex_modf - extract signed fractional value from floating-point number + * + * using fracmodf because fmodf() is alrady defined in a .h file + */ +static double +fracmodf(double x) +{ + double xx; + + return(modf(x, &xx)); +} +FUNC_DEF_UNARY(ex_modf, fracmodf, (double), 1); + +/* + * ex_ldexp - multiply floating-point number by integral power of 2 + */ +FUNC_DEF(ex_ldexp, ldexp, (double), (int), 1); + +#ifndef NT +/* + * ex_cbrt - cube root + */ +FUNC_DEF_UNARY(ex_cbrt, cbrt, (double), 1); + +/* + * ex_erf - error function + */ +FUNC_DEF_UNARY(ex_erf, erf, (double), 1); + +/* + * ex_erfc - complementary error function + */ +FUNC_DEF_UNARY(ex_erfc, erfc, (double), 1); + +/* + * ex_expm1 - exponential minus 1, + */ +FUNC_DEF_UNARY(ex_expm1, expm1, (double), 1); + +/* + * ex_log1p - logarithm of 1 plus + */ +FUNC_DEF_UNARY(ex_log1p, log1p, (double), 1); + +/* + * ex_isinf - is the value infinite, + */ +FUNC_DEF_UNARY(ex_isinf, isinf, (double), 0); + +/* + * ex_finite - is the value finite + */ +FUNC_DEF_UNARY(ex_finite, finite, (double), 0); + +/* + * ex_isnan -- is the resut a nan (Not a number) + */ +FUNC_DEF_UNARY(ex_isnan, isnan, (double), 0); + +/* + * ex_copysign - copy sign of a number + */ +FUNC_DEF(ex_copysign, copysign, (double), (double), 1); + +/* + * ex_drem - floating-point remainder function + */ +FUNC_DEF(ex_drem, drem, (double), (double), 1); +#endif + +#ifdef notdef +/* the following will be added once they are more popular in math libraries */ +/* + * ex_hypoth - Euclidean distance function + */ +FUNC_DEF(ex_hypoth, hypoth, (double), (double), 1); + +/* + * ex_round - round to nearest integer, away from zero + */ +FUNC_DEF_UNARY(ex_round, round, (double), 1); + +/* + * ex_trunc - round to interger, towards zero + */ +FUNC_DEF_UNARY(ex_trunc, trunc, (double), 1); + +/* + * ex_nearbyint - round to nearest integer + */ +FUNC_DEF_UNARY(ex_nearbyint, nearbyint, (double), 1); +#endif diff --git a/pd/extra/expr~/vexp_if.c b/pd/extra/expr~/vexp_if.c index 6d86ff1c..c75013ba 100644 --- a/pd/extra/expr~/vexp_if.c +++ b/pd/extra/expr~/vexp_if.c @@ -27,23 +27,22 @@ /* "expr" was written by Shahrokh Yadegari c. 1989. -msp */ /* "expr~" and "fexpr~" conversion by Shahrokh Yadegari c. 1999,2000 */ +/* + * Feb 2002 - added access to variables + * multiple expression support + * new short hand forms for fexpr~ + * now $y or $y1 = $y1[-1] and $y2 = $y2[-1] + * --sdy + */ + #include <stdio.h> +#include <string.h> #include <stdlib.h> #include "vexp.h" -#ifndef MSP -#ifndef MACOSX -/* - * the compiler on mac seems not to like this, perhaps we could get away with - * not having it at all. - */ -#include "stdlib.h" -#endif -#endif -#include "string.h" -static char *exp_version = "0.3"; +static char *exp_version = "0.4"; extern struct ex_ex *ex_eval(struct expr *exp, struct ex_ex *eptr, struct ex_ex *optr, int n); @@ -149,6 +148,7 @@ static void expr_ff(t_expr *x) { t_exprproxy *y; + int i; y = x->exp_proxy; while (y) @@ -162,20 +162,32 @@ expr_ff(t_expr *x) #endif y = x->exp_proxy; } - if (x->exp_stack) - fts_free(x->exp_stack); + for (i = 0 ; i < x->exp_nexpr; i++); + if (x->exp_stack[i]) + fts_free(x->exp_stack[i]); /* * SDY free all the allocated buffers here for expr~ and fexpr~ + * check to see if there are others */ + for (i = 0; i < MAX_VARS; i++) { + if (x->exp_p_var[i]) + fts_free(x->exp_p_var[i]); + if (x->exp_p_res[i]) + fts_free(x->exp_p_res[i]); + if (x->exp_tmpres[i]) + fts_free(x->exp_tmpres[i]); + } + + } static void expr_bang(t_expr *x) { + int i; #ifdef EXPR_DEBUG { - int i; struct ex_ex *eptr; for (i = 0, eptr = x->exp_var; ; eptr++, i++) @@ -202,28 +214,30 @@ expr_bang(t_expr *x) if (!IS_EXPR(x)) return; - if (!ex_eval(x, x->exp_stack, &x->exp_res, 0)) - { - /* fprintf(stderr,"expr_bang(error evaluation)\n"); */ - return; - } - - - switch(x->exp_res.ex_type) - { - case ET_INT: - outlet_float(x->exp_outlet, (t_float) x->exp_res.ex_int); - break; + for (i = x->exp_nexpr - 1; i > -1 ; i--) { + if (!ex_eval(x, x->exp_stack[i], &x->exp_res[i], 0)) { + /*fprintf(stderr,"expr_bang(error evaluation)\n"); */ + /* SDY now that we have mutiple ones, on error we should + * continue + return; + */ + } + switch(x->exp_res[i].ex_type) { + case ET_INT: + outlet_float(x->exp_outlet[i], + (t_float) x->exp_res[i].ex_int); + break; - case ET_FLT: - outlet_float(x->exp_outlet, x->exp_res.ex_flt); - break; + case ET_FLT: + outlet_float(x->exp_outlet[i], x->exp_res[i].ex_flt); + break; - case ET_SYM: - /* CHANGE this will have to be taken care of */ + case ET_SYM: + /* CHANGE this will have to be taken care of */ - default: - post("expr: bang: unrecognized result %ld\n", x->exp_res.ex_type); + default: + post("expr: bang: unrecognized result %ld\n", x->exp_res[i].ex_type); + } } } @@ -280,19 +294,21 @@ Nexpr_new(t_symbol *s, int ac, t_atom *av) /* * initialize the newly allocated object */ - x->exp_stack = (struct ex_ex *)0; x->exp_proxy = 0; x->exp_nivec = 0; + x->exp_nexpr = 0; x->exp_error = 0; - x->exp_outlet = (t_outlet *)0; - x->exp_res.ex_type = 0; - x->exp_res.ex_int = 0; - x->exp_p_res = (t_float *)0; - x->exp_tmpres = (t_float *)0; for (i = 0; i < MAX_VARS; i++) { + x->exp_stack[i] = (struct ex_ex *)0; + x->exp_outlet[i] = (t_outlet *)0; + x->exp_res[i].ex_type = 0; + x->exp_res[i].ex_int = 0; + x->exp_p_res[i] = (t_float *)0; x->exp_var[i].ex_type = 0; x->exp_var[i].ex_int = 0; x->exp_p_var[i] = (t_float *)0; + x->exp_tmpres[i] = (t_float *)0; + x->exp_vsize = 0; } x->exp_f = 0; /* save the control value to be transformed to signal */ @@ -369,15 +385,25 @@ SDY the following coredumps why? } } if (IS_EXPR(x)) { - x->exp_outlet = outlet_new(&x->exp_ob, 0); + for (i = 0; i < x->exp_nexpr; i++) + x->exp_outlet[i] = outlet_new(&x->exp_ob, 0); } else { -#ifdef PD - x->exp_outlet = outlet_new(&x->exp_ob, gensym("signal")); -#else /* MSP */ - x->exp_outlet = outlet_new(&x->exp_ob, "signal"); -#endif + for (i = 0; i < x->exp_nexpr; i++) + x->exp_outlet[i] = outlet_new(&x->exp_ob, + gensym("signal")); x->exp_nivec = dsp_index; } + /* + * for now assume a 64 sample size block but this may change once + * expr_dsp is called + */ + x->exp_vsize = 64; + for (i = 0; i < x->exp_nexpr; i++) { + x->exp_p_res[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + x->exp_tmpres[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + } + for (i = 0; i < MAX_VARS; i++) + x->exp_p_var[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); return (x); } @@ -385,7 +411,7 @@ SDY the following coredumps why? t_int * expr_perform(t_int *w) { - int i; + int i, j; t_expr *x = (t_expr *)w[1]; struct ex_ex res; int n; @@ -397,34 +423,54 @@ expr_perform(t_int *w) } if (x->exp_flags & EF_STOP) { - memset(x->exp_res.ex_vec, 0, x->exp_vsize * sizeof (float)); + for (i = 0; i < x->exp_nexpr; i++) + memset(x->exp_res[i].ex_vec, 0, + x->exp_vsize * sizeof (float)); return (w + 2); } if (IS_EXPR_TILDE(x)) { - ex_eval(x, x->exp_stack, &x->exp_res, 0); + /* + * if we have only one expression, we can right on + * on the output directly, otherwise we have to copy + * the data because, outputs could be the same buffer as + * inputs + */ + if ( x->exp_nexpr == 1) + ex_eval(x, x->exp_stack[0], &x->exp_res[0], 0); + else { + res.ex_type = ET_VEC; + for (i = 0; i < x->exp_nexpr; i++) { + res.ex_vec = x->exp_tmpres[i]; + ex_eval(x, x->exp_stack[i], &res, 0); + } + n = x->exp_vsize * sizeof(t_float); + for (i = 0; i < x->exp_nexpr; i++) + memcpy(x->exp_res[i].ex_vec, x->exp_tmpres[i], + n); + } return (w + 2); } if (!IS_FEXPR_TILDE(x)) { post("expr_perform: bad x->exp_flags = %d - expecting fexpr", x->exp_flags); - abort(); + return (w + 2); } /* * since the output buffer could be the same as one of the inputs * we need to keep the output in a different buffer */ - for (i = 0; i < x->exp_vsize; i++) { + for (i = 0; i < x->exp_vsize; i++) for (j = 0; j < x->exp_nexpr; j++) { res.ex_type = 0; res.ex_int = 0; - ex_eval(x, x->exp_stack, &res, i); + ex_eval(x, x->exp_stack[j], &res, i); switch (res.ex_type) { case ET_INT: - x->exp_tmpres[i] = (t_float) res.ex_int; + x->exp_tmpres[j][i] = (t_float) res.ex_int; break; case ET_FLT: - x->exp_tmpres[i] = res.ex_flt; + x->exp_tmpres[j][i] = res.ex_flt; break; default: post("expr_perform: bad result type %d", res.ex_type); @@ -439,8 +485,10 @@ expr_perform(t_int *w) for (i = 0; i < MAX_VARS; i++) if (x->exp_var[i].ex_type == ET_XI) memcpy(x->exp_p_var[i], x->exp_var[i].ex_vec, n); - memcpy(x->exp_p_res, x->exp_tmpres, n); - memcpy(x->exp_res.ex_vec, x->exp_tmpres, n); + for (i = 0; i < x->exp_nexpr; i++) { + memcpy(x->exp_p_res[i], x->exp_tmpres[i], n); + memcpy(x->exp_res[i].ex_vec, x->exp_tmpres[i], n); + } return (w + 2); } @@ -453,8 +501,10 @@ expr_dsp(t_expr *x, t_signal **sp) x->exp_error = 0; /* reset all errors */ newsize = (x->exp_vsize != sp[0]->s_n); x->exp_vsize = sp[0]->s_n; /* record the vector size */ - x->exp_res.ex_type = ET_VEC; - x->exp_res.ex_vec = sp[x->exp_nivec]->s_vec; + for (i = 0; i < x->exp_nexpr; i++) { + x->exp_res[i].ex_type = ET_VEC; + x->exp_res[i].ex_vec = sp[x->exp_nivec + i]->s_vec; + } for (i = 0, nv = 0; i < MAX_VARS; i++) /* * the first inlet is always a signal @@ -481,27 +531,55 @@ expr_dsp(t_expr *x, t_signal **sp) dsp_add(expr_perform, 1, (t_int *) x); + /* + * The buffer are now being allocated for expr~ and fexpr~ + * because if we have more than one expression we need the + * temporary buffers, The save buffers are not really needed if (!IS_FEXPR_TILDE(x)) return; - if (x->exp_p_res) { + */ + /* + * if we have already allocated the buffers and we have a + * new size free all the buffers + */ + if (x->exp_p_res[0]) { if (!newsize) return; /* * if new size, reallocate all the previous buffers for fexpr~ */ - fts_free(x->exp_p_res); - fts_free(x->exp_tmpres); + for (i = 0; i < x->exp_nexpr; i++) { + fts_free(x->exp_p_res[i]); + fts_free(x->exp_tmpres[i]); + } for (i = 0; i < MAX_VARS; i++) fts_free(x->exp_p_var[i]); } - x->exp_p_res = fts_calloc(x->exp_vsize, sizeof (t_float)); - x->exp_tmpres = fts_calloc(x->exp_vsize, sizeof (t_float)); + for (i = 0; i < x->exp_nexpr; i++) { + x->exp_p_res[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + x->exp_tmpres[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); + } for (i = 0; i < MAX_VARS; i++) x->exp_p_var[i] = fts_calloc(x->exp_vsize, sizeof (t_float)); } /* + * expr_verbose -- toggle the verbose switch + */ +static void +expr_verbose(t_expr *x) +{ + if (x->exp_flags & EF_VERBOSE) { + x->exp_flags &= ~EF_VERBOSE; + post ("verbose off"); + } else { + x->exp_flags |= EF_VERBOSE; + post ("verbose on"); + } +} + +/* * expr_start -- turn on expr processing for now only used for fexpr~ */ static void @@ -518,6 +596,195 @@ expr_stop(t_expr *x) { x->exp_flags |= EF_STOP; } +static void +fexpr_set_usage(void) +{ + post("fexpr~: set val ..."); + post("fexpr~: set {xy}[#] val ..."); +} + +/* + * fexpr_tilde_set -- set previous values of the buffers + * set val val ... - sets the first elements of output buffers + * set x val ... - sets the elements of the first input buffer + * set x# val ... - sets the elements of the #th input buffers + * set y val ... - sets the elements of the first output buffer + * set y# val ... - sets the elements of the #th output buffers + */ +static void +fexpr_tilde_set(t_expr *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sx; + int vecno; + int i, nargs; + + if (!argc) + return; + sx = atom_getsymbolarg(0, argc, argv); + switch(sx->s_name[0]) { + case 'x': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.set: bad set x vector number"); + fexpr_set_usage(); + return; + } + if (vecno >= MAX_VARS) { + post("fexpr~.set: no more than %d inlets", + MAX_VARS); + return; + } + vecno--; + } + if (x->exp_var[vecno].ex_type != ET_XI) { + post("fexpr~-set: no signal at inlet %d", vecno + 1); + return; + } + nargs = argc - 1; + if (!nargs) { + post("fexpr~-set: no argument to set"); + return; + } + if (nargs > x->exp_vsize) { + post("fexpr~.set: %d set values larger than vector size(%d)", + nargs, x->exp_vsize); + post("fexpr~.set: only the first %d values will be set", + x->exp_vsize); + nargs = x->exp_vsize; + } + for (i = 0; i < nargs; i++) { + x->exp_p_var[vecno][x->exp_vsize - i - 1] = + atom_getfloatarg(i + 1, argc, argv); + } + return; + case 'y': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.set: bad set y vector number"); + fexpr_set_usage(); + return; + } + vecno--; + } + if (vecno >= x->exp_nexpr) { + post("fexpr~.set: only %d outlets", x->exp_nexpr); + return; + } + nargs = argc - 1; + if (!nargs) { + post("fexpr~-set: no argument to set"); + return; + } + if (nargs > x->exp_vsize) { + post("fexpr~-set: %d set values larger than vector size(%d)", + nargs, x->exp_vsize); + post("fexpr~.set: only the first %d values will be set", + x->exp_vsize); + nargs = x->exp_vsize; + } + for (i = 0; i < nargs; i++) { + x->exp_p_res[vecno][x->exp_vsize - i - 1] = + atom_getfloatarg(i + 1, argc, argv); + } + return; + case 0: + if (argc > x->exp_nexpr) { + post("fexpr~.set: only %d outlets available", + x->exp_nexpr); + post("fexpr~.set: the extra set values are ignored"); + } + for (i = 0; i < x->exp_nexpr && i < argc; i++) + x->exp_p_res[i][x->exp_vsize - 1] = + atom_getfloatarg(i, argc, argv); + return; + default: + fexpr_set_usage(); + return; + } + return; +} + +/* + * fexpr_tilde_clear - clear the past buffers + */ +static void +fexpr_tilde_clear(t_expr *x, t_symbol *s, int argc, t_atom *argv) +{ + t_symbol *sx; + int vecno; + int i, nargs; + + /* + * if no arguement clear all input and output buffers + */ + if (!argc) { + for (i = 0; i < x->exp_nexpr; i++) + memset(x->exp_p_res[i], 0, x->exp_vsize*sizeof(float)); + for (i = 0; i < MAX_VARS; i++) + if (x->exp_var[i].ex_type == ET_XI) + memset(x->exp_p_var[i], 0, + x->exp_vsize*sizeof(float)); + return; + } + if (argc > 1) { + post("fexpr~ usage: 'clear' or 'clear {xy}[#]'"); + return; + } + + sx = atom_getsymbolarg(0, argc, argv); + switch(sx->s_name[0]) { + case 'x': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.clear: bad clear x vector number"); + return; + } + if (vecno >= MAX_VARS) { + post("fexpr~.clear: no more than %d inlets", + MAX_VARS); + return; + } + vecno--; + } + if (x->exp_var[vecno].ex_type != ET_XI) { + post("fexpr~-clear: no signal at inlet %d", vecno + 1); + return; + } + memset(x->exp_p_var[vecno], 0, x->exp_vsize*sizeof(float)); + return; + case 'y': + if (!sx->s_name[1]) + vecno = 0; + else { + vecno = atoi(sx->s_name + 1); + if (!vecno) { + post("fexpr~.clear: bad clear y vector number"); + return; + } + vecno--; + } + if (vecno >= x->exp_nexpr) { + post("fexpr~.clear: only %d outlets", x->exp_nexpr); + return; + } + memset(x->exp_p_res[vecno], 0, x->exp_vsize*sizeof(float)); + return; + return; + default: + post("fexpr~ usage: 'clear' or 'clear {xy}[#]'"); + return; + } + return; +} #ifdef PD @@ -542,7 +809,7 @@ expr_setup(void) class_addmethod(expr_tilde_class, nullfn, gensym("signal"), 0); CLASS_MAINSIGNALIN(expr_tilde_class, t_expr, exp_f); class_addmethod(expr_tilde_class,(t_method)expr_dsp, gensym("dsp"), 0); - + class_sethelpsymbol(expr_tilde_class, gensym("expr")); /* * fexpr~ initialization */ @@ -555,6 +822,15 @@ expr_setup(void) gensym("stop"), 0); class_addmethod(fexpr_tilde_class,(t_method)expr_dsp,gensym("dsp"), 0); + class_addmethod(fexpr_tilde_class, (t_method)fexpr_tilde_set, + gensym("set"), A_GIMME, 0); + class_addmethod(fexpr_tilde_class, (t_method)fexpr_tilde_clear, + gensym("clear"), A_GIMME, 0); + class_addmethod(fexpr_tilde_class,(t_method)expr_verbose, + gensym("verbose"), 0); + class_sethelpsymbol(fexpr_tilde_class, gensym("expr")); + + post("expr, expr~, fexpr~ version %s under GNU General Public License ", exp_version); @@ -586,7 +862,8 @@ main(void) /* -- the following functions use Pd internals and so are in the "if" file. */ -int ex_getsym(char *p, fts_symbol_t *s) +int +ex_getsym(char *p, fts_symbol_t *s) { *s = gensym(p); return (0); @@ -622,7 +899,7 @@ max_ex_tab(struct expr *exp,fts_symbol_t s,struct ex_ex *arg,struct ex_ex *optr) !garray_getfloatarray(garray, &size, &vec)) { optr->ex_type = ET_FLT; - optr->ex_int = 0; + optr->ex_flt = 0; pd_error(exp, "no such table '%s'", s->s_name); return (1); } @@ -655,6 +932,19 @@ max_ex_tab(struct expr *exp,fts_symbol_t s,struct ex_ex *arg,struct ex_ex *optr) return (0); } +int +max_ex_var(struct expr *exp, fts_symbol_t var, struct ex_ex *optr) +{ + optr->ex_type = ET_FLT; + if (value_getfloat(var, &(optr->ex_flt))) { + optr->ex_type = ET_FLT; + optr->ex_flt = 0; + pd_error(exp, "no such var '%s'", var->s_name); + return (1); + } + return (0); +} + #ifdef PD /* this goes to the end of this file as the following functions * should be defined in the expr object in MSP */ |