source: git/factory/facFactorize.cc @ 589ef64

jengelh-datetimespielwiese
Last change on this file since 589ef64 was 589ef64, checked in by Martin Lee <martinlee84@…>, 11 years ago
fix: need to buffer factors
  • Property mode set to 100644
File size: 46.0 KB
Line 
1/*****************************************************************************\
2 * Computer Algebra System SINGULAR
3\*****************************************************************************/
4/** @file facFqFactorize.cc
5 *
6 * multivariate factorization over Q(a)
7 *
8 * @author Martin Lee
9 *
10 **/
11/*****************************************************************************/
12
13#include "config.h"
14
15#include "assert.h"
16#include "debug.h"
17#include "timing.h"
18
19#include "cf_algorithm.h"
20#include "facFqFactorizeUtil.h"
21#include "facFactorize.h"
22#include "facFqFactorize.h"
23#include "cf_random.h"
24#include "facHensel.h"
25#include "cf_gcd_smallp.h"
26#include "cf_map_ext.h"
27#include "algext.h"
28#include "cf_reval.h"
29#include "facSparseHensel.h"
30
31TIMING_DEFINE_PRINT(fac_bi_factorize)
32TIMING_DEFINE_PRINT(fac_hensel_lift)
33TIMING_DEFINE_PRINT(fac_factor_recombination)
34
35#ifdef HAVE_NTL
36CFList evalPoints (const CanonicalForm& F, CFList& eval, Evaluation& E)
37{
38  CFList result;
39  Variable x= Variable (1);
40
41  bool found= false;
42  bool allZero= true;
43  bool foundZero= false;
44  CanonicalForm deriv_x, gcd_deriv;
45  CFListIterator iter;
46  do
47  {
48    eval.insert (F);
49    bool bad= false;
50    for (int i= E.max(); i >= E.min(); i--)
51    {
52      eval.insert (eval.getFirst()( E [i], i));
53      result.append (E[i]);
54      if (!E[i].isZero())
55        allZero= false;
56      else
57        foundZero= true;
58      if (!allZero && foundZero)
59      {
60        result= CFList();
61        eval= CFList();
62        bad= true;
63        foundZero= false;
64        break;
65      }
66      if (degree (eval.getFirst(), i - 1) != degree (F, i - 1))
67      {
68        result= CFList();
69        eval= CFList();
70        bad= true;
71        break;
72      }
73    }
74
75    if (bad)
76    {
77      E.nextpoint();
78      continue;
79    }
80
81    if (degree (eval.getFirst()) != degree (F, 1))
82    {
83      result= CFList();
84      eval= CFList();
85      E.nextpoint();
86      continue;
87    }
88
89    deriv_x= deriv (eval.getFirst(), x);
90    gcd_deriv= gcd (eval.getFirst(), deriv_x);
91    if (degree (gcd_deriv) > 0)
92    {
93      result= CFList();
94      eval= CFList();
95      E.nextpoint();
96      continue;
97    }
98    iter= eval;
99    iter++;
100    CanonicalForm contentx= content (iter.getItem(), x);
101    if (degree (contentx) > 0)
102    {
103      result= CFList();
104      eval= CFList();
105      E.nextpoint();
106      continue;
107    }
108    found= true;
109  }
110  while (!found);
111
112  if (!eval.isEmpty())
113    eval.removeFirst();
114  return result;
115}
116
117void
118factorizationWRTDifferentSecondVars (const CanonicalForm& A, CFList*& Aeval,
119                                     int& minFactorsLength, bool& irred,
120                                     const Variable& w)
121{
122  Variable x= Variable (1);
123  minFactorsLength= 0;
124  irred= false;
125  Variable v;
126  CFList factors;
127  CanonicalForm LCA= LC (A,1);
128  if (!LCA.inCoeffDomain())
129  {
130    for (int j= 0; j < A.level() - 2; j++)
131    {
132      if (!Aeval[j].isEmpty() && (degree (LCA, j+3) > 0))
133      {
134        v= Variable (Aeval[j].getFirst().level());
135
136        factors= ratBiSqrfFactorize (Aeval[j].getFirst(), w);
137
138        if (factors.getFirst().inCoeffDomain())
139          factors.removeFirst();
140
141        if (minFactorsLength == 0)
142          minFactorsLength= factors.length();
143        else
144          minFactorsLength= tmin (minFactorsLength, factors.length());
145
146        if (factors.length() == 1)
147        {
148          irred= true;
149          return;
150        }
151        sortList (factors, x);
152        Aeval [j]= factors;
153      }
154      else if (!Aeval[j].isEmpty())
155      {
156        Aeval[j]=CFList();
157      }
158    }
159  }
160  else
161  {
162    for (int j= 0; j < A.level() - 2; j++)
163      Aeval[j]= CFList();
164  }
165}
166
167int
168testFactors (const CanonicalForm& G, const CFList& uniFactors,
169             CanonicalForm& sqrfPartF, CFList& factors,
170             CFFList*& bufSqrfFactors, CFList& evalSqrfPartF,
171             const CFArray& evalPoint)
172{
173  CanonicalForm tmp;
174  CFListIterator j;
175  for (CFListIterator i= uniFactors; i.hasItem(); i++)
176  {
177    tmp= i.getItem();
178    if (i.hasItem())
179      i++;
180    else
181      break;
182    for (j= i; j.hasItem(); j++)
183    {
184      if (tmp == j.getItem())
185        return 0;
186    }
187  }
188
189  CanonicalForm F= G;
190  CFFList sqrfFactorization= sqrFree (F);
191
192  sqrfPartF= 1;
193  for (CFFListIterator i= sqrfFactorization; i.hasItem(); i++)
194    sqrfPartF *= i.getItem().factor();
195
196  evalSqrfPartF= evaluateAtEval (sqrfPartF, evalPoint);
197
198  CanonicalForm test= evalSqrfPartF.getFirst() (evalPoint[0], 2);
199
200  if (degree (test) != degree (sqrfPartF, 1) || test.inCoeffDomain())
201    return 0;
202
203  CFFList sqrfFactors;
204  CFList tmp2;
205  int k= 0;
206  factors= uniFactors;
207  CFFListIterator iter;
208  for (CFListIterator i= factors; i.hasItem(); i++, k++)
209  {
210    tmp= 1;
211    sqrfFactors= sqrFree (i.getItem());
212
213    for (iter= sqrfFactors; iter.hasItem(); iter++)
214    {
215      tmp2.append (iter.getItem().factor());
216      tmp *= iter.getItem().factor();
217    }
218    i.getItem()= tmp/Lc(tmp);
219    bufSqrfFactors [k]= sqrfFactors;
220  }
221
222  for (int i= 0; i < factors.length() - 1; i++)
223  {
224    for (int k= i + 1; k < factors.length(); k++)
225    {
226      gcdFreeBasis (bufSqrfFactors [i], bufSqrfFactors[k]);
227    }
228  }
229
230  factors= CFList();
231  for (int i= 0; i < uniFactors.length(); i++)
232  {
233    if (i == 0)
234    {
235      for (iter= bufSqrfFactors [i]; iter.hasItem(); iter++)
236      {
237        if (iter.getItem().factor().inCoeffDomain())
238          continue;
239        iter.getItem()= CFFactor (iter.getItem().factor()/
240                                  Lc (iter.getItem().factor()),
241                                  iter.getItem().exp());
242        factors.append (iter.getItem().factor());
243      }
244    }
245    else
246    {
247      for (iter= bufSqrfFactors [i]; iter.hasItem(); iter++)
248      {
249        if (iter.getItem().factor().inCoeffDomain())
250          continue;
251        iter.getItem()= CFFactor (iter.getItem().factor()/
252                               Lc (iter.getItem().factor()),
253                               iter.getItem().exp());
254        if (!find (factors, iter.getItem().factor()))
255          factors.append (iter.getItem().factor());
256      }
257    }
258  }
259
260  test= prod (factors);
261  tmp= evalSqrfPartF.getFirst() (evalPoint[0],2);
262  if (test/Lc (test) != tmp/Lc (tmp))
263    return 0;
264  else
265    return 1;
266}
267
268CFList
269precomputeLeadingCoeff (const CanonicalForm& LCF, const CFList& LCFFactors,
270                        const CFList& evaluation,CFList*& differentSecondVarLCs,
271                        int length, Variable& y
272                       )
273{
274  y= Variable (1);
275  if (LCF.inCoeffDomain())
276  {
277    CFList result;
278    for (int i= 1; i <= LCFFactors.length() + 1; i++)
279      result.append (1);
280    return result;
281  }
282
283  CFMap N, M;
284  CFArray dummy= CFArray (2);
285  dummy [0]= LCF;
286  dummy [1]= Variable (2);
287  compress (dummy, M, N);
288  CanonicalForm F= M (LCF);
289  if (LCF.isUnivariate())
290  {
291    CFList result;
292    int LCFLevel= LCF.level();
293    bool found= false;
294    if (LCFLevel == 2)
295    {
296    //bivariate leading coefficients are already the true leading coefficients
297      result= LCFFactors;
298      found= true;
299    }
300    else
301    {
302      CFListIterator j;
303      for (int i= 0; i < length; i++)
304      {
305        for (j= differentSecondVarLCs[i]; j.hasItem(); j++)
306        {
307          if (j.getItem().level() == LCFLevel)
308          {
309            found= true;
310            break;
311          }
312        }
313        if (found)
314        {
315          result= differentSecondVarLCs [i];
316          break;
317        }
318      }
319      if (!found)
320        result= LCFFactors;
321    }
322    if (found)
323      result.insert (Lc (LCF));
324    else
325      result.append (LCF);
326    return result;
327  }
328
329  CFList factors= LCFFactors;
330
331  for (CFListIterator i= factors; i.hasItem(); i++)
332    i.getItem()= M (i.getItem());
333
334  CanonicalForm sqrfPartF;
335  CFFList * bufSqrfFactors= new CFFList [factors.length()];
336  CFList evalSqrfPartF, bufFactors;
337  CFArray evalPoint= CFArray (evaluation.length() - 1);
338  CFArray buf= CFArray (evaluation.length());
339  CFArray swap= CFArray (evaluation.length());
340  CFListIterator iter= evaluation;
341  CanonicalForm vars=getVars (LCF)*Variable (2);
342  for (int i= evaluation.length() +1; i > 1; i--, iter++)
343  {
344    buf[i-2]=iter.getItem();
345    if (degree (vars, i) > 0)
346      swap[M(Variable (i)).level()-1]=buf[i-2];
347  }
348  buf= swap;
349  for (int i= 0; i < evaluation.length() - 1; i++)
350    evalPoint[i]= buf[i+1];
351
352  //TODO sqrfPartF einmal berechnen nicht stÀndig
353  int pass= testFactors (F, factors, sqrfPartF,
354                         bufFactors, bufSqrfFactors, evalSqrfPartF, evalPoint);
355
356  bool foundDifferent= false;
357  Variable z;
358  Variable x= y;
359  int j= 0;
360  if (!pass)
361  {
362    int lev= 0;
363    CanonicalForm bufF;
364    CFList bufBufFactors;
365    for (int i= 0; i < length; i++)
366    {
367      if (!differentSecondVarLCs [i].isEmpty())
368      {
369        bool allConstant= true;
370        for (iter= differentSecondVarLCs[i]; iter.hasItem(); iter++)
371        {
372          if (!iter.getItem().inCoeffDomain())
373          {
374            allConstant= false;
375            y= Variable (iter.getItem().level());
376            lev= M(y).level();
377          }
378        }
379        if (allConstant)
380          continue;
381
382        bufFactors= differentSecondVarLCs [i];
383        for (iter= bufFactors; iter.hasItem(); iter++)
384          iter.getItem()= swapvar (iter.getItem(), x, y);
385        bufF= F;
386        z= Variable (lev);
387        bufF= swapvar (bufF, x, z);
388        bufBufFactors= bufFactors;
389        evalPoint= CFArray (evaluation.length() - 1);
390        for (int k= 0; k < evaluation.length()-1; k++)
391        {
392          if (N (Variable (k+1)).level() != y.level())
393            evalPoint[k]= buf[k+1];
394          else
395            evalPoint[k]= buf[0];
396        }
397        pass= testFactors (bufF, bufBufFactors, sqrfPartF, bufFactors,
398                           bufSqrfFactors, evalSqrfPartF, evalPoint);
399        if (pass)
400        {
401          foundDifferent= true;
402          F= bufF;
403          CFList l= factors;
404          for (iter= l; iter.hasItem(); iter++)
405            iter.getItem()= swapvar (iter.getItem(), x, y);
406          differentSecondVarLCs [i]= l;
407          j= i;
408          break;
409        }
410        if (!pass && i == length - 1)
411        {
412          CFList result;
413          result.append (LCF);
414          for (int j= 1; j <= factors.length(); j++)
415            result.append (1);
416          result= distributeContent (result, differentSecondVarLCs, length);
417          if (!result.getFirst().inCoeffDomain())
418          {
419            CFListIterator iter= result;
420            CanonicalForm tmp= iter.getItem();
421            iter++;
422            for (; iter.hasItem(); iter++)
423              iter.getItem() *= tmp;
424          }
425
426          y= Variable (1);
427          delete [] bufSqrfFactors;
428          return result;
429        }
430      }
431    }
432  }
433  if (!pass)
434  {
435    CFList result;
436    result.append (LCF);
437    for (int j= 1; j <= factors.length(); j++)
438      result.append (LCF);
439    y= Variable (1);
440    delete [] bufSqrfFactors;
441    return result;
442  }
443  else
444    factors= bufFactors;
445
446
447  bufFactors= factors;
448
449  CFMap MM, NN;
450  dummy [0]= sqrfPartF;
451  dummy [1]= 1;
452  compress (dummy, MM, NN);
453  sqrfPartF= MM (sqrfPartF);
454  CanonicalForm varsSqrfPartF= getVars (sqrfPartF);
455  for (CFListIterator iter= factors; iter.hasItem(); iter++)
456    iter.getItem()= MM (iter.getItem());
457
458  CFList evaluation2;
459  for (int i= 2; i <= varsSqrfPartF.level(); i++)
460    evaluation2.insert (evalPoint[NN (Variable (i)).level()-2]);
461
462  CFList interMedResult;
463  CanonicalForm oldSqrfPartF= sqrfPartF;
464  sqrfPartF= shift2Zero (sqrfPartF, evalSqrfPartF, evaluation2);
465  if (factors.length() > 1)
466  {
467    CanonicalForm LC1= LC (oldSqrfPartF, 1);
468    CFList leadingCoeffs;
469    for (int i= 0; i < factors.length(); i++)
470      leadingCoeffs.append (LC1);
471
472    CFList LC1eval= evaluateAtEval (LC1, evaluation2,2);
473    CFList oldFactors= factors;
474    for (CFListIterator i= oldFactors; i.hasItem(); i++)
475      i.getItem() *= LC1eval.getFirst()/Lc (i.getItem());
476
477    bool success= false;
478    CanonicalForm oldSqrfPartFPowLC= oldSqrfPartF*power(LC1,factors.length()-1);
479    CFList heuResult;
480    if (size (oldSqrfPartFPowLC)/getNumVars (oldSqrfPartFPowLC) < 500 &&
481        LucksWangSparseHeuristic (oldSqrfPartFPowLC,
482                                  oldFactors, 2, leadingCoeffs, heuResult))
483    {
484      interMedResult= recoverFactors (oldSqrfPartF, heuResult);
485      if (oldFactors.length() == interMedResult.length())
486        success= true;
487    }
488    if (!success)
489    {
490      LC1= LC (evalSqrfPartF.getFirst(), 1);
491
492      CFArray leadingCoeffs= CFArray (factors.length());
493      for (int i= 0; i < factors.length(); i++)
494        leadingCoeffs[i]= LC1;
495
496      for (CFListIterator i= factors; i.hasItem(); i++)
497        i.getItem() *= LC1 (0,2)/Lc (i.getItem());
498      factors.insert (1);
499
500      CanonicalForm
501      newSqrfPartF= evalSqrfPartF.getFirst()*power (LC1, factors.length() - 2);
502
503      int liftBound= degree (newSqrfPartF,2) + 1;
504
505      CFMatrix M= CFMatrix (liftBound, factors.length() - 1);
506      CFArray Pi;
507      CFList diophant;
508      nonMonicHenselLift12 (newSqrfPartF, factors, liftBound, Pi, diophant, M,
509                            leadingCoeffs, false);
510
511      if (sqrfPartF.level() > 2)
512      {
513        int* liftBounds= new int [sqrfPartF.level() - 1];
514        liftBounds [0]= liftBound;
515        bool noOneToOne= false;
516        CFList *leadingCoeffs2= new CFList [sqrfPartF.level()-2];
517        LC1= LC (evalSqrfPartF.getLast(), 1);
518        CFList LCs;
519        for (int i= 0; i < factors.length(); i++)
520          LCs.append (LC1);
521        leadingCoeffs2 [sqrfPartF.level() - 3]= LCs;
522        for (int i= sqrfPartF.level() - 1; i > 2; i--)
523        {
524          for (CFListIterator j= LCs; j.hasItem(); j++)
525            j.getItem()= j.getItem() (0, i + 1);
526          leadingCoeffs2 [i - 3]= LCs;
527        }
528        sqrfPartF *= power (LC1, factors.length()-1);
529
530        int liftBoundsLength= sqrfPartF.level() - 1;
531        for (int i= 1; i < liftBoundsLength; i++)
532          liftBounds [i]= degree (sqrfPartF, i + 2) + 1;
533        evalSqrfPartF= evaluateAtZero (sqrfPartF);
534        evalSqrfPartF.removeFirst();
535        factors= nonMonicHenselLift (evalSqrfPartF, factors, leadingCoeffs2,
536                 diophant, Pi, liftBounds, sqrfPartF.level() - 1, noOneToOne);
537        delete [] leadingCoeffs2;
538        delete [] liftBounds;
539      }
540      for (CFListIterator iter= factors; iter.hasItem(); iter++)
541        iter.getItem()= reverseShift (iter.getItem(), evaluation2);
542
543      interMedResult=
544      recoverFactors (reverseShift(evalSqrfPartF.getLast(),evaluation2),
545                      factors);
546    }
547  }
548  else
549  {
550    CanonicalForm contF=content (oldSqrfPartF,1);
551    factors= CFList (oldSqrfPartF/contF);
552    interMedResult= recoverFactors (oldSqrfPartF, factors);
553  }
554
555  for (CFListIterator iter= interMedResult; iter.hasItem(); iter++)
556    iter.getItem()= NN (iter.getItem());
557
558  CFList result;
559  CFFListIterator k;
560  CanonicalForm tmp;
561  for (int i= 0; i < LCFFactors.length(); i++)
562  {
563    tmp= 1;
564    for (k= bufSqrfFactors[i]; k.hasItem(); k++)
565    {
566      int pos= findItem (bufFactors, k.getItem().factor());
567      if (pos)
568        tmp *= power (getItem (interMedResult, pos), k.getItem().exp());
569    }
570    result.append (tmp);
571  }
572
573  for (CFListIterator i= result; i.hasItem(); i++)
574  {
575    F /= i.getItem();
576    if (foundDifferent)
577      i.getItem()= swapvar (i.getItem(), x, z);
578    i.getItem()= N (i.getItem());
579  }
580
581  if (foundDifferent)
582  {
583    CFList l= differentSecondVarLCs [j];
584    for (CFListIterator i= l; i.hasItem(); i++)
585      i.getItem()= swapvar (i.getItem(), y, z);
586    differentSecondVarLCs [j]= l;
587    F= swapvar (F, x, z);
588  }
589
590  result.insert (N (F));
591
592  result= distributeContent (result, differentSecondVarLCs, length);
593
594  if (!result.getFirst().inCoeffDomain())
595  {
596    CFListIterator i= result;
597    CanonicalForm tmp;
598    if (foundDifferent)
599      i.getItem()= swapvar (i.getItem(), Variable (2), y);
600
601    tmp= i.getItem();
602
603    i++;
604    for (; i.hasItem(); i++)
605    {
606      if (foundDifferent)
607        i.getItem()= swapvar (i.getItem(), Variable (2), y)*tmp;
608      else
609        i.getItem() *= tmp;
610    }
611  }
612  else
613    y= Variable (1);
614
615  delete [] bufSqrfFactors;
616
617  return result;
618}
619
620
621CFList
622multiFactorize (const CanonicalForm& F, const Variable& v)
623{
624  if (F.inCoeffDomain())
625    return CFList (F);
626
627  // compress and find main Variable
628  CFMap N;
629  CanonicalForm A= myCompress (F, N);
630
631  //univariate case
632  if (F.isUnivariate())
633  {
634    CFList result;
635    if (v.level() != 1)
636      result= conv (factorize (F, v));
637    else
638      result= conv (factorize (F,true));
639    if (result.getFirst().inCoeffDomain())
640      result.removeFirst();
641    return result;
642  }
643
644  //bivariate case
645  if (A.level() == 2)
646  {
647    CFList buf= biFactorize (F, v);
648    return buf;
649  }
650
651  Variable x= Variable (1);
652  Variable y= Variable (2);
653
654  // remove content
655  CFList contentAi;
656  CanonicalForm lcmCont= lcmContent (A, contentAi);
657  A /= lcmCont;
658
659  // trivial after content removal
660  CFList contentAFactors;
661  if (A.inCoeffDomain())
662  {
663    for (CFListIterator i= contentAi; i.hasItem(); i++)
664    {
665      if (i.getItem().inCoeffDomain())
666        continue;
667      else
668      {
669        lcmCont /= i.getItem();
670        contentAFactors=
671        Union (multiFactorize (lcmCont, v),
672               multiFactorize (i.getItem(), v));
673        break;
674      }
675    }
676    decompress (contentAFactors, N);
677    if (isOn (SW_RATIONAL))
678      normalize (contentAFactors);
679    return contentAFactors;
680  }
681
682  // factorize content
683  contentAFactors= multiFactorize (lcmCont, v);
684
685  // univariate after content removal
686  CFList factors;
687  if (A.isUnivariate ())
688  {
689    if (v.level() != 1)
690      factors= conv (factorize (A, v));
691    else
692      factors= conv (factorize (A,true));
693    append (factors, contentAFactors);
694    decompress (factors, N);
695    return factors;
696  }
697
698  A *= bCommonDen (A);
699  // check main variable
700  CFList Aeval, list, evaluation, bufEvaluation, bufAeval;
701  int factorNums= 3;
702  CanonicalForm bivarEval;
703  CFList biFactors, bufBiFactors;
704  CanonicalForm evalPoly;
705  int lift, bufLift;
706  CFList* bufAeval2= new CFList [A.level() - 2];
707  CFList* Aeval2= new CFList [A.level() - 2];
708  int counter;
709  int differentSecondVar= 0;
710  CanonicalForm bufA;
711  // several bivariate factorizations
712  REvaluation E (2, A.level(), IntRandom (25));
713  for (int i= 0; i < factorNums; i++)
714  {
715    counter= 0;
716    bufA= A;
717    bufAeval= CFList();
718    bufEvaluation= evalPoints (bufA, bufAeval, E);
719    E.nextpoint();
720    evalPoly= 0;
721
722    bivarEval= bufEvaluation.getLast();
723
724    evaluationWRTDifferentSecondVars (bufAeval2, bufEvaluation, A);
725
726    for (int j= 0; j < A.level() - 1; j++)
727    {
728      if (!bufAeval2[j].isEmpty())
729        counter++;
730    }
731
732    bufLift= degree (A, y) + 1 + degree (LC(A, x), y);
733
734    TIMING_START (fac_bi_factorize);
735    bufBiFactors= ratBiSqrfFactorize (bufAeval.getFirst(), v);
736    TIMING_END_AND_PRINT (fac_bi_factorize,
737                          "time for bivariate factorization: ");
738    bufBiFactors.removeFirst();
739
740    if (bufBiFactors.length() == 1)
741    {
742      factors.append (A);
743      appendSwapDecompress (factors, contentAFactors, N, 0, 0, x);
744      if (isOn (SW_RATIONAL))
745        normalize (factors);
746      delete [] bufAeval2;
747      delete [] Aeval2;
748      return factors;
749    }
750
751    if (i == 0)
752    {
753      Aeval= bufAeval;
754      evaluation= bufEvaluation;
755      biFactors= bufBiFactors;
756      lift= bufLift;
757      for (int j= 0; j < A.level() - 2; j++)
758        Aeval2 [j]= bufAeval2 [j];
759      differentSecondVar= counter;
760    }
761    else
762    {
763      if (bufBiFactors.length() < biFactors.length() ||
764          ((bufLift < lift) && (bufBiFactors.length() == biFactors.length())) ||
765          counter > differentSecondVar)
766      {
767        Aeval= bufAeval;
768        evaluation= bufEvaluation;
769        biFactors= bufBiFactors;
770        lift= bufLift;
771        for (int j= 0; j < A.level() - 2; j++)
772          Aeval2 [j]= bufAeval2 [j];
773        differentSecondVar= counter;
774      }
775    }
776    int k= 0;
777    for (CFListIterator j= bufEvaluation; j.hasItem(); j++, k++)
778      evalPoly += j.getItem()*power (x, k);
779    list.append (evalPoly);
780  }
781
782  delete [] bufAeval2;
783
784  sortList (biFactors, x);
785
786  int minFactorsLength;
787  bool irred= false;
788  factorizationWRTDifferentSecondVars (A, Aeval2, minFactorsLength, irred, v);
789
790  if (irred)
791  {
792    factors.append (A);
793    appendSwapDecompress (factors, contentAFactors, N, 0, 0, x);
794    if (isOn (SW_RATIONAL))
795      normalize (factors);
796    delete [] Aeval2;
797    return factors;
798  }
799
800  if (minFactorsLength == 0)
801    minFactorsLength= biFactors.length();
802  else if (biFactors.length() > minFactorsLength)
803    refineBiFactors (A, biFactors, Aeval2, evaluation, minFactorsLength);
804
805  if (differentSecondVar == A.level() - 2 && getNumVars(LC(A,1)) == A.level()-1)
806  {
807    bool zeroOccured= false;
808    for (CFListIterator iter= evaluation; iter.hasItem(); iter++)
809    {
810      if (iter.getItem().isZero())
811      {
812        zeroOccured= true;
813        break;
814      }
815    }
816    if (!zeroOccured)
817    {
818      factors= sparseHeuristic (A, biFactors, Aeval2, evaluation,
819                                minFactorsLength);
820      if (factors.length() == biFactors.length())
821      {
822        appendSwapDecompress (factors, contentAFactors, N, 0, 0, x);
823        normalize (factors);
824        delete [] Aeval2;
825        return factors;
826      }
827      else
828        factors= CFList();
829      //TODO case where factors.length() > 0
830    }
831  }
832
833  CFList uniFactors= buildUniFactors (biFactors, evaluation.getLast(), y);
834
835  sortByUniFactors (Aeval2, A.level() - 2, uniFactors, evaluation);
836
837  CFList * oldAeval= new CFList [A.level() - 2];
838  for (int i= 0; i < A.level() - 2; i++)
839    oldAeval[i]= Aeval2[i];
840
841  getLeadingCoeffs (A, Aeval2, uniFactors, evaluation);
842
843  CFList biFactorsLCs;
844  for (CFListIterator i= biFactors; i.hasItem(); i++)
845    biFactorsLCs.append (LC (i.getItem(), 1));
846
847  Variable w;
848  CFList leadingCoeffs= precomputeLeadingCoeff (LC (A, 1), biFactorsLCs,
849                                          evaluation, Aeval2, A.level() - 2, w);
850
851  if (w.level() != 1)
852  {
853    A= swapvar (A, y, w);
854    int i= A.level();
855    CanonicalForm evalPoint;
856    for (CFListIterator iter= evaluation; iter.hasItem(); iter++, i--)
857    {
858      if (i == w.level())
859      {
860        evalPoint= iter.getItem();
861        iter.getItem()= evaluation.getLast();
862        evaluation.removeLast();
863        evaluation.append (evalPoint);
864        break;
865      }
866    }
867    for (i= 0; i < A.level() - 2; i++)
868    {
869      if (oldAeval[i].isEmpty())
870        continue;
871      if (oldAeval[i].getFirst().level() == w.level())
872      {
873        CFArray tmp= copy (oldAeval[i]);
874        oldAeval[i]= biFactors; 
875        for (CFListIterator iter= oldAeval[i]; iter.hasItem(); iter++)
876          iter.getItem()= swapvar (iter.getItem(), w, y);
877        for (int ii= 0; ii < tmp.size(); ii++)
878          tmp[ii]= swapvar (tmp[ii], w, y);
879        CFArray tmp2= CFArray (tmp.size());
880        CanonicalForm buf;
881        for (int ii= 0; ii < tmp.size(); ii++)
882        {
883          buf= tmp[ii] (evaluation.getLast(),y);
884          buf /= Lc (buf);
885          tmp2[findItem (uniFactors, buf)-1]=tmp[ii];
886        }
887        biFactors= CFList();
888        for (int j= 0; j < tmp2.size(); j++)
889          biFactors.append (tmp2[j]);
890      }
891    }
892  }
893
894  CFListIterator iter;
895  CanonicalForm oldA= A;
896  CFList oldBiFactors= biFactors;
897  if (!leadingCoeffs.getFirst().inCoeffDomain())
898  {
899    CanonicalForm tmp= power (leadingCoeffs.getFirst(), biFactors.length() - 1);
900    A *= tmp;
901    tmp= leadingCoeffs.getFirst();
902    iter= evaluation;
903    for (int i= A.level(); i > 2; i--, iter++)
904      tmp= tmp (iter.getItem(), i);
905    if (!tmp.inCoeffDomain())
906    {
907      for (CFListIterator i= biFactors; i.hasItem(); i++)
908      {
909        i.getItem() *= tmp/LC (i.getItem(), 1);
910        i.getItem() /= Lc (i.getItem());
911      }
912    }
913  }
914
915  CanonicalForm LCmultiplier= leadingCoeffs.getFirst();
916  bool LCmultiplierIsConst= LCmultiplier.inCoeffDomain();
917  leadingCoeffs.removeFirst();
918
919  //prepare leading coefficients
920  CFList* leadingCoeffs2= new CFList [A.level() - 2];
921  prepareLeadingCoeffs (leadingCoeffs2, A.level(), leadingCoeffs, biFactors,
922                        evaluation);
923
924
925  Aeval= evaluateAtEval (A, evaluation, 2);
926
927  CanonicalForm hh= Lc (Aeval.getFirst());
928
929  for (iter= Aeval; iter.hasItem(); iter++)
930    iter.getItem() /= hh;
931
932  A /= hh;
933
934  CFListIterator iter2;
935  CFList bufLeadingCoeffs2= leadingCoeffs2[A.level()-3];
936  bufBiFactors= biFactors;
937  bufA= A;
938  CanonicalForm bufLCmultiplier= LCmultiplier;
939  CFList bufFactors= CFList();
940  bool LCheuristic= false;
941  if (LucksWangSparseHeuristic (A, biFactors, 2, leadingCoeffs2 [A.level() - 3],
942                                factors))
943  {
944    int check= biFactors.length();
945    int * index= new int [factors.length()];
946    CFList oldFactors= factors;
947    factors= recoverFactors (A, factors, index);
948
949    if (check == factors.length())
950    {
951      if (w.level() != 1)
952      {
953        for (iter= factors; iter.hasItem(); iter++)
954          iter.getItem()= swapvar (iter.getItem(), w, y);
955      }
956
957      appendSwapDecompress (factors, contentAFactors, N, 0, 0, x);
958      normalize (factors);
959      delete [] index;
960      delete [] Aeval2;
961      return factors;
962    }
963    else if (factors.length() > 0)
964    {
965      int oneCount= 0;
966      CFList l;
967      for (int i= 0; i < check; i++)
968      {
969        if (index[i] == 1)
970        {
971          iter=biFactors;
972          for (int j=1; j <= i-oneCount; j++)
973            iter++;
974          iter.remove (1);
975          for (int j= 0; j < A.level() -2; j++)
976          {
977            l= leadingCoeffs2[j];
978            iter= l;
979            for (int k=1; k <= i-oneCount; k++)
980              iter++;
981            iter.remove (1);
982            leadingCoeffs2[j]=l;
983          }
984          oneCount++;
985        }
986      }
987      bufFactors= factors;
988      factors= CFList();
989    }
990    else if (!LCmultiplier.inCoeffDomain() && factors.length() == 0)
991    {
992      LCheuristic= true;
993      factors= oldFactors;
994      CanonicalForm cont;
995      CFList contents, LCs;
996      int index=1;
997      bool foundTrueMultiplier= false;
998      for (iter= factors; iter.hasItem(); iter++, index++)
999      {
1000        cont= content (iter.getItem(), 1);
1001        cont= gcd (cont , LCmultiplier);
1002        contents.append (cont);
1003        if (cont.inCoeffDomain()) // trivial content->LCmultiplier needs to go there
1004        {
1005          foundTrueMultiplier= true;
1006          int index2= 1;
1007          for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem(); iter2++,
1008                                                                    index2++)
1009          {
1010            if (index2 == index)
1011              continue;
1012            iter2.getItem() /= LCmultiplier;
1013          }
1014          A= oldA;
1015          leadingCoeffs= leadingCoeffs2[A.level()-3];
1016          for (int i= A.level()-3; i > -1; i--)
1017            leadingCoeffs2[i]= CFList();
1018          prepareLeadingCoeffs (leadingCoeffs2, A.level(), leadingCoeffs,
1019                                biFactors, evaluation );
1020          Aeval= evaluateAtEval (A, evaluation, 2);
1021
1022          hh= Lc (Aeval.getFirst());
1023
1024          for (iter2= Aeval; iter2.hasItem(); iter2++)
1025            iter2.getItem() /= hh;
1026
1027          A /= hh;
1028          break;
1029        }
1030        else
1031          LCs.append (LC (iter.getItem()/cont, 1));
1032      }
1033      if (!foundTrueMultiplier)
1034      {
1035        index= 1;
1036        iter2= factors;
1037        bool foundMultiplier= false;
1038        for (iter= contents; iter.hasItem(); iter++, iter2++, index++)
1039        {
1040          if (fdivides (iter.getItem(), LCmultiplier))
1041          {
1042            if ((LCmultiplier/iter.getItem()).inCoeffDomain() &&
1043                !isOnlyLeadingCoeff(iter2.getItem())) //content divides LCmultiplier completely and factor consists of more terms than just the leading coeff
1044            {
1045              int index2= 1;
1046              for (CFListIterator iter3= leadingCoeffs2[A.level()-3];
1047                   iter3.hasItem(); iter3++, index2++)
1048              {
1049                if (index2 == index)
1050                {
1051                  iter3.getItem() /= LCmultiplier;
1052                  break;
1053                }
1054              }
1055              A /= LCmultiplier;
1056              foundMultiplier= true;
1057              iter.getItem()= 1;
1058            }
1059          }
1060        }
1061        // coming from above: divide out more LCmultiplier if possible
1062        if (foundMultiplier)
1063        {
1064          foundMultiplier= false;
1065          index=1;
1066          iter2= factors;
1067          for (iter= contents; iter.hasItem(); iter++, iter2++, index++)
1068          {
1069            if (!iter.getItem().isOne() &&
1070                fdivides (iter.getItem(), LCmultiplier))
1071            {
1072              if (!isOnlyLeadingCoeff (iter2.getItem())) // factor is more than just leading coeff
1073              {
1074                int index2= 1;
1075                for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem();
1076                     iter2++, index2++)
1077                {
1078                  if (index2 == index)
1079                  {
1080                    iter2.getItem() /= iter.getItem();
1081                    foundMultiplier= true;
1082                    break;
1083                  }
1084                }
1085                A /= iter.getItem();
1086                LCmultiplier /= iter.getItem();
1087                iter.getItem()= 1;
1088              }
1089              else //factor consists of just leading coeff
1090              {
1091                Variable xx= Variable (2);
1092                CanonicalForm vars;
1093                vars= power (xx, degree (LC (getItem(oldBiFactors, index),1),
1094                                          xx));
1095                for (int i= 0; i < A.level() -2; i++)
1096                {
1097                  if (oldAeval[i].isEmpty())
1098                    continue;
1099                  xx= oldAeval[i].getFirst().mvar();
1100                  vars *= power (xx, degree (LC (getItem(oldAeval[i], index),1),
1101                                             xx));
1102                }
1103                if (myGetVars(content(getItem(leadingCoeffs2[A.level()-3],index),1))
1104                    /myGetVars (LCmultiplier) == vars)
1105                {
1106                  int index2= 1;
1107                  for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem();
1108                       iter2++, index2++)
1109                  {
1110                    if (index2 == index)
1111                    {
1112                      iter2.getItem() /= LCmultiplier;
1113                      foundMultiplier= true;
1114                      break;
1115                    }
1116                  }
1117                  A /= LCmultiplier;
1118                  iter.getItem()= 1;
1119                }
1120              }
1121            }
1122          }
1123        }
1124        else
1125        {
1126          CanonicalForm pLCs= prod (LCs);
1127          if (fdivides (pLCs, LC (oldA,1)) && (LC(oldA,1)/pLCs).inCoeffDomain()) // check if the product of the lead coeffs of the primitive factors equals the lead coeff of the old A
1128          {
1129            A= oldA;
1130            iter2= leadingCoeffs2[A.level()-3];
1131            for (iter= contents; iter.hasItem(); iter++, iter2++)
1132              iter2.getItem() /= iter.getItem();
1133            foundMultiplier= true;
1134          }
1135          if (!foundMultiplier)
1136          {
1137            Variable xx;
1138            CFList vars1;
1139            CFFList sqrfMultiplier= sqrFree (LCmultiplier);
1140            if (sqrfMultiplier.getFirst().factor().inCoeffDomain())
1141              sqrfMultiplier.removeFirst();
1142            sqrfMultiplier= sortCFFListByNumOfVars (sqrfMultiplier);
1143            xx= Variable (2);
1144            for (iter= oldBiFactors; iter.hasItem(); iter++)
1145              vars1.append (power (xx, degree (LC (iter.getItem(),1), xx)));
1146            for (int i= 0; i < A.level() -2; i++)
1147            {
1148              if (oldAeval[i].isEmpty())
1149                continue;
1150              xx= oldAeval[i].getFirst().mvar();
1151              iter2= vars1;
1152              for (iter= oldAeval[i]; iter.hasItem(); iter++, iter2++)
1153                iter2.getItem() *= power(xx,degree (LC (iter.getItem(),1), xx));
1154            }
1155            CanonicalForm tmp;
1156            iter2= vars1;
1157            for (iter= leadingCoeffs2[A.level()-3]; iter.hasItem(); iter++,
1158                                                                    iter2++)
1159            {
1160              tmp= iter.getItem()/LCmultiplier;
1161              for (int i=1; i <= tmp.level(); i++)
1162              {
1163                if (degree (tmp, i) > 0)
1164                  iter2.getItem() /= power (Variable (i), degree (tmp,i));
1165              }
1166            }
1167            int multi;
1168            for (CFFListIterator ii= sqrfMultiplier; ii.hasItem(); ii++)
1169            {
1170              multi= 0;
1171              for (iter= vars1; iter.hasItem(); iter++)
1172              {
1173                tmp= iter.getItem();
1174                while (fdivides (myGetVars (ii.getItem().factor()), tmp))
1175                {
1176                  multi++;
1177                  tmp /= myGetVars (ii.getItem().factor());
1178                }
1179              }
1180              if (multi == ii.getItem().exp())
1181              {
1182                index= 1;
1183                for (iter= vars1; iter.hasItem(); iter++, index++)
1184                {
1185                  while (fdivides (myGetVars(ii.getItem().factor()),
1186                                   iter.getItem()
1187                                  )
1188                        )
1189                  {
1190                    int index2= 1;
1191                    for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem();
1192                         iter2++, index2++)
1193                    {
1194                      if (index2 == index)
1195                        continue;
1196                      else
1197                      {
1198                        tmp= ii.getItem().factor();
1199                        iter2.getItem() /= tmp;
1200                        CFListIterator iter3= evaluation;
1201                        for (int jj= A.level(); jj > 2; jj--, iter3++)
1202                          tmp= tmp (iter3.getItem(), jj);
1203                        if (!tmp.inCoeffDomain())
1204                        {
1205                          int index3= 1;
1206                          for (iter3= biFactors; iter3.hasItem(); iter3++,
1207                                                                  index3++)
1208                          {
1209                            if (index3 == index2)
1210                            {
1211                              iter3.getItem() /= tmp;
1212                              iter3.getItem() /= Lc (iter3.getItem());
1213                              break;
1214                            }
1215                          }
1216                        }
1217                        A /= ii.getItem().factor();
1218                      }
1219                    }
1220                    iter.getItem() /= getVars (ii.getItem().factor());
1221                  }
1222                }
1223              }
1224              else
1225              {
1226                index= 1;
1227                for (iter= vars1; iter.hasItem(); iter++, index++)
1228                {
1229                  if (!fdivides (myGetVars (ii.getItem().factor()),
1230                                 iter.getItem()
1231                                )
1232                     )
1233                  {
1234                    int index2= 1;
1235                    for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem();
1236                         iter2++, index2++)
1237                    {
1238                      if (index2 == index)
1239                      {
1240                        tmp= power (ii.getItem().factor(), ii.getItem().exp());
1241                        iter2.getItem() /= tmp;
1242                        A /= tmp;
1243                        CFListIterator iter3= evaluation;
1244                        for (int jj= A.level(); jj > 2; jj--, iter3++)
1245                          tmp= tmp (iter3.getItem(), jj);
1246                        if (!tmp.inCoeffDomain())
1247                        {
1248                          int index3= 1;
1249                          for (iter3= biFactors; iter3.hasItem(); iter3++,
1250                                                                  index3++)
1251                          {
1252                            if (index3 == index2)
1253                            {
1254                              iter3.getItem() /= tmp;
1255                              iter3.getItem() /= Lc (iter3.getItem());
1256                              break;
1257                            }
1258                          }
1259                        }
1260                      }
1261                    }
1262                  }
1263                }
1264              }
1265            }
1266          }
1267        }
1268
1269        // patch everything together again
1270        leadingCoeffs= leadingCoeffs2[A.level()-3];
1271        for (int i= A.level()-3; i > -1; i--)
1272          leadingCoeffs2[i]= CFList();
1273        prepareLeadingCoeffs (leadingCoeffs2,A.level(),leadingCoeffs, biFactors,
1274                              evaluation);
1275        Aeval= evaluateAtEval (A, evaluation, 2);
1276
1277        hh= Lc (Aeval.getFirst());
1278
1279        for (CFListIterator i= Aeval; i.hasItem(); i++)
1280          i.getItem() /= hh;
1281
1282        A /= hh;
1283      }
1284      factors= CFList();
1285      if (!fdivides (LC (oldA,1),prod (leadingCoeffs2[A.level()-3])))
1286      {
1287        LCheuristic= false;
1288        A= bufA;
1289        biFactors= bufBiFactors;
1290        leadingCoeffs2[A.level()-3]= bufLeadingCoeffs2;
1291        LCmultiplier= bufLCmultiplier;
1292      }
1293    }
1294    else
1295      factors= CFList();
1296    delete [] index;
1297  }
1298  if (!LCheuristic && !LCmultiplierIsConst && bufFactors.isEmpty())
1299  {
1300    int index;
1301    Variable xx;
1302    CFList vars1;
1303    CFFList sqrfMultiplier= sqrFree (LCmultiplier);
1304    if (sqrfMultiplier.getFirst().factor().inCoeffDomain())
1305      sqrfMultiplier.removeFirst();
1306    sqrfMultiplier= sortCFFListByNumOfVars (sqrfMultiplier);
1307    xx= Variable (2);
1308    for (iter= oldBiFactors; iter.hasItem(); iter++)
1309      vars1.append (power (xx, degree (LC (iter.getItem(),1), xx)));
1310    for (int i= 0; i < A.level() -2; i++)
1311    {
1312      if (oldAeval[i].isEmpty())
1313        continue;
1314      xx= oldAeval[i].getFirst().mvar();
1315      iter2= vars1;
1316      for (iter= oldAeval[i]; iter.hasItem(); iter++, iter2++)
1317        iter2.getItem() *= power (xx, degree (LC (iter.getItem(),1), xx));
1318    }
1319    CanonicalForm tmp;
1320    iter2= vars1;
1321    for (iter= leadingCoeffs2[A.level()-3]; iter.hasItem(); iter++, iter2++)
1322    {
1323      tmp= iter.getItem()/LCmultiplier;
1324      for (int i=1; i <= tmp.level(); i++)
1325      {
1326        if (degree (tmp, i) > 0)
1327          iter2.getItem() /= power (Variable (i), degree (tmp,i));
1328      }
1329    }
1330    int multi;
1331    for (CFFListIterator ii= sqrfMultiplier; ii.hasItem(); ii++)
1332    {
1333      multi= 0;
1334      for (iter= vars1; iter.hasItem(); iter++)
1335      {
1336        tmp= iter.getItem();
1337        while (fdivides (myGetVars (ii.getItem().factor()), tmp))
1338        {
1339          multi++;
1340          tmp /= myGetVars (ii.getItem().factor());
1341        }
1342      }
1343      if (multi == ii.getItem().exp())
1344      {
1345        index= 1;
1346        for (iter= vars1; iter.hasItem(); iter++, index++)
1347        {
1348          while (fdivides (myGetVars (ii.getItem().factor()), iter.getItem()))
1349          {
1350            int index2= 1;
1351            for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem(); iter2++,
1352                                                                      index2++)
1353            {
1354              if (index2 == index)
1355                continue;
1356              else
1357              {
1358                tmp= ii.getItem().factor();
1359                iter2.getItem() /= tmp;
1360                CFListIterator iter3= evaluation;
1361                for (int jj= A.level(); jj > 2; jj--, iter3++)
1362                  tmp= tmp (iter3.getItem(), jj);
1363                if (!tmp.inCoeffDomain())
1364                {
1365                  int index3= 1;
1366                  for (iter3= biFactors; iter3.hasItem(); iter3++, index3++)
1367                  {
1368                    if (index3 == index2)
1369                    {
1370                      iter3.getItem() /= tmp;
1371                      iter3.getItem() /= Lc (iter3.getItem());
1372                      break;
1373                    }
1374                  }
1375                }
1376                A /= ii.getItem().factor();
1377              }
1378            }
1379            iter.getItem() /= getVars (ii.getItem().factor());
1380          }
1381        }
1382      }
1383      else
1384      {
1385        index= 1;
1386        for (iter= vars1; iter.hasItem(); iter++, index++)
1387        {
1388          if (!fdivides (myGetVars (ii.getItem().factor()), iter.getItem()))
1389          {
1390            int index2= 1;
1391            for (iter2= leadingCoeffs2[A.level()-3]; iter2.hasItem(); iter2++,
1392                                                                      index2++)
1393            {
1394              if (index2 == index)
1395              {
1396                tmp= power (ii.getItem().factor(), ii.getItem().exp());
1397                iter2.getItem() /= tmp;
1398                A /= tmp;
1399                CFListIterator iter3= evaluation;
1400                for (int jj= A.level(); jj > 2; jj--, iter3++)
1401                  tmp= tmp (iter3.getItem(), jj);
1402                if (!tmp.inCoeffDomain())
1403                {
1404                  int index3= 1;
1405                  for (iter3= biFactors; iter3.hasItem(); iter3++, index3++)
1406                  {
1407                    if (index3 == index2)
1408                    {
1409                      iter3.getItem() /= tmp;
1410                      iter3.getItem() /= Lc (iter3.getItem());
1411                      break;
1412                    }
1413                  }
1414                }
1415              }
1416            }
1417          }
1418        }
1419      }
1420    }
1421
1422    leadingCoeffs= leadingCoeffs2[A.level()-3];
1423    for (int i= A.level()-3; i > -1; i--)
1424      leadingCoeffs2[i]= CFList();
1425    prepareLeadingCoeffs (leadingCoeffs2,A.level(),leadingCoeffs, biFactors,
1426                          evaluation);
1427    Aeval= evaluateAtEval (A, evaluation, 2);
1428
1429    hh= Lc (Aeval.getFirst());
1430
1431    for (CFListIterator i= Aeval; i.hasItem(); i++)
1432      i.getItem() /= hh;
1433
1434    A /= hh;
1435  }
1436
1437tryAgainWithoutHeu:
1438  //shifting to zero
1439  A= shift2Zero (A, Aeval, evaluation);
1440
1441  for (iter= biFactors; iter.hasItem(); iter++)
1442    iter.getItem()= iter.getItem () (y + evaluation.getLast(), y);
1443
1444  for (int i= 0; i < A.level() - 3; i++)
1445    leadingCoeffs2[i]= CFList();
1446  for (iter= leadingCoeffs2[A.level() - 3]; iter.hasItem(); iter++)
1447  {
1448    iter.getItem()= shift2Zero (iter.getItem(), list, evaluation);
1449    for (int i= A.level() - 4; i > -1; i--)
1450    {
1451      if (i + 1 == A.level() - 3)
1452        leadingCoeffs2[i].append (iter.getItem() (0, i + 4));
1453      else
1454        leadingCoeffs2[i].append (leadingCoeffs2[i+1].getLast() (0, i + 4));
1455    }
1456  }
1457
1458  CFArray Pi;
1459  CFList diophant;
1460  int* liftBounds= new int [A.level() - 1];
1461  int liftBoundsLength= A.level() - 1;
1462  for (int i= 0; i < liftBoundsLength; i++)
1463    liftBounds [i]= degree (A, i + 2) + 1;
1464
1465  Aeval.removeFirst();
1466  bool noOneToOne= false;
1467
1468  CFList commonDenominators;
1469  for (iter=biFactors; iter.hasItem(); iter++)
1470    commonDenominators.append (bCommonDen (iter.getItem()));
1471  CanonicalForm tmp1, tmp2, tmp3=1;
1472  for (int i= 0; i < A.level() - 2; i++)
1473  {
1474    iter2= commonDenominators;
1475    for (iter= leadingCoeffs2[i]; iter.hasItem(); iter++, iter2++)
1476    {
1477      tmp1= bCommonDen (iter.getItem());
1478      Off (SW_RATIONAL);
1479      iter2.getItem()= lcm (iter2.getItem(), tmp1);
1480      On (SW_RATIONAL);
1481    }
1482  }
1483  tmp1= prod (commonDenominators);
1484  for (iter= Aeval; iter.hasItem(); iter++)
1485  {
1486    tmp2= bCommonDen (iter.getItem());
1487    Off (SW_RATIONAL);
1488    tmp3= lcm (tmp2,tmp3);
1489    On (SW_RATIONAL);
1490  }
1491  CanonicalForm multiplier;
1492  multiplier= tmp3/tmp1;
1493  iter2= commonDenominators;
1494  for (iter=biFactors; iter.hasItem(); iter++, iter2++)
1495    iter.getItem() *= iter2.getItem()*multiplier;
1496
1497  for (iter= Aeval; iter.hasItem(); iter++)
1498    iter.getItem() *= tmp3*power (multiplier, biFactors.length() - 1);
1499
1500  for (int i= 0; i < A.level() - 2; i++)
1501  {
1502    iter2= commonDenominators;
1503    for (iter= leadingCoeffs2[i]; iter.hasItem(); iter++, iter2++)
1504      iter.getItem() *= iter2.getItem()*multiplier;
1505  }
1506
1507
1508  factors= nonMonicHenselLift (Aeval, biFactors, leadingCoeffs2, diophant,
1509                               Pi, liftBounds, liftBoundsLength, noOneToOne);
1510
1511  if (!noOneToOne)
1512  {
1513    int check= factors.length();
1514    A= oldA;
1515    factors= recoverFactors (A, factors, evaluation);
1516    if (check != factors.length())
1517      noOneToOne= true;
1518    else
1519      factors= Union (factors, bufFactors);
1520  }
1521  if (noOneToOne)
1522  {
1523    if (!LCmultiplierIsConst && LCheuristic)
1524    {
1525      A= bufA;
1526      biFactors= bufBiFactors;
1527      leadingCoeffs2[A.level()-3]= bufLeadingCoeffs2;
1528      delete [] liftBounds;
1529      LCheuristic= false;
1530      goto tryAgainWithoutHeu;
1531      //something probably went wrong in the heuristic
1532    }
1533
1534    A= shift2Zero (oldA, Aeval, evaluation);
1535    biFactors= oldBiFactors;
1536    for (iter= biFactors; iter.hasItem(); iter++)
1537      iter.getItem()= iter.getItem () (y + evaluation.getLast(), y);
1538    CanonicalForm LCA= LC (Aeval.getFirst(), 1);
1539    CanonicalForm yToLift= power (y, lift);
1540    CFListIterator i= biFactors;
1541    lift= degree (i.getItem(), 2) + degree (LC (i.getItem(), 1)) + 1;
1542    i++;
1543
1544    for (; i.hasItem(); i++)
1545      lift= tmax (lift, degree (i.getItem(), 2)+degree (LC (i.getItem(), 1))+1);
1546
1547    lift= tmax (degree (Aeval.getFirst() , 2) + 1, lift);
1548
1549    i= biFactors;
1550    yToLift= power (y, lift);
1551    CanonicalForm dummy;
1552    for (; i.hasItem(); i++)
1553    {
1554      LCA= LC (i.getItem(), 1);
1555      extgcd (LCA, yToLift, LCA, dummy);
1556      i.getItem()= mod (i.getItem()*LCA, yToLift);
1557    }
1558
1559    liftBoundsLength= F.level() - 1;
1560    liftBounds= liftingBounds (A, lift);
1561
1562    CFList MOD;
1563    bool earlySuccess;
1564    CFList earlyFactors;
1565    ExtensionInfo info= ExtensionInfo (false);
1566    CFList liftedFactors;
1567    TIMING_START (fac_hensel_lift);
1568    liftedFactors= henselLiftAndEarly
1569                   (A, MOD, liftBounds, earlySuccess, earlyFactors,
1570                    Aeval, biFactors, evaluation, info);
1571    TIMING_END_AND_PRINT (fac_hensel_lift, "time for hensel lifting: ");
1572
1573    TIMING_START (fac_factor_recombination);
1574    factors= factorRecombination (A, liftedFactors, MOD);
1575    TIMING_END_AND_PRINT (fac_factor_recombination,
1576                          "time for factor recombination: ");
1577
1578    if (earlySuccess)
1579      factors= Union (factors, earlyFactors);
1580
1581    for (CFListIterator i= factors; i.hasItem(); i++)
1582    {
1583      int kk= Aeval.getLast().level();
1584      for (CFListIterator j= evaluation; j.hasItem(); j++, kk--)
1585      {
1586        if (i.getItem().level() < kk)
1587          continue;
1588       i.getItem()= i.getItem() (Variable (kk) - j.getItem(), kk);
1589      }
1590    }
1591  }
1592
1593  if (w.level() != 1)
1594  {
1595    for (CFListIterator iter= factors; iter.hasItem(); iter++)
1596      iter.getItem()= swapvar (iter.getItem(), w, y);
1597  }
1598
1599  swap (factors, 0, 0, x);
1600  append (factors, contentAFactors);
1601  decompress (factors, N);
1602  if (isOn (SW_RATIONAL))
1603    normalize (factors);
1604
1605  delete [] leadingCoeffs2;
1606  delete [] oldAeval;
1607  delete [] Aeval2;
1608  delete[] liftBounds;
1609
1610  return factors;
1611}
1612
1613#endif
Note: See TracBrowser for help on using the repository browser.