source: git/factory/facHensel.cc @ e23e9c

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