1 /* Gosper's algorithm */
3 /* RISC Institute, Linz, Austria */
4 /* by Fabrizio Caruso */
8 /* makeGosperForm2.macsyma */
9 /* poly2quint.macsyma */
10 /* GosperEq2.macsyma */
11 /* AlgUtil2.macsyma */
15 /* PREPROCESSING ROUTINES */
18 /* Preprocessing function "fRat" */
19 simpleFRatSlow(f,k) :=
21 factor((subst(k+1,k,f)/f)));
23 simpleFRatFast(f,k) :=
26 simpleFRat(f,k) := simpleFRatFast(f,k);
31 factor(expand(num(xthru(minfactorial(makefact(simpleFratSlow(f,k))))))/
32 expand(denom(xthru(minfactorial(makefact(simpleFratSlow(f,k))))))));
36 factor(expand(num(xthru(minfactorial(makefact(simpleFratFast(f,k))))))/
37 expand(denom(xthru(minfactorial(makefact(simpleFratFast(f,k)))))));
40 factor(expand(num(xthru(minfactorial(makefact(simpleFratFast(f,k))))))/
41 expand(denom(xthru(minfactorial(makefact(simpleFratFast(f,k)))))));
45 fRat(f,k) := fRatFast(f,k);
48 /* Postprocessing function that computes the rational function "certificate" */
49 telescope(Gsol,p,r,k) :=
52 /* Postprocessing function that computes the rational function "certificate" */
53 telescopeSimplified(Gsol,p,r,k) :=
57 /* Postprocessing function that computes the rational function "certificate" */
58 /* This is correct because we are telescoping w.r.t. a linear operator applied */
59 /* to the original function f , i.e. lin.op.(f) = (numNF/denNF)*f */
60 /* We telescoping solution is (r/p)*Gsol*(numNF/denNF)*f = */
61 /* = (r/gfP*numNF)*Gsol*(numNF/denNF) = (r*GSol)/(gfP*denNF) */
62 zTelescope(GSol,gfP,r,denNF) :=
65 /* Postprocessing function that computes the rational function "certificate" */
66 zTelescopeSimplified(GSol,gfP,r,denNF) :=
67 r*Gsol/(gfP*denNF); /* BOGUS */
70 printGosperSummary(fRat,GosperForm,AnsatzDegree,Gpoly,GosperSol,mode) :=
72 print("--------------------------------"),
73 print("Gosper-related summary"),
74 print("(1) fRat : " , fRat),
75 print("(2) Gosper form : ", GosperForm),
76 print("(3) AnsatzDegree : ", AnsatzDegree),
77 print("(4) Gosper polynomial : " , Gpoly),
78 if mode>= verbose then
79 print("(5) Gosper solution : ", GosperSol)
84 /* GOSPER'S ALGORITHM - Main routine - verbose */
85 GosperVerboseOpt(f,k,mode) :=
101 /* Computation of the shift quotient */
102 fRat : shiftQuoOnlyHyp(factor(f),k), /* factor might not be necessary */
106 print(f, " is not hypergeometric in ", k),
107 return(NON_HYPERGEOMETRIC)
110 if mode>=verbose then
111 print("Shift quotient computed! : " , fRat),
114 /* Computation of the Gosper form */
115 GosperForm: makeGosperFormVerboseOpt(factor(fRat),k,mode-1), /* factor ? */
117 if GosperForm = NON_HYPERGEOMETRIC then
119 print(f, " is not proper hypergeometric in ", k),
120 return(NON_HYPERGEOMETRIC)
123 p: takeP(GosperForm),
124 q: takeQ(GosperForm),
125 r: takeR(GosperForm),
126 if mode>=verbose then
127 print("p,q,r have been extracted! p: ", p, ", q: ", q, ", r: ", r),
129 /* Solution of the Gosper equation */
130 AnsatzDegree: AnsatzDegreeVerboseOpt(p,q,r,k,mode-1),
132 if mode>=verbose then
133 print("Ansatz degree computed ! : " , AnsatzDegree),
137 if AnsatzDegree >= 0 then
138 Gpoly: expand(GosperPoly(p,q,r,k,c,AnsatzDegree)),
139 if mode>=verbose then
140 print("Gosper polynomial created! : " , Gpoly),
144 sysSol: SolveSysVerboseOpt(Gpoly,c,AnsatzDegree+1,k,mode-1),
146 if mode>=very_verbose then
147 print("System of equations solved! : " , sysSol),
148 GosperSol: Gsol2Poly(first(sysSol),k),
149 if mode>=verbose then
150 print("Gosper solution created! : " , GosperSol),
152 if mode>=summary then
153 printGosperSummary(fRat,GosperForm,AnsatzDegree,Gpoly,GosperSol,mode-1),
156 /* Postprocessing : building the sol. to the telesc. probl. */
157 if GosperSol = 0 then
160 tlscope: telescope(GosperSol,p,r,k),
163 if simplified_output then
164 return(ratsimp(tlscope))
170 /* Macro for the normal verbose Gosper algorithm */
171 GosperVerbose(f,k) ::=
173 GosperVerboseOpt(f,k,verbose));
175 /* Macro for the very verbose Gosper algorithm */
176 GosperVeryVerbose(f,k) ::=
178 GosperVerboseOpt(f,k,very_verbose));
183 GosperVerboseOpt(f,k,extra));
185 /* Macro for the summary version of the Gosper algorithm */
186 GosperSummary(f,k) ::=
188 GosperVerboseOpt(f,k,summary));
191 /* Short name for the non verbose mode */
194 GosperVerboseOpt(f,k,nonverbose));
196 /* ----------------------------------------------------------------------- */
197 /* Anti-difference : It finds the anti-difference of a hypergeometric term */
199 AntiDifferenceVerboseOpt(f,k,mode) :=
201 gSol : GosperVerboseOpt(f,k,mode),
202 if gSol=NO_HYP_SOL then
203 return(NO_HYP_ANTIDIFFERENCE)
205 if gSol=NON_HYPERGEOMETRIC then
206 return(NON_HYPERGEOMETRIC)
208 if simplified_output then
209 return(factor(f*gSol))
215 AntiDifference(f,k) :=
216 AntiDifferenceVerboseOpt(f,k,nonverbose);
218 AntiDifferenceSummary(f,k) :=
219 AntiDifferenceVerboseOpt(f,k,summary);
221 AntiDifferenceVerbose(f,k) :=
222 AntiDifferenceVerboseOpt(f,k,verbose);
224 AntiDifferenceVeryVerbose(f,k) :=
225 AntiDifferenceVerboseOpt(f,k,very_verbose);
227 AntiDifferenceExtra(f,k) :=
228 AntiDifferenceVerboseOpt(f,k,extra);
231 /* ------------------------------------------------------------------ */
232 /* Gosper Sum : It sums Gosper-summable hypergeometric terms */
234 /* Gosper summation function - Summary mode */
235 GosperSumVerboseOpt(f,k,a,b,mode) :=
239 antiDiff:AntiDifferenceVerboseOpt(f,k,mode),
240 if antiDiff=NO_HYP_ANTIDIFFERENCE then
241 return(NON_GOSPER_SUMMABLE)
243 if antiDiff=NON_HYPERGEOMETRIC then
244 return(NON_HYPERGEOMETRIC)
247 if mode>= verbose then
248 print("Anti-difference : ", antiDiff),
249 return(subst(b+1,k,antiDiff)-subst(a,k,antiDiff))
253 /* Gosper summation function */
254 GosperSum(f,k,a,b) :=
255 GosperSumVerboseOpt(f,k,a,b,nonverbose);
258 /* Gosper summation function - Summary mode */
259 GosperSumSummary(f,k,a,b) :=
260 GosperSumVerboseOpt(f,k,a,b,summary);
262 GosperSumVerbose(f,k,a,b) :=
263 GosperSumVerboseOpt(f,k,a,b,verbose);
265 GosperSumVeryVerbose(f,k,a,b) :=
266 GosperSumVerboseOpt(f,k,a,b,very_verbose);
268 GosperSumExtra(f,k,a,b) :=
269 GosperSumVerboseOpt(f,k,a,b,extra);