PageRenderTime 84ms CodeModel.GetById 34ms RepoModel.GetById 0ms app.codeStats 1ms

/factory/facHensel.cc

https://github.com/hannes14/Singular
C++ | 3225 lines | 2827 code | 299 blank | 99 comment | 745 complexity | 57700a23d586cde3ee6a35c606de1422 MD5 | raw file
Possible License(s): AGPL-1.0, GPL-3.0, Unlicense
  1. /*****************************************************************************\
  2. * Computer Algebra System SINGULAR
  3. \*****************************************************************************/
  4. /** @file facHensel.cc
  5. *
  6. * This file implements functions to lift factors via Hensel lifting and
  7. * functions for modular multiplication and division with remainder.
  8. *
  9. * ABSTRACT: Hensel lifting is described in "Efficient Multivariate
  10. * Factorization over Finite Fields" by L. Bernardin & M. Monagon. Division with
  11. * remainder is described in "Fast Recursive Division" by C. Burnikel and
  12. * J. Ziegler. Karatsuba multiplication is described in "Modern Computer
  13. * Algebra" by J. von zur Gathen and J. Gerhard.
  14. *
  15. * @author Martin Lee
  16. *
  17. * @internal @version \$Id$
  18. *
  19. **/
  20. /*****************************************************************************/
  21. #include "assert.h"
  22. #include "debug.h"
  23. #include "timing.h"
  24. #include "facHensel.h"
  25. #include "cf_util.h"
  26. #include "fac_util.h"
  27. #include "cf_algorithm.h"
  28. #ifdef HAVE_NTL
  29. #include <NTL/lzz_pEX.h>
  30. #include "NTLconvert.h"
  31. CanonicalForm
  32. mulNTL (const CanonicalForm& F, const CanonicalForm& G)
  33. {
  34. if (F.inCoeffDomain() || G.inCoeffDomain() || getCharacteristic() == 0)
  35. return F*G;
  36. ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
  37. ASSERT (F.level() == G.level(), "expected polys of same level");
  38. if (CFFactory::gettype() == GaloisFieldDomain)
  39. return F*G;
  40. zz_p::init (getCharacteristic());
  41. Variable alpha;
  42. CanonicalForm result;
  43. if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
  44. {
  45. zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
  46. zz_pE::init (NTLMipo);
  47. zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
  48. zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
  49. mul (NTLF, NTLF, NTLG);
  50. result= convertNTLzz_pEX2CF(NTLF, F.mvar(), alpha);
  51. }
  52. else
  53. {
  54. zz_pX NTLF= convertFacCF2NTLzzpX (F);
  55. zz_pX NTLG= convertFacCF2NTLzzpX (G);
  56. mul (NTLF, NTLF, NTLG);
  57. result= convertNTLzzpX2CF(NTLF, F.mvar());
  58. }
  59. return result;
  60. }
  61. CanonicalForm
  62. modNTL (const CanonicalForm& F, const CanonicalForm& G)
  63. {
  64. if (F.inCoeffDomain() && G.isUnivariate())
  65. return F;
  66. else if (F.inCoeffDomain() && G.inCoeffDomain())
  67. return mod (F, G);
  68. else if (F.isUnivariate() && G.inCoeffDomain())
  69. return mod (F,G);
  70. if (getCharacteristic() == 0)
  71. return mod (F, G);
  72. ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
  73. ASSERT (F.level() == G.level(), "expected polys of same level");
  74. if (CFFactory::gettype() == GaloisFieldDomain)
  75. return mod (F, G);
  76. zz_p::init (getCharacteristic());
  77. Variable alpha;
  78. CanonicalForm result;
  79. if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
  80. {
  81. zz_pX NTLMipo= convertFacCF2NTLzzpX(getMipo (alpha));
  82. zz_pE::init (NTLMipo);
  83. zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
  84. zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
  85. rem (NTLF, NTLF, NTLG);
  86. result= convertNTLzz_pEX2CF(NTLF, F.mvar(), alpha);
  87. }
  88. else
  89. {
  90. zz_pX NTLF= convertFacCF2NTLzzpX (F);
  91. zz_pX NTLG= convertFacCF2NTLzzpX (G);
  92. rem (NTLF, NTLF, NTLG);
  93. result= convertNTLzzpX2CF(NTLF, F.mvar());
  94. }
  95. return result;
  96. }
  97. CanonicalForm
  98. divNTL (const CanonicalForm& F, const CanonicalForm& G)
  99. {
  100. if (F.inCoeffDomain() && G.isUnivariate())
  101. return F;
  102. else if (F.inCoeffDomain() && G.inCoeffDomain())
  103. return div (F, G);
  104. else if (F.isUnivariate() && G.inCoeffDomain())
  105. return div (F,G);
  106. if (getCharacteristic() == 0)
  107. return div (F, G);
  108. ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
  109. ASSERT (F.level() == G.level(), "expected polys of same level");
  110. if (CFFactory::gettype() == GaloisFieldDomain)
  111. return div (F, G);
  112. zz_p::init (getCharacteristic());
  113. Variable alpha;
  114. CanonicalForm result;
  115. if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
  116. {
  117. zz_pX NTLMipo= convertFacCF2NTLzzpX(getMipo (alpha));
  118. zz_pE::init (NTLMipo);
  119. zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
  120. zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
  121. div (NTLF, NTLF, NTLG);
  122. result= convertNTLzz_pEX2CF(NTLF, F.mvar(), alpha);
  123. }
  124. else
  125. {
  126. zz_pX NTLF= convertFacCF2NTLzzpX (F);
  127. zz_pX NTLG= convertFacCF2NTLzzpX (G);
  128. div (NTLF, NTLF, NTLG);
  129. result= convertNTLzzpX2CF(NTLF, F.mvar());
  130. }
  131. return result;
  132. }
  133. /*
  134. void
  135. divremNTL (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  136. CanonicalForm& R)
  137. {
  138. if (F.inCoeffDomain() && G.isUnivariate())
  139. {
  140. R= F;
  141. Q= 0;
  142. }
  143. else if (F.inCoeffDomain() && G.inCoeffDomain())
  144. {
  145. divrem (F, G, Q, R);
  146. return;
  147. }
  148. else if (F.isUnivariate() && G.inCoeffDomain())
  149. {
  150. divrem (F, G, Q, R);
  151. return;
  152. }
  153. ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
  154. ASSERT (F.level() == G.level(), "expected polys of same level");
  155. if (CFFactory::gettype() == GaloisFieldDomain)
  156. {
  157. divrem (F, G, Q, R);
  158. return;
  159. }
  160. zz_p::init (getCharacteristic());
  161. Variable alpha;
  162. CanonicalForm result;
  163. if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
  164. {
  165. zz_pX NTLMipo= convertFacCF2NTLzzpX(getMipo (alpha));
  166. zz_pE::init (NTLMipo);
  167. zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
  168. zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
  169. zz_pEX NTLQ;
  170. zz_pEX NTLR;
  171. DivRem (NTLQ, NTLR, NTLF, NTLG);
  172. Q= convertNTLzz_pEX2CF(NTLQ, F.mvar(), alpha);
  173. R= convertNTLzz_pEX2CF(NTLR, F.mvar(), alpha);
  174. return;
  175. }
  176. else
  177. {
  178. zz_pX NTLF= convertFacCF2NTLzzpX (F);
  179. zz_pX NTLG= convertFacCF2NTLzzpX (G);
  180. zz_pX NTLQ;
  181. zz_pX NTLR;
  182. DivRem (NTLQ, NTLR, NTLF, NTLG);
  183. Q= convertNTLzzpX2CF(NTLQ, F.mvar());
  184. R= convertNTLzzpX2CF(NTLR, F.mvar());
  185. return;
  186. }
  187. }*/
  188. CanonicalForm mod (const CanonicalForm& F, const CFList& M)
  189. {
  190. CanonicalForm A= F;
  191. for (CFListIterator i= M; i.hasItem(); i++)
  192. A= mod (A, i.getItem());
  193. return A;
  194. }
  195. zz_pX kronSubFp (const CanonicalForm& A, int d)
  196. {
  197. int degAy= degree (A);
  198. zz_pX result;
  199. result.rep.SetLength (d*(degAy + 1));
  200. zz_p *resultp;
  201. resultp= result.rep.elts();
  202. zz_pX buf;
  203. zz_p *bufp;
  204. for (CFIterator i= A; i.hasTerms(); i++)
  205. {
  206. if (i.coeff().inCoeffDomain())
  207. buf= convertFacCF2NTLzzpX (i.coeff());
  208. else
  209. buf= convertFacCF2NTLzzpX (i.coeff());
  210. int k= i.exp()*d;
  211. bufp= buf.rep.elts();
  212. int bufRepLength= (int) buf.rep.length();
  213. for (int j= 0; j < bufRepLength; j++)
  214. resultp [j + k]= bufp [j];
  215. }
  216. result.normalize();
  217. return result;
  218. }
  219. zz_pEX kronSub (const CanonicalForm& A, int d, const Variable& alpha)
  220. {
  221. int degAy= degree (A);
  222. zz_pEX result;
  223. result.rep.SetLength (d*(degAy + 1));
  224. Variable v;
  225. zz_pE *resultp;
  226. resultp= result.rep.elts();
  227. zz_pEX buf1;
  228. zz_pE *buf1p;
  229. zz_pX buf2;
  230. zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
  231. for (CFIterator i= A; i.hasTerms(); i++)
  232. {
  233. if (i.coeff().inCoeffDomain())
  234. {
  235. buf2= convertFacCF2NTLzzpX (i.coeff());
  236. buf1= to_zz_pEX (to_zz_pE (buf2));
  237. }
  238. else
  239. buf1= convertFacCF2NTLzz_pEX (i.coeff(), NTLMipo);
  240. int k= i.exp()*d;
  241. buf1p= buf1.rep.elts();
  242. int buf1RepLength= (int) buf1.rep.length();
  243. for (int j= 0; j < buf1RepLength; j++)
  244. resultp [j + k]= buf1p [j];
  245. }
  246. result.normalize();
  247. return result;
  248. }
  249. void
  250. kronSubRecipro (zz_pEX& subA1, zz_pEX& subA2,const CanonicalForm& A, int d,
  251. const Variable& alpha)
  252. {
  253. int degAy= degree (A);
  254. subA1.rep.SetLength ((long) d*(degAy + 1));
  255. subA2.rep.SetLength ((long) d*(degAy + 1));
  256. Variable v;
  257. zz_pE *subA1p;
  258. zz_pE *subA2p;
  259. subA1p= subA1.rep.elts();
  260. subA2p= subA2.rep.elts();
  261. zz_pEX buf;
  262. zz_pE *bufp;
  263. zz_pX buf2;
  264. zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
  265. for (CFIterator i= A; i.hasTerms(); i++)
  266. {
  267. if (i.coeff().inCoeffDomain())
  268. {
  269. buf2= convertFacCF2NTLzzpX (i.coeff());
  270. buf= to_zz_pEX (to_zz_pE (buf2));
  271. }
  272. else
  273. buf= convertFacCF2NTLzz_pEX (i.coeff(), NTLMipo);
  274. int k= i.exp()*d;
  275. int kk= (degAy - i.exp())*d;
  276. bufp= buf.rep.elts();
  277. int bufRepLength= (int) buf.rep.length();
  278. for (int j= 0; j < bufRepLength; j++)
  279. {
  280. subA1p [j + k]= bufp [j];
  281. subA2p [j + kk]= bufp [j];
  282. }
  283. }
  284. subA1.normalize();
  285. subA2.normalize();
  286. }
  287. void
  288. kronSubRecipro (zz_pX& subA1, zz_pX& subA2,const CanonicalForm& A, int d)
  289. {
  290. int degAy= degree (A);
  291. subA1.rep.SetLength ((long) d*(degAy + 1));
  292. subA2.rep.SetLength ((long) d*(degAy + 1));
  293. Variable v;
  294. zz_p *subA1p;
  295. zz_p *subA2p;
  296. subA1p= subA1.rep.elts();
  297. subA2p= subA2.rep.elts();
  298. zz_pX buf;
  299. zz_p *bufp;
  300. for (CFIterator i= A; i.hasTerms(); i++)
  301. {
  302. buf= convertFacCF2NTLzzpX (i.coeff());
  303. int k= i.exp()*d;
  304. int kk= (degAy - i.exp())*d;
  305. bufp= buf.rep.elts();
  306. int bufRepLength= (int) buf.rep.length();
  307. for (int j= 0; j < bufRepLength; j++)
  308. {
  309. subA1p [j + k]= bufp [j];
  310. subA2p [j + kk]= bufp [j];
  311. }
  312. }
  313. subA1.normalize();
  314. subA2.normalize();
  315. }
  316. CanonicalForm
  317. reverseSubst (const zz_pEX& F, const zz_pEX& G, int d, int k,
  318. const Variable& alpha)
  319. {
  320. Variable y= Variable (2);
  321. Variable x= Variable (1);
  322. zz_pEX f= F;
  323. zz_pEX g= G;
  324. int degf= deg(f);
  325. int degg= deg(g);
  326. zz_pEX buf1;
  327. zz_pEX buf2;
  328. zz_pEX buf3;
  329. zz_pE *buf1p;
  330. zz_pE *buf2p;
  331. zz_pE *buf3p;
  332. if (f.rep.length() < (long) d*(k+1)) //zero padding
  333. f.rep.SetLength ((long)d*(k+1));
  334. zz_pE *gp= g.rep.elts();
  335. zz_pE *fp= f.rep.elts();
  336. CanonicalForm result= 0;
  337. int i= 0;
  338. int lf= 0;
  339. int lg= d*k;
  340. int degfSubLf= degf;
  341. int deggSubLg= degg-lg;
  342. int repLengthBuf2;
  343. int repLengthBuf1;
  344. zz_pE zzpEZero= zz_pE();
  345. while (degf >= lf || lg >= 0)
  346. {
  347. if (degfSubLf >= d)
  348. repLengthBuf1= d;
  349. else if (degfSubLf < 0)
  350. repLengthBuf1= 0;
  351. else
  352. repLengthBuf1= degfSubLf + 1;
  353. buf1.rep.SetLength((long) repLengthBuf1);
  354. buf1p= buf1.rep.elts();
  355. for (int ind= 0; ind < repLengthBuf1; ind++)
  356. buf1p [ind]= fp [ind + lf];
  357. buf1.normalize();
  358. repLengthBuf1= buf1.rep.length();
  359. if (deggSubLg >= d - 1)
  360. repLengthBuf2= d - 1;
  361. else if (deggSubLg < 0)
  362. repLengthBuf2= 0;
  363. else
  364. repLengthBuf2= deggSubLg + 1;
  365. buf2.rep.SetLength ((long) repLengthBuf2);
  366. buf2p= buf2.rep.elts();
  367. for (int ind= 0; ind < repLengthBuf2; ind++)
  368. {
  369. buf2p [ind]= gp [ind + lg];
  370. }
  371. buf2.normalize();
  372. repLengthBuf2= buf2.rep.length();
  373. buf3.rep.SetLength((long) repLengthBuf2 + d);
  374. buf3p= buf3.rep.elts();
  375. buf2p= buf2.rep.elts();
  376. buf1p= buf1.rep.elts();
  377. for (int ind= 0; ind < repLengthBuf1; ind++)
  378. buf3p [ind]= buf1p [ind];
  379. for (int ind= repLengthBuf1; ind < d; ind++)
  380. buf3p [ind]= zzpEZero;
  381. for (int ind= 0; ind < repLengthBuf2; ind++)
  382. buf3p [ind + d]= buf2p [ind];
  383. buf3.normalize();
  384. result += convertNTLzz_pEX2CF (buf3, x, alpha)*power (y, i);
  385. i++;
  386. lf= i*d;
  387. degfSubLf= degf - lf;
  388. lg= d*(k-i);
  389. deggSubLg= degg - lg;
  390. buf1p= buf1.rep.elts();
  391. if (lg >= 0 && deggSubLg > 0)
  392. {
  393. if (repLengthBuf2 > degfSubLf + 1)
  394. degfSubLf= repLengthBuf2 - 1;
  395. int tmp= tmin (repLengthBuf1, deggSubLg);
  396. for (int ind= 0; ind < tmp; ind++)
  397. gp [ind + lg] -= buf1p [ind];
  398. }
  399. if (lg < 0)
  400. break;
  401. buf2p= buf2.rep.elts();
  402. if (degfSubLf >= 0)
  403. {
  404. for (int ind= 0; ind < repLengthBuf2; ind++)
  405. fp [ind + lf] -= buf2p [ind];
  406. }
  407. }
  408. return result;
  409. }
  410. CanonicalForm
  411. reverseSubst (const zz_pX& F, const zz_pX& G, int d, int k)
  412. {
  413. Variable y= Variable (2);
  414. Variable x= Variable (1);
  415. zz_pX f= F;
  416. zz_pX g= G;
  417. int degf= deg(f);
  418. int degg= deg(g);
  419. zz_pX buf1;
  420. zz_pX buf2;
  421. zz_pX buf3;
  422. zz_p *buf1p;
  423. zz_p *buf2p;
  424. zz_p *buf3p;
  425. if (f.rep.length() < (long) d*(k+1)) //zero padding
  426. f.rep.SetLength ((long)d*(k+1));
  427. zz_p *gp= g.rep.elts();
  428. zz_p *fp= f.rep.elts();
  429. CanonicalForm result= 0;
  430. int i= 0;
  431. int lf= 0;
  432. int lg= d*k;
  433. int degfSubLf= degf;
  434. int deggSubLg= degg-lg;
  435. int repLengthBuf2;
  436. int repLengthBuf1;
  437. zz_p zzpZero= zz_p();
  438. while (degf >= lf || lg >= 0)
  439. {
  440. if (degfSubLf >= d)
  441. repLengthBuf1= d;
  442. else if (degfSubLf < 0)
  443. repLengthBuf1= 0;
  444. else
  445. repLengthBuf1= degfSubLf + 1;
  446. buf1.rep.SetLength((long) repLengthBuf1);
  447. buf1p= buf1.rep.elts();
  448. for (int ind= 0; ind < repLengthBuf1; ind++)
  449. buf1p [ind]= fp [ind + lf];
  450. buf1.normalize();
  451. repLengthBuf1= buf1.rep.length();
  452. if (deggSubLg >= d - 1)
  453. repLengthBuf2= d - 1;
  454. else if (deggSubLg < 0)
  455. repLengthBuf2= 0;
  456. else
  457. repLengthBuf2= deggSubLg + 1;
  458. buf2.rep.SetLength ((long) repLengthBuf2);
  459. buf2p= buf2.rep.elts();
  460. for (int ind= 0; ind < repLengthBuf2; ind++)
  461. buf2p [ind]= gp [ind + lg];
  462. buf2.normalize();
  463. repLengthBuf2= buf2.rep.length();
  464. buf3.rep.SetLength((long) repLengthBuf2 + d);
  465. buf3p= buf3.rep.elts();
  466. buf2p= buf2.rep.elts();
  467. buf1p= buf1.rep.elts();
  468. for (int ind= 0; ind < repLengthBuf1; ind++)
  469. buf3p [ind]= buf1p [ind];
  470. for (int ind= repLengthBuf1; ind < d; ind++)
  471. buf3p [ind]= zzpZero;
  472. for (int ind= 0; ind < repLengthBuf2; ind++)
  473. buf3p [ind + d]= buf2p [ind];
  474. buf3.normalize();
  475. result += convertNTLzzpX2CF (buf3, x)*power (y, i);
  476. i++;
  477. lf= i*d;
  478. degfSubLf= degf - lf;
  479. lg= d*(k-i);
  480. deggSubLg= degg - lg;
  481. buf1p= buf1.rep.elts();
  482. if (lg >= 0 && deggSubLg > 0)
  483. {
  484. if (repLengthBuf2 > degfSubLf + 1)
  485. degfSubLf= repLengthBuf2 - 1;
  486. int tmp= tmin (repLengthBuf1, deggSubLg);
  487. for (int ind= 0; ind < tmp; ind++)
  488. gp [ind + lg] -= buf1p [ind];
  489. }
  490. if (lg < 0)
  491. break;
  492. buf2p= buf2.rep.elts();
  493. if (degfSubLf >= 0)
  494. {
  495. for (int ind= 0; ind < repLengthBuf2; ind++)
  496. fp [ind + lf] -= buf2p [ind];
  497. }
  498. }
  499. return result;
  500. }
  501. CanonicalForm reverseSubst (const zz_pEX& F, int d, const Variable& alpha)
  502. {
  503. Variable y= Variable (2);
  504. Variable x= Variable (1);
  505. zz_pEX f= F;
  506. zz_pE *fp= f.rep.elts();
  507. zz_pEX buf;
  508. zz_pE *bufp;
  509. CanonicalForm result= 0;
  510. int i= 0;
  511. int degf= deg(f);
  512. int k= 0;
  513. int degfSubK;
  514. int repLength;
  515. while (degf >= k)
  516. {
  517. degfSubK= degf - k;
  518. if (degfSubK >= d)
  519. repLength= d;
  520. else
  521. repLength= degfSubK + 1;
  522. buf.rep.SetLength ((long) repLength);
  523. bufp= buf.rep.elts();
  524. for (int j= 0; j < repLength; j++)
  525. bufp [j]= fp [j + k];
  526. buf.normalize();
  527. result += convertNTLzz_pEX2CF (buf, x, alpha)*power (y, i);
  528. i++;
  529. k= d*i;
  530. }
  531. return result;
  532. }
  533. CanonicalForm reverseSubstFp (const zz_pX& F, int d)
  534. {
  535. Variable y= Variable (2);
  536. Variable x= Variable (1);
  537. zz_pX f= F;
  538. zz_p *fp= f.rep.elts();
  539. zz_pX buf;
  540. zz_p *bufp;
  541. CanonicalForm result= 0;
  542. int i= 0;
  543. int degf= deg(f);
  544. int k= 0;
  545. int degfSubK;
  546. int repLength;
  547. while (degf >= k)
  548. {
  549. degfSubK= degf - k;
  550. if (degfSubK >= d)
  551. repLength= d;
  552. else
  553. repLength= degfSubK + 1;
  554. buf.rep.SetLength ((long) repLength);
  555. bufp= buf.rep.elts();
  556. for (int j= 0; j < repLength; j++)
  557. bufp [j]= fp [j + k];
  558. buf.normalize();
  559. result += convertNTLzzpX2CF (buf, x)*power (y, i);
  560. i++;
  561. k= d*i;
  562. }
  563. return result;
  564. }
  565. // assumes input to be reduced mod M and to be an element of Fq not Fp
  566. CanonicalForm
  567. mulMod2NTLFpReci (const CanonicalForm& F, const CanonicalForm& G, const
  568. CanonicalForm& M)
  569. {
  570. int d1= tmax (degree (F, 1), degree (G, 1)) + 1;
  571. int d2= tmax (degree (F, 2), degree (G, 2));
  572. zz_pX F1, F2;
  573. kronSubRecipro (F1, F2, F, d1);
  574. zz_pX G1, G2;
  575. kronSubRecipro (G1, G2, G, d1);
  576. int k= d1*degree (M);
  577. MulTrunc (F1, F1, G1, (long) k);
  578. mul (F2, F2, G2);
  579. if (deg (F2) > k)
  580. F2 >>= (k - d1);
  581. return reverseSubst (F1, F2, d1, d2);
  582. }
  583. //Kronecker substitution
  584. CanonicalForm
  585. mulMod2NTLFp (const CanonicalForm& F, const CanonicalForm& G, const
  586. CanonicalForm& M)
  587. {
  588. CanonicalForm A= F;
  589. CanonicalForm B= G;
  590. int degAx= degree (A, 1);
  591. int degAy= degree (A, 2);
  592. int degBx= degree (B, 1);
  593. int degBy= degree (B, 2);
  594. int d1= degAx + 1 + degBx;
  595. int d2= tmax (degree (A, 2), degree (B, 2));
  596. if (d1 > 128 && d2 > 160 && (degAy == degBy) && (2*degAy > degree (M)))
  597. return mulMod2NTLFpReci (A, B, M);
  598. zz_pX NTLA= kronSubFp (A, d1);
  599. zz_pX NTLB= kronSubFp (B, d1);
  600. int k= d1*degree (M);
  601. MulTrunc (NTLA, NTLA, NTLB, (long) k);
  602. A= reverseSubstFp (NTLA, d1);
  603. return A;
  604. }
  605. // assumes input to be reduced mod M and to be an element of Fq not Fp
  606. CanonicalForm
  607. mulMod2NTLFqReci (const CanonicalForm& F, const CanonicalForm& G, const
  608. CanonicalForm& M, const Variable& alpha)
  609. {
  610. int d1= tmax (degree (F, 1), degree (G, 1)) + 1;
  611. int d2= tmax (degree (F, 2), degree (G, 2));
  612. zz_pEX F1, F2;
  613. kronSubRecipro (F1, F2, F, d1, alpha);
  614. zz_pEX G1, G2;
  615. kronSubRecipro (G1, G2, G, d1, alpha);
  616. int k= d1*degree (M);
  617. MulTrunc (F1, F1, G1, (long) k);
  618. mul (F2, F2, G2);
  619. if (deg (F2) > k)
  620. F2 >>= (k-d1);
  621. CanonicalForm result= reverseSubst (F1, F2, d1, d2, alpha);
  622. return result;
  623. }
  624. CanonicalForm
  625. mulMod2NTLFq (const CanonicalForm& F, const CanonicalForm& G, const
  626. CanonicalForm& M)
  627. {
  628. Variable alpha;
  629. CanonicalForm A= F;
  630. CanonicalForm B= G;
  631. if (hasFirstAlgVar (A, alpha) || hasFirstAlgVar (B, alpha))
  632. {
  633. int degAx= degree (A, 1);
  634. int degAy= degree (A, 2);
  635. int degBx= degree (B, 1);
  636. int degBy= degree (B, 2);
  637. int d1= degAx + degBx + 1;
  638. int d2= tmax (degree (A, 2), degree (B, 2));
  639. zz_p::init (getCharacteristic());
  640. zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
  641. zz_pE::init (NTLMipo);
  642. int degMipo= degree (getMipo (alpha));
  643. if ((d1 > 128/degMipo) && (d2 > 160/degMipo) && (degAy == degBy) &&
  644. (2*degAy > degree (M)))
  645. return mulMod2NTLFqReci (A, B, M, alpha);
  646. zz_pEX NTLA= kronSub (A, d1, alpha);
  647. zz_pEX NTLB= kronSub (B, d1, alpha);
  648. int k= d1*degree (M);
  649. MulTrunc (NTLA, NTLA, NTLB, (long) k);
  650. A= reverseSubst (NTLA, d1, alpha);
  651. return A;
  652. }
  653. else
  654. return mulMod2NTLFp (A, B, M);
  655. }
  656. CanonicalForm mulMod2 (const CanonicalForm& A, const CanonicalForm& B,
  657. const CanonicalForm& M)
  658. {
  659. if (A.isZero() || B.isZero())
  660. return 0;
  661. ASSERT (M.isUnivariate(), "M must be univariate");
  662. CanonicalForm F= mod (A, M);
  663. CanonicalForm G= mod (B, M);
  664. if (F.inCoeffDomain() || G.inCoeffDomain())
  665. return F*G;
  666. Variable y= M.mvar();
  667. int degF= degree (F, y);
  668. int degG= degree (G, y);
  669. if ((degF < 1 && degG < 1) && (F.isUnivariate() && G.isUnivariate()) &&
  670. (F.level() == G.level()))
  671. {
  672. CanonicalForm result= mulNTL (F, G);
  673. return mod (result, M);
  674. }
  675. else if (degF <= 1 && degG <= 1)
  676. {
  677. CanonicalForm result= F*G;
  678. return mod (result, M);
  679. }
  680. int sizeF= size (F);
  681. int sizeG= size (G);
  682. int fallBackToNaive= 50;
  683. if (sizeF < fallBackToNaive || sizeG < fallBackToNaive)
  684. return mod (F*G, M);
  685. if (getCharacteristic() > 0 && CFFactory::gettype() != GaloisFieldDomain &&
  686. (((degF-degG) < 50 && degF > degG) || ((degG-degF) < 50 && degF <= degG)))
  687. return mulMod2NTLFq (F, G, M);
  688. int m= (int) ceil (degree (M)/2.0);
  689. if (degF >= m || degG >= m)
  690. {
  691. CanonicalForm MLo= power (y, m);
  692. CanonicalForm MHi= power (y, degree (M) - m);
  693. CanonicalForm F0= mod (F, MLo);
  694. CanonicalForm F1= div (F, MLo);
  695. CanonicalForm G0= mod (G, MLo);
  696. CanonicalForm G1= div (G, MLo);
  697. CanonicalForm F0G1= mulMod2 (F0, G1, MHi);
  698. CanonicalForm F1G0= mulMod2 (F1, G0, MHi);
  699. CanonicalForm F0G0= mulMod2 (F0, G0, M);
  700. return F0G0 + MLo*(F0G1 + F1G0);
  701. }
  702. else
  703. {
  704. m= (int) ceil (tmax (degF, degG)/2.0);
  705. CanonicalForm yToM= power (y, m);
  706. CanonicalForm F0= mod (F, yToM);
  707. CanonicalForm F1= div (F, yToM);
  708. CanonicalForm G0= mod (G, yToM);
  709. CanonicalForm G1= div (G, yToM);
  710. CanonicalForm H00= mulMod2 (F0, G0, M);
  711. CanonicalForm H11= mulMod2 (F1, G1, M);
  712. CanonicalForm H01= mulMod2 (F0 + F1, G0 + G1, M);
  713. return H11*yToM*yToM + (H01 - H11 - H00)*yToM + H00;
  714. }
  715. DEBOUTLN (cerr, "fatal end in mulMod2");
  716. }
  717. CanonicalForm mulMod (const CanonicalForm& A, const CanonicalForm& B,
  718. const CFList& MOD)
  719. {
  720. if (A.isZero() || B.isZero())
  721. return 0;
  722. if (MOD.length() == 1)
  723. return mulMod2 (A, B, MOD.getLast());
  724. CanonicalForm M= MOD.getLast();
  725. CanonicalForm F= mod (A, M);
  726. CanonicalForm G= mod (B, M);
  727. if (F.inCoeffDomain() || G.inCoeffDomain())
  728. return F*G;
  729. Variable y= M.mvar();
  730. int degF= degree (F, y);
  731. int degG= degree (G, y);
  732. if ((degF <= 1 && F.level() <= M.level()) &&
  733. (degG <= 1 && G.level() <= M.level()))
  734. {
  735. CFList buf= MOD;
  736. buf.removeLast();
  737. if (degF == 1 && degG == 1)
  738. {
  739. CanonicalForm F0= mod (F, y);
  740. CanonicalForm F1= div (F, y);
  741. CanonicalForm G0= mod (G, y);
  742. CanonicalForm G1= div (G, y);
  743. if (degree (M) > 2)
  744. {
  745. CanonicalForm H00= mulMod (F0, G0, buf);
  746. CanonicalForm H11= mulMod (F1, G1, buf);
  747. CanonicalForm H01= mulMod (F0 + F1, G0 + G1, buf);
  748. return H11*y*y + (H01 - H00 - H11)*y + H00;
  749. }
  750. else //here degree (M) == 2
  751. {
  752. buf.append (y);
  753. CanonicalForm F0G1= mulMod (F0, G1, buf);
  754. CanonicalForm F1G0= mulMod (F1, G0, buf);
  755. CanonicalForm F0G0= mulMod (F0, G0, MOD);
  756. CanonicalForm result= F0G0 + y*(F0G1 + F1G0);
  757. return result;
  758. }
  759. }
  760. else if (degF == 1 && degG == 0)
  761. return mulMod (div (F, y), G, buf)*y + mulMod (mod (F, y), G, buf);
  762. else if (degF == 0 && degG == 1)
  763. return mulMod (div (G, y), F, buf)*y + mulMod (mod (G, y), F, buf);
  764. else
  765. return mulMod (F, G, buf);
  766. }
  767. int m= (int) ceil (degree (M)/2.0);
  768. if (degF >= m || degG >= m)
  769. {
  770. CanonicalForm MLo= power (y, m);
  771. CanonicalForm MHi= power (y, degree (M) - m);
  772. CanonicalForm F0= mod (F, MLo);
  773. CanonicalForm F1= div (F, MLo);
  774. CanonicalForm G0= mod (G, MLo);
  775. CanonicalForm G1= div (G, MLo);
  776. CFList buf= MOD;
  777. buf.removeLast();
  778. buf.append (MHi);
  779. CanonicalForm F0G1= mulMod (F0, G1, buf);
  780. CanonicalForm F1G0= mulMod (F1, G0, buf);
  781. CanonicalForm F0G0= mulMod (F0, G0, MOD);
  782. return F0G0 + MLo*(F0G1 + F1G0);
  783. }
  784. else
  785. {
  786. m= (int) ceil (tmax (degF, degG)/2.0);
  787. CanonicalForm yToM= power (y, m);
  788. CanonicalForm F0= mod (F, yToM);
  789. CanonicalForm F1= div (F, yToM);
  790. CanonicalForm G0= mod (G, yToM);
  791. CanonicalForm G1= div (G, yToM);
  792. CanonicalForm H00= mulMod (F0, G0, MOD);
  793. CanonicalForm H11= mulMod (F1, G1, MOD);
  794. CanonicalForm H01= mulMod (F0 + F1, G0 + G1, MOD);
  795. return H11*yToM*yToM + (H01 - H11 - H00)*yToM + H00;
  796. }
  797. DEBOUTLN (cerr, "fatal end in mulMod");
  798. }
  799. CanonicalForm prodMod (const CFList& L, const CanonicalForm& M)
  800. {
  801. if (L.isEmpty())
  802. return 1;
  803. int l= L.length();
  804. if (l == 1)
  805. return mod (L.getFirst(), M);
  806. else if (l == 2) {
  807. CanonicalForm result= mulMod2 (L.getFirst(), L.getLast(), M);
  808. return result;
  809. }
  810. else
  811. {
  812. l /= 2;
  813. CFList tmp1, tmp2;
  814. CFListIterator i= L;
  815. CanonicalForm buf1, buf2;
  816. for (int j= 1; j <= l; j++, i++)
  817. tmp1.append (i.getItem());
  818. tmp2= Difference (L, tmp1);
  819. buf1= prodMod (tmp1, M);
  820. buf2= prodMod (tmp2, M);
  821. CanonicalForm result= mulMod2 (buf1, buf2, M);
  822. return result;
  823. }
  824. }
  825. CanonicalForm prodMod (const CFList& L, const CFList& M)
  826. {
  827. if (L.isEmpty())
  828. return 1;
  829. else if (L.length() == 1)
  830. return L.getFirst();
  831. else if (L.length() == 2)
  832. return mulMod (L.getFirst(), L.getLast(), M);
  833. else
  834. {
  835. int l= L.length()/2;
  836. CFListIterator i= L;
  837. CFList tmp1, tmp2;
  838. CanonicalForm buf1, buf2;
  839. for (int j= 1; j <= l; j++, i++)
  840. tmp1.append (i.getItem());
  841. tmp2= Difference (L, tmp1);
  842. buf1= prodMod (tmp1, M);
  843. buf2= prodMod (tmp2, M);
  844. return mulMod (buf1, buf2, M);
  845. }
  846. }
  847. CanonicalForm reverse (const CanonicalForm& F, int d)
  848. {
  849. if (d == 0)
  850. return F;
  851. CanonicalForm A= F;
  852. Variable y= Variable (2);
  853. Variable x= Variable (1);
  854. if (degree (A, x) > 0)
  855. {
  856. A= swapvar (A, x, y);
  857. CanonicalForm result= 0;
  858. CFIterator i= A;
  859. while (d - i.exp() < 0)
  860. i++;
  861. for (; i.hasTerms() && (d - i.exp() >= 0); i++)
  862. result += swapvar (i.coeff(),x,y)*power (x, d - i.exp());
  863. return result;
  864. }
  865. else
  866. return A*power (x, d);
  867. }
  868. CanonicalForm
  869. newtonInverse (const CanonicalForm& F, const int n, const CanonicalForm& M)
  870. {
  871. int l= ilog2(n);
  872. CanonicalForm g= mod (F, M)[0] [0];
  873. ASSERT (!g.isZero(), "expected a unit");
  874. Variable alpha;
  875. if (!g.isOne())
  876. g = 1/g;
  877. Variable x= Variable (1);
  878. CanonicalForm result;
  879. int exp= 0;
  880. if (n & 1)
  881. {
  882. result= g;
  883. exp= 1;
  884. }
  885. CanonicalForm h;
  886. for (int i= 1; i <= l; i++)
  887. {
  888. h= mulMod2 (g, mod (F, power (x, (1 << i))), M);
  889. h= mod (h, power (x, (1 << i)) - 1);
  890. h= div (h, power (x, (1 << (i - 1))));
  891. h= mod (h, M);
  892. g -= power (x, (1 << (i - 1)))*
  893. mod (mulMod2 (g, h, M), power (x, (1 << (i - 1))));
  894. if (n & (1 << i))
  895. {
  896. if (exp)
  897. {
  898. h= mulMod2 (result, mod (F, power (x, exp + (1 << i))), M);
  899. h= mod (h, power (x, exp + (1 << i)) - 1);
  900. h= div (h, power (x, exp));
  901. h= mod (h, M);
  902. result -= power(x, exp)*mod (mulMod2 (g, h, M),
  903. power (x, (1 << i)));
  904. exp += (1 << i);
  905. }
  906. else
  907. {
  908. exp= (1 << i);
  909. result= g;
  910. }
  911. }
  912. }
  913. return result;
  914. }
  915. CanonicalForm
  916. newtonDiv (const CanonicalForm& F, const CanonicalForm& G, const CanonicalForm&
  917. M)
  918. {
  919. ASSERT (getCharacteristic() > 0, "positive characteristic expected");
  920. ASSERT (CFFactory::gettype() != GaloisFieldDomain, "no GF expected");
  921. CanonicalForm A= mod (F, M);
  922. CanonicalForm B= mod (G, M);
  923. Variable x= Variable (1);
  924. int degA= degree (A, x);
  925. int degB= degree (B, x);
  926. int m= degA - degB;
  927. if (m < 0)
  928. return 0;
  929. CanonicalForm Q;
  930. if (degB <= 1 || CFFactory::gettype() == GaloisFieldDomain)
  931. {
  932. CanonicalForm R;
  933. divrem2 (A, B, Q, R, M);
  934. }
  935. else
  936. {
  937. CanonicalForm R= reverse (A, degA);
  938. CanonicalForm revB= reverse (B, degB);
  939. revB= newtonInverse (revB, m + 1, M);
  940. Q= mulMod2 (R, revB, M);
  941. Q= mod (Q, power (x, m + 1));
  942. Q= reverse (Q, m);
  943. }
  944. return Q;
  945. }
  946. void
  947. newtonDivrem (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  948. CanonicalForm& R, const CanonicalForm& M)
  949. {
  950. CanonicalForm A= mod (F, M);
  951. CanonicalForm B= mod (G, M);
  952. Variable x= Variable (1);
  953. int degA= degree (A, x);
  954. int degB= degree (B, x);
  955. int m= degA - degB;
  956. if (m < 0)
  957. {
  958. R= A;
  959. Q= 0;
  960. return;
  961. }
  962. if (degB <= 1 || CFFactory::gettype() == GaloisFieldDomain)
  963. {
  964. divrem2 (A, B, Q, R, M);
  965. }
  966. else
  967. {
  968. R= reverse (A, degA);
  969. CanonicalForm revB= reverse (B, degB);
  970. revB= newtonInverse (revB, m + 1, M);
  971. Q= mulMod2 (R, revB, M);
  972. Q= mod (Q, power (x, m + 1));
  973. Q= reverse (Q, m);
  974. R= A - mulMod2 (Q, B, M);
  975. }
  976. }
  977. static inline
  978. CFList split (const CanonicalForm& F, const int m, const Variable& x)
  979. {
  980. CanonicalForm A= F;
  981. CanonicalForm buf= 0;
  982. bool swap= false;
  983. if (degree (A, x) <= 0)
  984. return CFList(A);
  985. else if (x.level() != A.level())
  986. {
  987. swap= true;
  988. A= swapvar (A, x, A.mvar());
  989. }
  990. int j= (int) floor ((double) degree (A)/ m);
  991. CFList result;
  992. CFIterator i= A;
  993. for (; j >= 0; j--)
  994. {
  995. while (i.hasTerms() && i.exp() - j*m >= 0)
  996. {
  997. if (swap)
  998. buf += i.coeff()*power (A.mvar(), i.exp() - j*m);
  999. else
  1000. buf += i.coeff()*power (x, i.exp() - j*m);
  1001. i++;
  1002. }
  1003. if (swap)
  1004. result.append (swapvar (buf, x, F.mvar()));
  1005. else
  1006. result.append (buf);
  1007. buf= 0;
  1008. }
  1009. return result;
  1010. }
  1011. static inline
  1012. void divrem32 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  1013. CanonicalForm& R, const CFList& M);
  1014. static inline
  1015. void divrem21 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  1016. CanonicalForm& R, const CFList& M)
  1017. {
  1018. CanonicalForm A= mod (F, M);
  1019. CanonicalForm B= mod (G, M);
  1020. Variable x= Variable (1);
  1021. int degB= degree (B, x);
  1022. int degA= degree (A, x);
  1023. if (degA < degB)
  1024. {
  1025. Q= 0;
  1026. R= A;
  1027. return;
  1028. }
  1029. ASSERT (2*degB > degA, "expected degree (F, 1) < 2*degree (G, 1)");
  1030. if (degB < 1)
  1031. {
  1032. divrem (A, B, Q, R);
  1033. Q= mod (Q, M);
  1034. R= mod (R, M);
  1035. return;
  1036. }
  1037. int m= (int) ceil ((double) (degB + 1)/2.0) + 1;
  1038. CFList splitA= split (A, m, x);
  1039. if (splitA.length() == 3)
  1040. splitA.insert (0);
  1041. if (splitA.length() == 2)
  1042. {
  1043. splitA.insert (0);
  1044. splitA.insert (0);
  1045. }
  1046. if (splitA.length() == 1)
  1047. {
  1048. splitA.insert (0);
  1049. splitA.insert (0);
  1050. splitA.insert (0);
  1051. }
  1052. CanonicalForm xToM= power (x, m);
  1053. CFListIterator i= splitA;
  1054. CanonicalForm H= i.getItem();
  1055. i++;
  1056. H *= xToM;
  1057. H += i.getItem();
  1058. i++;
  1059. H *= xToM;
  1060. H += i.getItem();
  1061. i++;
  1062. divrem32 (H, B, Q, R, M);
  1063. CFList splitR= split (R, m, x);
  1064. if (splitR.length() == 1)
  1065. splitR.insert (0);
  1066. H= splitR.getFirst();
  1067. H *= xToM;
  1068. H += splitR.getLast();
  1069. H *= xToM;
  1070. H += i.getItem();
  1071. CanonicalForm bufQ;
  1072. divrem32 (H, B, bufQ, R, M);
  1073. Q *= xToM;
  1074. Q += bufQ;
  1075. return;
  1076. }
  1077. static inline
  1078. void divrem32 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  1079. CanonicalForm& R, const CFList& M)
  1080. {
  1081. CanonicalForm A= mod (F, M);
  1082. CanonicalForm B= mod (G, M);
  1083. Variable x= Variable (1);
  1084. int degB= degree (B, x);
  1085. int degA= degree (A, x);
  1086. if (degA < degB)
  1087. {
  1088. Q= 0;
  1089. R= A;
  1090. return;
  1091. }
  1092. ASSERT (3*(degB/2) > degA, "expected degree (F, 1) < 3*(degree (G, 1)/2)");
  1093. if (degB < 1)
  1094. {
  1095. divrem (A, B, Q, R);
  1096. Q= mod (Q, M);
  1097. R= mod (R, M);
  1098. return;
  1099. }
  1100. int m= (int) ceil ((double) (degB + 1)/ 2.0);
  1101. CFList splitA= split (A, m, x);
  1102. CFList splitB= split (B, m, x);
  1103. if (splitA.length() == 2)
  1104. {
  1105. splitA.insert (0);
  1106. }
  1107. if (splitA.length() == 1)
  1108. {
  1109. splitA.insert (0);
  1110. splitA.insert (0);
  1111. }
  1112. CanonicalForm xToM= power (x, m);
  1113. CanonicalForm H;
  1114. CFListIterator i= splitA;
  1115. i++;
  1116. if (degree (splitA.getFirst(), x) < degree (splitB.getFirst(), x))
  1117. {
  1118. H= splitA.getFirst()*xToM + i.getItem();
  1119. divrem21 (H, splitB.getFirst(), Q, R, M);
  1120. }
  1121. else
  1122. {
  1123. R= splitA.getFirst()*xToM + i.getItem() + splitB.getFirst() -
  1124. splitB.getFirst()*xToM;
  1125. Q= xToM - 1;
  1126. }
  1127. H= mulMod (Q, splitB.getLast(), M);
  1128. R= R*xToM + splitA.getLast() - H;
  1129. while (degree (R, x) >= degB)
  1130. {
  1131. xToM= power (x, degree (R, x) - degB);
  1132. Q += LC (R, x)*xToM;
  1133. R -= mulMod (LC (R, x), B, M)*xToM;
  1134. Q= mod (Q, M);
  1135. R= mod (R, M);
  1136. }
  1137. return;
  1138. }
  1139. void divrem2 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  1140. CanonicalForm& R, const CanonicalForm& M)
  1141. {
  1142. CanonicalForm A= mod (F, M);
  1143. CanonicalForm B= mod (G, M);
  1144. if (B.inCoeffDomain())
  1145. {
  1146. divrem (A, B, Q, R);
  1147. return;
  1148. }
  1149. if (A.inCoeffDomain() && !B.inCoeffDomain())
  1150. {
  1151. Q= 0;
  1152. R= A;
  1153. return;
  1154. }
  1155. if (B.level() < A.level())
  1156. {
  1157. divrem (A, B, Q, R);
  1158. return;
  1159. }
  1160. if (A.level() > B.level())
  1161. {
  1162. R= A;
  1163. Q= 0;
  1164. return;
  1165. }
  1166. if (B.level() == 1 && B.isUnivariate())
  1167. {
  1168. divrem (A, B, Q, R);
  1169. return;
  1170. }
  1171. if (!(B.level() == 1 && B.isUnivariate()) && (A.level() == 1 && A.isUnivariate()))
  1172. {
  1173. Q= 0;
  1174. R= A;
  1175. return;
  1176. }
  1177. Variable x= Variable (1);
  1178. int degB= degree (B, x);
  1179. if (degB > degree (A, x))
  1180. {
  1181. Q= 0;
  1182. R= A;
  1183. return;
  1184. }
  1185. CFList splitA= split (A, degB, x);
  1186. CanonicalForm xToDegB= power (x, degB);
  1187. CanonicalForm H, bufQ;
  1188. Q= 0;
  1189. CFListIterator i= splitA;
  1190. H= i.getItem()*xToDegB;
  1191. i++;
  1192. H += i.getItem();
  1193. CFList buf;
  1194. while (i.hasItem())
  1195. {
  1196. buf= CFList (M);
  1197. divrem21 (H, B, bufQ, R, buf);
  1198. i++;
  1199. if (i.hasItem())
  1200. H= R*xToDegB + i.getItem();
  1201. Q *= xToDegB;
  1202. Q += bufQ;
  1203. }
  1204. return;
  1205. }
  1206. void divrem (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
  1207. CanonicalForm& R, const CFList& MOD)
  1208. {
  1209. CanonicalForm A= mod (F, MOD);
  1210. CanonicalForm B= mod (G, MOD);
  1211. Variable x= Variable (1);
  1212. int degB= degree (B, x);
  1213. if (degB > degree (A, x))
  1214. {
  1215. Q= 0;
  1216. R= A;
  1217. return;
  1218. }
  1219. if (degB <= 0)
  1220. {
  1221. divrem (A, B, Q, R);
  1222. Q= mod (Q, MOD);
  1223. R= mod (R, MOD);
  1224. return;
  1225. }
  1226. CFList splitA= split (A, degB, x);
  1227. CanonicalForm xToDegB= power (x, degB);
  1228. CanonicalForm H, bufQ;
  1229. Q= 0;
  1230. CFListIterator i= splitA;
  1231. H= i.getItem()*xToDegB;
  1232. i++;
  1233. H += i.getItem();
  1234. while (i.hasItem())
  1235. {
  1236. divrem21 (H, B, bufQ, R, MOD);
  1237. i++;
  1238. if (i.hasItem())
  1239. H= R*xToDegB + i.getItem();
  1240. Q *= xToDegB;
  1241. Q += bufQ;
  1242. }
  1243. return;
  1244. }
  1245. void sortList (CFList& list, const Variable& x)
  1246. {
  1247. int l= 1;
  1248. int k= 1;
  1249. CanonicalForm buf;
  1250. CFListIterator m;
  1251. for (CFListIterator i= list; l <= list.length(); i++, l++)
  1252. {
  1253. for (CFListIterator j= list; k <= list.length() - l; k++)
  1254. {
  1255. m= j;
  1256. m++;
  1257. if (degree (j.getItem(), x) > degree (m.getItem(), x))
  1258. {
  1259. buf= m.getItem();
  1260. m.getItem()= j.getItem();
  1261. j.getItem()= buf;
  1262. j++;
  1263. j.getItem()= m.getItem();
  1264. }
  1265. else
  1266. j++;
  1267. }
  1268. k= 1;
  1269. }
  1270. }
  1271. static inline
  1272. CFList diophantine (const CanonicalForm& F, const CFList& factors)
  1273. {
  1274. CanonicalForm buf1, buf2, buf3, S, T;
  1275. CFListIterator i= factors;
  1276. CFList result;
  1277. if (i.hasItem())
  1278. i++;
  1279. buf1= F/factors.getFirst();
  1280. buf2= divNTL (F, i.getItem());
  1281. buf3= extgcd (buf1, buf2, S, T);
  1282. result.append (S);
  1283. result.append (T);
  1284. if (i.hasItem())
  1285. i++;
  1286. for (; i.hasItem(); i++)
  1287. {
  1288. buf1= divNTL (F, i.getItem());
  1289. buf3= extgcd (buf3, buf1, S, T);
  1290. CFListIterator k= factors;
  1291. for (CFListIterator j= result; j.hasItem(); j++, k++)
  1292. {
  1293. j.getItem()= mulNTL (j.getItem(), S);
  1294. j.getItem()= modNTL (j.getItem(), k.getItem());
  1295. }
  1296. result.append (T);
  1297. }
  1298. return result;
  1299. }
  1300. void
  1301. henselStep12 (const CanonicalForm& F, const CFList& factors,
  1302. CFArray& bufFactors, const CFList& diophant, CFMatrix& M,
  1303. CFArray& Pi, int j)
  1304. {
  1305. CanonicalForm E;
  1306. CanonicalForm xToJ= power (F.mvar(), j);
  1307. Variable x= F.mvar();
  1308. // compute the error
  1309. if (j == 1)
  1310. E= F[j];
  1311. else
  1312. {
  1313. if (degree (Pi [factors.length() - 2], x) > 0)
  1314. E= F[j] - Pi [factors.length() - 2] [j];
  1315. else
  1316. E= F[j];
  1317. }
  1318. CFArray buf= CFArray (diophant.length());
  1319. bufFactors[0]= mod (factors.getFirst(), power (F.mvar(), j + 1));
  1320. int k= 0;
  1321. CanonicalForm remainder;
  1322. // actual lifting
  1323. for (CFListIterator i= diophant; i.hasItem(); i++, k++)
  1324. {
  1325. if (degree (bufFactors[k], x) > 0)
  1326. {
  1327. if (k > 0)
  1328. remainder= modNTL (E, bufFactors[k] [0]);
  1329. else
  1330. remainder= E;
  1331. }
  1332. else
  1333. remainder= modNTL (E, bufFactors[k]);
  1334. buf[k]= mulNTL (i.getItem(), remainder);
  1335. if (degree (bufFactors[k], x) > 0)
  1336. buf[k]= modNTL (buf[k], bufFactors[k] [0]);
  1337. else
  1338. buf[k]= modNTL (buf[k], bufFactors[k]);
  1339. }
  1340. for (k= 1; k < factors.length(); k++)
  1341. bufFactors[k] += xToJ*buf[k];
  1342. // update Pi [0]
  1343. int degBuf0= degree (bufFactors[0], x);
  1344. int degBuf1= degree (bufFactors[1], x);
  1345. if (degBuf0 > 0 && degBuf1 > 0)
  1346. M (j + 1, 1)= mulNTL (bufFactors[0] [j], bufFactors[1] [j]);
  1347. CanonicalForm uIZeroJ;
  1348. if (j == 1)
  1349. {
  1350. if (degBuf0 > 0 && degBuf1 > 0)
  1351. uIZeroJ= mulNTL ((bufFactors[0] [0] + bufFactors[0] [j]),
  1352. (bufFactors[1] [0] + buf[1])) - M(1, 1) - M(j + 1, 1);
  1353. else if (degBuf0 > 0)
  1354. uIZeroJ= mulNTL (bufFactors[0] [j], bufFactors[1]);
  1355. else if (degBuf1 > 0)
  1356. uIZeroJ= mulNTL (bufFactors[0], buf[1]);
  1357. else
  1358. uIZeroJ= 0;
  1359. Pi [0] += xToJ*uIZeroJ;
  1360. }
  1361. else
  1362. {
  1363. if (degBuf0 > 0 && degBuf1 > 0)
  1364. uIZeroJ= mulNTL ((bufFactors[0] [0] + bufFactors[0] [j]),
  1365. (bufFactors[1] [0] + buf[1])) - M(1, 1) - M(j + 1, 1);
  1366. else if (degBuf0 > 0)
  1367. uIZeroJ= mulNTL (bufFactors[0] [j], bufFactors[1]);
  1368. else if (degBuf1 > 0)
  1369. uIZeroJ= mulNTL (bufFactors[0], buf[1]);
  1370. else
  1371. uIZeroJ= 0;
  1372. Pi [0] += xToJ*uIZeroJ;
  1373. }
  1374. CFArray tmp= CFArray (factors.length() - 1);
  1375. for (k= 0; k < factors.length() - 1; k++)
  1376. tmp[k]= 0;
  1377. CFIterator one, two;
  1378. one= bufFactors [0];
  1379. two= bufFactors [1];
  1380. if (degBuf0 > 0 && degBuf1 > 0)
  1381. {
  1382. for (k= 1; k <= (int) ceil (j/2.0); k++)
  1383. {
  1384. if (k != j - k + 1)
  1385. {
  1386. if ((one.hasTerms() && one.exp() == j - k + 1) && (two.hasTerms() && two.exp() == j - k + 1))
  1387. {
  1388. tmp[0] += mulNTL ((bufFactors[0] [k] + one.coeff()), (bufFactors[1] [k] +
  1389. two.coeff())) - M (k + 1, 1) - M (j - k + 2, 1);
  1390. one++;
  1391. two++;
  1392. }
  1393. else if (one.hasTerms() && one.exp() == j - k + 1)
  1394. {
  1395. tmp[0] += mulNTL ((bufFactors[0] [k] + one.coeff()), bufFactors[1] [k]) -
  1396. M (k + 1, 1);
  1397. one++;
  1398. }
  1399. else if (two.hasTerms() && two.exp() == j - k + 1)
  1400. {
  1401. tmp[0] += mulNTL (bufFactors[0] [k], (bufFactors[1] [k] + two.coeff())) -
  1402. M (k + 1, 1);
  1403. two++;
  1404. }
  1405. }
  1406. else
  1407. {
  1408. tmp[0] += M (k + 1, 1);
  1409. }
  1410. }
  1411. }
  1412. Pi [0] += tmp[0]*xToJ*F.mvar();
  1413. // update Pi [l]
  1414. int degPi, degBuf;
  1415. for (int l= 1; l < factors.length() - 1; l++)
  1416. {
  1417. degPi= degree (Pi [l - 1], x);
  1418. degBuf= degree (bufFactors[l + 1], x);
  1419. if (degPi > 0 && degBuf > 0)
  1420. M (j + 1, l + 1)= mulNTL (Pi [l - 1] [j], bufFactors[l + 1] [j]);
  1421. if (j == 1)
  1422. {
  1423. if (degPi > 0 && degBuf > 0)
  1424. Pi [l] += xToJ*(mulNTL (Pi [l - 1] [0] + Pi [l - 1] [j],
  1425. bufFactors[l + 1] [0] + buf[l + 1]) - M (j + 1, l +1) -
  1426. M (1, l + 1));
  1427. else if (degPi > 0)
  1428. Pi [l] += xToJ*(mulNTL (Pi [l - 1] [j], bufFactors[l + 1]));
  1429. else if (degBuf > 0)
  1430. Pi [l] += xToJ*(mulNTL (Pi [l - 1], buf[l + 1]));
  1431. }
  1432. else
  1433. {
  1434. if (degPi > 0 && degBuf > 0)
  1435. {
  1436. uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1] [0]);
  1437. uIZeroJ += mulNTL (Pi [l - 1] [0], buf [l + 1]);
  1438. }
  1439. else if (degPi > 0)
  1440. uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1]);
  1441. else if (degBuf > 0)
  1442. {
  1443. uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1] [0]);
  1444. uIZeroJ += mulNTL (Pi [l - 1], buf[l + 1]);
  1445. }
  1446. Pi[l] += xToJ*uIZeroJ;
  1447. }
  1448. one= bufFactors [l + 1];
  1449. two= Pi [l - 1];
  1450. if (two.hasTerms() && two.exp() == j + 1)
  1451. {
  1452. if (degBuf > 0 && degPi > 0)
  1453. {
  1454. tmp[l] += mulNTL (two.coeff(), bufFactors[l + 1][0]);
  1455. two++;
  1456. }
  1457. else if (degPi > 0)
  1458. {
  1459. tmp[l] += mulNTL (two.coeff(), bufFactors[l + 1]);
  1460. two++;
  1461. }
  1462. }
  1463. if (degBuf > 0 && degPi > 0)
  1464. {
  1465. for (k= 1; k <= (int) ceil (j/2.0); k++)
  1466. {
  1467. if (k != j - k + 1)
  1468. {
  1469. if ((one.hasTerms() && one.exp() == j - k + 1) &&
  1470. (two.hasTerms() && two.exp() == j - k + 1))
  1471. {
  1472. tmp[l] += mulNTL ((bufFactors[l + 1] [k] + one.coeff()), (Pi[l - 1] [k] +
  1473. two.coeff())) - M (k + 1, l + 1) - M (j - k + 2, l + 1);
  1474. one++;
  1475. two++;
  1476. }
  1477. else if (one.hasTerms() && one.exp() == j - k + 1)
  1478. {
  1479. tmp[l] += mulNTL ((bufFactors[l + 1] [k] + one.coeff()), Pi[l - 1] [k]) -
  1480. M (k + 1, l + 1);
  1481. one++;
  1482. }
  1483. else if (two.hasTerms() && two.exp() == j - k + 1)
  1484. {
  1485. tmp[l] += mulNTL (bufFactors[l + 1] [k], (Pi[l - 1] [k] + two.coeff())) -
  1486. M (k + 1, l + 1);
  1487. two++;
  1488. }
  1489. }
  1490. else
  1491. tmp[l] += M (k + 1, l + 1);
  1492. }
  1493. }
  1494. Pi[l] += tmp[l]*xToJ*F.mvar();
  1495. }
  1496. return;
  1497. }
  1498. void
  1499. henselLift12 (const CanonicalForm& F, CFList& factors, int l, CFArray& Pi,
  1500. CFList& diophant, CFMatrix& M, bool sort)
  1501. {
  1502. if (sort)
  1503. sortList (factors, Variable (1));
  1504. Pi= CFArray (factors.length() - 1);
  1505. CFListIterator j= factors;
  1506. diophant= diophantine (F[0], factors);
  1507. DEBOUTLN (cerr, "diophant= " << diophant);
  1508. j++;
  1509. Pi [0]= mulNTL (j.getItem(), mod (factors.getFirst(), F.mvar()));
  1510. M (1, 1)= Pi [0];
  1511. int i= 1;
  1512. if (j.hasItem())
  1513. j++;
  1514. for (; j.hasItem(); j++, i++)
  1515. {
  1516. Pi [i]= mulNTL (Pi [i - 1], j.getItem());
  1517. M (1, i + 1)= Pi [i];
  1518. }
  1519. CFArray bufFactors= CFArray (factors.length());
  1520. i= 0;
  1521. for (CFListIterator k= factors; k.hasItem(); i++, k++)
  1522. {
  1523. if (i == 0)
  1524. bufFactors[i]= mod (k.getItem(), F.mvar());
  1525. else
  1526. bufFactors[i]= k.getItem();
  1527. }
  1528. for (i= 1; i < l; i++)
  1529. henselStep12 (F, factors, bufFactors, diophant, M, Pi, i);
  1530. CFListIterator k= factors;
  1531. for (i= 0; i < factors.length (); i++, k++)
  1532. k.getItem()= bufFactors[i];
  1533. factors.removeFirst();
  1534. return;
  1535. }
  1536. void
  1537. henselLiftResume12 (const CanonicalForm& F, CFList& factors, int start, int
  1538. end, CFArray& Pi, const CFList& diophant, CFMatrix& M)
  1539. {
  1540. CFArray bufFactors= CFArray (factors.length());
  1541. int i= 0;
  1542. CanonicalForm xToStart= power (F.mvar(), start);
  1543. for (CFListIterator k= factors; k.hasItem(); k++, i++)
  1544. {
  1545. if (i == 0)
  1546. bufFactors[i]= mod (k.getItem(), xToStart);
  1547. else
  1548. bufFactors[i]= k.getItem();
  1549. }
  1550. for (i= start; i < end; i++)
  1551. henselStep12 (F, factors, bufFactors, diophant, M, Pi, i);
  1552. CFListIterator k= factors;
  1553. for (i= 0; i < factors.length(); k++, i++)
  1554. k.getItem()= bufFactors [i];
  1555. factors.removeFirst();
  1556. return;
  1557. }
  1558. static inline
  1559. CFList
  1560. biDiophantine (const CanonicalForm& F, const CFList& factors, const int d)
  1561. {
  1562. Variable y= F.mvar();
  1563. CFList result;
  1564. if (y.level() == 1)
  1565. {
  1566. result= diophantine (F, factors);
  1567. return result;
  1568. }
  1569. else
  1570. {
  1571. CFList buf= factors;
  1572. for (CFListIterator i= buf; i.hasItem(); i++)
  1573. i.getItem()= mod (i.getItem(), y);
  1574. CanonicalForm A= mod (F, y);
  1575. int bufD= 1;
  1576. CFList recResult= biDiophantine (A, buf, bufD);
  1577. CanonicalForm e= 1;
  1578. CFList p;
  1579. CFArray bufFactors= CFArray (factors.length());
  1580. CanonicalForm yToD= power (y, d);
  1581. int k= 0;
  1582. for (CFListIterator i= factors; i.hasItem(); i++, k++)
  1583. {
  1584. bufFactors [k]= i.getItem();
  1585. }
  1586. CanonicalForm b;
  1587. for (k= 0; k < factors.length(); k++) //TODO compute b's faster
  1588. {
  1589. b= 1;
  1590. if (fdivides (bufFactors[k], F))
  1591. b= F/bufFactors[k];
  1592. else
  1593. {
  1594. for (int l= 0; l < factors.length(); l++)
  1595. {
  1596. if (l == k)
  1597. continue;
  1598. else
  1599. {
  1600. b= mulMod2 (b, bufFactors[l], yToD);
  1601. }
  1602. }
  1603. }
  1604. p.append (b);
  1605. }
  1606. CFListIterator j= p;
  1607. for (CFListIterator i= recResult; i.hasItem(); i++, j++)
  1608. e -= i.getItem()*j.getItem();
  1609. if (e.isZero())
  1610. return recResult;
  1611. CanonicalForm coeffE;
  1612. CFList s;
  1613. result= recResult;
  1614. CanonicalForm g;
  1615. for (int i= 1; i < d; i++)
  1616. {
  1617. if (degree (e, y) > 0)
  1618. coeffE= e[i];
  1619. else
  1620. coeffE= 0;
  1621. if (!coeffE.isZero())
  1622. {
  1623. CFListIterator k= result;
  1624. CFListIterator l= p;
  1625. int ii= 0;
  1626. j= recResult;
  1627. for (; j.hasItem(); j++, k++, l++, ii++)
  1628. {
  1629. g= coeffE*j.getItem();
  1630. if (degree (bufFactors[ii], y) <= 0)
  1631. g= mod (g, bufFactors[ii]);
  1632. else
  1633. g= mod (g, bufFactors[ii][0]);
  1634. k.getItem() += g*power (y, i);
  1635. e -= mulMod2 (g*power(y, i), l.getItem(), yToD);
  1636. DEBOUTLN (cerr, "mod (e, power (y, i + 1))= " <<
  1637. mod (e, power (y, i + 1)));
  1638. }
  1639. }
  1640. if (e.isZero())
  1641. break;
  1642. }
  1643. DEBOUTLN (cerr, "mod (e, y)= " << mod (e, y));
  1644. #ifdef DEBUGOUTPUT
  1645. CanonicalForm test= 0;
  1646. j= p;
  1647. for (CFListIterator i= result; i.hasItem(); i++, j++)
  1648. test += mod (i.getItem()*j.getItem(), power (y, d));
  1649. DEBOUTLN (cerr, "test= " << test);
  1650. #endif
  1651. return result;
  1652. }
  1653. }
  1654. static inline
  1655. CFList
  1656. multiRecDiophantine (const CanonicalForm& F, const CFList& factors,
  1657. const CFList& recResult, const CFList& M, const int d)
  1658. {
  1659. Variable y= F.mvar();
  1660. CFList result;
  1661. CFListIterator i;
  1662. CanonicalForm e= 1;
  1663. CFListIterator j= factors;
  1664. CFList p;
  1665. CFArray bufFactors= CFArray (factors.length());
  1666. CanonicalForm yToD= power (y, d);
  1667. int k= 0;
  1668. for (CFListIterator i= factors; i.hasItem(); i++, k++)
  1669. bufFactors [k]= i.getItem();
  1670. CanonicalForm b;
  1671. CFList buf= M;
  1672. buf.removeLast();
  1673. buf.append (yToD);
  1674. for (k= 0; k < factors.length(); k++) //TODO compute b's faster
  1675. {
  1676. b= 1;
  1677. if (fdivides (bufFactors[k], F))
  1678. b= F/bufFactors[k];
  1679. else
  1680. {
  1681. for (int l= 0; l < factors.length(); l++)
  1682. {
  1683. if (l == k)
  1684. continue;
  1685. else
  1686. {
  1687. b= mulMod (b, bufFactors[l], buf);
  1688. }
  1689. }
  1690. }
  1691. p.append (b);
  1692. }
  1693. j= p;
  1694. for (CFListIterator i= recResult; i.hasItem(); i++, j++)
  1695. e -= mulMod (i.getItem(), j.getItem(), M);
  1696. if (e.isZero())
  1697. return recResult;
  1698. CanonicalForm coeffE;
  1699. CFList s;
  1700. result= recResult;
  1701. CanonicalForm g;
  1702. for (int i= 1; i < d; i++)
  1703. {
  1704. if (degree (e, y) > 0)
  1705. coeffE= e[i];
  1706. else
  1707. coeffE= 0;
  1708. if (!coeffE.isZero())
  1709. {
  1710. CFListIterator k= result;
  1711. CFListIterator l= p;
  1712. j= recResult;
  1713. int ii= 0;
  1714. CanonicalForm dummy;
  1715. for (; j.hasItem(); j++, k++, l++, ii++)
  1716. {
  1717. g= mulMod (coeffE, j.getItem(), M);
  1718. if (degree (bufFactors[ii], y) <= 0)
  1719. divrem (g, mod (bufFactors[ii], Variable (y.level() - 1)), dummy,
  1720. g, M);
  1721. else
  1722. divrem (g, bufFactors[ii][0], dummy, g, M);
  1723. k.getItem() += g*power (y, i);
  1724. e -= mulMod (g*power (y, i), l.getItem(), M);
  1725. }
  1726. }
  1727. if (e.isZero())
  1728. break;
  1729. }
  1730. #ifdef DEBUGOUTPUT
  1731. CanonicalForm test= 0;
  1732. j= p;
  1733. for (CFListIterator i= result; i.hasItem(); i++, j++)
  1734. test += mod (i.getItem()*j.getItem(), power (y, d));
  1735. DEBOUTLN (cerr, "test= " << test);
  1736. #endif
  1737. return result;
  1738. }
  1739. static inline
  1740. void
  1741. henselStep (const CanonicalForm& F, const CFList& factors, CFArray& bufFactors,
  1742. const CFList& diophant, CFMatrix& M, CFArray& Pi, int j,
  1743. const CFList& MOD)
  1744. {
  1745. CanonicalForm E;
  1746. CanonicalForm xToJ= power (F.mvar(), j);
  1747. Variable x= F.mvar();
  1748. // compute the error
  1749. if (j == 1)
  1750. {
  1751. E= F[j];
  1752. #ifdef DEBUGOUTPUT
  1753. CanonicalForm test= 1;
  1754. for (int i= 0; i < factors.length(); i++)
  1755. {
  1756. if (i == 0)
  1757. test= mulMod (test, mod (bufFactors [i], xToJ), MOD);
  1758. else
  1759. test= mulMod (test, bufFactors[i], MOD);
  1760. }
  1761. CanonicalForm test2= mod (F-test, xToJ);
  1762. test2= mod (test2, MOD);
  1763. DEBOUTLN (cerr, "test= " << test2);
  1764. #endif
  1765. }
  1766. else
  1767. {
  1768. #ifdef DEBUGOUTPUT
  1769. CanonicalForm test= 1;
  1770. for (int i= 0; i < factors.length(); i++)
  1771. {
  1772. if (i == 0)
  1773. test *= mod (bufFactors [i], power (x, j));
  1774. else
  1775. test *= bufFactors[i];
  1776. }
  1777. test= mod (test, power (x, j));
  1778. test= mod (test, MOD);
  1779. CanonicalForm test2= mod (F, power (x, j - 1)) - mod (test, power (x, j-1));
  1780. DEBOUTLN (cerr, "test= " << test2);
  1781. #endif
  1782. if (degree (Pi [factors.length() - 2], x) > 0)
  1783. E= F[j] - Pi [factors.length() - 2] [j];
  1784. else
  1785. E= F[j];
  1786. }
  1787. CFArray buf= CFArray (diophant.length());
  1788. bufFactors[0]= mod (factors.getFirst(), power (F.mvar(), j + 1));
  1789. int k= 0;
  1790. // actual lifting
  1791. CanonicalForm dummy, rest1;
  1792. for (CFListIterator i= diophant; i.hasItem(); i++, k++)
  1793. {
  1794. if (degree (bufFactors[k], x) > 0)
  1795. {
  1796. if (k > 0)
  1797. divrem (E, bufFactors[k] [0], dummy, rest1, MOD);
  1798. else
  1799. rest1= E;
  1800. }
  1801. else
  1802. divrem (E, bufFactors[k], dummy, rest1, MOD);
  1803. buf[k]= mulMod (i.getItem(), rest1, MOD);
  1804. if (degree (bufFactors[k], x) > 0)
  1805. divrem (buf[k], bufFactors[k] [0], dummy, buf[k], MOD);
  1806. else
  1807. divrem (buf[k], bufFactors[k], dummy, buf[k], MOD);
  1808. }
  1809. for (k= 1; k < factors.length(); k++)
  1810. bufFactors[k] += xToJ*buf[k];
  1811. // update Pi [0]
  1812. int degBuf0= degree (bufFactors[0], x);
  1813. int degBuf1= degree (bufFactors[1], x);
  1814. if (degBuf0 > 0 && degBuf1 > 0)
  1815. M (j + 1, 1)= mulMod (bufFactors[0] [j], bufFactors[1] [j], MOD);
  1816. CanonicalForm uIZeroJ;
  1817. if (j == 1)
  1818. {
  1819. if (degBuf0 > 0 && degBuf1 > 0)
  1820. uIZeroJ= mulMod ((bufFactors[0] [0] + bufFactors[0] [j]),
  1821. (bufFactors[1] [0] + buf[1]), MOD) - M(1, 1) - M(j + 1, 1);
  1822. else if (degBuf0 > 0)
  1823. uIZeroJ= mulMod (bufFactors[0] [j], bufFactors[1], MOD);
  1824. else if (degBuf1 > 0)
  1825. uIZeroJ= mulMod (bufFactors[0], buf[1], MOD);
  1826. else
  1827. uIZeroJ= 0;
  1828. Pi [0] += xToJ*uIZeroJ;
  1829. }
  1830. else
  1831. {
  1832. if (degBuf0 > 0 && degBuf1 > 0)
  1833. uIZeroJ= mulMod ((bufFactors[0] [0] + bufFactors[0] [j]),
  1834. (bufFactors[1] [0] + buf[1]), MOD) - M(1, 1) - M(j + 1, 1);
  1835. else if (degBuf0 > 0)
  1836. uIZeroJ= mulMod (bufFactors[0] [j], bufFactors[1], MOD);
  1837. else if (degBuf1 > 0)
  1838. uIZeroJ= mulMod (bufFactors[0], buf[1], MOD);
  1839. else
  1840. uIZeroJ= 0;
  1841. Pi [0] += xToJ*uIZeroJ;
  1842. }
  1843. CFArray tmp= CFArray (factors.length() - 1);
  1844. for (k= 0; k < factors.length() - 1; k++)
  1845. tmp[k]= 0;
  1846. CFIterator one, two;
  1847. one= bufFactors [0];
  1848. two= bufFactors [1];
  1849. if (degBuf0 > 0 && degBuf1 > 0)
  1850. {
  1851. for (k= 1; k <= (int) ceil (j/2.0); k++)
  1852. {
  1853. if (k != j - k + 1)
  1854. {
  1855. if ((one.hasTerms() && one.exp() == j - k + 1) &&
  1856. (two.hasTerms() && two.exp() == j - k + 1))
  1857. {
  1858. tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()),
  1859. (bufFactors[1] [k] + two.coeff()), MOD) - M (k + 1, 1) -
  1860. M (j - k + 2, 1);
  1861. one++;
  1862. two++;
  1863. }
  1864. else if (one.hasTerms() && one.exp() == j - k + 1)
  1865. {
  1866. tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()),
  1867. bufFactors[1] [k], MOD) - M (k + 1, 1);
  1868. one++;
  1869. }
  1870. else if (two.hasTerms() && two.exp() == j - k + 1)
  1871. {
  1872. tmp[0] += mulMod (bufFactors[0] [k], (bufFactors[1] [k] +
  1873. two.coeff()), MOD) - M (k + 1, 1);
  1874. two++;
  1875. }
  1876. }
  1877. else
  1878. {
  1879. tmp[0] += M (k + 1, 1);
  1880. }
  1881. }
  1882. }
  1883. Pi [0] += tmp[0]*xToJ*F.mvar();
  1884. // update Pi [l]
  1885. int degPi, degBuf;
  1886. for (int l= 1; l < factors.length() - 1; l++)
  1887. {
  1888. degPi= degree (Pi [l - 1], x);
  1889. degBuf= degree (bufFactors[l + 1], x);
  1890. if (degPi > 0 && degBuf > 0)
  1891. M (j + 1, l + 1)= mulMod (Pi [l - 1] [j], bufFactors[l + 1] [j], MOD);
  1892. if (j == 1)
  1893. {
  1894. if (degPi > 0 && degBuf > 0)
  1895. Pi [l] += xToJ*(mulMod ((Pi [l - 1] [0] + Pi [l - 1] [j]),
  1896. (bufFactors[l + 1] [0] + buf[l + 1]), MOD) - M (j + 1, l +1)-
  1897. M (1, l + 1));
  1898. else if (degPi > 0)
  1899. Pi [l] += xToJ*(mulMod (Pi [l - 1] [j], bufFactors[l + 1], MOD));
  1900. else if (degBuf > 0)
  1901. Pi [l] += xToJ*(mulMod (Pi [l - 1], buf[l + 1], MOD));
  1902. }
  1903. else
  1904. {
  1905. if (degPi > 0 && degBuf > 0)
  1906. {
  1907. uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1] [0], MOD);
  1908. uIZeroJ += mulMod (Pi [l - 1] [0], buf [l + 1], MOD);
  1909. }
  1910. else if (degPi > 0)
  1911. uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1], MOD);
  1912. else if (degBuf > 0)
  1913. {
  1914. uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1] [0], MOD);
  1915. uIZeroJ += mulMod (Pi [l - 1], buf[l + 1], MOD);
  1916. }
  1917. Pi[l] += xToJ*uIZeroJ;
  1918. }
  1919. one= bufFactors [l + 1];
  1920. two= Pi [l - 1];
  1921. if (two.hasTerms() && two.exp() == j + 1)
  1922. {
  1923. if (degBuf > 0 && degPi > 0)
  1924. {
  1925. tmp[l] += mulMod (two.coeff(), bufFactors[l + 1][0], MOD);
  1926. two++;
  1927. }
  1928. else if (degPi > 0)
  1929. {
  1930. tmp[l] += mulMod (two.coeff(), bufFactors[l + 1], MOD);
  1931. two++;
  1932. }
  1933. }
  1934. if (degBuf > 0 && degPi > 0)
  1935. {
  1936. for (k= 1; k <= (int) ceil (j/2.0); k++)
  1937. {
  1938. if (k != j - k + 1)
  1939. {
  1940. if ((one.hasTerms() && one.exp() == j - k + 1) &&
  1941. (two.hasTerms() && two.exp() == j - k + 1))
  1942. {
  1943. tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()),
  1944. (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1) -
  1945. M (j - k + 2, l + 1);
  1946. one++;
  1947. two++;
  1948. }
  1949. else if (one.hasTerms() && one.exp() == j - k + 1)
  1950. {
  1951. tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()),
  1952. Pi[l - 1] [k], MOD) - M (k + 1, l + 1);
  1953. one++;
  1954. }
  1955. else if (two.hasTerms() && two.exp() == j - k + 1)
  1956. {
  1957. tmp[l] += mulMod (bufFactors[l + 1] [k],
  1958. (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1);
  1959. two++;
  1960. }
  1961. }
  1962. else
  1963. tmp[l] += M (k + 1, l + 1);
  1964. }
  1965. }
  1966. Pi[l] += tmp[l]*xToJ*F.mvar();
  1967. }
  1968. return;
  1969. }
  1970. CFList
  1971. henselLift23 (const CFList& eval, const CFList& factors, const int* l, CFList&
  1972. diophant, CFArray& Pi, CFMatrix& M)
  1973. {
  1974. CFList buf= factors;
  1975. int k= 0;
  1976. int liftBoundBivar= l[k];
  1977. diophant= biDiophantine (eval.getFirst(), buf, liftBoundBivar);
  1978. CFList MOD;
  1979. MOD.append (power (Variable (2), liftBoundBivar));
  1980. CFArray bufFactors= CFArray (factors.length());
  1981. k= 0;
  1982. CFListIterator j= eval;
  1983. j++;
  1984. buf.removeFirst();
  1985. buf.insert (LC (j.getItem(), 1));
  1986. for (CFListIterator i= buf; i.hasItem(); i++, k++)
  1987. bufFactors[k]= i.getItem();
  1988. Pi= CFArray (factors.length() - 1);
  1989. CFListIterator i= buf;
  1990. i++;
  1991. Variable y= j.getItem().mvar();
  1992. Pi [0]= mulMod (i.getItem(), mod (buf.getFirst(), y), MOD);
  1993. M (1, 1)= Pi [0];
  1994. k= 1;
  1995. if (i.hasItem())
  1996. i++;
  1997. for (; i.hasItem(); i++, k++)
  1998. {
  1999. Pi [k]= mulMod (Pi [k - 1], i.getItem(), MOD);
  2000. M (1, k + 1)= Pi [k];
  2001. }
  2002. for (int d= 1; d < l[1]; d++)
  2003. henselStep (j.getItem(), buf, bufFactors, diophant, M, Pi, d, MOD);
  2004. CFList result;
  2005. for (k= 1; k < factors.length(); k++)
  2006. result.append (bufFactors[k]);
  2007. return result;
  2008. }
  2009. void
  2010. henselLiftResume (const CanonicalForm& F, CFList& factors, int start, int end,
  2011. CFArray& Pi, const CFList& diophant, CFMatrix& M,
  2012. const CFList& MOD)
  2013. {
  2014. CFArray bufFactors= CFArray (factors.length());
  2015. int i= 0;
  2016. CanonicalForm xToStart= power (F.mvar(), start);
  2017. for (CFListIterator k= factors; k.hasItem(); k++, i++)
  2018. {
  2019. if (i == 0)
  2020. bufFactors[i]= mod (k.getItem(), xToStart);
  2021. else
  2022. bufFactors[i]= k.getItem();
  2023. }
  2024. for (i= start; i < end; i++)
  2025. henselStep (F, factors, bufFactors, diophant, M, Pi, i, MOD);
  2026. CFListIterator k= factors;
  2027. for (i= 0; i < factors.length(); k++, i++)
  2028. k.getItem()= bufFactors [i];
  2029. factors.removeFirst();
  2030. return;
  2031. }
  2032. CFList
  2033. henselLift (const CFList& F, const CFList& factors, const CFList& MOD, CFList&
  2034. diophant, CFArray& Pi, CFMatrix& M, const int lOld, const int
  2035. lNew)
  2036. {
  2037. diophant= multiRecDiophantine (F.getFirst(), factors, diophant, MOD, lOld);
  2038. int k= 0;
  2039. CFArray bufFactors= CFArray (factors.length());
  2040. for (CFListIterator i= factors; i.hasItem(); i++, k++)
  2041. {
  2042. if (k == 0)
  2043. bufFactors[k]= LC (F.getLast(), 1);
  2044. else
  2045. bufFactors[k]= i.getItem();
  2046. }
  2047. CFList buf= factors;
  2048. buf.removeFirst();
  2049. buf.insert (LC (F.getLast(), 1));
  2050. CFListIterator i= buf;
  2051. i++;
  2052. Variable y= F.getLast().mvar();
  2053. Variable x= F.getFirst().mvar();
  2054. CanonicalForm xToLOld= power (x, lOld);
  2055. Pi [0]= mod (Pi[0], xToLOld);
  2056. M (1, 1)= Pi [0];
  2057. k= 1;
  2058. if (i.hasItem())
  2059. i++;
  2060. for (; i.hasItem(); i++, k++)
  2061. {
  2062. Pi [k]= mod (Pi [k], xToLOld);
  2063. M (1, k + 1)= Pi [k];
  2064. }
  2065. for (int d= 1; d < lNew; d++)
  2066. henselStep (F.getLast(), buf, bufFactors, diophant, M, Pi, d, MOD);
  2067. CFList result;
  2068. for (k= 1; k < factors.length(); k++)
  2069. result.append (bufFactors[k]);
  2070. return result;
  2071. }
  2072. CFList
  2073. henselLift (const CFList& eval, const CFList& factors, const int* l, const int
  2074. lLength, bool sort)
  2075. {
  2076. CFList diophant;
  2077. CFList buf= factors;
  2078. buf.insert (LC (eval.getFirst(), 1));
  2079. if (sort)
  2080. sortList (buf, Variable (1));
  2081. CFArray Pi;
  2082. CFMatrix M= CFMatrix (l[1], factors.length());
  2083. CFList result= henselLift23 (eval, buf, l, diophant, Pi, M);
  2084. if (eval.length() == 2)
  2085. return result;
  2086. CFList MOD;
  2087. for (int i= 0; i < 2; i++)
  2088. MOD.append (power (Variable (i + 2), l[i]));
  2089. CFListIterator j= eval;
  2090. j++;
  2091. CFList bufEval;
  2092. bufEval.append (j.getItem());
  2093. j++;
  2094. for (int i= 2; i < lLength && j.hasItem(); i++, j++)
  2095. {
  2096. result.insert (LC (bufEval.getFirst(), 1));
  2097. bufEval.append (j.getItem());
  2098. M= CFMatrix (l[i], factors.length());
  2099. result= henselLift (bufEval, result, MOD, diophant, Pi, M, l[i - 1], l[i]);
  2100. MOD.append (power (Variable (i + 2), l[i]));
  2101. bufEval.removeFirst();
  2102. }
  2103. return result;
  2104. }
  2105. void
  2106. henselStep122 (const CanonicalForm& F, const CFList& factors,
  2107. CFArray& bufFactors, const CFList& diophant, CFMatrix& M,
  2108. CFArray& Pi, int j, const CFArray& LCs)
  2109. {
  2110. Variable x= F.mvar();
  2111. CanonicalForm xToJ= power (x, j);
  2112. CanonicalForm E;
  2113. // compute the error
  2114. if (degree (Pi [factors.length() - 2], x) > 0)
  2115. E= F[j] - Pi [factors.length() - 2] [j];
  2116. else
  2117. E= F[j];
  2118. CFArray buf= CFArray (diophant.length());
  2119. int k= 0;
  2120. CanonicalForm remainder;
  2121. // actual lifting
  2122. for (CFListIterator i= diophant; i.hasItem(); i++, k++)
  2123. {
  2124. if (degree (bufFactors[k], x) > 0)
  2125. remainder= modNTL (E, bufFactors[k] [0]);
  2126. else
  2127. remainder= modNTL (E, bufFactors[k]);
  2128. buf[k]= mulNTL (i.getItem(), remainder);
  2129. if (degree (bufFactors[k], x) > 0)
  2130. buf[k]= modNTL (buf[k], bufFactors[k] [0]);
  2131. else
  2132. buf[k]= modNTL (buf[k], bufFactors[k]);
  2133. }
  2134. for (k= 0; k < factors.length(); k++)
  2135. bufFactors[k] += xToJ*buf[k];
  2136. // update Pi [0]
  2137. int degBuf0= degree (bufFactors[0], x);
  2138. int degBuf1= degree (bufFactors[1], x);
  2139. if (degBuf0 > 0 && degBuf1 > 0)
  2140. {
  2141. M (j + 1, 1)= mulNTL (bufFactors[0] [j], bufFactors[1] [j]);
  2142. if (j + 2 <= M.rows())
  2143. M (j + 2, 1)= mulNTL (bufFactors[0] [j + 1], bufFactors[1] [j + 1]);
  2144. }
  2145. CanonicalForm uIZeroJ;
  2146. if (degBuf0 > 0 && degBuf1 > 0)
  2147. uIZeroJ= mulNTL(bufFactors[0][0],buf[1])+mulNTL (bufFactors[1][0], buf[0]);
  2148. else if (degBuf0 > 0)
  2149. uIZeroJ= mulNTL (buf[0], bufFactors[1]);
  2150. else if (degBuf1 > 0)
  2151. uIZeroJ= mulNTL (bufFactors[0], buf [1]);
  2152. else
  2153. uIZeroJ= 0;
  2154. Pi [0] += xToJ*uIZeroJ;
  2155. CFArray tmp= CFArray (factors.length() - 1);
  2156. for (k= 0; k < factors.length() - 1; k++)
  2157. tmp[k]= 0;
  2158. CFIterator one, two;
  2159. one= bufFactors [0];
  2160. two= bufFactors [1];
  2161. if (degBuf0 > 0 && degBuf1 > 0)
  2162. {
  2163. while (one.hasTerms() && one.exp() > j) one++;
  2164. while (two.hasTerms() && two.exp() > j) two++;
  2165. for (k= 1; k <= (int) ceil (j/2.0); k++)
  2166. {
  2167. if (one.hasTerms() && two.hasTerms())
  2168. {
  2169. if (k != j - k + 1)
  2170. {
  2171. if ((one.hasTerms() && one.exp() == j - k + 1) && +
  2172. (two.hasTerms() && two.exp() == j - k + 1))
  2173. {
  2174. tmp[0] += mulNTL ((bufFactors[0][k]+one.coeff()),(bufFactors[1][k] +
  2175. two.coeff())) - M (k + 1, 1) - M (j - k + 2, 1);
  2176. one++;
  2177. two++;
  2178. }
  2179. else if (one.hasTerms() && one.exp() == j - k + 1)
  2180. {
  2181. tmp[0] += mulNTL ((bufFactors[0][k]+one.coeff()), bufFactors[1] [k]) -
  2182. M (k + 1, 1);
  2183. one++;
  2184. }
  2185. else if (two.hasTerms() && two.exp() == j - k + 1)
  2186. {
  2187. tmp[0] += mulNTL (bufFactors[0][k],(bufFactors[1][k] + two.coeff())) -
  2188. M (k + 1, 1);
  2189. two++;
  2190. }
  2191. }
  2192. else
  2193. tmp[0] += M (k + 1, 1);
  2194. }
  2195. }
  2196. }
  2197. if (degBuf0 >= j + 1 && degBuf1 >= j + 1)
  2198. {
  2199. if (j + 2 <= M.rows())
  2200. tmp [0] += mulNTL ((bufFactors [0] [j + 1]+ bufFactors [0] [0]),
  2201. (bufFactors [1] [j + 1] + bufFactors [1] [0]))
  2202. - M(1,1) - M (j + 2,1);
  2203. }
  2204. else if (degBuf0 >= j + 1)
  2205. {
  2206. if (degBuf1 > 0)
  2207. tmp[0] += mulNTL (bufFactors [0] [j+1], bufFactors [1] [0]);
  2208. else
  2209. tmp[0] += mulNTL (bufFactors [0] [j+1], bufFactors [1]);
  2210. }
  2211. else if (degBuf1 >= j + 1)
  2212. {
  2213. if (degBuf0 > 0)
  2214. tmp[0] += mulNTL (bufFactors [0] [0], bufFactors [1] [j + 1]);
  2215. else
  2216. tmp[0] += mulNTL (bufFactors [0], bufFactors [1] [j + 1]);
  2217. }
  2218. Pi [0] += tmp[0]*xToJ*F.mvar();
  2219. return;
  2220. }
  2221. void
  2222. henselLift122 (const CanonicalForm& F, CFList& factors, int l, CFArray& Pi,
  2223. CFList& diophant, CFMatrix& M, const CFArray& LCs, bool sort)
  2224. {
  2225. if (sort)
  2226. sortList (factors, Variable (1));
  2227. Pi= CFArray (factors.length() - 2);
  2228. CFList bufFactors2= factors;
  2229. bufFactors2.removeFirst();
  2230. diophant.removeFirst();
  2231. CFListIterator iter= diophant;
  2232. CanonicalForm s,t;
  2233. extgcd (bufFactors2.getFirst(), bufFactors2.getLast(), s, t);
  2234. diophant= CFList();
  2235. diophant.append (t);
  2236. diophant.append (s);
  2237. DEBOUTLN (cerr, "diophant= " << diophant);
  2238. CFArray bufFactors= CFArray (bufFactors2.length());
  2239. int i= 0;
  2240. for (CFListIterator k= bufFactors2; k.hasItem(); i++, k++)
  2241. bufFactors[i]= replaceLc (k.getItem(), LCs [i]);
  2242. Variable x= F.mvar();
  2243. if (degree (bufFactors[0], x) > 0 && degree (bufFactors [1], x) > 0)
  2244. {
  2245. M (1, 1)= mulNTL (bufFactors [0] [0], bufFactors[1] [0]);
  2246. Pi [0]= M (1, 1) + (mulNTL (bufFactors [0] [1], bufFactors[1] [0]) +
  2247. mulNTL (bufFactors [0] [0], bufFactors [1] [1]))*x;
  2248. }
  2249. else if (degree (bufFactors[0], x) > 0)
  2250. {
  2251. M (1, 1)= mulNTL (bufFactors [0] [0], bufFactors[1]);
  2252. Pi [0]= M (1, 1) +
  2253. mulNTL (bufFactors [0] [1], bufFactors[1])*x;
  2254. }
  2255. else if (degree (bufFactors[1], x) > 0)
  2256. {
  2257. M (1, 1)= mulNTL (bufFactors [0], bufFactors[1] [0]);
  2258. Pi [0]= M (1, 1) +
  2259. mulNTL (bufFactors [0], bufFactors[1] [1])*x;
  2260. }
  2261. else
  2262. {
  2263. M (1, 1)= mulNTL (bufFactors [0], bufFactors[1]);
  2264. Pi [0]= M (1, 1);
  2265. }
  2266. for (i= 1; i < l; i++)
  2267. henselStep122 (F, bufFactors2, bufFactors, diophant, M, Pi, i, LCs);
  2268. factors= CFList();
  2269. for (i= 0; i < bufFactors.size(); i++)
  2270. factors.append (bufFactors[i]);
  2271. return;
  2272. }
  2273. /// solve \f$ E=sum_{i= 1}^{r}{\sigma_{i}prod_{j=1, j\neq i}^{r}{f_{i}}}\f$
  2274. /// mod M, products contains \f$ prod_{j=1, j\neq i}^{r}{f_{i}}} \f$
  2275. static inline
  2276. CFList
  2277. diophantine (const CFList& recResult, const CFList& factors,
  2278. const CFList& products, const CFList& M, const CanonicalForm& E,
  2279. bool& bad)
  2280. {
  2281. if (M.isEmpty())
  2282. {
  2283. CFList result;
  2284. CFListIterator j= factors;
  2285. CanonicalForm buf;
  2286. for (CFListIterator i= recResult; i.hasItem(); i++, j++)
  2287. {
  2288. ASSERT (E.isUnivariate() || E.inCoeffDomain(),
  2289. "constant or univariate poly expected");
  2290. ASSERT (i.getItem().isUnivariate() || i.getItem().inCoeffDomain(),
  2291. "constant or univariate poly expected");
  2292. ASSERT (j.getItem().isUnivariate() || j.getItem().inCoeffDomain(),
  2293. "constant or univariate poly expected");
  2294. buf= mulNTL (E, i.getItem());
  2295. result.append (modNTL (buf, j.getItem()));
  2296. }
  2297. return result;
  2298. }
  2299. Variable y= M.getLast().mvar();
  2300. CFList bufFactors= factors;
  2301. for (CFListIterator i= bufFactors; i.hasItem(); i++)
  2302. i.getItem()= mod (i.getItem(), y);
  2303. CFList bufProducts= products;
  2304. for (CFListIterator i= bufProducts; i.hasItem(); i++)
  2305. i.getItem()= mod (i.getItem(), y);
  2306. CFList buf= M;
  2307. buf.removeLast();
  2308. CanonicalForm bufE= mod (E, y);
  2309. CFList recDiophantine= diophantine (recResult, bufFactors, bufProducts, buf,
  2310. bufE, bad);
  2311. if (bad)
  2312. return CFList();
  2313. CanonicalForm e= E;
  2314. CFListIterator j= products;
  2315. for (CFListIterator i= recDiophantine; i.hasItem(); i++, j++)
  2316. e -= i.getItem()*j.getItem();
  2317. CFList result= recDiophantine;
  2318. int d= degree (M.getLast());
  2319. CanonicalForm coeffE;
  2320. for (int i= 1; i < d; i++)
  2321. {
  2322. if (degree (e, y) > 0)
  2323. coeffE= e[i];
  2324. else
  2325. coeffE= 0;
  2326. if (!coeffE.isZero())
  2327. {
  2328. CFListIterator k= result;
  2329. recDiophantine= diophantine (recResult, bufFactors, bufProducts, buf,
  2330. coeffE, bad);
  2331. if (bad)
  2332. return CFList();
  2333. CFListIterator l= products;
  2334. for (j= recDiophantine; j.hasItem(); j++, k++, l++)
  2335. {
  2336. k.getItem() += j.getItem()*power (y, i);
  2337. e -= j.getItem()*power (y, i)*l.getItem();
  2338. }
  2339. }
  2340. if (e.isZero())
  2341. break;
  2342. }
  2343. if (!e.isZero())
  2344. {
  2345. bad= true;
  2346. return CFList();
  2347. }
  2348. return result;
  2349. }
  2350. static inline
  2351. void
  2352. henselStep2 (const CanonicalForm& F, const CFList& factors, CFArray& bufFactors,
  2353. const CFList& diophant, CFMatrix& M, CFArray& Pi,
  2354. const CFList& products, int j, const CFList& MOD, bool& noOneToOne)
  2355. {
  2356. CanonicalForm E;
  2357. CanonicalForm xToJ= power (F.mvar(), j);
  2358. Variable x= F.mvar();
  2359. // compute the error
  2360. #ifdef DEBUGOUTPUT
  2361. CanonicalForm test= 1;
  2362. for (int i= 0; i < factors.length(); i++)
  2363. {
  2364. if (i == 0)
  2365. test *= mod (bufFactors [i], power (x, j));
  2366. else
  2367. test *= bufFactors[i];
  2368. }
  2369. test= mod (test, power (x, j));
  2370. test= mod (test, MOD);
  2371. CanonicalForm test2= mod (F, power (x, j - 1)) - mod (test, power (x, j-1));
  2372. DEBOUTLN (cerr, "test= " << test2);
  2373. #endif
  2374. if (degree (Pi [factors.length() - 2], x) > 0)
  2375. E= F[j] - Pi [factors.length() - 2] [j];
  2376. else
  2377. E= F[j];
  2378. CFArray buf= CFArray (diophant.length());
  2379. // actual lifting
  2380. CFList diophantine2= diophantine (diophant, factors, products, MOD, E,
  2381. noOneToOne);
  2382. if (noOneToOne)
  2383. return;
  2384. int k= 0;
  2385. for (CFListIterator i= diophantine2; k < factors.length(); k++, i++)
  2386. {
  2387. buf[k]= i.getItem();
  2388. bufFactors[k] += xToJ*i.getItem();
  2389. }
  2390. // update Pi [0]
  2391. int degBuf0= degree (bufFactors[0], x);
  2392. int degBuf1= degree (bufFactors[1], x);
  2393. if (degBuf0 > 0 && degBuf1 > 0)
  2394. {
  2395. M (j + 1, 1)= mulMod (bufFactors[0] [j], bufFactors[1] [j], MOD);
  2396. if (j + 2 <= M.rows())
  2397. M (j + 2, 1)= mulMod (bufFactors[0] [j + 1], bufFactors[1] [j + 1], MOD);
  2398. }
  2399. CanonicalForm uIZeroJ;
  2400. if (degBuf0 > 0 && degBuf1 > 0)
  2401. uIZeroJ= mulMod (bufFactors[0] [0], buf[1], MOD) +
  2402. mulMod (bufFactors[1] [0], buf[0], MOD);
  2403. else if (degBuf0 > 0)
  2404. uIZeroJ= mulMod (buf[0], bufFactors[1], MOD);
  2405. else if (degBuf1 > 0)
  2406. uIZeroJ= mulMod (bufFactors[0], buf[1], MOD);
  2407. else
  2408. uIZeroJ= 0;
  2409. Pi [0] += xToJ*uIZeroJ;
  2410. CFArray tmp= CFArray (factors.length() - 1);
  2411. for (k= 0; k < factors.length() - 1; k++)
  2412. tmp[k]= 0;
  2413. CFIterator one, two;
  2414. one= bufFactors [0];
  2415. two= bufFactors [1];
  2416. if (degBuf0 > 0 && degBuf1 > 0)
  2417. {
  2418. while (one.hasTerms() && one.exp() > j) one++;
  2419. while (two.hasTerms() && two.exp() > j) two++;
  2420. for (k= 1; k <= (int) ceil (j/2.0); k++)
  2421. {
  2422. if (k != j - k + 1)
  2423. {
  2424. if ((one.hasTerms() && one.exp() == j - k + 1) &&
  2425. (two.hasTerms() && two.exp() == j - k + 1))
  2426. {
  2427. tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()),
  2428. (bufFactors[1] [k] + two.coeff()), MOD) - M (k + 1, 1) -
  2429. M (j - k + 2, 1);
  2430. one++;
  2431. two++;
  2432. }
  2433. else if (one.hasTerms() && one.exp() == j - k + 1)
  2434. {
  2435. tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()),
  2436. bufFactors[1] [k], MOD) - M (k + 1, 1);
  2437. one++;
  2438. }
  2439. else if (two.hasTerms() && two.exp() == j - k + 1)
  2440. {
  2441. tmp[0] += mulMod (bufFactors[0] [k], (bufFactors[1] [k] +
  2442. two.coeff()), MOD) - M (k + 1, 1);
  2443. two++;
  2444. }
  2445. }
  2446. else
  2447. {
  2448. tmp[0] += M (k + 1, 1);
  2449. }
  2450. }
  2451. }
  2452. if (degBuf0 >= j + 1 && degBuf1 >= j + 1)
  2453. {
  2454. if (j + 2 <= M.rows())
  2455. tmp [0] += mulMod ((bufFactors [0] [j + 1]+ bufFactors [0] [0]),
  2456. (bufFactors [1] [j + 1] + bufFactors [1] [0]), MOD)
  2457. - M(1,1) - M (j + 2,1);
  2458. }
  2459. else if (degBuf0 >= j + 1)
  2460. {
  2461. if (degBuf1 > 0)
  2462. tmp[0] += mulMod (bufFactors [0] [j+1], bufFactors [1] [0], MOD);
  2463. else
  2464. tmp[0] += mulMod (bufFactors [0] [j+1], bufFactors [1], MOD);
  2465. }
  2466. else if (degBuf1 >= j + 1)
  2467. {
  2468. if (degBuf0 > 0)
  2469. tmp[0] += mulMod (bufFactors [0] [0], bufFactors [1] [j + 1], MOD);
  2470. else
  2471. tmp[0] += mulMod (bufFactors [0], bufFactors [1] [j + 1], MOD);
  2472. }
  2473. Pi [0] += tmp[0]*xToJ*F.mvar();
  2474. // update Pi [l]
  2475. int degPi, degBuf;
  2476. for (int l= 1; l < factors.length() - 1; l++)
  2477. {
  2478. degPi= degree (Pi [l - 1], x);
  2479. degBuf= degree (bufFactors[l + 1], x);
  2480. if (degPi > 0 && degBuf > 0)
  2481. {
  2482. M (j + 1, l + 1)= mulMod (Pi [l - 1] [j], bufFactors[l + 1] [j], MOD);
  2483. if (j + 2 <= M.rows())
  2484. M (j + 2, l + 1)= mulMod (Pi [l - 1] [j + 1], bufFactors[l + 1] [j + 1],
  2485. MOD);
  2486. }
  2487. if (degPi > 0 && degBuf > 0)
  2488. uIZeroJ= mulMod (Pi[l -1] [0], buf[l + 1], MOD) +
  2489. mulMod (uIZeroJ, bufFactors[l+1] [0], MOD);
  2490. else if (degPi > 0)
  2491. uIZeroJ= mulMod (uIZeroJ, bufFactors[l + 1], MOD);
  2492. else if (degBuf > 0)
  2493. uIZeroJ= mulMod (Pi[l - 1], buf[1], MOD);
  2494. else
  2495. uIZeroJ= 0;
  2496. Pi [l] += xToJ*uIZeroJ;
  2497. one= bufFactors [l + 1];
  2498. two= Pi [l - 1];
  2499. if (degBuf > 0 && degPi > 0)
  2500. {
  2501. while (one.hasTerms() && one.exp() > j) one++;
  2502. while (two.hasTerms() && two.exp() > j) two++;
  2503. for (k= 1; k <= (int) ceil (j/2.0); k++)
  2504. {
  2505. if (k != j - k + 1)
  2506. {
  2507. if ((one.hasTerms() && one.exp() == j - k + 1) &&
  2508. (two.hasTerms() && two.exp() == j - k + 1))
  2509. {
  2510. tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()),
  2511. (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1) -
  2512. M (j - k + 2, l + 1);
  2513. one++;
  2514. two++;
  2515. }
  2516. else if (one.hasTerms() && one.exp() == j - k + 1)
  2517. {
  2518. tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()),
  2519. Pi[l - 1] [k], MOD) - M (k + 1, l + 1);
  2520. one++;
  2521. }
  2522. else if (two.hasTerms() && two.exp() == j - k + 1)
  2523. {
  2524. tmp[l] += mulMod (bufFactors[l + 1] [k],
  2525. (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1);
  2526. two++;
  2527. }
  2528. }
  2529. else
  2530. tmp[l] += M (k + 1, l + 1);
  2531. }
  2532. }
  2533. if (degPi >= j + 1 && degBuf >= j + 1)
  2534. {
  2535. if (j + 2 <= M.rows())
  2536. tmp [l] += mulMod ((Pi [l - 1] [j + 1]+ Pi [l - 1] [0]),
  2537. (bufFactors [l + 1] [j + 1] + bufFactors [l + 1] [0])
  2538. , MOD) - M(1,l+1) - M (j + 2,l+1);
  2539. }
  2540. else if (degPi >= j + 1)
  2541. {
  2542. if (degBuf > 0)
  2543. tmp[l] += mulMod (Pi [l - 1] [j+1], bufFactors [l + 1] [0], MOD);
  2544. else
  2545. tmp[l] += mulMod (Pi [l - 1] [j+1], bufFactors [l + 1], MOD);
  2546. }
  2547. else if (degBuf >= j + 1)
  2548. {
  2549. if (degPi > 0)
  2550. tmp[l] += mulMod (Pi [l - 1] [0], bufFactors [l + 1] [j + 1], MOD);
  2551. else
  2552. tmp[l] += mulMod (Pi [l - 1], bufFactors [l + 1] [j + 1], MOD);
  2553. }
  2554. Pi[l] += tmp[l]*xToJ*F.mvar();
  2555. }
  2556. return;
  2557. }
  2558. // wrt. Variable (1)
  2559. CanonicalForm replaceLC (const CanonicalForm& F, const CanonicalForm& c)
  2560. {
  2561. if (degree (F, 1) <= 0)
  2562. return c;
  2563. else
  2564. {
  2565. CanonicalForm result= swapvar (F, Variable (F.level() + 1), Variable (1));
  2566. result += (swapvar (c, Variable (F.level() + 1), Variable (1))
  2567. - LC (result))*power (result.mvar(), degree (result));
  2568. return swapvar (result, Variable (F.level() + 1), Variable (1));
  2569. }
  2570. }
  2571. CFList
  2572. henselLift232 (const CFList& eval, const CFList& factors, int* l, CFList&
  2573. diophant, CFArray& Pi, CFMatrix& M, const CFList& LCs1,
  2574. const CFList& LCs2, bool& bad)
  2575. {
  2576. CFList buf= factors;
  2577. int k= 0;
  2578. int liftBoundBivar= l[k];
  2579. CFList bufbuf= factors;
  2580. Variable v= Variable (2);
  2581. CFList MOD;
  2582. MOD.append (power (Variable (2), liftBoundBivar));
  2583. CFArray bufFactors= CFArray (factors.length());
  2584. k= 0;
  2585. CFListIterator j= eval;
  2586. j++;
  2587. CFListIterator iter1= LCs1;
  2588. CFListIterator iter2= LCs2;
  2589. iter1++;
  2590. iter2++;
  2591. bufFactors[0]= replaceLC (buf.getFirst(), iter1.getItem());
  2592. bufFactors[1]= replaceLC (buf.getLast(), iter2.getItem());
  2593. CFListIterator i= buf;
  2594. i++;
  2595. Variable y= j.getItem().mvar();
  2596. if (y.level() != 3)
  2597. y= Variable (3);
  2598. Pi[0]= mod (Pi[0], power (v, liftBoundBivar));
  2599. M (1, 1)= Pi[0];
  2600. if (degree (bufFactors[0], y) > 0 && degree (bufFactors [1], y) > 0)
  2601. Pi [0] += (mulMod (bufFactors [0] [1], bufFactors[1] [0], MOD) +
  2602. mulMod (bufFactors [0] [0], bufFactors [1] [1], MOD))*y;
  2603. else if (degree (bufFactors[0], y) > 0)
  2604. Pi [0] += mulMod (bufFactors [0] [1], bufFactors[1], MOD)*y;
  2605. else if (degree (bufFactors[1], y) > 0)
  2606. Pi [0] += mulMod (bufFactors [0], bufFactors[1] [1], MOD)*y;
  2607. CFList products;
  2608. for (int i= 0; i < bufFactors.size(); i++)
  2609. {
  2610. if (degree (bufFactors[i], y) > 0)
  2611. products.append (eval.getFirst()/bufFactors[i] [0]);
  2612. else
  2613. products.append (eval.getFirst()/bufFactors[i]);
  2614. }
  2615. for (int d= 1; d < l[1]; d++)
  2616. {
  2617. henselStep2 (j.getItem(), buf, bufFactors, diophant, M, Pi, products, d, MOD, bad);
  2618. if (bad)
  2619. return CFList();
  2620. }
  2621. CFList result;
  2622. for (k= 0; k < factors.length(); k++)
  2623. result.append (bufFactors[k]);
  2624. return result;
  2625. }
  2626. CFList
  2627. henselLift2 (const CFList& F, const CFList& factors, const CFList& MOD, CFList&
  2628. diophant, CFArray& Pi, CFMatrix& M, const int lOld, int&
  2629. lNew, const CFList& LCs1, const CFList& LCs2, bool& bad)
  2630. {
  2631. int k= 0;
  2632. CFArray bufFactors= CFArray (factors.length());
  2633. bufFactors[0]= replaceLC (factors.getFirst(), LCs1.getLast());
  2634. bufFactors[1]= replaceLC (factors.getLast(), LCs2.getLast());
  2635. CFList buf= factors;
  2636. Variable y= F.getLast().mvar();
  2637. Variable x= F.getFirst().mvar();
  2638. CanonicalForm xToLOld= power (x, lOld);
  2639. Pi [0]= mod (Pi[0], xToLOld);
  2640. M (1, 1)= Pi [0];
  2641. if (degree (bufFactors[0], y) > 0 && degree (bufFactors [1], y) > 0)
  2642. Pi [0] += (mulMod (bufFactors [0] [1], bufFactors[1] [0], MOD) +
  2643. mulMod (bufFactors [0] [0], bufFactors [1] [1], MOD))*y;
  2644. else if (degree (bufFactors[0], y) > 0)
  2645. Pi [0] += mulMod (bufFactors [0] [1], bufFactors[1], MOD)*y;
  2646. else if (degree (bufFactors[1], y) > 0)
  2647. Pi [0] += mulMod (bufFactors [0], bufFactors[1] [1], MOD)*y;
  2648. CFList products;
  2649. for (int i= 0; i < bufFactors.size(); i++)
  2650. {
  2651. if (degree (bufFactors[i], y) > 0)
  2652. {
  2653. if (!fdivides (bufFactors[i] [0], F.getFirst()))
  2654. {
  2655. bad= true;
  2656. return CFList();
  2657. }
  2658. products.append (F.getFirst()/bufFactors[i] [0]);
  2659. }
  2660. else
  2661. {
  2662. if (!fdivides (bufFactors[i], F.getFirst()))
  2663. {
  2664. bad= true;
  2665. return CFList();
  2666. }
  2667. products.append (F.getFirst()/bufFactors[i]);
  2668. }
  2669. }
  2670. for (int d= 1; d < lNew; d++)
  2671. {
  2672. henselStep2 (F.getLast(), buf, bufFactors, diophant, M, Pi, products, d, MOD, bad);
  2673. if (bad)
  2674. return CFList();
  2675. }
  2676. CFList result;
  2677. for (k= 0; k < factors.length(); k++)
  2678. result.append (bufFactors[k]);
  2679. return result;
  2680. }
  2681. CFList
  2682. henselLift2 (const CFList& eval, const CFList& factors, int* l, const int
  2683. lLength, bool sort, const CFList& LCs1, const CFList& LCs2,
  2684. const CFArray& Pi, const CFList& diophant, bool& bad)
  2685. {
  2686. CFList bufDiophant= diophant;
  2687. CFList buf= factors;
  2688. if (sort)
  2689. sortList (buf, Variable (1));
  2690. CFArray bufPi= Pi;
  2691. CFMatrix M= CFMatrix (l[1], factors.length());
  2692. CFList result= henselLift232(eval, buf, l, bufDiophant, bufPi, M, LCs1, LCs2,
  2693. bad);
  2694. if (bad)
  2695. return CFList();
  2696. if (eval.length() == 2)
  2697. return result;
  2698. CFList MOD;
  2699. for (int i= 0; i < 2; i++)
  2700. MOD.append (power (Variable (i + 2), l[i]));
  2701. CFListIterator j= eval;
  2702. j++;
  2703. CFList bufEval;
  2704. bufEval.append (j.getItem());
  2705. j++;
  2706. CFListIterator jj= LCs1;
  2707. CFListIterator jjj= LCs2;
  2708. CFList bufLCs1, bufLCs2;
  2709. jj++, jjj++;
  2710. bufLCs1.append (jj.getItem());
  2711. bufLCs2.append (jjj.getItem());
  2712. jj++, jjj++;
  2713. for (int i= 2; i < lLength && j.hasItem(); i++, j++, jj++, jjj++)
  2714. {
  2715. bufEval.append (j.getItem());
  2716. bufLCs1.append (jj.getItem());
  2717. bufLCs2.append (jjj.getItem());
  2718. M= CFMatrix (l[i], factors.length());
  2719. result= henselLift2 (bufEval, result, MOD, bufDiophant, bufPi, M, l[i - 1],
  2720. l[i], bufLCs1, bufLCs2, bad);
  2721. if (bad)
  2722. return CFList();
  2723. MOD.append (power (Variable (i + 2), l[i]));
  2724. bufEval.removeFirst();
  2725. bufLCs1.removeFirst();
  2726. bufLCs2.removeFirst();
  2727. }
  2728. return result;
  2729. }
  2730. CFList
  2731. nonMonicHenselLift23 (const CanonicalForm& F, const CFList& factors, const
  2732. CFList& LCs, CFList& diophant, CFArray& Pi, int liftBound,
  2733. int bivarLiftBound, bool& bad)
  2734. {
  2735. CFList bufFactors2= factors;
  2736. Variable y= Variable (2);
  2737. for (CFListIterator i= bufFactors2; i.hasItem(); i++)
  2738. i.getItem()= mod (i.getItem(), y);
  2739. CanonicalForm bufF= F;
  2740. bufF= mod (bufF, y);
  2741. bufF= mod (bufF, Variable (3));
  2742. diophant= diophantine (bufF, bufFactors2);
  2743. CFMatrix M= CFMatrix (liftBound, bufFactors2.length() - 1);
  2744. Pi= CFArray (bufFactors2.length() - 1);
  2745. CFArray bufFactors= CFArray (bufFactors2.length());
  2746. CFListIterator j= LCs;
  2747. int i= 0;
  2748. for (CFListIterator k= factors; k.hasItem(); j++, k++, i++)
  2749. bufFactors[i]= replaceLC (k.getItem(), j.getItem());
  2750. //initialise Pi
  2751. Variable v= Variable (3);
  2752. CanonicalForm yToL= power (y, bivarLiftBound);
  2753. if (degree (bufFactors[0], v) > 0 && degree (bufFactors [1], v) > 0)
  2754. {
  2755. M (1, 1)= mulMod2 (bufFactors [0] [0], bufFactors[1] [0], yToL);
  2756. Pi [0]= M (1,1) + (mulMod2 (bufFactors [0] [1], bufFactors[1] [0], yToL) +
  2757. mulMod2 (bufFactors [0] [0], bufFactors [1] [1], yToL))*v;
  2758. }
  2759. else if (degree (bufFactors[0], v) > 0)
  2760. {
  2761. M (1,1)= mulMod2 (bufFactors [0] [0], bufFactors [1], yToL);
  2762. Pi [0]= M(1,1) + mulMod2 (bufFactors [0] [1], bufFactors[1], yToL)*v;
  2763. }
  2764. else if (degree (bufFactors[1], v) > 0)
  2765. {
  2766. M (1,1)= mulMod2 (bufFactors [0], bufFactors [1] [0], yToL);
  2767. Pi [0]= M (1,1) + mulMod2 (bufFactors [0], bufFactors[1] [1], yToL)*v;
  2768. }
  2769. else
  2770. {
  2771. M (1,1)= mulMod2 (bufFactors [0], bufFactors [1], yToL);
  2772. Pi [0]= M (1,1);
  2773. }
  2774. for (i= 1; i < Pi.size(); i++)
  2775. {
  2776. if (degree (Pi[i-1], v) > 0 && degree (bufFactors [i+1], v) > 0)
  2777. {
  2778. M (1,i+1)= mulMod2 (Pi[i-1] [0], bufFactors[i+1] [0], yToL);
  2779. Pi [i]= M (1,i+1) + (mulMod2 (Pi[i-1] [1], bufFactors[i+1] [0], yToL) +
  2780. mulMod2 (Pi[i-1] [0], bufFactors [i+1] [1], yToL))*v;
  2781. }
  2782. else if (degree (Pi[i-1], v) > 0)
  2783. {
  2784. M (1,i+1)= mulMod2 (Pi[i-1] [0], bufFactors [i+1], yToL);
  2785. Pi [i]= M(1,i+1) + mulMod2 (Pi[i-1] [1], bufFactors[i+1], yToL)*v;
  2786. }
  2787. else if (degree (bufFactors[i+1], v) > 0)
  2788. {
  2789. M (1,i+1)= mulMod2 (Pi[i-1], bufFactors [i+1] [0], yToL);
  2790. Pi [i]= M (1,i+1) + mulMod2 (Pi[i-1], bufFactors[i+1] [1], yToL)*v;
  2791. }
  2792. else
  2793. {
  2794. M (1,i+1)= mulMod2 (Pi [i-1], bufFactors [i+1], yToL);
  2795. Pi [i]= M (1,i+1);
  2796. }
  2797. }
  2798. CFList products;
  2799. bufF= mod (F, Variable (3));
  2800. for (CFListIterator k= factors; k.hasItem(); k++)
  2801. products.append (bufF/k.getItem());
  2802. CFList MOD= CFList (power (v, liftBound));
  2803. MOD.insert (yToL);
  2804. for (int d= 1; d < liftBound; d++)
  2805. {
  2806. henselStep2 (F, factors, bufFactors, diophant, M, Pi, products, d, MOD, bad);
  2807. if (bad)
  2808. return CFList();
  2809. }
  2810. CFList result;
  2811. for (i= 0; i < factors.length(); i++)
  2812. result.append (bufFactors[i]);
  2813. return result;
  2814. }
  2815. CFList
  2816. nonMonicHenselLift (const CFList& F, const CFList& factors, const CFList& LCs,
  2817. CFList& diophant, CFArray& Pi, CFMatrix& M, const int lOld,
  2818. int& lNew, const CFList& MOD, bool& noOneToOne
  2819. )
  2820. {
  2821. int k= 0;
  2822. CFArray bufFactors= CFArray (factors.length());
  2823. CFListIterator j= LCs;
  2824. for (CFListIterator i= factors; i.hasItem(); i++, j++, k++)
  2825. bufFactors [k]= replaceLC (i.getItem(), j.getItem());
  2826. Variable y= F.getLast().mvar();
  2827. Variable x= F.getFirst().mvar();
  2828. CanonicalForm xToLOld= power (x, lOld);
  2829. Pi [0]= mod (Pi[0], xToLOld);
  2830. M (1, 1)= Pi [0];
  2831. if (degree (bufFactors[0], y) > 0 && degree (bufFactors [1], y) > 0)
  2832. Pi [0] += (mulMod (bufFactors [0] [1], bufFactors[1] [0], MOD) +
  2833. mulMod (bufFactors [0] [0], bufFactors [1] [1], MOD))*y;
  2834. else if (degree (bufFactors[0], y) > 0)
  2835. Pi [0] += mulMod (bufFactors [0] [1], bufFactors[1], MOD)*y;
  2836. else if (degree (bufFactors[1], y) > 0)
  2837. Pi [0] += mulMod (bufFactors [0], bufFactors[1] [1], MOD)*y;
  2838. for (int i= 1; i < Pi.size(); i++)
  2839. {
  2840. Pi [i]= mod (Pi [i], xToLOld);
  2841. M (1, i + 1)= Pi [i];
  2842. if (degree (Pi[i-1], y) > 0 && degree (bufFactors [i+1], y) > 0)
  2843. Pi [i] += (mulMod (Pi[i-1] [1], bufFactors[i+1] [0], MOD) +
  2844. mulMod (Pi[i-1] [0], bufFactors [i+1] [1], MOD))*y;
  2845. else if (degree (Pi[i-1], y) > 0)
  2846. Pi [i] += mulMod (Pi[i-1] [1], bufFactors[i+1], MOD)*y;
  2847. else if (degree (bufFactors[i+1], y) > 0)
  2848. Pi [i] += mulMod (Pi[i-1], bufFactors[i+1] [1], MOD)*y;
  2849. }
  2850. CFList products;
  2851. CanonicalForm bufF= F.getFirst();
  2852. for (int i= 0; i < bufFactors.size(); i++)
  2853. {
  2854. if (degree (bufFactors[i], y) > 0)
  2855. {
  2856. if (!fdivides (bufFactors[i] [0], bufF))
  2857. {
  2858. noOneToOne= true;
  2859. return factors;
  2860. }
  2861. products.append (bufF/bufFactors[i] [0]);
  2862. }
  2863. else
  2864. {
  2865. if (!fdivides (bufFactors[i], bufF))
  2866. {
  2867. noOneToOne= true;
  2868. return factors;
  2869. }
  2870. products.append (bufF/bufFactors[i]);
  2871. }
  2872. }
  2873. for (int d= 1; d < lNew; d++)
  2874. {
  2875. henselStep2 (F.getLast(), factors, bufFactors, diophant, M, Pi, products, d,
  2876. MOD, noOneToOne);
  2877. if (noOneToOne)
  2878. return CFList();
  2879. }
  2880. CFList result;
  2881. for (k= 0; k < factors.length(); k++)
  2882. result.append (bufFactors[k]);
  2883. return result;
  2884. }
  2885. CFList
  2886. nonMonicHenselLift (const CFList& eval, const CFList& factors,
  2887. CFList* const& LCs, CFList& diophant, CFArray& Pi,
  2888. int* liftBound, int length, bool& noOneToOne
  2889. )
  2890. {
  2891. CFList bufDiophant= diophant;
  2892. CFList buf= factors;
  2893. CFArray bufPi= Pi;
  2894. CFMatrix M= CFMatrix (liftBound[1], factors.length() - 1);
  2895. int k= 0;
  2896. CFList result=
  2897. nonMonicHenselLift23 (eval.getFirst(), factors, LCs [0], diophant, bufPi,
  2898. liftBound[1], liftBound[0], noOneToOne);
  2899. if (noOneToOne)
  2900. return CFList();
  2901. if (eval.length() == 1)
  2902. return result;
  2903. k++;
  2904. CFList MOD;
  2905. for (int i= 0; i < 2; i++)
  2906. MOD.append (power (Variable (i + 2), liftBound[i]));
  2907. CFListIterator j= eval;
  2908. CFList bufEval;
  2909. bufEval.append (j.getItem());
  2910. j++;
  2911. for (int i= 2; i <= length && j.hasItem(); i++, j++, k++)
  2912. {
  2913. bufEval.append (j.getItem());
  2914. M= CFMatrix (liftBound[i], factors.length() - 1);
  2915. result= nonMonicHenselLift (bufEval, result, LCs [i-1], diophant, bufPi, M,
  2916. liftBound[i-1], liftBound[i], MOD, noOneToOne);
  2917. if (noOneToOne)
  2918. return result;
  2919. MOD.append (power (Variable (i + 2), liftBound[i]));
  2920. bufEval.removeFirst();
  2921. }
  2922. return result;
  2923. }
  2924. #endif
  2925. /* HAVE_NTL */