multihen.red 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  1. module multihen; % Hensel construction for the multivariate case.
  2. % (This version is highly recursive.)
  3. % Authors: A. C. Norman and P. M. A. Moore, 1979.
  4. fluid '(!*overshoot
  5. !*trfac
  6. alphavec
  7. bad!-case
  8. factor!-level
  9. factor!-trace!-list
  10. fhatvec
  11. hensel!-growth!-size
  12. max!-unknowns
  13. number!-of!-factors
  14. number!-of!-unknowns
  15. predictions);
  16. symbolic procedure find!-multivariate!-factors!-mod!-p(poly,
  17. best!-factors,variable!-set);
  18. % All arithmetic is done mod p, best-factors is overwritten.
  19. if null variable!-set then best!-factors
  20. else (lambda factor!-level; begin
  21. scalar growth!-factor,b0s,res,v,
  22. bhat0s,w,degbd,first!-time,redpoly,
  23. predicted!-forms,number!-of!-unknowns,solve!-count,
  24. correction!-vectors,soln!-matrices,max!-unknowns,
  25. unknowns!-count!-list,poly!-remaining,
  26. prediction!-results,one!-prediction!-failed;
  27. v:=car variable!-set;
  28. degbd:=get!-degree!-bound car v;
  29. first!-time:=t;
  30. growth!-factor:=make!-growth!-factor v;
  31. poly!-remaining:=poly;
  32. prediction!-results:=mkvect number!-of!-factors;
  33. find!-msg1(best!-factors,growth!-factor,poly);
  34. b0s:=reduce!-vec!-by!-one!-var!-mod!-p(best!-factors,
  35. v,number!-of!-factors);
  36. % The above made a copy of the vector.
  37. for i:=1:number!-of!-factors do
  38. putv(best!-factors,i,
  39. difference!-mod!-p(getv(best!-factors,i),getv(b0s,i)));
  40. redpoly:=evaluate!-mod!-p(poly,car v,cdr v);
  41. find!-msg2(v,variable!-set);
  42. find!-multivariate!-factors!-mod!-p(redpoly,b0s,cdr variable!-set);
  43. % answers in b0s.
  44. if bad!-case then return;
  45. for i:=1:number!-of!-factors do
  46. putv(best!-factors,i,
  47. plus!-mod!-p(getv(b0s,i),getv(best!-factors,i)));
  48. find!-msg3(best!-factors,v);
  49. res:=diff!-over!-k!-mod!-p(
  50. difference!-mod!-p(poly,
  51. times!-vector!-mod!-p(best!-factors,number!-of!-factors)),
  52. 1,car v);
  53. % RES is the residue and must eventually be reduced to zero.
  54. factor!-trace << printsf res; terpri!*(nil) >>;
  55. if not polyzerop res and
  56. cdr variable!-set and not zerop cdr v then <<
  57. predicted!-forms:=make!-bivariate!-vec!-mod!-p(best!-factors,
  58. cdr variable!-set,car v,number!-of!-factors);
  59. find!-multivariate!-factors!-mod!-p(
  60. make!-bivariate!-mod!-p(poly,cdr variable!-set,car v),
  61. predicted!-forms,list v);
  62. % Answers in PREDICTED!-FORMS.
  63. find!-msg4(predicted!-forms,v);
  64. make!-predicted!-forms(predicted!-forms,car v);
  65. % Sets max!-unknowns and number!-of!-unknowns.
  66. find!-msg5();
  67. unknowns!-count!-list:=number!-of!-unknowns;
  68. while unknowns!-count!-list and
  69. (car (w:=car unknowns!-count!-list))=1 do
  70. begin scalar i,r;
  71. unknowns!-count!-list:=cdr unknowns!-count!-list;
  72. i:=cdr w;
  73. w:=quotient!-mod!-p(poly!-remaining,r:=getv(best!-factors,i));
  74. if didntgo w or
  75. not polyzerop difference!-mod!-p(poly!-remaining,
  76. times!-mod!-p(w,r)) then
  77. if one!-prediction!-failed then <<
  78. factor!-trace printstr "Predictions are no good";
  79. max!-unknowns:=nil >>
  80. else <<
  81. factor!-trace <<
  82. prin2!* "Guess for f(";
  83. prin2!* i;
  84. printstr ") was bad." >>;
  85. one!-prediction!-failed:=i >>
  86. else <<
  87. putv(prediction!-results,i,r);
  88. factor!-trace <<
  89. prin2!* "Prediction for f("; prin2!* i;
  90. prin2!* ") worked: ";
  91. printsf r >>;
  92. poly!-remaining:=w >>
  93. end;
  94. w:=length unknowns!-count!-list;
  95. if w=1 and not one!-prediction!-failed then <<
  96. putv(best!-factors,cdar unknowns!-count!-list,poly!-remaining);
  97. go to exit >>
  98. else if w=0 and one!-prediction!-failed then <<
  99. putv(best!-factors,one!-prediction!-failed,poly!-remaining);
  100. go to exit >>;
  101. solve!-count:=1;
  102. if max!-unknowns then
  103. correction!-vectors:=
  104. make!-correction!-vectors(best!-factors,max!-unknowns) >>;
  105. bhat0s:=make!-multivariate!-hatvec!-mod!-p(b0s,number!-of!-factors);
  106. return multihen1(list(res,
  107. growth!-factor,
  108. first!-time,
  109. bhat0s,
  110. b0s,
  111. variable!-set,
  112. solve!-count,
  113. correction!-vectors,
  114. unknowns!-count!-list,
  115. best!-factors,
  116. v,
  117. degbd,
  118. soln!-matrices,
  119. predicted!-forms,
  120. poly!-remaining,
  121. prediction!-results,
  122. one!-prediction!-failed),
  123. nil);
  124. exit:
  125. multihen!-exit(first!-time,best!-factors,nil);
  126. end) (factor!-level+1);
  127. symbolic procedure multihen1(u,zz);
  128. begin scalar res,test!-prediction,growth!-factor,first!-time,hat0s,
  129. x0s,variable!-set,solve!-count,correction!-vectors,
  130. unknowns!-count!-list,correction!-factor,frvec,v,
  131. degbd,soln!-matrices,predicted!-forms,poly!-remaining,
  132. fvec,previous!-prediction!-holds,
  133. prediction!-results,one!-prediction!-failed,
  134. bool,d,x1,k,kk,substres,w;
  135. res := car u; u := cdr u;
  136. growth!-factor := car u; u := cdr u;
  137. first!-time := car u; u := cdr u;
  138. hat0s := car u; u := cdr u;
  139. x0s := car u; u := cdr u;
  140. variable!-set := car u; u := cdr u;
  141. solve!-count := car u; u := cdr u;
  142. correction!-vectors := car u; u := cdr u;
  143. unknowns!-count!-list := car u; u := cdr u;
  144. frvec := car u; u := cdr u;
  145. v := car u; u := cdr u;
  146. degbd := car u; u := cdr u;
  147. soln!-matrices := car u; u := cdr u;
  148. predicted!-forms := car u; u := cdr u;
  149. poly!-remaining := car u; u := cdr u;
  150. prediction!-results := car u; u := cdr u;
  151. if zz then <<fvec := car u; u := cdr u;
  152. previous!-prediction!-holds := car u; u := cdr u>>;
  153. one!-prediction!-failed := car u;
  154. correction!-factor:=growth!-factor;
  155. % Next power of growth-factor we are adding to the factors.
  156. x1:=mkvect number!-of!-factors;
  157. k:=1;
  158. kk:=0;
  159. temploop:
  160. bool := nil;
  161. while not bool and not polyzerop res and (null max!-unknowns
  162. or null test!-prediction) do
  163. if k>degbd then <<
  164. factor!-trace <<
  165. prin2!* "We have overshot the degree bound for ";
  166. printvar car v >>;
  167. if !*overshoot then
  168. prin2t "Multivariate degree bound overshoot -> restart";
  169. bad!-case:= bool := t >>
  170. else
  171. if polyzerop(substres:=evaluate!-mod!-p(res,car v,cdr v))
  172. then <<
  173. k:=iadd1 k;
  174. res:=diff!-over!-k!-mod!-p(res,k,car v);
  175. correction!-factor:=
  176. times!-mod!-p(correction!-factor,growth!-factor) >>
  177. else begin
  178. multihen!-msg(growth!-factor,first!-time,k,kk,substres,zz);
  179. if null zz
  180. then <<kk := kk#+1; if first!-time then first!-time := nil>>;
  181. solve!-for!-corrections(substres,hat0s,x0s,x1,
  182. cdr variable!-set);
  183. % Answers left in x1.
  184. if bad!-case then return (bool := t);
  185. if max!-unknowns then <<
  186. solve!-count:=iadd1 solve!-count;
  187. for i:=1:number!-of!-factors do
  188. putv(getv(correction!-vectors,i),solve!-count,getv(x1,i));
  189. if solve!-count=caar unknowns!-count!-list then
  190. test!-prediction:=t >>;
  191. if zz then
  192. for i:=1:number!-of!-factors do
  193. putv(frvec,i,plus!-mod!-p(getv(frvec,i),times!-mod!-p(
  194. getv(x1,i),correction!-factor)));
  195. factor!-trace <<
  196. printstr " Giving:";
  197. if null zz then
  198. printvec(" f(",number!-of!-factors,",1) = ",x1)
  199. else <<
  200. printvec(" a(",number!-of!-factors,",1) = ",x1);
  201. printstr " New a's are now:";
  202. printvec(" a(",number!-of!-factors,") = ",frvec) >>>>;
  203. d:=times!-mod!-p(correction!-factor,
  204. if zz then form!-sum!-and!-product!-mod!-p(x1,fhatvec,
  205. number!-of!-factors)
  206. else terms!-done!-mod!-p(frvec,x1,correction!-factor));
  207. if degree!-in!-variable(d,car v)>degbd then <<
  208. factor!-trace <<
  209. prin2!* "We have overshot the degree bound for ";
  210. printvar car v >>;
  211. if !*overshoot then
  212. prin2t "Multivariate degree bound overshoot -> restart";
  213. bad!-case:=t;
  214. return (bool := t)>>;
  215. d:=diff!-k!-times!-mod!-p(d,k,car v);
  216. if null zz then
  217. for i:=1:number!-of!-factors do
  218. putv(frvec,i,
  219. plus!-mod!-p(getv(frvec,i),
  220. times!-mod!-p(getv(x1,i),correction!-factor)));
  221. k:=iadd1 k;
  222. res:=diff!-over!-k!-mod!-p(difference!-mod!-p(res,d),k,car v);
  223. factor!-trace <<
  224. if null zz then <<printstr " New factors are now:";
  225. printvec(" f(",number!-of!-factors,") = ",frvec)>>;
  226. prin2!* " and residue = ";
  227. printsf res;
  228. printstr "-------------"
  229. >>;
  230. correction!-factor:=
  231. times!-mod!-p(correction!-factor,growth!-factor) end;
  232. if not polyzerop res and not bad!-case then <<
  233. if null zz or null soln!-matrices then
  234. soln!-matrices
  235. := construct!-soln!-matrices(predicted!-forms,cdr v);
  236. factor!-trace <<
  237. if null zz then <<
  238. printstr "We use the results from the Hensel growth to";
  239. printstr "produce a set of linear equations to solve";
  240. printstr "for coefficients in the relevant factors:" >>
  241. else <<
  242. printstr "The Hensel growth so far allows us to test some of";
  243. printstr "our predictions:" >>>>;
  244. bool := nil;
  245. while not bool and unknowns!-count!-list and
  246. (car (w:=car unknowns!-count!-list))=solve!-count do <<
  247. unknowns!-count!-list:=cdr unknowns!-count!-list;
  248. factor!-trace
  249. print!-linear!-system(cdr w,soln!-matrices,
  250. correction!-vectors,predicted!-forms,car v);
  251. w:=try!-prediction(soln!-matrices,correction!-vectors,
  252. predicted!-forms,car w,cdr w,poly!-remaining,car v,
  253. if zz then fvec else nil,
  254. if zz then fhatvec else nil);
  255. if car w='singular or car w='bad!-prediction then
  256. if one!-prediction!-failed then <<
  257. factor!-trace printstr "Predictions were no help.";
  258. max!-unknowns:=nil;
  259. bool := t>>
  260. else if null zz then one!-prediction!-failed:=cdr w
  261. else <<
  262. if previous!-prediction!-holds then <<
  263. predictions:=delasc(car v,predictions);
  264. previous!-prediction!-holds:=nil >>;
  265. one!-prediction!-failed:=cdr w >>
  266. else <<
  267. putv(prediction!-results,car w,cadr w);
  268. poly!-remaining:=caddr w >> >>;
  269. if null max!-unknowns then <<
  270. if zz and previous!-prediction!-holds then
  271. predictions:=delasc(car v,predictions);
  272. goto temploop >>;
  273. w:=length unknowns!-count!-list;
  274. if w>1 or (w=1 and one!-prediction!-failed) then <<
  275. test!-prediction:=nil;
  276. goto temploop >>;
  277. if w=1 or one!-prediction!-failed then <<
  278. w:=if one!-prediction!-failed then one!-prediction!-failed
  279. else cdar unknowns!-count!-list;
  280. putv(prediction!-results,w,
  281. if null zz then poly!-remaining
  282. else quotfail!-mod!-p(poly!-remaining,
  283. getv(fhatvec,w)))>>;
  284. for i:=1:number!-of!-factors do
  285. putv(frvec,i,getv(prediction!-results,i));
  286. if (not previous!-prediction!-holds or null zz)
  287. and not one!-prediction!-failed then
  288. predictions:=
  289. (car v .
  290. list(soln!-matrices,predicted!-forms,max!-unknowns,
  291. number!-of!-unknowns))
  292. . predictions >>;
  293. multihen!-exit(first!-time,frvec,zz)
  294. end;
  295. symbolic
  296. procedure multihen!-msg(growth!-factor,first!-time,k,kk,substres,zz);
  297. factor!-trace <<
  298. prin2!* "Hensel Step "; printstr (kk:=kk #+ 1);
  299. prin2!* "-------------";
  300. if kk>10 then printstr "-" else terpri!*(t);
  301. prin2!* "Next corrections are for (";
  302. prinsf growth!-factor;
  303. if not (k=1) then <<
  304. prin2!* ") ** ";
  305. prin2!* k >> else prin2!* '!);
  306. printstr ". To find these we solve:";
  307. if zz then prin2!* " sum over i [ a(i,1)*fhat(i,0) ] = "
  308. else prin2!* " sum over i [ f(i,1)*fhat(i,0) ] = ";
  309. prinsf substres;
  310. prin2!* " mod ";
  311. prin2!* hensel!-growth!-size;
  312. if zz then printstr " for a(i,1). "
  313. else printstr " for f(i,1), ";
  314. if null zz and first!-time then <<
  315. prin2!*
  316. " where fhat(i,0) = product over j [ f(j,0) ]";
  317. prin2!* " / f(i,0) mod ";
  318. printstr hensel!-growth!-size >>;
  319. terpri!*(nil)
  320. >>;
  321. symbolic procedure multihen!-exit(first!-time,frvec,zz);
  322. factor!-trace <<
  323. if not bad!-case then
  324. if first!-time then
  325. if zz then printstr "But these a's are already correct."
  326. else printstr "Therefore these factors are already correct."
  327. else <<
  328. if zz then <<printstr "Correct a's are:";
  329. printvec(" a(",number!-of!-factors,") = ",frvec)>>
  330. else <<printstr "Correct factors are:";
  331. printvec(" f(",number!-of!-factors,") = ",frvec) >>>>;
  332. terpri!*(nil);
  333. printstr "**************************************************";
  334. terpri!*(nil)>>;
  335. symbolic procedure find!-msg1(best!-factors,growth!-factor,poly);
  336. factor!-trace <<
  337. printstr "Want f(i) s.t.";
  338. prin2!* " product over i [ f(i) ] = ";
  339. prinsf poly;
  340. prin2!* " mod ";
  341. printstr hensel!-growth!-size;
  342. terpri!*(nil);
  343. printstr "We know f(i) as follows:";
  344. printvec(" f(",number!-of!-factors,") = ",best!-factors);
  345. prin2!* " and we shall put in powers of ";
  346. prinsf growth!-factor;
  347. printstr " to find them fully."
  348. >>;
  349. symbolic procedure find!-msg2(v,variable!-set);
  350. factor!-trace <<
  351. prin2!*
  352. "First solve the problem in one less variable by putting ";
  353. prinvar car v; prin2!* "="; printstr cdr v;
  354. if cdr variable!-set then <<
  355. prin2!* "and growing wrt ";
  356. printvar caadr variable!-set
  357. >>;
  358. terpri!*(nil)
  359. >>;
  360. symbolic procedure find!-msg3(best!-factors,v);
  361. factor!-trace <<
  362. prin2!* "After putting back any knowledge of ";
  363. prinvar car v;
  364. printstr ", we have the";
  365. printstr "factors so far as:";
  366. printvec(" f(",number!-of!-factors,") = ",best!-factors);
  367. printstr "Subtracting the product of these from the polynomial";
  368. prin2!* "and differentiating wrt "; prinvar car v;
  369. printstr " gives a residue:"
  370. >>;
  371. symbolic procedure find!-msg4(predicted!-forms,v);
  372. factor!-trace <<
  373. printstr "To help reduce the number of Hensel steps we try";
  374. prin2!* "predicting how many terms each factor will have wrt ";
  375. prinvar car v; printstr ".";
  376. printstr
  377. "Predictions are based on the bivariate factors :";
  378. printvec(" f(",number!-of!-factors,") = ",predicted!-forms)
  379. >>;
  380. symbolic procedure find!-msg5;
  381. factor!-trace <<
  382. terpri!*(nil);
  383. printstr "We predict :";
  384. for each w in number!-of!-unknowns do <<
  385. prin2!* car w;
  386. prin2!* " terms in f("; prin2!* cdr w; printstr '!) >>;
  387. if (caar number!-of!-unknowns)=1 then <<
  388. prin2!* "Since we predict only one term for f(";
  389. prin2!* cdar number!-of!-unknowns;
  390. printstr "), we can try";
  391. printstr "dividing it out now:" >>
  392. else <<
  393. prin2!* "So we shall do at least ";
  394. prin2!* isub1 caar number!-of!-unknowns;
  395. prin2!* " Hensel step";
  396. if (caar number!-of!-unknowns)=2 then printstr "."
  397. else printstr "s." >>;
  398. terpri!*(nil) >>;
  399. symbolic procedure solve!-for!-corrections(c,fhatvec,fvec,resvec,vset);
  400. % ....;
  401. if null vset then
  402. for i:=1:number!-of!-factors do
  403. putv(resvec,i,
  404. remainder!-mod!-p(
  405. times!-mod!-p(c,getv(alphavec,i)),
  406. getv(fvec,i)))
  407. else (lambda factor!-level; begin
  408. scalar residue,growth!-factor,f0s,fhat0s,v,
  409. degbd,first!-time,redc,
  410. predicted!-forms,max!-unknowns,solve!-count,number!-of!-unknowns,
  411. correction!-vectors,soln!-matrices,w,previous!-prediction!-holds,
  412. unknowns!-count!-list,poly!-remaining,
  413. prediction!-results,one!-prediction!-failed;
  414. v:=car vset;
  415. degbd:=get!-degree!-bound car v;
  416. first!-time:=t;
  417. growth!-factor:=make!-growth!-factor v;
  418. poly!-remaining:=c;
  419. prediction!-results:=mkvect number!-of!-factors;
  420. redc:=evaluate!-mod!-p(c,car v,cdr v);
  421. solve!-msg1(c,fvec,v);
  422. solve!-for!-corrections(redc,
  423. fhat0s:=reduce!-vec!-by!-one!-var!-mod!-p(
  424. fhatvec,v,number!-of!-factors),
  425. f0s:=reduce!-vec!-by!-one!-var!-mod!-p(
  426. fvec,v,number!-of!-factors),
  427. resvec,
  428. cdr vset); % Results left in RESVEC.
  429. if bad!-case then return;
  430. solve!-msg2(resvec,v);
  431. residue:=diff!-over!-k!-mod!-p(difference!-mod!-p(c,
  432. form!-sum!-and!-product!-mod!-p(resvec,fhatvec,
  433. number!-of!-factors)),1,car v);
  434. factor!-trace <<
  435. printsf residue;
  436. prin2!* " Now we shall put in the powers of ";
  437. prinsf growth!-factor;
  438. printstr " to find the a's fully."
  439. >>;
  440. if not polyzerop residue and not zerop cdr v then <<
  441. w:=atsoc(car v,predictions);
  442. if w then <<
  443. previous!-prediction!-holds:=t;
  444. factor!-trace <<
  445. printstr
  446. "We shall use the previous prediction for the form of";
  447. prin2!* "polynomials wrt "; printvar car v >>;
  448. w:=cdr w;
  449. soln!-matrices:=car w;
  450. predicted!-forms:=cadr w;
  451. max!-unknowns:=caddr w;
  452. number!-of!-unknowns:=cadr cddr w >>
  453. else <<
  454. factor!-trace <<
  455. printstr
  456. "We shall use a new prediction for the form of polynomials ";
  457. prin2!* "wrt "; printvar car v >>;
  458. predicted!-forms:=mkvect number!-of!-factors;
  459. for i:=1:number!-of!-factors do
  460. putv(predicted!-forms,i,getv(fvec,i));
  461. % Make a copy of the factors in a vector we shall overwrite.
  462. make!-predicted!-forms(predicted!-forms,car v);
  463. % Sets max!-unknowns and number!-of!-unknowns.
  464. >>;
  465. solve!-msg3();
  466. unknowns!-count!-list:=number!-of!-unknowns;
  467. while unknowns!-count!-list and
  468. (car (w:=car unknowns!-count!-list))=1 do
  469. begin scalar i,r,wr,fi;
  470. unknowns!-count!-list:=cdr unknowns!-count!-list;
  471. i:=cdr w;
  472. w:=quotient!-mod!-p(
  473. wr:=difference!-mod!-p(poly!-remaining,
  474. times!-mod!-p(r:=getv(resvec,i),getv(fhatvec,i))),
  475. fi:=getv(fvec,i));
  476. if didntgo w or not polyzerop
  477. difference!-mod!-p(wr,times!-mod!-p(w,fi)) then
  478. if one!-prediction!-failed then <<
  479. factor!-trace printstr "Predictions are no good.";
  480. max!-unknowns:=nil >>
  481. else <<
  482. factor!-trace <<
  483. prin2!* "Guess for a(";
  484. prin2!* i;
  485. printstr ") was bad." >>;
  486. one!-prediction!-failed:=i >>
  487. else <<
  488. putv(prediction!-results,i,r);
  489. factor!-trace <<
  490. prin2!* "Prediction for a("; prin2!* i;
  491. prin2!* ") worked: ";
  492. printsf r >>;
  493. poly!-remaining:=wr >>
  494. end;
  495. w:=length unknowns!-count!-list;
  496. if w=1 and not one!-prediction!-failed then <<
  497. putv(resvec,cdar unknowns!-count!-list,
  498. quotfail!-mod!-p(poly!-remaining,getv(fhatvec,
  499. cdar unknowns!-count!-list)));
  500. go to exit >>
  501. else if w=0 and one!-prediction!-failed and max!-unknowns then <<
  502. putv(resvec,one!-prediction!-failed,
  503. quotfail!-mod!-p(poly!-remaining,getv(fhatvec,
  504. one!-prediction!-failed)));
  505. go to exit >>;
  506. solve!-count:=1;
  507. if max!-unknowns then
  508. correction!-vectors:=
  509. make!-correction!-vectors(resvec,max!-unknowns) >>;
  510. if not polyzerop residue then first!-time:=nil;
  511. return multihen1(list(residue,
  512. growth!-factor,
  513. first!-time,
  514. fhat0s,
  515. f0s,
  516. vset,
  517. solve!-count,
  518. correction!-vectors,
  519. unknowns!-count!-list,
  520. resvec,
  521. v,
  522. degbd,
  523. soln!-matrices,
  524. predicted!-forms,
  525. poly!-remaining,
  526. prediction!-results,
  527. fvec,
  528. previous!-prediction!-holds,
  529. one!-prediction!-failed),
  530. t);
  531. exit:
  532. multihen!-exit(first!-time,resvec,t);
  533. end) (factor!-level+1);
  534. symbolic procedure solve!-msg1(c,fvec,v);
  535. factor!-trace <<
  536. printstr "Want a(i) s.t.";
  537. prin2!* "(*) sum over i [ a(i)*fhat(i) ] = ";
  538. prinsf c;
  539. prin2!* " mod ";
  540. printstr hensel!-growth!-size;
  541. prin2!* " where fhat(i) = product over j [ f(j) ]";
  542. prin2!* " / f(i) mod ";
  543. printstr hensel!-growth!-size;
  544. printstr " and";
  545. printvec(" f(",number!-of!-factors,") = ",fvec);
  546. terpri!*(nil);
  547. prin2!*
  548. "First solve the problem in one less variable by putting ";
  549. prinvar car v; prin2!* '!=; printstr cdr v;
  550. terpri!*(nil)
  551. >>;
  552. symbolic procedure solve!-msg2(resvec,v);
  553. factor!-trace <<
  554. printstr "Giving:";
  555. printvec(" a(",number!-of!-factors,",0) = ",resvec);
  556. printstr "Subtracting the contributions these give in (*) from";
  557. prin2!* "the R.H.S. of (*) ";
  558. prin2!* "and differentiating wrt "; prinvar car v;
  559. printstr " gives a residue:"
  560. >>;
  561. symbolic procedure solve!-msg3;
  562. factor!-trace <<
  563. terpri!*(nil);
  564. printstr "We predict :";
  565. for each w in number!-of!-unknowns do <<
  566. prin2!* car w;
  567. prin2!* " terms in a("; prin2!* cdr w; printstr '!) >>;
  568. if (caar number!-of!-unknowns)=1 then <<
  569. prin2!* "Since we predict only one term for a(";
  570. prin2!* cdar number!-of!-unknowns;
  571. printstr "), we can test it right away:" >>
  572. else <<
  573. prin2!* "So we shall do at least ";
  574. prin2!* isub1 caar number!-of!-unknowns;
  575. prin2!* " Hensel step";
  576. if (caar number!-of!-unknowns)=2 then printstr "."
  577. else printstr "s." >>;
  578. terpri!*(nil) >>;
  579. endmodule;
  580. end;