2 /* Author: Barton Willis, copyright 2022
4 Maxima code for simplifying expressions that involve sums of psi functions.
6 See LICENSE.md for licensing information.*/
8 /* We need the function gatherargs--it's in "opsubst." */
13 /* This function is inflag sensitive. */
14 mtimesp(e) := not mapatom(e) and part(e,0) = "*";
15 mplusp(e) := not mapatom(e) and part(e,0) = "+";
17 mysubst(new,old,e) := block([inflag : true, q, prederror : false,listconstvars : false],
20 print(is(equal(e,old))),
21 if equal(e,old)=true then new else e)
23 elseif isequal(e,old) then new
25 elseif mtimesp(e) then (
26 q : apply('divide, append([e, old], listofvars(old))),
27 if equal(second(q),0) then (
28 new*mysubst(new,old,first(q)))
31 elseif mplusp(e) then (
32 q : apply('divide, append([e, old], listofvars(old))),
33 if lfreeof(listofvars(old),second(q)) then (
34 first(q)*new + second(q))
36 else map(lambda([s], mysubst(new, old, s)), e));
38 make_psi_sum_id(g) := buildq([g,x : gensym(), k : gensym(),n : gensym()],
39 lambda([x,n], -g(x) + sum(1/(x+k),k,0,n-1) = g(x+n)));
41 psi_simp(e) := block([a,g : gensym(),n,fn,id],
42 e : opsubst(g, psi[0],e),
43 a : map('first, gatherargs(e,g)),
47 /* see http://dlmf.nist.gov/5.5.E2 */
48 if featurep(n,'integer) and n > 0 then (
49 fn : make_psi_sum_id(g),
51 e : mysubst(lhs(id),rhs(id), e)),
53 /* see http://dlmf.nist.gov/5.5.E8 */
54 if featurep(2*n,'integer) and n > 0 then (
55 e : mysubst(2*log(2) + 2*g(ak), g(ak)+g(bk),e)),
58 /* see http://dlmf.nist.gov/5.5.E4 */
59 if featurep(n,'integer) and n = 1 and gamma_simp_complexity(ak) < gamma_simp_complexity(bk) then (
60 e : mysubst(g(ak)+%pi/tan(%pi*ak), g(bk),e)))),
61 opsubst(psi[0],g, e));