source: git/factory/facHensel.cc @ ad3c3ff

spielwiese
Last change on this file since ad3c3ff was ad3c3ff, checked in by Martin Lee <martinlee84@…>, 14 years ago
new Hensel lifting, modular multiplication and modular division git-svn-id: file:///usr/local/Singular/svn/trunk@12857 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 39.0 KB
Line 
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
22#include "assert.h"
23#include "debug.h"
24#include "timing.h"
25
26#include "facHensel.h"
27#include "cf_util.h"
28
29#ifdef HAVE_NTL
30#include <NTL/lzz_pEX.h>
31#include "NTLconvert.h"
32
33static inline
34CanonicalForm
35mulNTL (const CanonicalForm& F, const CanonicalForm& G)
36{
37  if (F.inCoeffDomain() || G.inCoeffDomain())
38    return F*G;
39  ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
40  ASSERT (F.level() == G.level(), "expected polys of same level");
41  if (CFFactory::gettype() == GaloisFieldDomain)
42    return F*G;
43  zz_p::init (getCharacteristic());
44  Variable alpha;
45  CanonicalForm result;
46  if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
47  {
48    zz_pX NTLMipo= convertFacCF2NTLzzpX (getMipo (alpha));
49    zz_pE::init (NTLMipo);
50    zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
51    zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
52    mul (NTLF, NTLF, NTLG);
53    result= convertNTLzz_pEX2CF(NTLF, F.mvar(), alpha);
54  }
55  else
56  {
57    zz_pX NTLF= convertFacCF2NTLzzpX (F);
58    zz_pX NTLG= convertFacCF2NTLzzpX (G);
59    mul (NTLF, NTLF, NTLG);
60    result= convertNTLzzpX2CF(NTLF, F.mvar());
61  }
62  return result;
63}
64
65static inline
66CanonicalForm
67modNTL (const CanonicalForm& F, const CanonicalForm& G)
68{
69  if (F.inCoeffDomain() && G.isUnivariate())
70    return F;
71  else if (F.inCoeffDomain() && G.inCoeffDomain())
72    return mod (F, G);
73  else if (F.isUnivariate() && G.inCoeffDomain())
74    return mod (F,G);
75   
76  ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
77  ASSERT (F.level() == G.level(), "expected polys of same level");
78  if (CFFactory::gettype() == GaloisFieldDomain)
79    return mod (F, G);
80  zz_p::init (getCharacteristic());
81  Variable alpha;
82  CanonicalForm result;
83  if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
84  {
85    zz_pX NTLMipo= convertFacCF2NTLzzpX(getMipo (alpha));
86    zz_pE::init (NTLMipo);
87    zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
88    zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
89    rem (NTLF, NTLF, NTLG);
90    result= convertNTLzz_pEX2CF(NTLF, F.mvar(), alpha);
91  }
92  else
93  {
94    zz_pX NTLF= convertFacCF2NTLzzpX (F);
95    zz_pX NTLG= convertFacCF2NTLzzpX (G);
96    rem (NTLF, NTLF, NTLG);
97    result= convertNTLzzpX2CF(NTLF, F.mvar());
98  }
99  return result;
100}
101
102static inline
103CanonicalForm
104divNTL (const CanonicalForm& F, const CanonicalForm& G)
105{
106  if (F.inCoeffDomain() && G.isUnivariate())
107    return F;
108  else if (F.inCoeffDomain() && G.inCoeffDomain())
109    return div (F, G);
110  else if (F.isUnivariate() && G.inCoeffDomain())
111    return div (F,G);
112
113  ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
114  ASSERT (F.level() == G.level(), "expected polys of same level");
115  if (CFFactory::gettype() == GaloisFieldDomain)
116    return div (F, G);
117  zz_p::init (getCharacteristic());
118  Variable alpha;
119  CanonicalForm result;
120  if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
121  {
122    zz_pX NTLMipo= convertFacCF2NTLzzpX(getMipo (alpha));
123    zz_pE::init (NTLMipo);
124    zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
125    zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
126    div (NTLF, NTLF, NTLG);
127    result= convertNTLzz_pEX2CF(NTLF, F.mvar(), alpha);
128  }
129  else
130  {
131    zz_pX NTLF= convertFacCF2NTLzzpX (F);
132    zz_pX NTLG= convertFacCF2NTLzzpX (G);
133    div (NTLF, NTLF, NTLG);
134    result= convertNTLzzpX2CF(NTLF, F.mvar());
135  }
136  return result;
137}
138
139/*static inline
140void
141divremNTL (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
142           CanonicalForm& R)
143{
144  if (F.inCoeffDomain() && G.isUnivariate())
145  {
146    R= F;
147    Q= 0;
148  }
149  else if (F.inCoeffDomain() && G.inCoeffDomain())
150  {
151    divrem (F, G, Q, R);
152    return;
153  }
154  else if (F.isUnivariate() && G.inCoeffDomain())
155  {
156    divrem (F, G, Q, R);
157    return;
158  }
159
160  ASSERT (F.isUnivariate() && G.isUnivariate(), "expected univariate polys");
161  ASSERT (F.level() == G.level(), "expected polys of same level");
162  if (CFFactory::gettype() == GaloisFieldDomain)
163  {
164    divrem (F, G, Q, R);
165    return;
166  }
167  zz_p::init (getCharacteristic());
168  Variable alpha;
169  CanonicalForm result;
170  if (hasFirstAlgVar (F, alpha) || hasFirstAlgVar (G, alpha))
171  {
172    zz_pX NTLMipo= convertFacCF2NTLzzpX(getMipo (alpha));
173    zz_pE::init (NTLMipo);
174    zz_pEX NTLF= convertFacCF2NTLzz_pEX (F, NTLMipo);
175    zz_pEX NTLG= convertFacCF2NTLzz_pEX (G, NTLMipo);
176    zz_pEX NTLQ;
177    zz_pEX NTLR;
178    DivRem (NTLQ, NTLR, NTLF, NTLG);
179    Q= convertNTLzz_pEX2CF(NTLQ, F.mvar(), alpha);
180    R= convertNTLzz_pEX2CF(NTLR, F.mvar(), alpha);
181    return;
182  }
183  else
184  {
185    zz_pX NTLF= convertFacCF2NTLzzpX (F);
186    zz_pX NTLG= convertFacCF2NTLzzpX (G);
187    zz_pX NTLQ;
188    zz_pX NTLR;
189    DivRem (NTLQ, NTLR, NTLF, NTLG);
190    Q= convertNTLzzpX2CF(NTLQ, F.mvar());
191    R= convertNTLzzpX2CF(NTLR, F.mvar());
192    return;
193  }
194}*/
195
196CanonicalForm mod (const CanonicalForm& F, const CFList& M) 
197{
198  CanonicalForm A= F;
199  for (CFListIterator i= M; i.hasItem(); i++) 
200    A= mod (A, i.getItem());
201  return A;
202}
203
204CanonicalForm mulMod2 (const CanonicalForm& A, const CanonicalForm& B, 
205                       const CanonicalForm& M)
206{
207  if (A.isZero() || B.isZero())
208    return 0;
209
210  ASSERT (M.isUnivariate(), "M must be univariate");
211
212  CanonicalForm F= mod (A, M);
213  CanonicalForm G= mod (B, M);
214  if (F.inCoeffDomain() || G.inCoeffDomain())
215    return F*G;
216  Variable y= M.mvar();
217  int degF= degree (F, y);
218  int degG= degree (G, y);
219
220  if ((degF < 1 && degG < 1) && (F.isUnivariate() && G.isUnivariate()) && 
221      (F.level() == G.level()))
222  { 
223    CanonicalForm result= mulNTL (F, G);
224    return mod (result, M);
225  }
226  else if (degF <= 1 && degG <= 1)
227  { 
228    CanonicalForm result= F*G;
229    return mod (result, M);
230  }
231 
232  int m= (int) ceil (degree (M)/2.0);
233  if (degF >= m || degG >= m)
234  {
235    CanonicalForm MLo= power (y, m);
236    CanonicalForm MHi= power (y, degree (M) - m);
237    CanonicalForm F0= mod (F, MLo);
238    CanonicalForm F1= div (F, MLo);
239    CanonicalForm G0= mod (G, MLo);
240    CanonicalForm G1= div (G, MLo);
241    CanonicalForm F0G1= mulMod2 (F0, G1, MHi);
242    CanonicalForm F1G0= mulMod2 (F1, G0, MHi);
243    CanonicalForm F0G0= mulMod2 (F0, G0, M);
244    return F0G0 + MLo*(F0G1 + F1G0);
245  }
246  else
247  {
248    m= (int) ceil (tmax (degF, degG)/2.0);
249    CanonicalForm yToM= power (y, m);
250    CanonicalForm F0= mod (F, yToM);
251    CanonicalForm F1= div (F, yToM);
252    CanonicalForm G0= mod (G, yToM);
253    CanonicalForm G1= div (G, yToM);
254    CanonicalForm H00= mulMod2 (F0, G0, M);
255    CanonicalForm H11= mulMod2 (F1, G1, M);
256    CanonicalForm H01= mulMod2 (F0 + F1, G0 + G1, M);
257    return H11*yToM*yToM + (H01 - H11 - H00)*yToM + H00;
258  } 
259  DEBOUTLN (cerr, "fatal end in mulMod2");
260}
261
262CanonicalForm mulMod (const CanonicalForm& A, const CanonicalForm& B, 
263                      const CFList& MOD)
264{
265  if (A.isZero() || B.isZero())
266    return 0;
267
268  if (MOD.length() == 1)
269    return mulMod2 (A, B, MOD.getLast());
270
271  CanonicalForm M= MOD.getLast();
272  CanonicalForm F= mod (A, M);
273  CanonicalForm G= mod (B, M);
274  if (F.inCoeffDomain() || G.inCoeffDomain())
275    return F*G;
276  Variable y= M.mvar();
277  int degF= degree (F, y);
278  int degG= degree (G, y);
279
280  if ((degF <= 1 && F.level() <= M.level()) && 
281      (degG <= 1 && G.level() <= M.level()))
282  {
283    CFList buf= MOD;
284    buf.removeLast();
285    if (degF == 1 && degG == 1)
286    {
287      CanonicalForm F0= mod (F, y);
288      CanonicalForm F1= div (F, y);
289      CanonicalForm G0= mod (G, y);
290      CanonicalForm G1= div (G, y);
291      if (degree (M) > 2)
292      {
293        CanonicalForm H00= mulMod (F0, G0, buf);
294        CanonicalForm H11= mulMod (F1, G1, buf);
295        CanonicalForm H01= mulMod (F0 + F1, G0 + G1, buf);
296        return H11*y*y + (H01 - H00 - H11)*y + H00;
297      }
298      else //here degree (M) == 2
299      {
300        buf.append (y);
301        CanonicalForm F0G1= mulMod (F0, G1, buf);
302        CanonicalForm F1G0= mulMod (F1, G0, buf);
303        CanonicalForm F0G0= mulMod (F0, G0, MOD);
304        CanonicalForm result= F0G0 + y*(F0G1 + F1G0);
305        return result;
306      }
307    }
308    else if (degF == 1 && degG == 0)
309      return mulMod (div (F, y), G, buf)*y + mulMod (mod (F, y), G, buf);
310    else if (degF == 0 && degG == 1)
311      return mulMod (div (G, y), F, buf)*y + mulMod (mod (G, y), F, buf);
312    else
313      return mulMod (F, G, buf);
314  }
315  int m= (int) ceil (degree (M)/2.0);
316  if (degF >= m || degG >= m)
317  {
318    CanonicalForm MLo= power (y, m);
319    CanonicalForm MHi= power (y, degree (M) - m);
320    CanonicalForm F0= mod (F, MLo);
321    CanonicalForm F1= div (F, MLo);
322    CanonicalForm G0= mod (G, MLo);
323    CanonicalForm G1= div (G, MLo);
324    CFList buf= MOD;
325    buf.removeLast();
326    buf.append (MHi);
327    CanonicalForm F0G1= mulMod (F0, G1, buf);
328    CanonicalForm F1G0= mulMod (F1, G0, buf);
329    CanonicalForm F0G0= mulMod (F0, G0, MOD);
330    return F0G0 + MLo*(F0G1 + F1G0);
331  }
332  else
333  {
334    m= (int) ceil (tmax (degF, degG)/2.0);
335    CanonicalForm yToM= power (y, m);
336    CanonicalForm F0= mod (F, yToM);
337    CanonicalForm F1= div (F, yToM);
338    CanonicalForm G0= mod (G, yToM);
339    CanonicalForm G1= div (G, yToM);
340    CanonicalForm H00= mulMod (F0, G0, MOD);
341    CanonicalForm H11= mulMod (F1, G1, MOD);
342    CanonicalForm H01= mulMod (F0 + F1, G0 + G1, MOD);
343    return H11*yToM*yToM + (H01 - H11 - H00)*yToM + H00;
344  } 
345  DEBOUTLN (cerr, "fatal end in mulMod");
346}
347
348CanonicalForm prodMod (const CFList& L, const CanonicalForm& M) 
349{
350  if (L.isEmpty())
351    return 1;
352  int l= L.length();
353  if (l == 1)
354    return mod (L.getFirst(), M);
355  else if (l == 2) {
356    CanonicalForm result= mulMod2 (L.getFirst(), L.getLast(), M);
357    return result;
358  }
359  else
360  {
361    l /= 2;
362    CFList tmp1, tmp2;
363    CFListIterator i= L;
364    CanonicalForm buf1, buf2;
365    for (int j= 1; j <= l; j++, i++) 
366      tmp1.append (i.getItem());
367    tmp2= Difference (L, tmp1);
368    buf1= prodMod (tmp1, M);
369    buf2= prodMod (tmp2, M);
370    CanonicalForm result= mulMod2 (buf1, buf2, M);
371    return result;
372  } 
373}
374
375CanonicalForm prodMod (const CFList& L, const CFList& M) 
376{
377  if (L.isEmpty())
378    return 1;
379  else if (L.length() == 1)
380    return L.getFirst();
381  else if (L.length() == 2)
382    return mulMod (L.getFirst(), L.getLast(), M);
383  else
384  {
385    int l= L.length()/2;
386    CFListIterator i= L;
387    CFList tmp1, tmp2;
388    CanonicalForm buf1, buf2;
389    for (int j= 1; j <= l; j++, i++) 
390      tmp1.append (i.getItem());
391    tmp2= Difference (L, tmp1);
392    buf1= prodMod (tmp1, M);
393    buf2= prodMod (tmp2, M);
394    return mulMod (buf1, buf2, M);
395  }
396}
397
398static inline
399CFList split (const CanonicalForm& F, const int m, const Variable& x) 
400{
401  CanonicalForm A= F;
402  CanonicalForm buf= 0;
403  bool swap= false;
404  if (degree (A, x) <= 0)
405    return CFList(A);
406  else if (x.level() != A.level())
407  {
408    swap= true;
409    A= swapvar (A, x, A.mvar());
410  }
411
412  int j= (int) floor ((double) degree (A)/ m);
413  CFList result; 
414  CFIterator i= A;
415  for (; j >= 0; j--)
416  {
417    while (i.hasTerms() && i.exp() - j*m >= 0) 
418    {
419      if (swap)
420        buf += i.coeff()*power (A.mvar(), i.exp() - j*m);
421      else
422        buf += i.coeff()*power (x, i.exp() - j*m);
423      i++;
424    }
425    if (swap)
426      result.append (swapvar (buf, x, F.mvar()));
427    else
428      result.append (buf); 
429    buf= 0;
430  }
431  return result; 
432}
433
434static inline
435void divrem32 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q, 
436               CanonicalForm& R, const CFList& M);
437
438static inline 
439void divrem21 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q, 
440               CanonicalForm& R, const CFList& M)
441{
442  CanonicalForm A= mod (F, M);
443  CanonicalForm B= mod (G, M);
444  Variable x= Variable (1);
445  int degB= degree (B, x);
446  int degA= degree (A, x);
447  if (degA < degB)
448  {
449    Q= 0;
450    R= A;
451    return;
452  }
453  ASSERT (2*degB > degA, "expected degree (F, 1) < 2*degree (G, 1)");
454  if (degB < 1)
455  {
456    divrem (A, B, Q, R);
457    Q= mod (Q, M);
458    R= mod (R, M);
459    return;
460  }
461 
462  int m= (int) ceil ((double) (degB + 1)/2.0) + 1; 
463  CFList splitA= split (A, m, x);
464  CFList splitB= split (B, m, x);
465  if (splitA.length() == 3)
466    splitA.insert (0);
467  if (splitA.length() == 2)
468  {
469    splitA.insert (0);
470    splitA.insert (0);
471  } 
472  if (splitA.length() == 1)
473  {
474    splitA.insert (0);
475    splitA.insert (0);
476    splitA.insert (0);
477  }
478
479  CanonicalForm xToM= power (x, m);
480
481  CFListIterator i= splitA;
482  CanonicalForm H= i.getItem();
483  i++;
484  H *= xToM;
485  H += i.getItem();
486  i++;
487  H *= xToM;
488  H += i.getItem();
489  i++;
490
491  divrem32 (H, B, Q, R, M);
492
493  CFList splitR= split (R, m, x);
494  if (splitR.length() == 1)
495    splitR.insert (0);
496
497  H= splitR.getFirst();
498  H *= xToM;
499  H += splitR.getLast();
500  H *= xToM;
501  H += i.getItem();
502
503  CanonicalForm bufQ;
504  divrem32 (H, B, bufQ, R, M);
505
506  Q *= xToM;
507  Q += bufQ;
508  return;
509}
510
511static inline
512void divrem32 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q, 
513               CanonicalForm& R, const CFList& M) 
514{
515  CanonicalForm A= mod (F, M);
516  CanonicalForm B= mod (G, M);
517  Variable x= Variable (1);
518  int degB= degree (B, x);
519  int degA= degree (A, x);
520  if (degA < degB) 
521  {
522    Q= 0;
523    R= A;
524    return;
525  }
526  ASSERT (3*(degB/2) > degA, "expected degree (F, 1) < 3*(degree (G, 1)/2)");
527  if (degB < 1)
528  {
529    divrem (A, B, Q, R);
530    Q= mod (Q, M);
531    R= mod (R, M);
532    return;
533  }
534  int m= (int) ceil ((double) (degB + 1)/ 2.0);
535
536  CFList splitA= split (A, m, x);
537  CFList splitB= split (B, m, x);
538
539  if (splitA.length() == 2)
540  {
541    splitA.insert (0);
542  }
543  if (splitA.length() == 1)
544  {
545    splitA.insert (0);
546    splitA.insert (0);
547  }
548  CanonicalForm xToM= power (x, m);
549
550  CanonicalForm H;
551  CFListIterator i= splitA;
552  i++;
553
554  if (degree (splitA.getFirst(), x) < degree (splitB.getFirst(), x))
555  {
556    H= splitA.getFirst()*xToM + i.getItem();
557    divrem21 (H, splitB.getFirst(), Q, R, M);
558  }
559  else 
560  {
561    R= splitA.getFirst()*xToM + i.getItem() + splitB.getFirst() - 
562       splitB.getFirst()*xToM;
563    Q= xToM - 1;
564  }
565
566  H= mulMod (Q, splitB.getLast(), M);
567
568  R= R*xToM + splitA.getLast() - H;
569
570  while (degree (R, x) >= degB)
571  {
572    xToM= power (x, degree (R, x) - degB);
573    Q += LC (R, x)*xToM;
574    R -= mulMod (LC (R, x), B, M)*xToM;
575    Q= mod (Q, M);
576    R= mod (R, M);
577  }
578
579  return;
580}
581
582void divrem2 (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
583              CanonicalForm& R, const CanonicalForm& M) 
584{
585  CanonicalForm A= mod (F, M);
586  CanonicalForm B= mod (G, M);
587  Variable x= Variable (1);
588  int degB= degree (B, x);
589  if (degB > degree (A, x)) 
590  {
591    Q= 0;
592    R= A;
593    return;
594  }
595
596  CFList splitA= split (A, degB, x);
597
598  CanonicalForm xToDegB= power (x, degB);
599  CanonicalForm H, bufQ;
600  Q= 0;
601  CFListIterator i= splitA;
602  H= i.getItem()*xToDegB;
603  i++;
604  H += i.getItem();
605  CFList buf;
606  while (i.hasItem()) 
607  {
608    buf= CFList (M);
609    divrem21 (H, B, bufQ, R, buf);
610    i++;
611    if (i.hasItem())
612      H= R*xToDegB + i.getItem();
613    Q *= xToDegB;
614    Q += bufQ; 
615  }
616  return;
617}
618
619void divrem (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
620             CanonicalForm& R, const CFList& MOD)
621{
622  CanonicalForm A= mod (F, MOD);
623  CanonicalForm B= mod (G, MOD);
624  Variable x= Variable (1);
625  int degB= degree (B, x);
626  if (degB > degree (A, x)) 
627  {
628    Q= 0;
629    R= A;
630    return;
631  }
632
633  if (degB == 0)
634  {
635    divrem (A, B, Q, R);
636    Q= mod (Q, MOD);
637    R= mod (R, MOD);
638    return;
639  }
640  CFList splitA= split (A, degB, x);
641
642  CanonicalForm xToDegB= power (x, degB);
643  CanonicalForm H, bufQ;
644  Q= 0;
645  CFListIterator i= splitA;
646  H= i.getItem()*xToDegB;
647  i++;
648  H += i.getItem();
649  while (i.hasItem()) 
650  {
651    divrem21 (H, B, bufQ, R, MOD);
652    i++;
653    if (i.hasItem())
654      H= R*xToDegB + i.getItem();
655    Q *= xToDegB;
656    Q += bufQ; 
657  }
658  return;
659}
660
661void sortList (CFList& list, const Variable& x) 
662{ 
663  int l= 1;
664  int k= 1;
665  CanonicalForm buf;
666  CFListIterator m;
667  for (CFListIterator i= list; l <= list.length(); i++, l++) 
668  {
669    for (CFListIterator j= list; k <= list.length() - l; k++) 
670    {
671      m= j;
672      m++;
673      if (degree (j.getItem(), x) > degree (m.getItem(), x)) 
674      {
675        buf= m.getItem();
676        m.getItem()= j.getItem();
677        j.getItem()= buf;
678        j++;
679        j.getItem()= m.getItem();
680      } 
681      else
682        j++;
683    }
684    k= 1;
685  }
686}
687
688static inline
689CFList diophantine (const CanonicalForm& F, const CFList& factors) 
690{
691  CanonicalForm buf1, buf2, buf3, S, T;
692  CFListIterator i= factors;
693  CFList result;
694  if (i.hasItem())
695    i++;
696  buf1= F/factors.getFirst(); 
697  buf2= divNTL (F, i.getItem());
698  buf3= extgcd (buf1, buf2, S, T);
699  result.append (S);
700  result.append (T);
701  if (i.hasItem())
702    i++;
703  for (; i.hasItem(); i++)
704  {
705    buf1= divNTL (F, i.getItem());
706    buf3= extgcd (buf3, buf1, S, T);
707    CFListIterator k= factors;
708    for (CFListIterator j= result; j.hasItem(); j++, k++)
709    {
710      j.getItem()= mulNTL (j.getItem(), S);
711      j.getItem()= modNTL (j.getItem(), k.getItem());
712    }
713    result.append (T);
714  }
715  return result;
716}
717
718void 
719henselStep12 (const CanonicalForm& F, const CFList& factors, 
720              CFArray& bufFactors, const CFList& diophant, CFMatrix& M,
721              CFArray& Pi, int j)
722{
723  CanonicalForm E;
724  CanonicalForm xToJ= power (F.mvar(), j);
725  Variable x= F.mvar();
726  // compute the error
727  if (j == 1)
728    E= F[j]; 
729  else
730  {
731    if (degree (Pi [factors.length() - 2], x) > 0) 
732      E= F[j] - Pi [factors.length() - 2] [j];
733    else
734      E= F[j]; 
735  }
736
737  CFArray buf= CFArray (diophant.length());
738  bufFactors[0]= mod (factors.getFirst(), power (F.mvar(), j + 1));
739  int k= 0;
740  CanonicalForm remainder;
741  // actual lifting
742  for (CFListIterator i= diophant; i.hasItem(); i++, k++) 
743  {
744    if (degree (bufFactors[k], x) > 0)
745    {
746      if (k > 0)
747        remainder= modNTL (E, bufFactors[k] [0]);
748      else
749        remainder= E;
750    }
751    else
752      remainder= modNTL (E, bufFactors[k]);
753
754    buf[k]= mulNTL (i.getItem(), remainder);
755    if (degree (bufFactors[k], x) > 0)
756      buf[k]= modNTL (buf[k], bufFactors[k] [0]);
757    else 
758      buf[k]= modNTL (buf[k], bufFactors[k]); 
759  }
760  for (k= 1; k < factors.length(); k++)
761    bufFactors[k] += xToJ*buf[k];
762
763  // update Pi [0]
764  int degBuf0= degree (bufFactors[0], x);
765  int degBuf1= degree (bufFactors[1], x);
766  if (degBuf0 > 0 && degBuf1 > 0)
767    M (j + 1, 1)= mulNTL (bufFactors[0] [j], bufFactors[1] [j]);
768  CanonicalForm uIZeroJ;
769  if (j == 1)
770  {
771    if (degBuf0 > 0 && degBuf1 > 0)
772      uIZeroJ= mulNTL ((bufFactors[0] [0] + bufFactors[0] [j]),
773                  (bufFactors[1] [0] + buf[1])) - M(1, 1) - M(j + 1, 1);
774    else if (degBuf0 > 0)
775      uIZeroJ= mulNTL (bufFactors[0] [j], bufFactors[1]);
776    else if (degBuf1 > 0)
777      uIZeroJ= mulNTL (bufFactors[0], buf[1]);
778    else
779      uIZeroJ= 0;
780    Pi [0] += xToJ*uIZeroJ; 
781  } 
782  else
783  {
784    if (degBuf0 > 0 && degBuf1 > 0)
785      uIZeroJ= mulNTL ((bufFactors[0] [0] + bufFactors[0] [j]),
786                  (bufFactors[1] [0] + buf[1])) - M(1, 1) - M(j + 1, 1);
787    else if (degBuf0 > 0)
788      uIZeroJ= mulNTL (bufFactors[0] [j], bufFactors[1]);
789    else if (degBuf1 > 0)
790      uIZeroJ= mulNTL (bufFactors[0], buf[1]);
791    else
792      uIZeroJ= 0;
793    Pi [0] += xToJ*uIZeroJ; 
794  }
795  CFArray tmp= CFArray (factors.length() - 1);
796  for (k= 0; k < factors.length() - 1; k++)
797    tmp[k]= 0;
798  CFIterator one, two;
799  one= bufFactors [0];
800  two= bufFactors [1];
801  if (degBuf0 > 0 && degBuf1 > 0)
802  {
803    for (k= 1; k <= (int) ceil (j/2.0); k++)
804    { 
805      if (k != j - k + 1)
806      {
807        if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
808        {
809          tmp[0] += mulNTL ((bufFactors[0] [k] + one.coeff()), (bufFactors[1] [k] +
810                     two.coeff())) - M (k + 1, 1) - M (j - k + 2, 1);
811          one++;
812          two++;
813        }
814        else if (one.exp() == j - k + 1)
815        {
816          tmp[0] += mulNTL ((bufFactors[0] [k] + one.coeff()), bufFactors[1] [k]) - 
817                     M (k + 1, 1);
818          one++;
819        }
820        else if (two.exp() == j - k + 1)
821        {
822          tmp[0] += mulNTL (bufFactors[0] [k], (bufFactors[1] [k] + two.coeff())) - 
823                    M (k + 1, 1);
824          two++;
825        }
826      }
827      else
828      {
829        tmp[0] += M (k + 1, 1);
830      }
831    }
832  }
833  Pi [0] += tmp[0]*xToJ*F.mvar();
834
835  // update Pi [l]
836  int degPi, degBuf;
837  for (int l= 1; l < factors.length() - 1; l++) 
838  {
839    degPi= degree (Pi [l - 1], x);
840    degBuf= degree (bufFactors[l + 1], x);
841    if (degPi > 0 && degBuf > 0)
842      M (j + 1, l + 1)= mulNTL (Pi [l - 1] [j], bufFactors[l + 1] [j]); 
843    if (j == 1)
844    {
845      if (degPi > 0 && degBuf > 0)
846        Pi [l] += xToJ*(mulNTL (Pi [l - 1] [0] + Pi [l - 1] [j],
847                  bufFactors[l + 1] [0] + buf[l + 1]) - M (j + 1, l +1) - 
848                  M (1, l + 1));
849      else if (degPi > 0)
850        Pi [l] += xToJ*(mulNTL (Pi [l - 1] [j], bufFactors[l + 1]));
851      else if (degBuf > 0)
852        Pi [l] += xToJ*(mulNTL (Pi [l - 1], buf[l + 1]));
853    }
854    else
855    {
856      if (degPi > 0 && degBuf > 0)
857      {
858        uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1] [0]);
859        uIZeroJ += mulNTL (Pi [l - 1] [0], buf [l + 1]); 
860      }
861      else if (degPi > 0)
862        uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1]);
863      else if (degBuf > 0)
864      {
865        uIZeroJ= mulNTL (uIZeroJ, bufFactors [l + 1] [0]);
866        uIZeroJ += mulNTL (Pi [l - 1], buf[l + 1]);
867      }
868      Pi[l] += xToJ*uIZeroJ;
869    }
870    one= bufFactors [l + 1];
871    two= Pi [l - 1];
872    if (two.exp() == j + 1)
873    {
874      if (degBuf > 0 && degPi > 0)
875      {
876          tmp[l] += mulNTL (two.coeff(), bufFactors[l + 1][0]);
877          two++;
878      }
879      else if (degPi > 0)
880      {     
881          tmp[l] += mulNTL (two.coeff(), bufFactors[l + 1]);
882          two++;
883      } 
884    }
885    if (degBuf > 0 && degPi > 0) 
886    {
887      for (k= 1; k <= (int) ceil (j/2.0); k++)
888      { 
889        if (k != j - k + 1)
890        {
891          if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
892          {
893            tmp[l] += mulNTL ((bufFactors[l + 1] [k] + one.coeff()), (Pi[l - 1] [k] +
894                       two.coeff())) - M (k + 1, l + 1) - M (j - k + 2, l + 1);
895            one++;
896            two++;
897          }
898          else if (one.exp() == j - k + 1)
899          {
900            tmp[l] += mulNTL ((bufFactors[l + 1] [k] + one.coeff()), Pi[l - 1] [k]) - 
901                       M (k + 1, l + 1);     
902            one++;
903          }
904          else if (two.exp() == j - k + 1)
905          {
906            tmp[l] += mulNTL (bufFactors[l + 1] [k], (Pi[l - 1] [k] + two.coeff())) - 
907                      M (k + 1, l + 1);
908            two++;
909          }
910        }
911        else
912          tmp[l] += M (k + 1, l + 1);
913      } 
914    } 
915    Pi[l] += tmp[l]*xToJ*F.mvar();
916  }
917  return;
918}
919
920void 
921henselLift12 (const CanonicalForm& F, CFList& factors, int l, CFArray& Pi, 
922              CFList& diophant, CFMatrix& M) 
923{
924  sortList (factors, Variable (1));
925  Pi= CFArray (factors.length() - 1);
926  CFListIterator j= factors;
927  diophant= diophantine (F[0], factors);
928  DEBOUTLN (cerr, "diophant= " << diophant);
929  j++;
930  Pi [0]= mulNTL (j.getItem(), mod (factors.getFirst(), F.mvar()));
931  M (1, 1)= Pi [0];
932  int i= 1;
933  if (j.hasItem())
934    j++;
935  for (j; j.hasItem(); j++, i++) 
936  {
937    Pi [i]= mulNTL (Pi [i - 1], j.getItem());
938    M (1, i + 1)= Pi [i];
939  }
940  CFArray bufFactors= CFArray (factors.length());
941  i= 0;
942  for (CFListIterator k= factors; k.hasItem(); i++, k++)
943  {
944    if (i == 0)
945      bufFactors[i]= mod (k.getItem(), F.mvar());
946    else
947      bufFactors[i]= k.getItem();
948  }
949  for (i= 1; i < l; i++)
950    henselStep12 (F, factors, bufFactors, diophant, M, Pi, i);
951
952  CFListIterator k= factors;
953  for (i= 0; i < factors.length (); i++, k++)
954    k.getItem()= bufFactors[i];
955  factors.removeFirst();
956  return;
957}
958
959void 
960henselLiftResume12 (const CanonicalForm& F, CFList& factors, int start, int
961                    end, CFArray& Pi, const CFList& diophant, CFMatrix& M)
962{
963  CFArray bufFactors= CFArray (factors.length());
964  int i= 0;
965  CanonicalForm xToStart= power (F.mvar(), start);
966  for (CFListIterator k= factors; k.hasItem(); k++, i++)
967  {
968    if (i == 0)
969      bufFactors[i]= mod (k.getItem(), xToStart);
970    else
971      bufFactors[i]= k.getItem();
972  }
973  for (i= start; i < end; i++)
974    henselStep12 (F, factors, bufFactors, diophant, M, Pi, i); 
975 
976  CFListIterator k= factors;
977  for (i= 0; i < factors.length(); k++, i++)
978    k.getItem()= bufFactors [i];
979  factors.removeFirst();
980  return; 
981} 
982
983static inline
984CFList
985biDiophantine (const CanonicalForm& F, const CFList& factors, const int d)
986{
987  Variable y= F.mvar();
988  CFList result;
989  if (y.level() == 1)
990  {
991    result= diophantine (F, factors);
992    return result;
993  }
994  else
995  {
996    CFList buf= factors;
997    for (CFListIterator i= buf; i.hasItem(); i++)
998      i.getItem()= mod (i.getItem(), y);
999    CanonicalForm A= mod (F, y);
1000    int bufD= 1;
1001    CFList recResult= biDiophantine (A, buf, bufD);
1002    CanonicalForm e= 1;
1003    CFList p;
1004    CFArray bufFactors= CFArray (factors.length());
1005    CanonicalForm yToD= power (y, d);
1006    int k= 0;
1007    for (CFListIterator i= factors; i.hasItem(); i++, k++)
1008    {
1009      bufFactors [k]= i.getItem();
1010    }
1011    CanonicalForm b;
1012    for (k= 0; k < factors.length(); k++) //TODO compute b's faster
1013    {
1014      b= 1;
1015      if (fdivides (bufFactors[k], F))
1016        b= F/bufFactors[k];
1017      else 
1018      {
1019        for (int l= 0; l < factors.length(); l++)
1020        {
1021          if (l == k)
1022            continue;
1023          else
1024          {
1025            b= mulMod2 (b, bufFactors[l], yToD);
1026          }
1027        }
1028      }
1029      p.append (b);
1030    } 
1031
1032    CFListIterator j= p;
1033    for (CFListIterator i= recResult; i.hasItem(); i++, j++)
1034      e -= i.getItem()*j.getItem();
1035
1036    if (e.isZero())
1037      return recResult; 
1038    CanonicalForm coeffE;
1039    CFList s;
1040    result= recResult;
1041    CanonicalForm g;
1042    for (int i= 1; i < d; i++)
1043    {
1044      if (degree (e, y) > 0)
1045        coeffE= e[i];
1046      else
1047        coeffE= 0;
1048      if (!coeffE.isZero())
1049      {
1050        CFListIterator k= result;
1051        CFListIterator l= p;
1052        int ii= 0;
1053        j= recResult;
1054        for (; j.hasItem(); j++, k++, l++, ii++)
1055        {
1056          g= coeffE*j.getItem();
1057          if (degree (bufFactors[ii], y) <= 0)
1058            g= mod (g, bufFactors[ii]);
1059          else
1060            g= mod (g, bufFactors[ii][0]);
1061          k.getItem() += g*power (y, i); 
1062          e -= mulMod2 (g*power(y, i), l.getItem(), yToD);
1063          DEBOUTLN (cerr, "mod (e, power (y, i + 1))= " << 
1064                    mod (e, power (y, i + 1)));
1065        } 
1066      } 
1067      if (e.isZero())
1068        break;
1069    }
1070
1071    DEBOUTLN (cerr, "mod (e, y)= " << mod (e, y));
1072
1073#ifdef DEBUGOUTPUT
1074    CanonicalForm test= 0;
1075    j= p; 
1076    for (CFListIterator i= result; i.hasItem(); i++, j++)
1077      test += mod (i.getItem()*j.getItem(), power (y, d));
1078    DEBOUTLN (cerr, "test= " << test);
1079#endif
1080    return result;
1081  }
1082}
1083
1084static inline
1085CFList
1086multiRecDiophantine (const CanonicalForm& F, const CFList& factors, 
1087                     const CFList& recResult, const CFList& M, const int d)
1088{
1089  Variable y= F.mvar();
1090  CFList result;
1091  CFListIterator i;
1092  CanonicalForm e= 1;
1093  CFListIterator j= factors;
1094  CFList p;
1095  CFArray bufFactors= CFArray (factors.length());
1096  CanonicalForm yToD= power (y, d);
1097  int k= 0;
1098  for (CFListIterator i= factors; i.hasItem(); i++, k++)
1099    bufFactors [k]= i.getItem();
1100  CanonicalForm b;
1101  CFList buf= M;
1102  buf.removeLast();
1103  buf.append (yToD);
1104  for (k= 0; k < factors.length(); k++) //TODO compute b's faster
1105  {
1106    b= 1;
1107    if (fdivides (bufFactors[k], F))
1108      b= F/bufFactors[k];
1109    else 
1110    {
1111      for (int l= 0; l < factors.length(); l++)
1112      {
1113        if (l == k)
1114          continue;
1115        else
1116        {
1117          b= mulMod (b, bufFactors[l], buf);
1118        }
1119      }
1120    }
1121    p.append (b);
1122  } 
1123  j= p;
1124  for (CFListIterator i= recResult; i.hasItem(); i++, j++)
1125    e -= mulMod (i.getItem(), j.getItem(), M);
1126
1127  if (e.isZero())
1128    return recResult; 
1129  CanonicalForm coeffE;
1130  CFList s;
1131  result= recResult;
1132  CanonicalForm g;
1133  for (int i= 1; i < d; i++)
1134  {
1135    if (degree (e, y) > 0)
1136      coeffE= e[i];
1137    else
1138      coeffE= 0;
1139    if (!coeffE.isZero())
1140    {
1141      CFListIterator k= result;
1142      CFListIterator l= p;
1143      j= recResult;
1144      int ii= 0;
1145      CanonicalForm dummy;
1146      for (; j.hasItem(); j++, k++, l++, ii++)
1147      {
1148        g= mulMod (coeffE, j.getItem(), M);
1149        if (degree (bufFactors[ii], y) <= 0)
1150          divrem (g, mod (bufFactors[ii], Variable (y.level() - 1)), dummy, 
1151                  g, M);
1152        else
1153          divrem (g, bufFactors[ii][0], dummy, g, M);
1154        k.getItem() += g*power (y, i);
1155        e -= mulMod (g*power (y, i), l.getItem(), M);
1156      } 
1157    }
1158 
1159    if (e.isZero())
1160      break;
1161  }
1162
1163#ifdef DEBUGOUTPUT
1164    CanonicalForm test= 0;
1165    j= p; 
1166    for (CFListIterator i= result; i.hasItem(); i++, j++)
1167      test += mod (i.getItem()*j.getItem(), power (y, d));
1168    DEBOUTLN (cerr, "test= " << test);
1169#endif
1170  return result;
1171}
1172
1173static inline
1174void 
1175henselStep (const CanonicalForm& F, const CFList& factors, CFArray& bufFactors, 
1176            const CFList& diophant, CFMatrix& M, CFArray& Pi, int j, 
1177            const CFList& MOD) 
1178{
1179  CanonicalForm E;
1180  CanonicalForm xToJ= power (F.mvar(), j);
1181  Variable x= F.mvar();
1182  // compute the error
1183  if (j == 1)
1184  {
1185    E= F[j];
1186#ifdef DEBUGOUTPUT
1187    CanonicalForm test= 1;
1188    for (int i= 0; i < factors.length(); i++)
1189    {
1190      if (i == 0)
1191        test= mulMod (test, mod (bufFactors [i], xToJ), MOD);
1192      else
1193        test= mulMod (test, bufFactors[i], MOD);
1194    }
1195    CanonicalForm test2= mod (F-test, xToJ);
1196
1197    test2= mod (test2, MOD);
1198    DEBOUTLN (cerr, "test= " << test2);
1199#endif
1200  } 
1201  else
1202  {
1203#ifdef DEBUGOUTPUT
1204    CanonicalForm test= 1;
1205    for (int i= 0; i < factors.length(); i++)
1206    {
1207      if (i == 0)
1208        test *= mod (bufFactors [i], power (x, j));
1209      else
1210        test *= bufFactors[i];
1211    }
1212    test= mod (test, power (x, j));
1213    test= mod (test, MOD);
1214    CanonicalForm test2= mod (F, power (x, j - 1)) - mod (test, power (x, j-1));
1215    DEBOUTLN (cerr, "test= " << test2);
1216#endif
1217
1218    if (degree (Pi [factors.length() - 2], x) > 0)
1219      E= F[j] - Pi [factors.length() - 2] [j];
1220    else
1221      E= F[j];
1222  }
1223
1224  CFArray buf= CFArray (diophant.length());
1225  bufFactors[0]= mod (factors.getFirst(), power (F.mvar(), j + 1));
1226  int k= 0;
1227  // actual lifting
1228  CanonicalForm dummy, rest1;
1229  for (CFListIterator i= diophant; i.hasItem(); i++, k++) 
1230  {
1231    if (degree (bufFactors[k], x) > 0)
1232    {
1233      if (k > 0)
1234        divrem (E, bufFactors[k] [0], dummy, rest1, MOD);
1235      else
1236        rest1= E;
1237    }
1238    else
1239      divrem (E, bufFactors[k], dummy, rest1, MOD);
1240
1241    buf[k]= mulMod (i.getItem(), rest1, MOD);
1242
1243    if (degree (bufFactors[k], x) > 0)
1244      divrem (buf[k], bufFactors[k] [0], dummy, buf[k], MOD);
1245    else 
1246      divrem (buf[k], bufFactors[k], dummy, buf[k], MOD);
1247  }
1248  for (k= 1; k < factors.length(); k++)
1249    bufFactors[k] += xToJ*buf[k];
1250
1251  // update Pi [0]
1252  int degBuf0= degree (bufFactors[0], x);
1253  int degBuf1= degree (bufFactors[1], x);
1254  if (degBuf0 > 0 && degBuf1 > 0)
1255    M (j + 1, 1)= mulMod (bufFactors[0] [j], bufFactors[1] [j], MOD);
1256  CanonicalForm uIZeroJ;
1257  if (j == 1)
1258  {
1259    if (degBuf0 > 0 && degBuf1 > 0)
1260      uIZeroJ= mulMod ((bufFactors[0] [0] + bufFactors[0] [j]),
1261                  (bufFactors[1] [0] + buf[1]), MOD) - M(1, 1) - M(j + 1, 1);
1262    else if (degBuf0 > 0)
1263      uIZeroJ= mulMod (bufFactors[0] [j], bufFactors[1], MOD);
1264    else if (degBuf1 > 0)
1265      uIZeroJ= mulMod (bufFactors[0], buf[1], MOD);
1266    else
1267      uIZeroJ= 0;
1268    Pi [0] += xToJ*uIZeroJ; 
1269  } 
1270  else
1271  {
1272    if (degBuf0 > 0 && degBuf1 > 0)
1273      uIZeroJ= mulMod ((bufFactors[0] [0] + bufFactors[0] [j]), 
1274                  (bufFactors[1] [0] + buf[1]), MOD) - M(1, 1) - M(j + 1, 1);
1275    else if (degBuf0 > 0)
1276      uIZeroJ= mulMod (bufFactors[0] [j], bufFactors[1], MOD);
1277    else if (degBuf1 > 0)
1278      uIZeroJ= mulMod (bufFactors[0], buf[1], MOD);
1279    else
1280      uIZeroJ= 0;
1281    Pi [0] += xToJ*uIZeroJ; 
1282  }
1283
1284  CFArray tmp= CFArray (factors.length() - 1);
1285  for (k= 0; k < factors.length() - 1; k++)
1286    tmp[k]= 0;
1287  CFIterator one, two;
1288  one= bufFactors [0];
1289  two= bufFactors [1];
1290  if (degBuf0 > 0 && degBuf1 > 0)
1291  {
1292    for (k= 1; k <= (int) ceil (j/2.0); k++)
1293    { 
1294      if (k != j - k + 1)
1295      {
1296        if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
1297        {
1298          tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()), 
1299                    (bufFactors[1] [k] + two.coeff()), MOD) - M (k + 1, 1) - 
1300                    M (j - k + 2, 1);
1301          one++;
1302          two++;
1303        }
1304        else if (one.exp() == j - k + 1)
1305        {
1306          tmp[0] += mulMod ((bufFactors[0] [k] + one.coeff()), 
1307                    bufFactors[1] [k], MOD) - M (k + 1, 1);
1308          one++;
1309        }
1310        else if (two.exp() == j - k + 1)
1311        {
1312          tmp[0] += mulMod (bufFactors[0] [k], (bufFactors[1] [k] + 
1313                    two.coeff()), MOD) - M (k + 1, 1);
1314          two++;
1315        }
1316      }
1317      else
1318      {
1319        tmp[0] += M (k + 1, 1);
1320      }
1321    }
1322  }
1323  Pi [0] += tmp[0]*xToJ*F.mvar();
1324
1325  // update Pi [l]
1326  int degPi, degBuf;
1327  for (int l= 1; l < factors.length() - 1; l++) 
1328  {
1329    degPi= degree (Pi [l - 1], x);
1330    degBuf= degree (bufFactors[l + 1], x);
1331    if (degPi > 0 && degBuf > 0)
1332      M (j + 1, l + 1)= mulMod (Pi [l - 1] [j], bufFactors[l + 1] [j], MOD); 
1333    if (j == 1)
1334    {
1335      if (degPi > 0 && degBuf > 0)
1336        Pi [l] += xToJ*(mulMod ((Pi [l - 1] [0] + Pi [l - 1] [j]), 
1337                  (bufFactors[l + 1] [0] + buf[l + 1]), MOD) - M (j + 1, l +1)- 
1338                  M (1, l + 1));
1339      else if (degPi > 0)
1340        Pi [l] += xToJ*(mulMod (Pi [l - 1] [j], bufFactors[l + 1], MOD));
1341      else if (degBuf > 0)
1342        Pi [l] += xToJ*(mulMod (Pi [l - 1], buf[l + 1], MOD));
1343    }
1344    else
1345    {
1346      if (degPi > 0 && degBuf > 0)
1347      {
1348        uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1] [0], MOD);
1349        uIZeroJ += mulMod (Pi [l - 1] [0], buf [l + 1], MOD); 
1350      }
1351      else if (degPi > 0)
1352        uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1], MOD);
1353      else if (degBuf > 0)
1354      {
1355        uIZeroJ= mulMod (uIZeroJ, bufFactors [l + 1] [0], MOD);
1356        uIZeroJ += mulMod (Pi [l - 1], buf[l + 1], MOD);
1357      }
1358      Pi[l] += xToJ*uIZeroJ;
1359    }
1360    one= bufFactors [l + 1];
1361    two= Pi [l - 1];
1362    if (two.exp() == j + 1)
1363    {
1364      if (degBuf > 0 && degPi > 0)
1365      {
1366          tmp[l] += mulMod (two.coeff(), bufFactors[l + 1][0], MOD);
1367          two++;
1368      }
1369      else if (degPi > 0)
1370      {     
1371          tmp[l] += mulMod (two.coeff(), bufFactors[l + 1], MOD);
1372          two++;
1373      } 
1374    }
1375    if (degBuf > 0 && degPi > 0) 
1376    {
1377      for (k= 1; k <= (int) ceil (j/2.0); k++)
1378      { 
1379        if (k != j - k + 1)
1380        {
1381          if (one.exp() == j - k + 1 && two.exp() == j - k + 1)
1382          {
1383            tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()), 
1384                      (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1) - 
1385                      M (j - k + 2, l + 1);
1386            one++;
1387            two++;
1388          }
1389          else if (one.exp() == j - k + 1)
1390          {
1391            tmp[l] += mulMod ((bufFactors[l + 1] [k] + one.coeff()), 
1392                      Pi[l - 1] [k], MOD) - M (k + 1, l + 1);     
1393            one++;
1394          }
1395          else if (two.exp() == j - k + 1)
1396          {
1397            tmp[l] += mulMod (bufFactors[l + 1] [k], 
1398                      (Pi[l - 1] [k] + two.coeff()), MOD) - M (k + 1, l + 1);
1399            two++;
1400          }
1401        }
1402        else
1403          tmp[l] += M (k + 1, l + 1);
1404      } 
1405    } 
1406    Pi[l] += tmp[l]*xToJ*F.mvar();
1407  }
1408
1409  return;
1410}
1411
1412CFList
1413henselLift23 (const CFList& eval, const CFList& factors, const int* l, CFList&
1414              diophant, CFArray& Pi, CFMatrix& M)
1415{
1416  CFList buf= factors;
1417  int k= 0;
1418  int liftBound;
1419  int liftBoundBivar= l[k];
1420  diophant= biDiophantine (eval.getFirst(), buf, liftBoundBivar);
1421  CFList MOD;
1422  MOD.append (power (Variable (2), liftBoundBivar));
1423  CFArray bufFactors= CFArray (factors.length());
1424  k= 0;
1425  CFListIterator j= eval;
1426  j++;
1427  buf.removeFirst();
1428  buf.insert (LC (j.getItem(), 1));
1429  for (CFListIterator i= buf; i.hasItem(); i++, k++)
1430    bufFactors[k]= i.getItem();
1431  Pi= CFArray (factors.length() - 1);
1432  CFListIterator i= buf;
1433  i++;
1434  Variable y= j.getItem().mvar();
1435  Pi [0]= mulMod (i.getItem(), mod (buf.getFirst(), y), MOD);
1436  M (1, 1)= Pi [0];
1437  k= 1;
1438  if (i.hasItem())
1439    i++;
1440  for (i; i.hasItem(); i++, k++) 
1441  {
1442    Pi [k]= mulMod (Pi [k - 1], i.getItem(), MOD);
1443    M (1, k + 1)= Pi [k];
1444  }
1445
1446  for (int d= 1; d < l[1]; d++)
1447    henselStep (j.getItem(), buf, bufFactors, diophant, M, Pi, d, MOD);
1448  CFList result;
1449  for (k= 1; k < factors.length(); k++)
1450    result.append (bufFactors[k]);
1451  return result;
1452} 
1453
1454void 
1455henselLiftResume (const CanonicalForm& F, CFList& factors, int start, int end, 
1456                  CFArray& Pi, const CFList& diophant, CFMatrix& M, 
1457                  const CFList& MOD)
1458{
1459  CFArray bufFactors= CFArray (factors.length());
1460  int i= 0;
1461  CanonicalForm xToStart= power (F.mvar(), start);
1462  for (CFListIterator k= factors; k.hasItem(); k++, i++)
1463  {
1464    if (i == 0)
1465      bufFactors[i]= mod (k.getItem(), xToStart);
1466    else
1467      bufFactors[i]= k.getItem();
1468  }
1469  for (i= start; i < end; i++)
1470    henselStep (F, factors, bufFactors, diophant, M, Pi, i, MOD); 
1471 
1472  CFListIterator k= factors;
1473  for (i= 0; i < factors.length(); k++, i++)
1474    k.getItem()= bufFactors [i];
1475  factors.removeFirst();
1476  return; 
1477} 
1478
1479CFList
1480henselLift (const CFList& F, const CFList& factors, const CFList& MOD, CFList&
1481            diophant, CFArray& Pi, CFMatrix& M, const int lOld, const int
1482            lNew)
1483{
1484  diophant= multiRecDiophantine (F.getFirst(), factors, diophant, MOD, lOld);
1485  int k= 0;
1486  CFArray bufFactors= CFArray (factors.length());
1487  for (CFListIterator i= factors; i.hasItem(); i++, k++)
1488  {
1489    if (k == 0)
1490      bufFactors[k]= LC (F.getLast(), 1);
1491    else
1492      bufFactors[k]= i.getItem();
1493  }
1494  CFList buf= factors;
1495  buf.removeFirst();
1496  buf.insert (LC (F.getLast(), 1));
1497  CFListIterator i= buf;
1498  i++;
1499  Variable y= F.getLast().mvar();
1500  Variable x= F.getFirst().mvar();
1501  CanonicalForm xToLOld= power (x, lOld);
1502  Pi [0]= mod (Pi[0], xToLOld);
1503  M (1, 1)= Pi [0];
1504  k= 1;
1505  if (i.hasItem())
1506    i++;
1507  for (i; i.hasItem(); i++, k++) 
1508  {
1509    Pi [k]= mod (Pi [k], xToLOld);
1510    M (1, k + 1)= Pi [k];
1511  }
1512
1513  for (int d= 1; d < lNew; d++)
1514    henselStep (F.getLast(), buf, bufFactors, diophant, M, Pi, d, MOD);
1515  CFList result;
1516  for (k= 1; k < factors.length(); k++)
1517    result.append (bufFactors[k]);
1518  return result;
1519}
1520
1521CFList
1522henselLift (const CFList& eval, const CFList& factors, const int* l, const int
1523            lLength)
1524{
1525  CFList diophant; 
1526  CFList buf= factors; 
1527  buf.insert (LC (eval.getFirst(), 1));
1528  sortList (buf, Variable (1));
1529  CFArray Pi;
1530  CFMatrix M= CFMatrix (l[1], factors.length());
1531  CFList result= henselLift23 (eval, buf, l, diophant, Pi, M);
1532  if (eval.length() == 2)
1533    return result;
1534  CFList MOD;
1535  for (int i= 0; i < 2; i++)
1536    MOD.append (power (Variable (i + 2), l[i]));
1537  CFListIterator j= eval;
1538  j++;
1539  CFList bufEval;
1540  bufEval.append (j.getItem());
1541  j++;
1542 
1543  for (int i= 2; i <= lLength && j.hasItem(); i++, j++)
1544  {
1545    result.insert (LC (bufEval.getFirst(), 1));
1546    bufEval.append (j.getItem());
1547    M= CFMatrix (l[i], factors.length());
1548    result= henselLift (bufEval, result, MOD, diophant, Pi, M, l[i - 1], l[i]);
1549    MOD.append (power (Variable (i + 2), l[i]));
1550    bufEval.removeFirst();
1551  }
1552  return result; 
1553}
1554
1555#endif
1556/* HAVE_NTL */
1557
Note: See TracBrowser for help on using the repository browser.