allroot.red 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448
  1. module allroot; % Routines for solving real polynomials by iteration.
  2. % Author: Stanley L. Kameny <stan_kameny@rand.org>.
  3. % Version and Date: Mod 1.96, 30 March 1995.
  4. % Copyright (c) 1988,1989,1990,1991,1992,1993,1994,1995.
  5. % Stanley L. Kameny. All Rights Reserved.
  6. Comment modules bfauxil, bfdoer, bfdoer2, complxp, rootaux, realroot,
  7. nrstroot and multroot needed also;
  8. exports accuroot, allroots, gfnewton, gfrootfind, sizatom;
  9. imports !!mfefix, a2gf, accupr, allout, automod, bfabs, bfdivide,
  10. bfeqp, bfleqp, bflessp, bfloat, bfloatem, bfmax, bfnewton,
  11. bfnump, bfnzp, bfp!:, bfprim, bfrlmult, bfrndem, bfsqrt,
  12. bftimes, bfzp, ceillog, cexpand, ckacc, ckpzro, cpxp, csep,
  13. cvt5, decimal2internal, deflate1, deflate1c, deflate2, divbf,
  14. domainp, dsply, ep!:, errorp, errorset!*, geq, getprec, gf2bf,
  15. gf2flt, gfdiff, gfdiffer, gfdot, gfeqp, gfexit, gfgetmin,
  16. gfim, gfminus, gfnewtset, gfplus, gfquotient, gfrl, gfrlmult,
  17. gfrootset, gfrsq, gfrtrnd, gfshift, gfsqfrf, gfsqfrf1, gfsqrt,
  18. gfstorval, gftimes, gfval, gfzerop, im2gf, lastpair,
  19. leq, lprim, minbnd1, minprec, mkquote, ncpxp, nwterr,
  20. nwterrfx, orgshift, pbfprint, pconstr, pflupd, pmsg, powerchk,
  21. rerror, restorefl, rl2gf, rlrtno, rlval, rootrnd, round!:mt,
  22. rrpwr, rxgfc, rxgfrl, rxrl, seteps, setflbf, setprec, smpart,
  23. sqrt, timbf, trmsg1, trmsg10, trmsg11, trmsg12, trmsg13,
  24. trmsg2, trmsg4, trmsg6, trmsg7, trmsg8, trmsg9, unshift,
  25. xnshift, xnsiz, xoshift;
  26. fluid '(!*trroot !*bftag !*rootmsg !*multiroot !*powergcd !*hardtst
  27. !*nosturm !2loop !*noinvert);
  28. switch trroot,rootmsg,multiroot,nosturm;
  29. fluid '(!*xnlist !*pfsav !*xmax !*xmax2 !*gfp pgcd!# allrl!#);
  30. fluid '(!*pcmp prec!# acc!# sprec!# !*xn eps!# accm!# !*xobf froot!#);
  31. fluid '(nwmax!# lgmax!# !*xo !*keepimp !1rp !*zx1 !*mb tht!# prm!#
  32. !*bfsh !*strm mltr!# emsg!# lims!# incmsg!$ cpxt!# sh!# pfl!# acfl!#
  33. pfactor!# rprec!# rr!# ss!# prx!# nrst!$ !*xd !*zp intv!# pnn!#);
  34. global '(bfone!* bfhalf!* bfz!* cpval!# polnix!$ polrem!$ lm!#);
  35. nwmax!# := 200; lgmax!# := 100;
  36. !*multiroot := !*powergcd := t;
  37. symbolic procedure gfrootfind(p,nx);
  38. % p is expected to be in the form returned by gfform, and
  39. % nx should be in the form (rl . im). returns nx in form (rl . im).
  40. begin scalar p1,p2,px,x1,x2,x3,x0,xd,nx,n1,gfqt,xz,rsc,njp,lgerr,
  41. pf,xn2,t1,t2,!*pfsav,pf0,pf1,pfn,lp,xlim,fg,fg2,ip,ip0,nxl2;
  42. integer n,r,m,ni; lm!# := 0;
  43. !*xnlist := emsg!# := !*xd := nil; pmsg pbfprint p; trmsg8();
  44. !*pcmp := cpxp p;
  45. if caar p>0 then
  46. <<restorefl();
  47. rerror(roots,7,"Roots error: zero root out of sequence!")>>;
  48. if (n := caar lastpair p)=1 then
  49. <<p := cdar bfprim p;
  50. nx := gfminus if !*pcmp then p else rl2gf p;
  51. gfshift nil; trmsg11(nx,1); go to ret1>>;
  52. if nx and bfp!: car nx and not !*bftag then
  53. <<p := !*gfp; !*bftag := t>>;
  54. !*xo := rl2gf 0; seteps();
  55. lm!# := 2*nwterrfx(n,nil);
  56. if n<3 or !*hardtst or not xoshift(p,nx) then gfshift nil
  57. else <<p := gfshift p; pmsg('xo . !*xo)>>;
  58. nx := if not nx then rl2gf 0 else xnshift nx;
  59. p1 := gfdiff p;
  60. if gfzerop nx then xz := t;
  61. px := gfval(p,nx); bfmax p; !*zp := 0;
  62. strt: pf := gfrsq px; trmsg13(n,nx,px);
  63. if bfzp pf then <<trmsg1 ('lag,nx); go to ret0>>;
  64. x1 := gfval(p1,nx);
  65. % avoid bad starting point using minbnd1 for offset.
  66. if (!*zx1 := not !*mb and bfnzp gfrsq x1) then go to st2;
  67. !*mb := x2 := nil; x1 := bfrlmult(2.0,minbnd1(p,nx));
  68. if !*keepimp then
  69. <<if !*pcmp or bfnzp gfim nx then x2 := gfdiffer(nx,im2gf x1);
  70. px := gfval(p,nx := gfplus(nx,im2gf x1));
  71. if not x2 then go to st1>>
  72. else
  73. <<x2 := gfdiffer(nx,rl2gf x1);
  74. px := gfval(p,nx := gfplus(nx,rl2gf x1))>>;
  75. if bflessp(gfrsq(p2 := gfval(p,x2)),gfrsq px) then
  76. <<nx := x2; px := p2>>;
  77. st1: xz := nil; go to strt;
  78. st2: n1 := n-1; p2 := gfdiff p1; xlim := bfrlmult(100.0,!*xmax2);
  79. ip := bfnzp gfim nx; nxl2 := {nx};
  80. lag: x3 := gfval(p2,nx);
  81. if not fg or bfzp gfrsq x1 then <<pmsg 0; go to lag0>>;
  82. gfqt := gfquotient(px,x1);
  83. % if newton is good enough, do it: it's cheaper.
  84. xn2 := gftimes(gftimes(gfqt,gfqt),
  85. gfrlmult(0.5,gfquotient(x3,x1)));
  86. t1 := bfabs gfdot(nx,xn2);
  87. t2 := bfabs bfrlmult(0.002,gfdot(nx,gfqt));
  88. pmsg if bfnzp t2 then gf2flt bfdivide(t1,t2) else "nwt_del->0";
  89. if bflessp(t1,t2) then go to ret;
  90. lag0: x2 := gfrlmult(n1,
  91. gfdiffer(gfrlmult(n1,gftimes(x1,x1)),
  92. gfrlmult(n,gftimes(px,x3))));
  93. x2 := gfsqrt x2;
  94. x0 := nx; xd := gfplus(x1,x2); x2 := gfdiffer(x1,x2);
  95. % determine correct sign of x2 for Laguerre iteration.
  96. if bflessp(gfrsq xd,gfrsq x2) then xd := x2;
  97. if bfzp(x2 := gfrsq xd) then
  98. <<trmsg10 'lag; return(!*xnlist := nil)>>;
  99. if bflessp(bftimes(xlim,x2),bfrlmult(n*n,gfrsq px))
  100. then <<lp := t; xn2 := gfrsq nx; go to lag1>>;
  101. xd := gfrlmult(-n,gfquotient(px,xd)); nx := gfplus(x0,xd);
  102. % constrain iteration to circle of radius !*xmax=maxbound p,
  103. % by scaling root to radius !*xmax/2.
  104. if bflessp(xn2 := gfrsq nx,!*xmax2) then go to lag2;
  105. lag1: if rsc then go to lag2;
  106. pf1 := pf0 := fg2 := !*pfsav := !*xnlist := nil;
  107. if lp then
  108. <<if !*trroot then <<write "root scaled"; terpri()>>;
  109. nx := if xz then rl2gf bfrlmult(0.5,!*xmax) else
  110. <<xn2 := bfrlmult(0.5,
  111. if atom xn2 then sqrt(!*xmax2/xn2)
  112. else bfsqrt divbf(!*xmax2,xn2));
  113. gfrlmult(xn2,nx)>>; rsc := t>>
  114. else if bflessp(xlim,xn2) then lp := t;
  115. pf := gfrsq(px := gfval(p,nx)); go to lag3;
  116. lag2: if !*xnlist then
  117. for each y in !*xnlist do if nx=cdr y then njp := t;
  118. pf := gfrsq(px := gfval(p,nx));
  119. % test for minimum in envelope of pf, but not on first iter.
  120. if not fg then fg := t else <<pf1 := pf0; pf0 := pfn>>;
  121. % if root has just turned complex, allow to settle.
  122. ip0 := ip; ip := bfnzp gfim nx;
  123. if ip and not ip0 then
  124. <<pf1 := pf0 := fg2 := !*pfsav := nil; ni := 1>>;
  125. pfn := pflupd pf;
  126. if pf1 then
  127. <<if not fg2 then <<if bflessp(pfn,pf0) then fg2 := t>> else
  128. <<if bflessp(pf0,pfn) or bfeqp(pf0,pf1) and bfeqp(pf0,pfn)
  129. then go to newt>> >>;
  130. if xz then xz := nil else gfstorval(pf,nx);
  131. pmsg mapcar(!*pfsav,function gf2flt);
  132. lag3: trmsg2('lag,nx,px); r := r+1; ni := ni+1;
  133. if (xd := gfexit(pf,nx,x0,'lag))=t then go to ret0
  134. % m logic delays this exit to allow settling.
  135. else if xd and (m := m+1) > 5
  136. then
  137. <<if gfeqp(nx,xd) then go to ret0
  138. else if r>2 then <<!*xd := nx := xd; go to ret2>> >>
  139. else if njp then go to newt;
  140. if not xd then m := 0;
  141. % this logic looks for loops of length 2 or lag limit exceeded.
  142. if ni>5 and gfeqp(car nxl2,nx) or (lgerr := (r>lgmax!#+lm!#)) then
  143. <<lprim(if lgerr then {"max LAG limit",lgmax!#+lm!#,"exceeded"}
  144. else "lag loop of length 2 found.");
  145. !2loop := t; return(!*xnlist := nil)>> else
  146. if length(nxl2 := nconc(nxl2,{nx})) > 2 then nxl2 := cdr nxl2;
  147. x1 := gfval(p1,nx); go to lag;
  148. ret1: nx := unshift nx; go to ret2;
  149. newt: nx := gfgetmin();
  150. ret: return gfnewt2(p,p1,nx,4);
  151. ret0: nx := unshift nx;
  152. ret2: !*xnlist := nil; dsply nx; return !*xn := nx end;
  153. symbolic procedure pshift p;
  154. orgshift(p,if cpxp p then !*xo else gfrl !*xo);
  155. symbolic procedure gfnewton(p,nx,k);
  156. <<p := pshift p; gfnewt2(p,gfdiff p,xnshift nx,k)>>;
  157. symbolic procedure gfnewt2(p,p1,nx,kmax);
  158. begin scalar pf0,pf,k,xk,loop,x0,x1,xd,px,rl; integer m,tht!#;
  159. !*xnlist := emsg!# := !*xd := nil; pmsg pbfprint p; trmsg8();
  160. if (rl := bfzp gfim nx) and ncpxp p then
  161. <<!*bfsh := t;
  162. nx := rl2gf bfnewton(p,p1,gfrl nx,intv!#,kmax);
  163. !*bfsh := nil; go to ret1>>;
  164. seteps(); !*zp := lm!# := 0;
  165. lm!# := nwterrfx(caar lastpair p,t);
  166. if gfzerop(px := gfval(p,nx)) then
  167. <<trmsg1('nwt,nx); go to ret1>>;
  168. gfstorval(gfrsq px,nx);
  169. ne0: x0 := nx;
  170. if gfzerop(x1 := gfval(p1,nx)) then
  171. <<trmsg10 'nwt; go to ret1>>;
  172. nx := gfdiffer(nx,gfquotient(px,x1)); pf0 := pf;
  173. for each y in !*xnlist do if nx=cdr y then loop := t;
  174. gfstorval(pf := gfrsq(px := gfval(p,nx)),nx);
  175. pmsg list gf2flt pf;
  176. % test for loop, but not on first iteration.
  177. if pf0 and bfleqp(pf0,pf) then
  178. <<loop := t;
  179. if kmax<2 then <<trmsg2('loop,nx,px); go to ret>> >>;
  180. trmsg2(if loop then 'loop else 'nwt,nx,px);
  181. if (xd := gfexit(pf,nx,x0,'nwt)) then
  182. <<if xd=t or gfeqp(nx,xd) then go to ret1
  183. else if m>0 then <<!*xd := nx := xd; go to ret2>> >>;
  184. if not loop then go to nlp;
  185. % next section updates loop variables.
  186. if k then <<xk := gfplus(xk,nx); k := k+1>>
  187. else <<k := 1; xk := nx>>;
  188. if k>=kmax then
  189. <<nx:=gfrlmult(1.0/k,xk);
  190. gfstorval(gfrsq(px := gfval(p,nx)),nx);
  191. trmsg6(k,nx,px); goto ret>>;
  192. nlp: nwterr(m := m+1); go to ne0;
  193. ret: nx := gfgetmin();trmsg7 nx;
  194. ret1: nx := unshift nx;
  195. ret2: !*xnlist := nil; dsply nx; return !*xn := nx end;
  196. symbolic procedure accuroot(y,p,xo); % p,xo,!*xn all bfloat
  197. begin scalar rprec,b,c,n,rl,x,pr0,ps,y0;
  198. ps := getprec(); rl := bfnump (y0 := y := gf2bf y); b := !*bftag;
  199. pr0 := minprec();
  200. !*xo := xo; !*bftag := t;
  201. if (n := caar lastpair p)<2 then
  202. <<setprec max(ps,acc!#+2);
  203. if prx!# then setprec max(getprec(),prx!#);
  204. y := gfrootfind(p,nil); go to ret>>;
  205. x := if rl then gfrl xnshift (y := rl2gf y) else xnshift y;
  206. if not(rprec := prreq(p,x,rl)) then <<setflbf b; return nil>>;
  207. if not (allrl!# or rl) and (bfzp gfim y or bfzp gfrl y)
  208. then !*xd := 1;
  209. if rprec<=pr0 then
  210. <<setprec pr0; if !*xd then go to bfp else go to ret>>;
  211. setprec rprec;
  212. bfp: y := if not rl and
  213. (rprec>=2*pr0 or bfzp gfim y or bfzp gfrl y)
  214. or !*xd then gfrootfind(p,y) else
  215. <<trmsg8(); gfnewton(p,y,if rl then 2 else 0)>>;
  216. if !*xd then <<setprec((3*getprec())/2);
  217. go to bfp>>;
  218. ret: if acfl!# then
  219. <<setprec(prec!# := prm!# := max(rprec,prm!#)); go to r3>>;
  220. prec!# := getprec();
  221. if rl or n<2 or not (c := smpart y) then go to r2;
  222. setprec(prec!# + 1);
  223. x := gfnewton(p,y := gf2bf !*xn,0);
  224. y := !*xn :=
  225. if c=t then
  226. if not !*pcmp and cvt5(gfrl y,gfrl x)
  227. and not cvt5(gfim y,gfim x)
  228. then rl2gf gfrl y else y
  229. else if cvt5(gfim y,gfim x) and not cvt5(gfrl y,gfrl x)
  230. then im2gf gfim y else y;
  231. r2: setprec ps;
  232. if not rl and
  233. (bfzp gfrl y and bfnzp gfrl y0
  234. or bfzp gfim y and bfnzp gfim y0)
  235. then acc!# := max(acc!#,accupr(p,if pgcd!# then p else !1rp,y));
  236. r3: y := if rl then rootrnd gfrl y else gfrtrnd y;
  237. trmsg12 y;
  238. setflbf b; !*xn := gf2bf !*xn;
  239. return y end;
  240. symbolic procedure prreq(p,x,rl);
  241. % find required precision to find root at x in polynomial p.
  242. begin scalar p1,x1,rx;
  243. p1 := gfdiff pshift p;
  244. if rl and ncpxp p then
  245. <<x1 := bfabs rlval(p1,x); rx := rxrl(p1,x)>>
  246. else
  247. <<rx := if cpxp p then rxgfc(p1,x) else rxgfrl(p1,x);
  248. x1 := bfsqrt gfrsq gfval(p1,x)>>;
  249. return if bfzp x1 then nil else
  250. <<x := getprec(); setprec 8;
  251. rl := ep!: round!:mt(
  252. divbf(timbf(rx,decimal2internal (1, (acc!#+2))),x1),1);
  253. setprec x; 1 + ceiling (rl / log2of10)>> end;
  254. symbolic procedure sizatom u;
  255. begin scalar c,x; c := !*complex; on complex;
  256. x := prepsq simp!* u;
  257. if not c then off complex;
  258. if x neq u then return x
  259. else rerror(roots,8,"non-numeric value") end;
  260. symbolic procedure dsplyrtno m;
  261. (<< write "rootno. ",m; wrs n>> where n=wrs nil);
  262. symbolic procedure allroots(p,p0); % p is always bfloated at this call.
  263. Comment With modifications for nosturm and offset iteration and root
  264. inversion.$
  265. % do the actual work of finding roots of p in appropriate environment.
  266. begin scalar q,n,n0,c,cc,cprq,rln,cpn,qf,ac,y,er,rl,z,mb,inc,prec,xo,
  267. pf,xof,qbf,sprec,b,red,sw,pfl!#,acfl,acfl!#,!*msg,prq,allrl!#,
  268. invp,invtd!*,pinv,!1rpinv,!1rp0,nmfg,p00,zi;
  269. integer req,npi,accm!#,prec!#,r15n,prm!#,k,rtn,invpb;
  270. prec := getprec(); polrem!$ := polnix!$ := nil; !*msg := t;
  271. ac := acc!#; n0 := caar lastpair p; pgcd!# := red := not p0;
  272. b := !*bftag; sprec := minprec(); invpb := n0/2;
  273. !*pcmp := cpxp p;
  274. if !*nosturm then req := nil else
  275. <<if not !*pcmp then req := if n0=1 then 1 else rlrtno p;
  276. if req>0 then trmsg4 req>>;
  277. % req = <no of real roots to determine unless nosturm is on>.
  278. % rtn is the number of separate root computations - 1 = max number
  279. % of restarts required.
  280. rtn := (if !*pcmp or !*nosturm then n0 else (n0+req)/2) - 1;
  281. % save original values of p and !1rp.
  282. p00 := p; !1rp0 := !1rp;
  283. %don't bother with inv mechanism if n0<11 unless !*noinvert="test".
  284. if !*noinvert="test" or n0>10 and not !*noinvert then
  285. <<pinv := invpoly p; !1rpinv := invpoly !1rp;
  286. if !*noinvert="test" or
  287. not bfleqp(maxbnd1 pinv,maxbnd1 p) then %% not perfect
  288. <<if !*trroot or !*rootmsg then
  289. lprim "inverting initially!";
  290. nmfg := t; go to inv>> >>;
  291. go to st0;
  292. tlp: if invtd!* then go to abrt else % prevents looping through tlp.
  293. <<if !*trroot or !*rootmsg then lprim
  294. "inverted polynomial tried";
  295. invtd!* := t>>;
  296. inv: k := 0;
  297. if not pinv then
  298. <<pinv := invpoly p00 ; !1rpinv := invpoly !1rp0>>;
  299. % toggle {p,!1rp,invp} from {p00,!1rp0,nil} to {pinv,!1rpinv,t}.
  300. % the first time only that invp is turned on, increase sprec.
  301. if (invp := not invp) then
  302. <<p := pinv; !1rp := !1rpinv>>
  303. else <<p := p00; !1rp := !1rp0>>;
  304. % increase precision the first time thru inv: when nmfb is off.
  305. if not nmfg and invpb neq 0 then
  306. <<prec := prec+invpb; setprec(prec-2); sprec := minprec();
  307. invpb := 0 ;if !*bftag then b := t>>;
  308. strt: if prq and (k := k+1)>rtn then go to abrt; mb := nil;
  309. if (!*rootmsg or !*rootmsg) and not nmfg then
  310. (<<write "allroots restart at prec ",getprec(); terpri(); wrs ch>>
  311. where ch=wrs nil);
  312. st0: n := n0; !*gfp := qbf := p; c := cc := pf := prq := nil;
  313. if not !*nosturm then
  314. <<cprq := n-req; if not !*pcmp then cprq := cprq/2>>;
  315. rln := cpn := prm!# := 0;
  316. root: qf := mb := !*mb := nmfg := nil;
  317. if not !*nosturm then allrl!# := cpn = cprq;
  318. if b then <<q := qbf; go to r0>>;
  319. q := if errorp(q := errorset!*({'cflotem,mkquote qbf},nil))
  320. then <<b := !*bftag := t; qbf>> else (qf := car q);
  321. r0: acc!# := ac; if not !*nosturm then !*keepimp := req-rln=0;
  322. r1: if !*rootmsg then dsplyrtno(1+n0-n);
  323. y := gfrootset(q,nil,b);
  324. if !2loop then <<!2loop := nil; go to tlp>>;
  325. r15n := 0;
  326. acfl := acfl!# := pfl!# := nil;
  327. if n=n0 then
  328. <<xo := !*xobf := gf2bf !*xo; p0 := qbf;
  329. if not b then <<xof := !*xo; pf := q>> >>;
  330. if not y then <<er := t; go to fl>>;
  331. if not (y := ckacc(qbf,if red then p0 else !1rp,gf2bf !*xn))
  332. then <<trmsg10 "ckacc"; go to inc0>>;
  333. if princreq(n,bfzp gfim y,sprec) then
  334. <<prq := t; sw := prec!#;
  335. if n>2 then sw := sw+n0; go to fl>>;
  336. r15: if(r15n := r15n+1)>3 then go to abrt;
  337. if invp or n0>2 and n0>n then
  338. <<if !*trroot
  339. then <<write "q(",n,") -> ";
  340. print_the_number gf2bf y; terpri()>>;
  341. y := if not pf or bfp!: car !*xn
  342. then gfnewtset(n0,p0,!*xn,xo,b)
  343. else gfnewtset(n0,pf,!*xn,xof,b);
  344. if not y then <<trmsg10 "gfnewtset"; go to inc0>> >>;
  345. if acfl then
  346. <<pfl!# := t;
  347. y := ckacc(qbf,if red then p0 else !1rp,gf2bf !*xn)>>;
  348. if !*trroot
  349. then <<write "p(",n,") -> ";print_the_number gf2bf y; terpri()>>;
  350. if gfzerop y then <<incmsg!$ := "illegal zero root"; go to incr>>;
  351. if not (y := accuroot(!*xn,p0,xo)) then
  352. <<trmsg10 "accuroot"; go to inc0>>;
  353. rl := bfzp gfim y;
  354. if princreq(n,rl,sprec) then
  355. <<prq := t; sw := prec!#; if n>3 then sw := sw+2; go to fl>>;
  356. r2: if not !*nosturm then
  357. (if rl then
  358. <<y := gfrl y; if rln+1>req then
  359. <<incmsg!$ := "excess real root"; go to incr>> >>
  360. else if cpn+1>cprq then
  361. <<incmsg!$ := "excess complex root"; go to incr>>);
  362. z := gf2bf(if rl then gfrl !*xn else !*xn); % set by lag or nwt.
  363. if not rl and not !*pcmp then
  364. <<y := (car y) . bfabs cdr y; z := (car z) . bfabs cdr z>>;
  365. if c and member(y,c) then
  366. <<incmsg!$ := "equal roots found"; go to incr>>;
  367. if rl then rln := rln+1 else cpn := cpn+1;
  368. c := y . c; %mb := nil;
  369. Comment If we are using the inverse polynomial, then we need to
  370. find roots at increased accuracy and precision, to allow for loss of
  371. accuracy in taking the inverse. Gfrootfind always provides that
  372. additional accuracy in the unrounded root z (which is used for
  373. deflation), so it is a simple matter to invert the root before
  374. rounding. When the rounding is done, using gfrtrnd, the binary
  375. bigfloat result is the output of gfrtrnd, and the decimal equivalent
  376. is
  377. returned as the value of the global variable cpval!#. $
  378. if invp then
  379. <<zi := gf2bf z;
  380. if red then zi := if rl then bfquotient(bfone!*,zi)
  381. else gfquotient(bfone!* . bfz!*,zi)
  382. else
  383. gfrtrnd gfquotient(bfone!* . bfz!*,
  384. if rl then (zi . bfz!*) else zi)>>;
  385. if not (rl or red or !*pcmp) then
  386. cpval!# := (car cpval!#) . (abs cadr cpval!#) . cddr cpval!#;
  387. cc := ((if red then if invp then zi else z else mkdn cpval!#)
  388. . acc!#) . cc;
  389. % the output list cc will be either z or :dn: objects, so
  390. % output functions will have to be clever!
  391. % c is rounded roots list used in testing for equal roots.
  392. if !*trroot then terpri();
  393. % firstroot computes first root found only. It could be wrong.
  394. if froot!# then goto ret;
  395. % new logic does all deflation in bfloat for greater accuracy.
  396. z := gf2bf z; q := bfloatem q;
  397. if (rl or !*pcmp) and (n := n-1)>0 and
  398. (q := cdr(if rl then deflate1(q,z) else deflate1c(q,z)))
  399. or (n := n-2)>0 and (q := deflate2(q,z)) then
  400. <<qbf := bfrndem q; go to root>>;
  401. ret: setprec max(prec,(acc!# := ac)+2);
  402. setflbf b; return cexpand cc;
  403. incr: lprim incmsg!$; polnix!$ := q;
  404. if mb then go to tlp
  405. else if !*zx1 then
  406. <<lprim "offset iteration attempted";
  407. !*mb := mb := t; go to r1>>;
  408. inc0: if (npi := npi+1)<=3 then go to inc1;
  409. abrt: lprim list("root finding aborted. Deflate degree = ",n);
  410. lprim list("poly = ",q); terpri();
  411. if n0>n then polrem!$ := q; go to ret;
  412. inc1: inc := max(n0,sprec/2);
  413. setprec(sprec := max(sprec+inc,2+2*acc!#)); trmsg9 sprec;
  414. if b then go to strt;
  415. fl: p := p0; xo := !*xo := gf2bf xo;
  416. b := !*bftag := t; !1rp := bfloatem !1rp;
  417. if er then <<er := nil; q := qbf; go to r1>>;
  418. acfl := t;
  419. if sw then
  420. % precision has increased: backup point depends on n.
  421. <<setprec (sprec := sw); sw := nil; q := p;
  422. if n=n0 then <<y := gf2bf y; go to r15>> >>;
  423. go to strt end;
  424. symbolic procedure princreq(n,rl,sprec);
  425. (n>2 or (rl or !*pcmp) and n>1) and min(prec!#,2*(accm!#+1))>sprec;
  426. endmodule;
  427. end;