contfrac.red 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503
  1. module contfrac; % Continued fractions.
  2. % Author: Lisa Temme
  3. % Date: August 1995.
  4. % Code to check for rational polynomials.
  5. % polynomials and rational functions
  6. % by Winfried Neun
  7. symbolic procedure PolynomQQQ (x);
  8. (if fixp xx then 1 else
  9. if not onep denr (xx := cadr xx) then NIL
  10. else begin scalar kerns,kern,aa,var,fform,mvv,degg;
  11. fform := sfp mvar numr xx;
  12. var := reval cadr x;
  13. if fform then << xx := numr xx;
  14. while (xx neq 1) do
  15. << mvv := mvar xx;
  16. degg := ldeg xx;
  17. xx := lc xx;
  18. if domainp mvv then <<if not freeof(mvv,var) then
  19. << xx := 1 ; kerns := list list('sin,var) >> >> else
  20. kerns := append ( append (kernels mvv,kernels degg),kerns) >> >>
  21. else kerns := kernels !*q2f xx;
  22. aa: if null kerns then return 1;
  23. kern := first kerns;
  24. kerns := cdr kerns;
  25. if not(eq (kern, var)) and depends(kern,var)
  26. then return NIL else go aa;
  27. end) where xx = aeval(car x);
  28. put('PolynomQQ,'psopfn,'polynomQQQ);
  29. symbolic procedure ttttype_ratpoly(u);
  30. ( if fixp xx then 1 else
  31. if not eqcar (xx , '!*sq) then nil
  32. else and(polynomQQQ(list(mk!*sq (numr cadr xx ./ 1),
  33. reval cadr u)),
  34. polynomQQQ(list(mk!*sq (denr cadr xx ./ 1),
  35. reval cadr u)))
  36. ) where xx = aeval(car u);
  37. flag ('(type_ratpoly),'boolean);
  38. put('type_ratpoly,'psopfn,'ttttype_ratpoly);
  39. symbolic procedure type_ratpoly(f,z);
  40. ttttype_ratpoly list(f,z);
  41. %% To combine number, rational and non-rational approaches
  42. %% (including truncated versions) include the following
  43. %% boolean returns and the cfracrules rulelist.
  44. flag ('(vari),'boolean);
  45. symbolic procedure vari(x);
  46. idp x;
  47. procedure polynomialp(u,x);
  48. if den u = 1 and (freeof (u,x) or deg(u,x) >= 1 ) then t else nil;
  49. flag ('(polynomialp),'boolean);
  50. algebraic;
  51. operator cfrac;
  52. operator contfrac;
  53. procedure a_constant (x);
  54. lisp constant_exprp (x);
  55. cfracrules :=
  56. { cfrac (~x) => (begin scalar cf, pt2, q, res;
  57. cf := continued_fraction x;
  58. pt2 := part(cf,2);
  59. res := for q := 2:(length pt2)
  60. collect append({1},{part(pt2,q)});
  61. return contfrac(part(cf,1),
  62. append({part(pt2,1)},res));
  63. end)
  64. when a_constant(x),
  65. cfrac (~x,~s) => (begin scalar kk, cf, cf1, pt2, cf2, cf3,
  66. bs, m, p, q, res;
  67. cf := continued_fraction(x);
  68. pt2 := part(cf,2);
  69. if s>=length(part(cf,2))
  70. then
  71. << cf1 :=
  72. for q:=2:(length pt2)
  73. collect append({1},{part(pt2,q)});
  74. res := contfrac(part(cf,1),
  75. append({part(pt2,1)},cf1));
  76. >>
  77. else
  78. << cf2 :=
  79. for kk:=1:s+1
  80. collect part(pt2,kk);
  81. bs := part(cf2,s+1);
  82. for m:= s step -1 until 1
  83. do bs := part(cf2,m)+1/bs;
  84. cf3 :=
  85. for p:=2:(length cf2)
  86. collect append({1},{part(cf2,p)});
  87. res:=contfrac(bs,append({part(cf2,1)},cf3))
  88. >>;
  89. %% res := continued_fraction(x,s);
  90. return res;
  91. end)
  92. when a_constant(x) and numberp s,
  93. cfrac (~x,~s) => (begin scalar cf, pt2, q, r, res;
  94. cf := cfracall(x,s);
  95. pt2 := part(cf,2);
  96. if type_ratpoly(x,s)
  97. then
  98. <<res :=
  99. for r:=2:(length pt2)
  100. collect append({1},{part(pt2,r)})
  101. >>
  102. else
  103. <<res :=
  104. for q:=2:(length pt2)
  105. collect list(num(part(pt2,q)),
  106. den(part(pt2,q)))
  107. >>;
  108. return contfrac(part(cf,1),
  109. append({part(pt2,1)},res));
  110. end)
  111. when not numberp x and vari s,
  112. cfrac(~a,~b,~c) => (begin scalar cf, pt2, q, res;
  113. cf := cfrac_ratpoly(a,b,c);
  114. pt2 := part(cf,2);
  115. res :=
  116. for q:=2:(length pt2)
  117. collect append({1},{part(pt2, q)});
  118. return contfrac(part(cf,1),
  119. append({part(pt2,1)},res));
  120. end)
  121. when numberp c and vari b
  122. and type_ratpoly(a,b),
  123. cfrac(~a,~b,~c) => (begin scalar cf, pt2, q, res;
  124. cf := cfrac_nonratpoly(a,b,c);
  125. pt2 := part(cf, 2);
  126. res :=
  127. for q:=2:length(pt2)
  128. collect list(num(part(pt2,q)),
  129. den(part(pt2,q)));
  130. return contfrac(part(cf,1),
  131. append({part(pt2,1)},res));
  132. end)
  133. when numberp c and vari b
  134. and NOT(type_ratpoly(a,b))%,
  135. };
  136. let cfracrules;
  137. % LOAD Taylor Package for non-rationals
  138. load taylor;
  139. %INPUT my code for rational polynomials
  140. procedure cfracall(rat_poly,var);
  141. begin
  142. scalar top_poly, bot_poly, euclidslist, ld_return;
  143. if type_ratpoly(rat_poly,var)
  144. then
  145. << top_poly := num rat_poly;
  146. bot_poly := den rat_poly;
  147. euclidslist := {};
  148. while part(longdiv(top_poly, bot_poly, var),2) neq 0 do
  149. <<
  150. ld_return := longdiv(top_poly, bot_poly, var);
  151. top_poly := bot_poly;
  152. bot_poly := part(ld_return,2);
  153. euclidslist := part(ld_return,1).euclidslist;
  154. >>;
  155. euclidslist := part(longdiv(top_poly, bot_poly, var),1)
  156. . euclidslist;
  157. return list(inv_cfracall(reverse(euclidslist)),
  158. reverse(euclidslist));
  159. >>
  160. else
  161. << return cfrac_nonratpoly(rat_poly,var,5)
  162. >>;
  163. end;
  164. %************
  165. %INPUT my code for rational polynomials (truncated)
  166. procedure cfrac_ratpoly(rat_poly,var,number);
  167. begin
  168. scalar top_poly, bot_poly, euclidslist, ld_return, k;
  169. if type_ratpoly(rat_poly,var)
  170. then
  171. << top_poly := num rat_poly;
  172. bot_poly := den rat_poly;
  173. euclidslist := {};
  174. k:=number; %-1;
  175. while part(longdiv(top_poly, bot_poly, var),2) neq 0
  176. and k neq 0
  177. do
  178. <<
  179. ld_return := longdiv(top_poly, bot_poly, var);
  180. top_poly := bot_poly;
  181. bot_poly := part(ld_return,2);
  182. euclidslist := part(ld_return,1).euclidslist;
  183. k := k-1;
  184. >>;
  185. euclidslist := part(longdiv(top_poly, bot_poly, var),1)
  186. . euclidslist;
  187. return list(inv_cfracall(reverse(euclidslist)),
  188. reverse(euclidslist));
  189. >>
  190. else
  191. << return cfrac_nonratpoly(rat_poly,var,number)
  192. >>;
  193. end;
  194. procedure longdiv(poly1, poly2,x);
  195. begin
  196. scalar numer, denom, div, div_list, elmt, flag, rem, answer;
  197. %longdiv called by cfracall so poly2 will never be zero.
  198. %on rounded;
  199. numer := poly1;
  200. denom := poly2;
  201. div_list := {};
  202. div := 0;
  203. flag := 0;
  204. answer := 0;
  205. if longdivdeg(numer,x) < longdivdeg(denom,x)
  206. then rem := numer
  207. else
  208. <<
  209. while (longdivdeg(numer,x) >= longdivdeg(denom,x)) AND flag neq 1 do
  210. <<
  211. if longdivlterm(numer,x) = 0
  212. then
  213. << div := numer/denom;
  214. rem :=0;
  215. flag :=1;
  216. >>
  217. else
  218. << div := longdivlterm(numer,x)/longdivlterm(denom,x);
  219. numer := numer - denom*div;
  220. rem := numer;
  221. >>;
  222. div_list := div.div_list;
  223. >>;
  224. answer := for each elmt in div_list sum elmt;
  225. >>;
  226. return list(answer,rem)
  227. end;
  228. procedure longdivdeg(i_p,i_p_var);
  229. begin scalar a;
  230. a:= if numberp(den(i_p))
  231. then deg(i_p*den(i_p),i_p_var);
  232. return a
  233. end;
  234. procedure longdivlterm(i_p,i_p_var);
  235. begin scalar b;
  236. b := if numberp(den(i_p))
  237. then lterm(den(i_p)*i_p,i_p_var)/den(i_p);
  238. return b
  239. end;
  240. %****************
  241. %Check for a polynomial
  242. %% flag ('(type_poly),'boolean);
  243. %% put('type_poly,'psopfn,'PolynomQQQ);
  244. %INPUT my code for non-rationals
  245. procedure cfrac_nonratpoly(nonrat,x,n);
  246. begin
  247. scalar hh,g, a_0, a_1, coeff_list, flag1, flag2,
  248. k, j, h, oneplus, xover;
  249. g := taylor(nonrat,x,0,2*n);
  250. h := 1;
  251. k:=n;
  252. if taylorp(taylortostandard g)
  253. then rederr "not yet implemented"
  254. else
  255. <<
  256. %%CHANGE TO: if not type_poly then ERROR
  257. %Include error here so that COEFF can be used in while condition
  258. if not type_ratpoly(taylortostandard g,x)
  259. or (type_ratpoly(taylortostandard g,x) and
  260. not(freeof(den(taylortostandard g),x)))
  261. then
  262. rederr "not yet implemented";
  263. while (length(coeff(taylortostandard g, x)) >1 and k>=0) do %0) do
  264. <<
  265. %%CHANGE TO: if not type_poly then ERROR
  266. %Include error here so that each time a new "g" is generated
  267. % it will be checked to see if it is a polynomial
  268. if not type_ratpoly(taylortostandard g,x)
  269. or (type_ratpoly(taylortostandard g,x) and
  270. not(freeof(den(taylortostandard g),x)))
  271. then
  272. rederr "not yet implemented";
  273. a_0 := first coeff(taylortostandard g, x);
  274. a_1 := second coeff(taylortostandard g, x);
  275. if flag1 =0
  276. then
  277. << coeff_list := {a_0};
  278. flag1 := 1;
  279. >>
  280. else
  281. << if a_1 neq 0
  282. then
  283. << g := taylorcombine(a_1*taylor(x^h,x,0,2*n)/(g - a_0));
  284. coeff_list := (a_1*x^h).coeff_list;
  285. >>
  286. else
  287. << j := 2;
  288. while j <= length coeff(taylortostandard g, x)
  289. and flag2=0 do
  290. <<
  291. if coeffn(taylortostandard g, x, j) neq 0
  292. then << a_n := coeffn(taylortostandard g, x, j);
  293. flag2 := 1;
  294. >>
  295. else j := j+1;
  296. >>;
  297. coeff_list := (a_n*x^j).coeff_list;
  298. g := taylorcombine(a_n*taylor(x^j,x,0,2*n)/(g - a_0));
  299. flag2 := 0;
  300. h := j
  301. >>;
  302. >>;
  303. k := k-1;
  304. >>;
  305. %% %"1+" form
  306. %% oneplus := list(inv_cfrac_nonratpoly1(reverse(coeff_list)),
  307. %% reverse(coeff_list));
  308. %"x/" form
  309. xover:= list(inv_cfrac_nonratpoly2(adaptcfrac(reverse(coeff_list))),
  310. adaptcfrac(reverse(coeff_list)));
  311. return xover %% list(oneplus,xover)
  312. >>;
  313. end;
  314. %***************
  315. %INPUT my code for different representation of cfrac_nonratpoly
  316. procedure adaptcfrac(l_list);
  317. begin
  318. scalar h, l, k, n, m, new_list;
  319. new_list := {};
  320. if length l_list < 3 then return l_list
  321. else
  322. << h := first l_list;
  323. l := second l_list;
  324. k := 2;
  325. while length l_list >= k do
  326. <<
  327. n := num l;
  328. d := den l;
  329. new_list := (n/d).new_list;
  330. k := k+1;
  331. if length l_list >= k
  332. then
  333. << l := part(l_list, k);
  334. l := d*l
  335. >>;
  336. >>;
  337. >>;
  338. return h.reverse(new_list)
  339. end;
  340. procedure inv_cfrac_nonratpoly1(c_list);
  341. begin
  342. scalar ans, j, expan;
  343. j := length c_list;
  344. if j < 3
  345. then
  346. << ans := for each m in c_list sum m;
  347. return ans;
  348. >>
  349. else
  350. << for k:=j step -1 until 2
  351. do << if k=j
  352. then expan := part(c_list,k)
  353. else expan := part(c_list,k) / (1 + expan);
  354. >>;
  355. expan := part(c_list,1) + expan;
  356. return expan
  357. >>;
  358. end;
  359. procedure inv_cfrac_nonratpoly2(c_list);
  360. begin
  361. scalar ans, j, expan;
  362. j := length c_list;
  363. if j < 3
  364. then
  365. << ans := for each m in c_list sum m;
  366. return ans;
  367. >>
  368. else
  369. << for k:=j step -1 until 2
  370. do << if k=j
  371. then expan := part(c_list,k)
  372. else expan :=
  373. num(part(c_list,k)) / (den(part(c_list,k)) + expan);
  374. >>;
  375. expan := part(c_list,1) + expan;
  376. return expan
  377. >>;
  378. end;
  379. procedure inv_cfracall(c_list);
  380. begin
  381. scalar ans, j;
  382. j := length c_list;
  383. if j=0 then return {}
  384. else
  385. << if j=1
  386. then ans := part(c_list,1)
  387. else
  388. << ans := part(c_list,j);
  389. for k:=j-1 step -1 until 1
  390. do << ans := part(c_list,k) + 1/ans >>;
  391. >>;
  392. >>;
  393. return ans
  394. end;
  395. symbolic procedure print!-contfract(x);
  396. % printing continued fractions
  397. begin scalar xx,xxx;
  398. if null !*nat or atom x or length x < 3
  399. or not eqcar(caddr x,'list)
  400. then return 'failed;
  401. xx := reverse cddr caddr x;
  402. if length xx > 12 then return 'failed;
  403. if xx then
  404. <<xxx := list('quotient ,cadr first xx,caddr first xx);
  405. for each tt in rest xx do
  406. xxx := list('quotient ,cadr tt,list('plus,caddr tt,xxx));
  407. if cadr caddr x = 0 then maprin list('list,cadr x,xxx) else
  408. maprin list('list,cadr x,list ('plus,cadr caddr x ,xxx));
  409. >> else maprin list('list,cadr x,cadr caddr x);
  410. return t;
  411. end;
  412. put('contfrac,'prifn,'print!-contfract);
  413. endmodule;
  414. end;