I appended functions 'gatherargs' and 'opsubstif' to 'opsubst.lisp.'
Here is a function (unredacted) that crunches linear combinations of
Bessel functions.
load("opsubst");
/* A function identity for Bessel functions. */
bessel_reduce_order : bessel_j = lambda([n,x], (2 * n -1) * bessel_j(n-1,x)
/ x - bessel_j(n-2,x));
besselcrunch(e) := block([ords, minord, maxord, prd, n : ?gensym()],
e : expand(e),
ords : map('first, gatherargs(e,bessel_j)),
minord : lmin(ords),
maxord : lmax(ords),
if maxord - minord < 2 then e else (
prd : buildq([n,minord], lambda([n,x], n >= minord + 2)),
besselcrunch(opsubstif(bessel_reduce_order, prd, e))));
Examples:
(%i5)
besselcrunch((-(1+2*n)*bessel_j(n,x))/x+bessel_j(1+n,x)+bessel_j(n-1,x))
(%o5) 0
(%i6)
besselcrunch((-29*bessel_j(14,y+x))/(y+x)+bessel_j(15,y+x)+bessel_j(13,y+x))
(%o6) 0
(%i7) besselcrunch(bessel_j(4,x^2)+bessel_j(3,x^2)+bessel_j(1,x^2))
(%o7) (7*bessel_j(3,x^2))/x^2+(5*bessel_j(2,x^2))/x^2-bessel_j(2,x^2)
Barton