## C’est une pipe for Maxima

I really love the pipe operator \$>\$ introduced into R by the package magrittr.  Not least because of the reference to the piece pictured here — “The Treachery of Images” by the Belgian surrealist painter René Magritte.

I don’t know yet whether this will be a really useful Maxima feature, but it is easy enough to make a simple pipe operation using infix():

infix("%>%",1,1);
"%>%" (a,b):=b(a);

Notice the 2nd and 3rd arguments of infix() control the precedence of operations (the left and right hand binding powers lbp and rbp).  We want to set those values lower than lbp and rbp for multiplication * in 2*%pi  and for for addition + in 1+%i (which by default in Maxima have lbp=180 and rbp=180).  Here’s the maxima document that gives the details about operators and binding power.

To make the pipe idea slightly more powerful so as to work with functions like integrate() and diff() which require more than one argument, we could try something like this, which makes use of the matlab-like find() I wrote about recently.

infix("%>%",1,1);
"%>%" (a,b):=block([i,bb],
if atom(b) then
b(a)
else (
i:find(b=%P),
bb:append(firstn(b,i[1]-1),[a],rest(b,i[1])),
apply(first(bb),rest(bb,1))
)
);

Note that we’ve introduced the convention that the piped expression is referred to as %P, and that we call functions using a lisp-like construction where diff(%P,x) becomes [diff,%P,x].

## A MATLAB-like find() function for Maxima

In MATLAB, you can find the indices of array entries that match a user-supplied condition with the function find()

Here’s a similar function in Maxima.  This makes liberal use of the functions sublist_indices()lambda(),  and several functions from the stringproc package: sequal()eval_string(), and simplode().  Oh, and also the shameless hack of using ascii(32) as the space character 🙂

Here are some examples.  The code is included at the bottom.

find(exp):=block(
oo:op(exp),
if sequal(oo,"=") or sequal(oo,">") or sequal(oo,">=") or sequal(oo,"<") or sequal(oo,"<=") or sequal(oo,"#") then
sublist_indices(first(exp),lambda([x1],eval_string(simplode([x1,op(exp),last(exp)]))))
else
if sequal(oo,"and") or sequal(oo,"or") then(
e1:first(exp),
e2:second(exp),
sublist_indices(first(e1),lambda([x1],
eval_string(simplode([x1,op(e1),last(e1),ascii(32),oo,ascii(32),x1,op(e2),last(e2)]))))
)
)\$

## Two little list utilities for MATLAB-like array indexing

I grew up with MATLAB, where extracting a subset of a vector V was easy as feeding a vector of indices into a vector.  For example entries i thru j could be had with V(i:j) and an more complicated index scheme could be accomplished with a vector of indices i_index and then V(i_index).

In Maxima, first(), last(), firstn(), rest(), and most generally makelist() allows for all that and more but with a little more cumbersome calling protocols.  Here are one-liners that achieve something like the two canonical MATLAB examples above:

## A maxima function to replicate MATLAB diff() and an efficiency comparison

I needed a function to compute a list containing the difference between adjacent entries in another list, as diff() does for an array in MATLAB.

I first wrote  something using makelist() and found it very slow for large lists.  I then rewrote the function using rest() and found it much faster:

## An improved Maxima function for inverse Laplace transform

Maxima has a fairly serviceable Laplace transform utility built-in.  Here’s an example from the popular ordinary differential equations book by Blanchard, Devaney and Hall:

Trouble arises when we look at discontinuous forcing functions, which is especially sad because it seems to me that’s what makes it worthwhile to spend time with Laplace transforms.  In particular, the inverse transform function ilt() fails on the Heaviside Function and Dirac Delta, even though the built-in laplace() treats them correctly:

So, I’ve written an alternative inverse Laplace function laplaceInv() that fixes that problem:

Here are a few differential equation solutions to show how the new function behaves:

A second-order linear equation with a constant forcing function that vanishes at $t=7$

A second-order equation with two impulsive forces: