# [Maxima] complex function works only after defining it twice

Barton Willis willisb at unk.edu
Thu May 15 15:43:19 CDT 2008

```Try something like this:

(%i3) error(f) := block([listconstvars : false, var, acc : 0],
var : listofvars(f),
for x in var do
acc : acc + diff(f,x) * concat('delta_,x),
acc)\$
(%i4) error(x^2 - y^2 + %pi);
(%o4) 2*delta_x*x-2*delta_y*y

I didn't try to find the bug in your code --- I'm off to an appointment.
This code doesn't work for things like depends(v,x), error(v). Another
thing:  "error" is a Maxima function -- overwriting it with your definition
can cause trouble.

welcome to Maxima.

Barton

-----maxima-bounces at math.utexas.edu wrote: -----

>To: maxima at math.utexas.edu
>From: Christoph Sarnowski <pixelbrei at h3c.de>
>Sent by: maxima-bounces at math.utexas.edu
>Date: 05/15/2008 03:12PM
>Subject: [Maxima] complex function works only after defining it twice
>
>First of all i want to say hello, as i am new to this mailing list,
>and new to maxima.
>
>I have defined a (programming) function, which take a mathematical
>function as an argument, and should give me a new (mathematical)
>function:
>
>
>-8<-------------------------------------
>/* the error is defined as
>
>                     | df |             | df |
>error(f(x,y, ...)) = | -- | * delta_x + | -- | * delta_y + ...
>                     | dx |             | dy |
>
>and is a function of all arguments to f() plus all deltas of its
>arguments:
>df(x, y, ...., dx, dy, ...) */
>error(fun, ret) :=
>block(
>  [
>  dep:dependencies,
>  N:length(dependencies),
>  vars:[],
>  all_vars:[],
>  dvars:[],
>  num_vars,
>  reservoir: [d1, d2, d3, d4, d5, d6, d7, d8, d9, d10]
>  ],
>  /* find out what arguments fun() takes via dependencies */
>  (for i:1 step 1 while i<=N
>    do     if (part(dep[i], 0) = fun) then
>    (for j:1 thru length(dep[i])
>      do (vars: cons(part(dep[i], j), vars)))),
>  vars: reverse(vars),
>  num_vars:length(vars),
>
>  /* define delta-parameter list */
>  (for i:1 thru num_vars
>    do dvars: cons(reservoir[i], dvars)),
>  dvars: reverse(dvars),
>
>  /* argument list for the error function contains
>     all of the arguments of the original function
>     plus all the deltas of those arguments */
>  all_vars: append(vars, dvars),
>
>  ret_f: funmake(ret, all_vars),
>  temp_f: funmake(tempfunc, all_vars),
>  fun_f: funmake(fun, vars),
>  pt_f: funmake(pt, vars),
>
>  /* initialize ret(...) */
>  define(''ret_f, 0),
>  /* main stuff, construct error function */
>  (for i:1 thru num_vars
>    do (
>      define(''pt_f, ''diff(''fun_f, vars[i])),
>      define(''temp_f, ''ret_f), /* save current return function */
>      define(''ret_f, abs( ''pt_f)*dvars[i] + ''temp_f))), /* add the new
>partdiff */
> ''ret_f);
>-8<------------------------------------
>
>I hope, with the comments, you understand what i am trying to do.
>It is (at least for me :) ) not a simple task, as it should work with
>any function (of any argument count, with my "reservoir" it is limited
>to 10 args...).
>
>The behaviour of the code above is as follows (i have it in a file,
>partdiff.max):
>
>(%o1)            /home/pixelbrei/projects/maxima/partdiff.max
>/* first definition of the function */
>
>(%i2) v(x):=x^2;
>                                           2
>(%o2)                             v(x) := x
>(%i3) depends(v, x);
>(%o3)                               [v(x)]
>/* define a trivial example function, and inform maxima of the
>dependencies */
>
>
>(%i4) error(v, dv);
>
>Improper function definition:
>ret_f
>#0: error(fun=v,ret=dv)
> -- an error.  To debug this try debugmode(true);
>/* this is the error message it throws. */
>
>
>(%o5)            /home/pixelbrei/projects/maxima/partdiff.max
>/* i define the function a second time */
>
>(%i6) error(v, dv);
>(%o6)                             2 d1 abs(x)
>/* now it works */
>
>The second definition of the function only works, if i try to execute
>my "error" function between the two batchloads.
>As you see, i pass the name for the function i want to build as a
>second argument.
>
>So, can anyone explain why this code behaves like it does?
>And/or point me to some changes i can do to make it work the first
>time?
>