1 /* Gosper form routine */
3 /* RISC Institite, Linz, Austria */
4 /* by Fabrizio Caruso */
7 /* List select wrt a criterion */
12 if crit(first(list)) then
13 cons(first(list),select(rest(list),crit))
15 select(rest(list),crit);
17 /* List split wrt a criterion */
18 splitList(list,crit) :=
19 block([trueList,falseList,i],
24 if crit(first(list)) then
25 trueList : endcons(first(list),trueList)
27 falseList : endcons(first(list),falseList),
30 return([trueList,falseList])
33 /* true if a given expr has a given degree */
34 degreeSelect(expr,var,deg) := is(degree(expr,var)=deg);
37 /* integer distance */
38 intDistance(expr1,expr2) := integerp(expr1-expr2);
41 /* It splits a list into a part with a given coefficient and the rest */
42 candSplit(list,coef,constCoef) :=
43 block([candRes,restRes],
48 if (first(first(list))=coef) and integerp(second(first(list))-constCoef) then
49 candRes : endcons(first(list),candRes)
51 restRes : endcons(first(list),restRes),
54 return([candRes, restRes])
59 /* It checks whether a factored expression is linear */
60 /* with integer coefficients */
61 integerLinear(expr,var) :=
62 if not(zb_operatorp(expr,"^")) then
63 is(degree(expr,var) < 2)
66 (integerp(coeff(expr,var,1)))
69 integerLinear(first(expr),var);
71 /* Separate the constant and the normalized part of an integer linear*/
72 intLinConstSep(intLin) :=
73 block([i,intLinRes,constRes],
76 for i : 1 thru length(intLin) do
78 intLinRes : endcons(first(part(intLin,i)),intLinRes),
79 constRes : constRes * second(part(intLin,i))
81 return([intLinRes, constRes])
86 block([i,intLinRes,constRes],
89 for i : 1 thru length(intLin) do
91 intLinRes : endcons(first(part(intLin,i)),intLinRes),
92 constRes : constRes * second(part(intLin,i))
94 return([intLinRes, constRes])
98 makeGosperForm(expr,k) :=
99 makeGosperFormVerboseOpt(expr,k,nonvernose);
101 makeGosperFormVerboseOpt(expr,k,mode) :=
102 first(makeGosperFormPrHypCheckVerboseOpt(expr,k,mode));
104 makeGosperPrHypCheck(expr,k) :=
105 makeGosperFormPrHypCheckVerboseOpt(expr,k,nonverbose);
107 /* Check Gosper's condition */
108 /* We are assuming that the input is factored */
109 /* into irreducible factors */
111 /* The numerator is q(k) and the denominator is r(k) */
112 makeGosperFormPrHypCheckVerboseOpt(expr,k,mode) :=
114 /* Local variables */
115 [num,den,numList,denList,lengthNumList,lengthDenList,
117 i__,j,h,minExp,pulledPoly,pPoly,curExp,compPoly,formSign,
118 p,q,r,pList,qList,rList,
119 negNumFlag,negDenFlag,
120 intLinNum,nonIntLinNum,intLinDen,nonIntLinDen,
121 sepNumList,sepDenList,
122 constIntLinNum, constIntLinDen, constSep,
123 normIntLinNum, normNonIntLinNum, normIntLinDen, normNonIntLinDen,
125 numExp,denExp,diff,candListSplit,item,hyp_flag, candNumList, candDenList, intLinNumConst, intLinDenConst, nonIntLinNumConst, nonIntLinDenConst],
129 return([[1,1,1],true]),
132 num:factor(num(expr)),
133 den:factor(denom(expr)),
139 if mode>= verbose then
145 negNumFlag : zb_operatorp(num,"-"),
146 negDenFlag : zb_operatorp(den,"-"),
153 if (negNumFlag and not(negDenFlag))or(not(negNumFlag) and negDenFlag) then
163 sepNumList:intLinSep(num,k),
164 sepDenList:intLinSep(den,k),
166 if mode >= verbose then
168 print("sepNumList : ", sepNumList),
169 print("sepDenList : ", sepDenList)
172 nonIntLinNum : first(sepNumList),
173 intLinNum : second(sepNumList),
174 nonIntLinDen : first(sepDenList),
175 intLinDen : second(sepDenList),
184 if numList # [] or denList # [] then
187 /* Non-integer linear computation */
189 numList : normList(nonIntLinNum,k),
190 denList : normList(nonIntLinDen,k),
192 if mode>= verbose then
194 print("numList : ", numList),
195 print("denList : ", denList)
198 constSep : constSep(numList),
199 normNonIntLinNum : constSep[1],
200 nonIntLinNumConst : constSep[2],
201 if mode>= verbose then
203 print("normIntLinNum : ", normNonIntLinNum),
204 print("intLinNumConst : ", nonIntLinNumConst)
207 constSep : constSep(denList),
208 normNonIntLinDen : constSep[1],
209 nonIntLinDenConst : constSep[2],
210 if mode>= verbose then
212 print("normIntLinDen : ", normNonIntLinDen),
213 print("nonIntLinDenConst : ", nonIntLinDenConst)
216 q : q * nonIntLinNumConst,
217 r : r * nonIntLinDenConst,
219 numList : normNonIntLinNum,
220 denList : normNonIntLinDen,
222 /* entering outer loop */
224 if mode >= verbose then
225 print("denList : ", denList),
226 unless ((numList = []) or (denList = [])) do
228 denItem : first(denList),
229 if mode >= verbose then
230 print("denItem : ", denItem),
231 candListSplit : splitList(numList,
232 lambda([x],degreeSelect(x,k,degree(first(denList),k)))
235 candListSplit : splitList(numList,
236 lambda([x],degreeSelect(x,k,degree(first(denItem),k)))
240 candNumList : first(candListSplit),
242 numList : second(candListSplit),
244 candListSplit : splitList(denList,
245 lambda([x],degreeSelect(x,k,degree(first(denList),k)))
248 candListSplit : splitList(denList,
249 lambda([x],degreeSelect(x,k,degree(first(denItem),k)))
254 candDenList : first(candListSplit),
255 denList : second(candListSplit),
260 unless candDenList = [] do
262 denItem : first(candDenList),
263 tempList : candNumList,
265 unless tempList = [] do
269 shiftRes : resultant(norm2polyPower(first(tempList)),
270 expand(subst(k+j,k,norm2polyPower(denItem))),k),
271 if mode >= very_verbose then
272 print("shiftRes : ", shiftRes),
274 factList : poly2list(factor(shiftRes)),
276 intFactList : first(splitList(factList, lambda([y],integerLinear(y,j)and degree(y,j)>0))),
278 solList : makelist(second(first(solve(part(intFactList,i),j))),i,1,length(intFactList)),
280 intSolList : first(splitList(solList,lambda([y],integerp(y) and (y>=0)))),
282 if intSolList # [] then
284 minSol : apply(min,intSolList),
286 numExp : second(first(tempList)),
287 denExp : second(denItem),
288 minExp : min(numExp,denExp),
290 if numExp = denExp then
292 p : p * product(norm2polyPower(subst(k+j,k,denItem)),j,0,minSol-1),
300 item : [first(denItem),minExp],
302 p : p * product(norm2polyPower(subst(k+j,k,item)),j,0,minSol-1),
304 if numExp > denExp then
306 candNumList : endcons([first(first(tempList)),numExp-minExp],candNumList),
312 denItem : [first(denItem), denExp-minExp],
313 tempList : rest(tempList)
319 if mode>= verbose then
320 print("no positive integer solutions"),
321 candNumList : endcons(first(tempList),candNumList),
322 tempList : rest(tempList)
326 r : r * norm2polyPower(denItem),
327 candDenList : rest(candDenList)
331 /* end of inner loop */
332 q : q * product(norm2polyPower(part(candNumList,i__)),i__,1,length(candNumList))
335 /* end of outer loop */
336 if mode>= verbose then
338 print("numList : ", numList),
339 print("denList : ", denList)
342 q : q * product(norm2polyPower(part(numList,i__)),i__,1,length(numList)),
344 r : r * product(norm2polyPower(part(denList,i__)),i__,1,length(denList)),
346 if mode>= verbose then
353 /* Integer linear computation */
355 numList : intLinNormList(intLinNum,k),
357 numList : sort(numList),
359 denList : intLinNormList(intLinDen,k),
361 denList : sort(denList),
363 constSep : intLinConstSep(numList),
364 normIntLinNum : constSep[1],
365 intLinNumConst : constSep[2],
366 if mode>= verbose then
368 print("normIntLinNum : ", normIntLinNum),
369 print("intLinNumConst : ", intLinNumConst)
372 constSep : intLinConstSep(denList),
373 normIntLinDen : constSep[1],
374 intLinDenConst : constSep[2],
375 if mode>= verbose then
377 print("normIntLinDen : ", normIntLinDen),
378 print("intLinDenConst : ", intLinDenConst)
381 numList : normIntLinNum,
382 denList : normIntLinDen,
384 lengthNumList:length(numList),
385 lengthDenList:length(denList),
387 unless ((numList = []) or (denList = [])) do
389 denItem : first(denList),
391 /* This is an adaptation of Schorn-Riese's Mathematica code */
393 if mode>= verbose then
395 print("denItem : ", denItem),
396 print("numList : ", numList),
397 print("denList : ", denList)
401 candListSplit : splitList(numList,
402 lambda([x],intDistance(first(x),first(denItem)))),
404 if mode>= verbose then
405 print("num) candListSplit : ", candListSplit),
408 candNumList : first(candListSplit),
410 numList : second(candListSplit),
411 candListSplit : splitList(denList,
412 lambda([x],intDistance(first(x),first(denItem)))),
414 if mode>= verbose then
415 print("den) candListSplit : ", candListSplit),
418 candDenList : first(candListSplit),
420 denList : second(candListSplit),
423 unless ((candNumList = []) or (candDenList = [])) do
426 diff : first(first(candNumList))-first(first(candDenList)),
427 if mode>= verbose then
429 print("diff : ", diff),
430 print("inner cycle) candNumList : ", candNumList),
431 print("inner cycle) candDenList : ", candDenList)
433 if not(integerp(diff)) or (integerp(diff) and (diff<0)) then
435 /* q must be updated here */
436 /* Gosper-condition satisfied */
438 q : q * norm2polyPower(first(candNumList)),
439 candNumList : rest(candNumList)
443 /* Gosper-condition NOT satisfied */
444 /* p must be updated here */
445 numExp:second(first(candNumList)),
446 denExp:second(first(candDenList)),
447 minExp:min(numExp,denExp),
449 p : p * product(subst(k+i__,k,norm2intLin(first(candDenList),k)^minExp),i__,0,diff-1),
450 if mode>= verbose then
451 print("p computed : ", p),
452 if(numExp>denExp) then
454 item : [first(first(candNumList)),numExp-minExp],
456 candNumList : cons(item,rest(candNumList)),
458 candDenList : rest(candDenList)
461 if(numExp<denExp) then
463 item : [first(first(candDenList)),denExp-minExp],
464 candNumList : rest(candNumList),
465 candDenList : cons(item,rest(candDenList))
469 candNumList : rest(candNumList),
470 candDenList : rest(candDenList)
474 ), /* end inner unless cycle */
476 /* out of inner cycle */
478 if (candNumList # []) then
479 q : q * product(norm2polyPower(part(candNumList,i__)),i__,1,length(candNumList)),
482 if(candDenList # []) then
483 r : r * product(norm2polyPower(part(candDenList,i__)),i__,1,length(candDenList))
487 if (numList # []) then
488 q : q*product(norm2polyPower(part(numList,i__)),i__,1,length(numList)),
490 if (denList # []) then
491 r : r*product(norm2polyPower(part(denList,i__)),i__,1,length(denList)),
496 return([[p,q*formSign*intLinNumConst,r*intLinDenConst],hyp_flag])
504 makeGosperForm(expr,var) ::=
505 buildq([expr,var],makeGosperFormVerboseOpt(expr,var,nonverbose));
507 makeGosperFormVerbose(expr,var) ::=
508 buildq([expr,var],makeGosperFormVerboseOpt(expr,var,verbose));
513 /* Macro that extracts p out of the Gosper form */
514 takeP(GosperForm) ::=
515 buildq([GosperForm],first(GosperForm));
518 /* Macro that extracts q out of the Gosper form */
519 takeQ(GosperForm) ::=
520 buildq([GosperForm],second(GosperForm));
523 /* Macro that extracts r out of the Gosper form */
524 takeR(GosperForm) ::=
525 buildq([GosperForm],third(GosperForm));