aboutsummaryrefslogtreecommitdiff
path: root/pd/extra/expr~
diff options
context:
space:
mode:
Diffstat (limited to 'pd/extra/expr~')
-rw-r--r--pd/extra/expr~/README36
-rw-r--r--pd/extra/expr~/help-expr.pd231
-rw-r--r--pd/extra/expr~/makefile52
-rw-r--r--pd/extra/expr~/vexp.c422
-rw-r--r--pd/extra/expr~/vexp.h57
-rw-r--r--pd/extra/expr~/vexp_fun.c611
-rw-r--r--pd/extra/expr~/vexp_if.c420
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
*/