contfr.red 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. module contfr; % Simultaneous approximation of a real number by a
  2. % continued fraction and a rational number with optional
  3. % user controlled precision (upper bound for numerator).
  4. % Author: Herbert Melenk.
  5. symbolic procedure contfract2 (u,b1);
  6. % compute continued fraction until either numerator exceeds b1
  7. % or approximation has reached system precision.
  8. begin scalar b0,l,a,b,g,gg,ggg,h,hh,hhh;
  9. b:= u; g:=0; gg:=1; h:=1; hh:=0;
  10. if null b1 then b0:= absf !:times(b,!:expt(10,- precision 0));
  11. loop:
  12. a:=rd!-fix b;
  13. ggg:=a*gg + g;
  14. hhh:=a*hh + h;
  15. if b1 and abs hhh > b1 then goto ret;
  16. g := gg; gg:=ggg; h:=hh; hh:=hhh;
  17. l:=a.l;
  18. b:=!:difference(b,a);
  19. if null b
  20. or !:lessp(absf !:difference(!:quotient(i2rd!* gg,i2rd!* hh),u),
  21. b0)
  22. then go to ret;
  23. b:=!:quotient(1,b);
  24. go to loop;
  25. ret:
  26. return (gg . hh) . reversip l
  27. end;
  28. symbolic procedure !:lessp(u,v); !:minusp !:difference(u,v);
  29. symbolic procedure rd!-fix u;
  30. if atom cdr u then fix cdr u else ashift(cadr u,cddr u);
  31. symbolic procedure contfract1(u,b);
  32. begin scalar oldmode,v;
  33. if eqcar(v:=u,'!:rd!:) then goto c;
  34. oldmode := get(dmode!*,'dname).!*rounded;
  35. if car oldmode then setdmode(car oldmode,nil);
  36. setdmode('rounded,t); !*rounded := t;
  37. v:=reval u;
  38. setdmode('rounded,nil);
  39. if car oldmode then setdmode(car oldmode,t);
  40. !*rounded:=cdr oldmode;
  41. if eqcar(v,'minus) and (numberp cadr v or eqcar(cadr v,'!:rd!:))
  42. then v:=!:minus cadr v;
  43. if fixp v then return (v . 1).{v};
  44. if not eqcar(v,'!:rd!:) then
  45. typerr(u,"continued fraction argument");
  46. c:
  47. return contfract2(v,b);
  48. end;
  49. symbolic procedure cont!-fract u;
  50. <<u:=contfract1(car u,if cdr u then ieval cadr u);
  51. {'list,{'quotient,caar u,cdar u},'list . cdr u}>>;
  52. put('continued_fraction,'psopfn,'cont!-fract);
  53. endmodule;
  54. end;