Speeding Up Maxima Functions with compile()

In my differential equations class, we implement the first-order-accurate Euler method for numerical approximation of a solution of the initial value problem y' = f(x,y) , y(x_0)=y_0.

eulerloop

We implement this in an appealing way — from an algorithm translation point of view — but the inner loop with all that list indexing takes a lot of time.   To verify the accuracy of the method, we run the function with more and more successively smaller steps.

eulermethod(f,x0,y0,h,nsteps):=block(
 [i,x,y], 
 x:makelist(0,i,1,nsteps+1,1),
 y:makelist(0,i,1,nsteps+1,1),
 x[1]:x0,
 y[1]:y0,
 for i:1 thru nsteps do (
    x[i+1]:x[i]+h,
    y[i+1]:y[i]+h*ev(f,x=x[i],y=y[i])
 ),
 return ([x,y])
)$

Below I’ve used the time() function so you can see how simply running compile() on the function makes it run lots faster for ten thousand steps!

compileeuler

The Maxima documentation says this:

Function: compile
compile (f_1, …, f_n)
compile (functions)
compile (all)

Translates Maxima functions f_1, …, f_n into Lisp, evaluates the Lisp translations, and calls the Lisp function COMPILE on each translated function. compile returns a list of the names of the compiled functions.

compile (all) or compile (functions) compiles all user-defined functions.

compile quotes its arguments; the quote-quote operator '' defeats quotation.

Compiling a function to native code can mean a big increase in speed and might cause the memory footprint to reduce drastically. Code tends to be especially effective when the flexibility it needs to provide is limited. If compilation doesn’t provide the speed that is needed a few ways to limit the code’s functionality are the following:

  • If the function accesses global variables the complexity of the function can be drastically be reduced by limiting these variables to one data type, for example using mode_declare or a statement like the following one: put(x_1, bigfloat, numerical_type)
  • The compiler might warn about undeclared variables if text could either be a named option to a command or (if they are assigned a value to) the name of a variable. Prepending the option with a single quote ' tells the compiler that the text is meant as an option.

 

Here are the specs of the machine I ran these timings on:

processorinfo