mmj
mmj

Reputation: 5780

Maxima - function definition (define statement)

Starting from the following Maxima code taken from here

/* piecewise function definition */
itvs: [[x<0],[x>=0,x<1], [x>=1]]; /* intervals */
pfun:  [ a,    x^2+b,      c*x  ]; /* local functions */

/* piecewise function constructor */
f:0$
for i: 1 thru 3 do f:f+charfun(apply("and",itvs[i]))*pfun[i]$
f;

/* differentiation of piecewise function */
gradef(charfun(dummy),0)$
diff(f,x);

I'd like to make a function able to take 2 arguments like itvsand pfun and return a piecewise function like f, but I was not able to do it because of errors due to evaluation of symbols. For example in the following try I get the error "incorrect syntax: itvs is not an infix operator":

define(pfc(itvs,pfun),(
    f:0,
    for i: 1 thru length(itvs) do f:f+charfun("and" itvs[i])*pfun[i],
    f
));

How can I define such a function? The documentation I found is very concise and could not help me, is there some less known documentation about this subject?

EDIT

An alternative format of input argument, maybe simpler and more flexible, could be:

/* piecewise function definition */
pfd: [
    [a,     x<0],
    [x^2+b, x>=0 and x<1],
    [c*x,   x>=1]
]; 

Writing a function constructor with this argument might be simpler.

FOLLOW UP

If you don't actually need a piecewise function since a piecewise expression is enough (as -- I discovered later -- in my case), writing a piecewise expression constructor (using the alternative format of input argument) becomes straightforward:

/* pec=piecewise expression constructor */
/* argument is an array of [expression,interval] couples */
pec(x) := sum(x[i][1]*charfun(x[i][2]), i,1,length(x));

f: pec( [[(1+x)/2, x>=-1 and x<1],[3, x<-1 or x>=1]] )

(f)   3*charfun(x<-1 or x>=1)+((x+1)*charfun(x>=-1 and x<1))/2

Upvotes: 0

Views: 1685

Answers (2)

Robert Dodier
Robert Dodier

Reputation: 17577

OP indicates that they want pfc to construct a piecewise function. Here is an attempt:

pfc (itvs, pfun) := block ([body],
    body : sum (charfun (apply ("and", itvs[i]))*pfun[i], i, 1, length(itvs)),
    buildq ([body], lambda ([x], body)));

Now pfc takes intervals and expressions and constructs an unnamed function of one argument. It's assumed the argument is named x; I guess if one wanted to make this a little more complicated, one could specify a different variable as an argument for pfc and make it another variable for buildq, e.g. buildq([body, var], lambda([var], body).

Upvotes: 2

Robert Dodier
Robert Dodier

Reputation: 17577

Couple of things. (1) Instead of charfun("and" itvs[i]) you want charfun(apply("and", itvs[i])). (2) Instead of pfc(itvs,pfun) you want pfc(x). Also (3) probably you want to make f a local variable.

I think this might work:

define(pfc(x), block([f:0],
    for i: 1 thru length(itvs)
        do f:f+charfun(apply("and", itvs[i]))*pfun[i],
    f));

Upvotes: 2

Related Questions