source: git/libfac/factor/Factor.cc @ d77a70

spielwiese
Last change on this file since d77a70 was d77a70, checked in by Hans Schoenemann <hannes@…>, 13 years ago
experimenatl stuff removed git-svn-id: file:///usr/local/Singular/svn/trunk@13653 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 41.7 KB
RevLine 
[1a80b4]1///////////////////////////////////////////////////////////////////////////////
[341696]2/* $Id$ */
[36b7a3]3static const char * errmsg = "\nYou found a bug!\nPlease inform singular@mathematik.uni-kl.de\nPlease include above information and your input (the ideal/polynomial and characteristic) in your bug-report.\nThank you.";
[1a80b4]4///////////////////////////////////////////////////////////////////////////////
5// FACTORY - Includes
6#include <factory.h>
[14b1e65]7#ifndef NOSTREAMIO
[e2ca88]8#ifdef HAVE_IOSTREAM
9#include <iostream>
10#define CERR std::cerr
11#define CIN std::cin
12#elif defined(HAVE_IOSTREAM_H)
[14b1e65]13#include <iostream.h>
[e2ca88]14#define CERR cerr
15#define CIN cin
16#endif
[14b1e65]17#endif
[1a80b4]18// Factor - Includes
19#include "tmpl_inst.h"
20#include "SqrFree.h"
21#include "helpstuff.h"
22#include "MVMultiHensel.h"
23#include "Truefactor.h"
24#include "homogfactor.h"
[3e55bc]25#include "interrupt.h"
[4a81ec]26// some CC's need this:
27#include "Factor.h"
28
[0be2bc]29#include "alg_factor.h"
[a38d45]30void out_cf(char *s1,const CanonicalForm &f,char *s2);
31void out_cff(CFFList &L);
32
[0be2bc]33
[1a80b4]34#ifdef FACTORDEBUG
35#  define DEBUGOUTPUT
36#else
37#  undef DEBUGOUTPUT
38#endif
39
40#include "debug.h"
41#include "timing.h"
42TIMING_DEFINE_PRINT(factorize_time);
43TIMING_DEFINE_PRINT(sqrfree_time);
44TIMING_DEFINE_PRINT(discr_time);
45TIMING_DEFINE_PRINT(evaluate_time);
46TIMING_DEFINE_PRINT(hensel_time);
47TIMING_DEFINE_PRINT(truefactor_time);
48
[1048e0c]49/*
50* a wrapper for factorize over algebraic extensions:
51* does a sanity check and, if nec., a conversion
52* before calling factorize(f,alpha)
53* ( in factorize, alpha.level() must be < 0 )
54*/
[5c4b32]55CFFList factorize2 ( const CanonicalForm & f,
[1048e0c]56                     const Variable & alpha, const CanonicalForm & mipo )
57{
58  if (alpha.level() <0)
[fb4f62e]59  {
60    if (f.isUnivariate())
61      return factorize(f,alpha);
62    else
63    {
64      return Factorize(f,mipo);
65    }
[5c4b32]66  }
[1048e0c]67  else
68  {
69    bool repl=(f.mvar() != alpha);
70    //out_cf("f2 - factor:",f,"\n");
71    //out_cf("f2 - ext:",alpha,"\n");
72    //out_cf("f2 - mipo:",mipo,"\n");
73    Variable X=rootOf(mipo);
74    CanonicalForm F=f;
75    if (repl) F=replacevar(f,alpha,X);
76    //out_cf("call - factor:",F,"\n");
77    //out_cf("call - ext:",X,"\n");
78    //out_cf("call - mipo:",getMipo(X,'A'),"\n");
79    CFFList L=factorize(F,X);
80    CFFListIterator i=L;
81    if (repl)
82    {
83      CFFList Outputlist;
84      for(;i.hasItem(); i++ )
85      {
86        Outputlist.append(CFFactor(
87        replacevar(i.getItem().factor(),X,alpha),
88        i.getItem().exp()));
89      }
90      return Outputlist;
91    }
92    else return L;
93  }
94}
[1a80b4]95///////////////////////////////////////////////////////////////
96// Choose a main variable if the user didn`t wish a          //
97// special one. Returns level of main variable.              //
98///////////////////////////////////////////////////////////////
[0be2bc]99static int
[1a80b4]100choose_main_variable( const CanonicalForm & f, int Mainvar=0){
101  CanonicalForm remlc, newlc;
102  int n= level(f), mainvar= Mainvar;
103
104  if (mainvar != 0) return mainvar ; // We force use of the wished mainvar
105  remlc= LC(f,n); mainvar = n;
106  if ( totaldegree(remlc)==0 ){ remlc=f.genOne() ; }
[e2ca88]107  DEBOUTLN(CERR, "remlc= " , remlc);
[aa7480c]108  for ( int i=n-1; i>=1; i-- )
109  {
[1a80b4]110    newlc= LC(f,i);
111    if ( totaldegree(newlc)==0 ){ newlc=f.genOne() ; }
[e2ca88]112    DEBOUTLN(CERR, "newlc= " , newlc);
[1a80b4]113    if ( (remlc.isOne()) && (newlc.isOne()) ){ // take care of the degrees
114      if ( degree(f,i) < degree(f,mainvar) ){
[0be2bc]115        remlc= newlc;
116        mainvar= i;
[1a80b4]117      }
118    }
119    else  if ( (! remlc.isOne() ) && ( newlc.isOne() ) ){
[0be2bc]120      remlc= newlc;
[1a80b4]121      mainvar= i;
122    }
123  }
124  return mainvar;
125}
126
127///////////////////////////////////////////////////////////////
128// Check if the derivative is nonzero for oldmainvar.        //
129// Returns the level of the choosen main variable.           //
130///////////////////////////////////////////////////////////////
[0be2bc]131static int
[1a80b4]132necessary_condition( const CanonicalForm & F, int oldmainvar){
133  CanonicalForm g;
134  int n=level(F);
135
[0be2bc]136  g= swapvar(F,oldmainvar,n);
[1a80b4]137  g= g.deriv();
[0be2bc]138  if ( g.isZero() )
[52e543]139  {
140    for ( int i=n; i>=1; i-- )
141    {
[0be2bc]142      g= swapvar(F,i,n);
[1a80b4]143      g= g.deriv();
144      if ( ! g.isZero() ) return i;
145    }
[52e543]146  }
[1a80b4]147  return oldmainvar;
148}
149
150///////////////////////////////////////////////////////////////
151// Make F monic. Return monic polynomial.                    //
152///////////////////////////////////////////////////////////////
[0be2bc]153static CanonicalForm
[7fa52c2]154make_monic( const CanonicalForm & F, const CanonicalForm & lt)
155{
[1a80b4]156  CanonicalForm intermediatpoly,f;
157  Variable x(level(F));
158
159  if ( degree(lt) == 0 ) f= 1/lt * F ;
[7fa52c2]160  else
161  {
[1a80b4]162    intermediatpoly= power(lt,degree(F)-1);
163    for ( int i=0; i<=degree(F); i++ )
164      if ( ! F[i].isZero())
[0be2bc]165        f+= (F[i] * intermediatpoly*power(x,i))/power(lt,i);
[1a80b4]166  }
167  return f;
168}
169
170///////////////////////////////////////////////////////////////
[0be2bc]171// Decide whether num/denum (num,denum both from the         //
[1a80b4]172// FiniteFielddomain)  lies in the RationalDomain.           //
173// If false, return num/denum else return the zero poly from //
174// the FiniteFielddomain.                                    //
175///////////////////////////////////////////////////////////////
[0be2bc]176static CanonicalForm
[1a80b4]177is_rational( const CanonicalForm & num, const CanonicalForm & denum ){
178  CanonicalForm a, b;
179  int retvalue;
180
181  retvalue= mydivremt(num,denum,a,b);
[e89e56]182  if ( retvalue && b == num.genZero() ) // num/denum from FFdomain
[1a80b4]183    return a;
184  else // num/denum is rational
185    return num.genZero();
186}
187
188///////////////////////////////////////////////////////////////
189// lt_is_product returns 1 iff lt is a product, 0 iff lt is  //
190// a sum.                                                    //
191///////////////////////////////////////////////////////////////
[0be2bc]192static int
[1a80b4]193lt_is_product( const CanonicalForm & lt ){
194  CFList result;
195
196  result= get_Terms(lt);
197  if ( result.length() > 1 ) return 0;
198  else return 1;
199}
200
201///////////////////////////////////////////////////////////////
202// Reverse the make_monic transformation.                    //
203// Return the list of factors.                               //
204///////////////////////////////////////////////////////////////
[0be2bc]205static CFFList
[265aa7]206not_monic( const CFFList & TheList, const CanonicalForm & ltt, const CanonicalForm & F, int levelF)
207{
[1a80b4]208  CFFList Returnlist,IntermediateList;
209  CFFListIterator i;
210  CanonicalForm intermediate,lt= ltt,savelc;
211  CanonicalForm numerator,denumerator,test,a,b;
212  Variable x(level(F));
213  int test1;
214
[aa7480c]215  if ( lt.isOne() ) return TheList; // the poly was already monic
[265aa7]216  if ( TheList.length() <= 1 ) // only one factor to substitute back
217  {
[1a80b4]218    if ( totaldegree(lt) == 0 ) // lt is type numeric
219      Returnlist.append( CFFactor(lt*TheList.getFirst().factor(),
[0be2bc]220                                  TheList.getFirst().exp()) );
[265aa7]221    else
222    {
[1a80b4]223      intermediate = F(x*lt, levelF)/power(lt,degree(F,levelF)-1);
224      Returnlist.append(CFFactor(intermediate,TheList.getFirst().exp()));
225    }
226  }
[265aa7]227  else // more then one factor
228  {
[1a80b4]229    IntermediateList= TheList;
230    if ( totaldegree(lt) == 0 ){ // lt is type numeric;(SqrFree-use, see above)
231      Returnlist.append( CFFactor(lt*IntermediateList.getFirst().factor()
[0be2bc]232                                  , IntermediateList.getFirst().exp()) );
[1a80b4]233      IntermediateList.removeFirst();
234      Returnlist= Union(Returnlist,IntermediateList);
235    }
[265aa7]236    else // lt is a) a product or b) a sum of terms
237    {
238      if ( lt_is_product(lt) ) // case a)
239      {
[e2ca88]240        DEBOUTLN(CERR, "lt_is_product: ", lt);
[0be2bc]241        savelc= content(lt) ; // can we simplify to savelc= lc(lt); ?
242        while ( getNumVars(savelc) != 0 )
243          savelc= content(savelc);
[265aa7]244        for ( i=TheList; i.hasItem();i++ )
245        {
[0be2bc]246          numerator= i.getItem().factor();
247          numerator= numerator(x*lt,levelF); // x <- x*lt
248          denumerator= power(lt,degree(F,levelF)-1); // == lt^(1-degree(F,x)
[e89e56]249          while (numerator.genZero() == is_rational(numerator, denumerator))
[0be2bc]250            numerator*= lt;
251          intermediate= is_rational(numerator,denumerator);
252
253          Returnlist.append( CFFactor(lc(content(intermediate))*intermediate/content(intermediate), i.getItem().exp() ) );
254        }
255        // Now we add a test. If product(factors)/F is a multiple of
256        // savelc, we have to add 1/multiplicity to the factors
257        IntermediateList= Returnlist;
258        intermediate= 1;
259        for ( CFFListIterator j=IntermediateList; j.hasItem(); j++)
260          intermediate*= j.getItem().factor();
261        test1= mydivremt( intermediate,F,a,b);
[e89e56]262        if ( test1 && b == intermediate.genZero() ) // Yupp!
[265aa7]263        {
[0be2bc]264          IntermediateList.append(CFFactor(1/a,1));
265          Returnlist= IntermediateList;
266        }
267        else { Returnlist= IntermediateList; }
[1a80b4]268      }
[265aa7]269      else // case b)
270      {
[e2ca88]271        DEBOUTLN(CERR, "lt_is_sum: ", lt);
[0be2bc]272        CanonicalForm save_denumerator= 1;
[265aa7]273        for ( i=TheList; i.hasItem(); i++ )
274        {
[0be2bc]275          numerator= i.getItem().factor();
276          numerator= numerator(x*lt,levelF); // x <- x*lt
277          denumerator= power(lt,degree(numerator,levelF)); // == lt^(-degree(numerator,x)
278          test= content(numerator,x);
279          test1= mydivremt(denumerator,test,a,b);
[e89e56]280          if ( test1 && b == numerator.genZero() ) // Yupp!
[265aa7]281          {
[0be2bc]282            save_denumerator*= a;
283            Returnlist.append(CFFactor(numerator/test ,1));
284          }
[265aa7]285          else
286          {
[a13956]287            factoryError("libfac: ERROR: not_monic1: case lt is a sum.");
[0be2bc]288          }
289        }
290        // Now we add a test if we did the right thing:
291        // save_denumerator should be a multiple of the leading coeff
292        test1= mydivremt(save_denumerator,lt,a,b);
[e89e56]293        if ( test1 && b == save_denumerator.genZero() ) // Yupp!
[0be2bc]294          // We have to multiply one of the factors with
295          // the multiplicity of the save_denumerator <-> lc
296          // the following will do what we want
[e89e56]297          Returnlist= myUnion( CFFList(CFFactor(1/a,1)),Returnlist) ;
[265aa7]298        else
299        {
[a13956]300          factoryError("libfac: ERROR: not_monic2: case lt is a sum.");
[0be2bc]301        }
[1a80b4]302      }
303    }
304  }
[e2ca88]305  DEBOUTLN(CERR,"Returnlist: ", Returnlist);
[1a80b4]306  return Returnlist;
307}
308
309///////////////////////////////////////////////////////////////
310// Substitute the (Variable,Value)-Pair(s) from Substitution-//
311// list into the polynomial F. Returns the resulting poly.   //
312///////////////////////////////////////////////////////////////
[0be2bc]313static CanonicalForm
[1a80b4]314substitutePoly( const CanonicalForm & F, const SFormList & Substitutionlist){
315  CanonicalForm f= F;
316
317  for ( SFormListIterator i=Substitutionlist; i.hasItem(); i++ )
318    f= f(i.getItem().exp(),level(i.getItem().factor()));
319  return f;
320}
321
322///////////////////////////////////////////////////////////////
323// Find specialization values for the poly F. Returns 0 if   //
324// procedure failed, 1 otherwise. On success Substitutionlist//
325// holds (Variable,Value)-pairs. On failure we only have a   //
326// partitial list.                                           //
327///////////////////////////////////////////////////////////////
328//      *** This is the version with extensions ***          //
329///////////////////////////////////////////////////////////////
330
331///////////////////////////////////////////////////////////////
332// is CF g ok?                                               //
333///////////////////////////////////////////////////////////////
334static int
[aa7480c]335various_tests( const CanonicalForm & g, int deg, int vars_left)
336{
[1a80b4]337  CFMap m;
338
339  if ( degree(g) == deg ) // degrees match
340    if ( level(compress(g,m)) == (vars_left) ) // exactly one variable less
[e89e56]341      if ( SqrFreeTest(g,1) ) // poly is sqrfree
[aa7480c]342        if ( gcd(g,g.deriv()).isOne() ) // Discriminante != 0
[0be2bc]343           return 1;
[1a80b4]344  return 0;
345}
346
347///////////////////////////////////////////////////////////////
348// specialize one variable over the given field.             //
349///////////////////////////////////////////////////////////////
[0be2bc]350// substitutes in poly f of degree deg with former
[1a80b4]351// former_nr_of_variables variables the variable nr_of_variable ;
352// this is done in the field of Char getCharacteristic() and
353// Extension given by Extgenerator.
354///////////////////////////////////////////////////////////////
355static int
[b96e07]356specialize_variable( CanonicalForm & f, int deg, SFormList & Substitutionlist, int nr_of_variable,
357                     int former_nr_of_variables, CFGenerator & Extgenerator ){
358  CanonicalForm g;
359  Variable x(nr_of_variable);
360
[e2ca88]361  DEBOUTLN(CERR, "specialize_variable: called with: ", f);
[b96e07]362  for ( Extgenerator.reset(); Extgenerator.hasItems(); Extgenerator.next() ){
[e2ca88]363    DEBOUTLN(CERR, "  specialize_variable: trying:  ", Extgenerator.item());
[b96e07]364    g= f( Extgenerator.item(), x );
[e2ca88]365    DEBOUTLN(CERR, "  specialize_variable: resulting g= ", g);
[b96e07]366    if ( various_tests(g,deg,former_nr_of_variables - nr_of_variable ) ){
367      Substitutionlist.insert(SForm(x,Extgenerator.item())); // append (Var,value) pair
368      f= g;
369      return 1;
370    }
371  }
372  return 0;
373}
374static int
375specialize_agvariable( CanonicalForm & f, int deg, SFormList & Substitutionlist, int nr_of_variable,
376                     int former_nr_of_variables, AlgExtGenerator & Extgenerator ){
[1a80b4]377  CanonicalForm g;
378  Variable x(nr_of_variable);
379
[e2ca88]380  DEBOUTLN(CERR, "specialize_variable: called with: ", f);
[1a80b4]381  for ( Extgenerator.reset(); Extgenerator.hasItems(); Extgenerator.next() ){
[e2ca88]382    DEBOUTLN(CERR, "  specialize_variable: trying:  ", Extgenerator.item());
[1a80b4]383    g= f( Extgenerator.item(), x );
[e2ca88]384    DEBOUTLN(CERR, "  specialize_variable: resulting g= ", g);
[0be2bc]385    if ( various_tests(g,deg,former_nr_of_variables - nr_of_variable ) ){
[1a80b4]386      Substitutionlist.insert(SForm(x,Extgenerator.item())); // append (Var,value) pair
387      f= g;
388      return 1;
389    }
390  }
391  return 0;
392}
393
394///////////////////////////////////////////////////////////////
395// generate a minpoly of degree degree_of_Extension in the   //
396// field getCharacteristik()^Extension.                      //
397///////////////////////////////////////////////////////////////
[4a81ec]398CanonicalForm
[1a80b4]399generate_mipo( int degree_of_Extension , const Variable & Extension ){
[0be2bc]400  FFRandom gen;
401  if ( degree(Extension) > 0 ) GFRandom gen;
[1a80b4]402  else {
403    if ( degree(Extension) == 0 ) FFRandom gen;
[a13956]404    else
405    {
406      factoryError("libfac: evaluate: Extension not inFF() or inGF() !");
[1a80b4]407    }
408  }
409  return find_irreducible( degree_of_Extension, gen, Variable(1) );
410}
411
412///////////////////////////////////////////////////////////////
413// Try to find a specialization for f over the field of char //
414// f.getCharacteristic() and (possible) extension defined by //
415// the variable Extension .                                  //
416// Returns 1 iff specialisation was found, 0 otherwise.      //
417// If 0 is returned there are variables left to substitute.  //
418// We check if Substitutionlist.length() > 0, i.e. we        //
419// previously tried to find specialization values for some   //
420// values. We take them and work with the resulting poly.    //
421///////////////////////////////////////////////////////////////
422static int
[38e7b3]423try_specializePoly(const CanonicalForm & f, const Variable & Extension, int deg, SFormList & Substitutionlist, int ii,int j)
424{
[1a80b4]425  int ok,i= ii;
426  CanonicalForm ff= f;
427
428  if ( Substitutionlist.length() > 0 ){ // we formerly tried to specialize
429    ff= substitutePoly(f,Substitutionlist); // substitute found values
430    i= Substitutionlist.length() + 1;
431  }
432
[38e7b3]433  if ( degree(Extension) > 0 )
434  { // working over Extensions
[e2ca88]435    DEBOUTLN(CERR, "try_specializePoly: working over Extensions: ", Extension);
[38e7b3]436    if (Extension.level() > 0)
437    {
438    //  AlgExtGenerator g(Extension,minpoly );
439    //  for ( int k=i ; k<j ; k++ ) // try to find specialization for all
440    //  {                           // variables (# = k ) beginning with the
441    //                             // starting value i
442    //    ok= specialize_agvariable( ff, deg, Substitutionlist, k, j, g );
443    //    if ( ! ok ) return 0; // we failed
444    //  }
[52e543]445      #ifndef NDEBUG
[7cb56a9]446        //printf("libfac: try_specializePoly: extension level >0\n");
[52e543]447      #endif
[38e7b3]448      return 0; // we failed
449    }
450    else
451    {
452      AlgExtGenerator g(Extension);
453      for ( int k=i ; k<j ; k++ ) // try to find specialization for all
454      {                           // variables (# = k ) beginning with the
[1a80b4]455                                 // starting value i
[38e7b3]456        ok= specialize_agvariable( ff, deg, Substitutionlist, k, j, g );
457        if ( ! ok ) return 0; // we failed
458      }
[1a80b4]459    }
460  }
461  else{ // working over the ground-field
462    FFGenerator g;
[e2ca88]463    DEBOUTMSG(CERR, "try_specializePoly: working over the ground-field.");
[1a80b4]464    for ( int k=i ; k<j ; k++ ){
465      ok= specialize_variable( ff, deg, Substitutionlist, k, j, g );
466      if ( ! ok ) return 0; // we failed
467    }
468  }
469  return 1;
470}
471
472static int
473specializePoly(const CanonicalForm & f, Variable & Extension, int deg, SFormList & Substitutionlist, int i,int j){
474  Variable minpoly= Extension;
475  int ok,extended= degree(Extension), working_over_extension;
476
477  // Remember if we are working over an extension-field
478  if ( extended >= 2 )    { working_over_extension = 1; }
479  else                    { working_over_extension = 0; extended = 1; }
480  // First try:
481  ok = try_specializePoly(f,minpoly,deg,Substitutionlist,i,j);
482  while ( ! ok ){ // we have to extend!
483    extended+= 1;
484    if ( ! working_over_extension ){
485      minpoly= rootOf(generate_mipo( extended,Extension ));
486      Extension= minpoly;
487      ok= try_specializePoly(f,minpoly,deg,Substitutionlist,i,j);
488    }
[a13956]489    else
490    {
491      factoryError("libfac: spezializePoly ERROR: Working over given extension-field not yet implemented!");
[1a80b4]492      return 0;
493    }
494  }
495  return 1;
496}
497
498
499// This is a procedure to play with: lot's of parameters!
500// returns: 0  iff no success (possibly because Extension isn't great enough
501//          >0 iff g (univariate) splits into n factors;
502// if n>0 BestEvaluationpoint contains the choice of values for the variables
503//
504// tries to find at least maxtries evaluation points
505// if g factored sametries into the same number of poly's the procedure stops
506// if we tried failtries evaluations not found valid, we stop. Perhaps
507// Extension isn't big enough!
508static int
[1048e0c]509evaluate( int maxtries, int sametries, int failtries, const CanonicalForm &f , const Variable & Extension, const CanonicalForm &mipo, SFormList & BestEvaluationpoint, CFFList & BestFactorisation ){
[1a80b4]510  int minfactors=degree(f),degf=degree(f),n=level(f.mvar())-1;
511  SFormList minEvaluation;
512  CFFList minFactorisation;
513  int samefactors=0, failedfactor=0, tried=0;
514  FFRandom gen;
515  CFFList unilist;
516
[0be2bc]517  if ( degree(Extension) >0 ) GFRandom gen;
[a13956]518  else
519  {
520    if ( degree(Extension) == 0 ) FFRandom gen;
521    else
522    {
523      factoryError("libfac: evaluate: Extension not inFF() or inGF() !");
524    }
525  }
[1a80b4]526  REvaluation k(1,n,gen);
[4a81ec]527  k.nextpoint();
[a13956]528  for ( int i=1; i<=maxtries ; i++)
529  {
[4a81ec]530    // k.nextpoint();
[1a80b4]531    SFormList Substitutionlist;
532    for ( int j=1; j<=n; j++ )
[0be2bc]533     Substitutionlist.insert(SForm(Variable(j),k[j]));
[1a80b4]534    k.nextpoint();
535    CanonicalForm g=substitutePoly(f,Substitutionlist);
[a13956]536    if ( various_tests(g, degf,1) )
537    { // found a valid point
[1a80b4]538      failedfactor = 0; tried += 1;
539      if ( degree(Extension) == 0   )
[0be2bc]540        unilist = factorize(g,1); // poly is sqr-free!
[1a80b4]541      else
[b4ea1d]542      {
[1048e0c]543        unilist = factorize2(g,Extension,mipo);
544      }
[aa7480c]545      if (unilist.length() <= minfactors )
546      {
[0be2bc]547        minfactors=unilist.length();
548        minEvaluation=Substitutionlist;
549        minFactorisation=unilist;
[1a80b4]550      }
551      else samefactors +=1;
552
[aa7480c]553      if (unilist.length() == 1 ) // wow! we found f is irreducible!
554      {
[0be2bc]555        BestEvaluationpoint=minEvaluation;
556        BestFactorisation=minFactorisation;
557        return 1;
[1a80b4]558      }
559
[aa7480c]560      if ( samefactors >= sametries ) // now we stop ( maybe polynomial *has*
561                                      // minfactors factors? )
562      {
[0be2bc]563        BestEvaluationpoint=minEvaluation;
564        BestFactorisation=minFactorisation;
565        return minfactors;
[1a80b4]566      }
567
568    }
[aa7480c]569    else
570      failedfactor += 1;
[1a80b4]571
[aa7480c]572    if ( failedfactor >= failtries ) // now we stop ( perhaps Extension isn't
573                                     // big enough )
574    {
[1a80b4]575      if ( tried == 0 )
[0be2bc]576        return 0;
[aa7480c]577      else
578      {
[0be2bc]579        BestEvaluationpoint=minEvaluation;
580        BestFactorisation=minFactorisation;
581        return minfactors;
[1a80b4]582      }
583    }
584  }
585  BestEvaluationpoint=minEvaluation;
586  BestFactorisation=minFactorisation;
587  return minfactors;
588}
589
590///////////////////////////////////////////////////////////////
591// A factorization routine for a sqrfree polynomial.         //
592// Returns the list of factors.                              //
593///////////////////////////////////////////////////////////////
[0be2bc]594CFFList
[8de151]595Factorized( const CanonicalForm & F, const CanonicalForm & alpha, int Mainvar)
596{
[1a80b4]597  CanonicalForm f,lt,ff,ffuni;
[639047e]598  Variable Extension=alpha.mvar();
[1a80b4]599  CFFList Outputlist,UnivariateFactorlist,Outputlist2;
600  SFormList Substitutionlist, Evaluationpoint;
601  CFFactor copy;
602  int mainvar=Mainvar,success,oldmainvar;
603  CFMap m;
604
[3e55bc]605  // INTERRUPTHANDLER
606  if ( interrupt_handle() ) return CFFList() ;
607  // INTERRUPTHANDLER
608
[924d8f]609  if (F.inCoeffDomain()) {  return CFFList(CFFactor(F,1)); }
[8de151]610  if ( F.isUnivariate() ) // could have lost one Variable elsewhere
611  {
612    if ( degree(Extension) == 0 )
613    {
[1a80b4]614      TIMING_START(evaluate_time);
615      Outputlist = factorize(F,1); // poly is sqr-free
616      TIMING_END(evaluate_time);
617      return Outputlist;
618    }
[8de151]619    else
620    {
[1048e0c]621      if (Extension.level()<0)
[e2ca88]622      DEBOUTLN(CERR, "Univ. Factorization over extension of degree ",
[0be2bc]623               degree(getMipo(Extension,'x')) );
[5c4b32]624      else
[e2ca88]625      DEBOUTLN(CERR, "Univ. Factorization over extension of level ??",
[1048e0c]626                Extension.level());
[1a80b4]627      TIMING_START(evaluate_time);
[b87513c]628     #if 1
[1048e0c]629     Outputlist = factorize2(F,Extension,alpha);
[0be2bc]630     #else
631      Variable X;
632      CanonicalForm mipo=getMipo(Extension,X);
633      CFList as(mipo);
634      Outputlist = newfactoras( F, as, 1);
[14b1e65]635     #endif
[1a80b4]636      TIMING_END(evaluate_time);
637      return Outputlist;
638    }
639  }
640
641  if ( Mainvar ) oldmainvar=Mainvar; else oldmainvar=level(F);
642  // First choose a main variable; this may be revisted in the next step
643  mainvar = choose_main_variable(F);
644  // Let`s look if @f/@mainvar is nonzero
645  mainvar = necessary_condition(F,mainvar);
646  // Now we have definetly choosen a main variable
647  // swap poly such that the mainvar has highest level
648  f=swapvar(F,mainvar,level(F));
[0be2bc]649
[3e55bc]650  // INTERRUPTHANDLER
651  if ( interrupt_handle() ) return CFFList() ;
652  // INTERRUPTHANDLER
653
[1a80b4]654  if ( oldmainvar != mainvar ){
[e2ca88]655    DEBOUTSL(CERR); DEBOUT(CERR,"Swapped poly ", F);
656    DEBOUT(CERR, " in ", f); DEBOUTNL(CERR);
657    DEBOUTSL(CERR); DEBOUT(CERR,"Swapped  ", oldmainvar );
658    DEBOUT(CERR, " <-- ", mainvar ); DEBOUT(CERR, "  Mainvar= ", f.mvar());
659    DEBOUTNL(CERR);
[1a80b4]660    ff = f.deriv();
661    TIMING_START(discr_time);
[38e7b3]662    ffuni = gcd(f,ff);
[1a80b4]663    TIMING_END(discr_time);
[20722e4]664    if ( !(ffuni.isOne()) ){ //discriminante nonzero: split poly
[e2ca88]665      DEBOUTLN(CERR,"Nontrivial GCD of f= ", f);
666      DEBOUTLN(CERR,"             and @f= ", ff);
667      DEBOUTLN(CERR,"          GCD(f,@f)= ", ffuni);
[1a80b4]668      ff=f/ffuni;
669      CFFList Outputlist_a, Outputlist_b;
670      Outputlist_a = Factorized(ff,alpha);
[e2ca88]671      DEBOUTLN(CERR, "Outputlist_a = ", Outputlist_a);
[1a80b4]672      Outputlist_b = Factorized(ffuni,alpha);
[e2ca88]673      DEBOUTLN(CERR, "Outputlist_b = ", Outputlist_b);
[e89e56]674      Outputlist = myUnion(Outputlist_a, Outputlist_b);
[1a80b4]675      // have to back-swapvar the factors....
676      for ( CFFListIterator i=Outputlist; i.hasItem(); i++ ){
[0be2bc]677        copy=i.getItem();
678        Outputlist2.append(CFFactor(swapvar(copy.factor(),oldmainvar,mainvar),copy.exp()));
[1a80b4]679      }
[e2ca88]680      DEBOUTLN(CERR, "Outputlist2 (a+b swapped) (to return) = ", Outputlist2);
[1a80b4]681      return Outputlist2;
682    }
683  }
684
685  // Check special cases
686  for ( int i=1; i<=level(F); i++)
[aa7480c]687  {
[8e0cdf]688    if ( degree(f,Variable(i) ) == 1 )
[aa7480c]689    //test trivial case; only true iff F is primitiv w.r.t every variable; else check (if F=ax+b) gcd(a,b)=1 ?
690    {
[e2ca88]691      DEBOUTLN(CERR, "Trivial case: ", F);
[1a80b4]692      Outputlist.append(CFFactor(F,1));
693      return Outputlist;
694    }
[aa7480c]695  }
[1a80b4]696
697  // Look at the leading term:
698  lt = LC(f);
[e2ca88]699  DEBOUTLN(CERR, "Leading term: ", lt);
[aa7480c]700  //if ( lt != f.genOne() )
701  if ( !lt.isOne() )
[38e7b3]702  {
[1a80b4]703    // make the polynomial monic in the main variable
704    ff = make_monic(f,lt); ffuni = ff;
[e2ca88]705    DEBOUTLN(CERR, "make_monic returned: ", ff);
[1a80b4]706  }
707  else{ ff= f; ffuni= ff; }
708
709  TIMING_START(evaluate_time);
[1048e0c]710  success=evaluate(min(10,max(degree(ff), 5)), min(degree(ff),3), min(degree(ff),3), ff, Extension, alpha, Substitutionlist,UnivariateFactorlist);
[e2ca88]711  DEBOUTLN(CERR,  "Returned from evaluate: success: ", success);
[38e7b3]712  for ( SFormListIterator ii=Substitutionlist; ii.hasItem(); ii++ )
713  {
[e2ca88]714    DEBOUTLN(CERR, "Substituting ", ii.getItem().factor());
715    DEBOUTLN(CERR, "       with value: ", ii.getItem().exp());
[1a80b4]716  }
717
[38e7b3]718  if ( success==0 ) // evalute wasn't successfull
719  {
[1a80b4]720    success= specializePoly(ffuni,Extension,degree(ff),Substitutionlist,1,getNumVars(compress(ff,m)));
[e2ca88]721    DEBOUTLN(CERR,  "Returned from specializePoly: success: ", success);
[38e7b3]722    if (success == 0 ) // No spezialisation could be found
723    {
[a13956]724      factoryError("libfac: Factorize: ERROR: Not able to find a valid specialization!");
[1a80b4]725      Outputlist.append(CFFactor(F,1));
726      return Outputlist;
727    }
[3e55bc]728
729    // INTERRUPTHANDLER
730    if ( interrupt_handle() ) return CFFList() ;
731    // INTERRUPTHANDLER
732
[1a80b4]733    ffuni = substitutePoly(ff,Substitutionlist);
734    // We now have an univariat poly; factorize that
[38e7b3]735    if ( degree(Extension) == 0   )
736    {
[e2ca88]737      DEBOUTMSG(CERR, "Univ. Factorization over the ground field");
[1a80b4]738      UnivariateFactorlist = factorize(ffuni,1); // univ. poly is sqr-free!
739    }
[38e7b3]740    else
741    {
[e2ca88]742      DEBOUTLN(CERR, "Univ. Factorization over extension of degree ",
[0be2bc]743               degree(getMipo(Extension,'x')) );
[b87513c]744     #if 1
[1048e0c]745      UnivariateFactorlist = factorize2(ffuni,Extension,alpha);
[0be2bc]746     #else
747      Variable X;
748      CanonicalForm mipo=getMipo(Extension,X);
749      CFList as(mipo);
750      UnivariateFactorlist = newfactoras( ffuni, as, 1);
[14b1e65]751     #endif
[1a80b4]752    }
753  }
[38e7b3]754  else
755  {
[0be2bc]756    ffuni = substitutePoly(ff,Substitutionlist);
[1a80b4]757  }
758    TIMING_END(evaluate_time);
[38e7b3]759  if (UnivariateFactorlist.length() == 1)
760  { // poly is irreduzibel
[e2ca88]761    DEBOUTLN(CERR, "Univ. poly is irreduzible: ", UnivariateFactorlist);
[1a80b4]762    Outputlist.append(CFFactor(F,1));
763    return Outputlist;
764  }
[38e7b3]765  else
766  { // we have factors
[e2ca88]767    DEBOUTSL(CERR);
768    DEBOUT(CERR, "Univariate poly has " , UnivariateFactorlist.length());
769    DEBOUT(CERR, " factors:  ", ffuni);
770    DEBOUT(CERR, " = ", UnivariateFactorlist); DEBOUTNL(CERR);
[1a80b4]771
[3e55bc]772    // INTERRUPTHANDLER
773    if ( interrupt_handle() ) return CFFList() ;
774    // INTERRUPTHANDLER
775
[1a80b4]776    TIMING_START(hensel_time);
[8de151]777    Outputlist = MultiHensel(ff,UnivariateFactorlist,Substitutionlist, alpha);
[e2ca88]778    DEBOUTLN(CERR, "Outputlist after MultiHensel: ", Outputlist);
[1a80b4]779    TIMING_END(hensel_time);
780
[3e55bc]781    // INTERRUPTHANDLER
782    if ( interrupt_handle() ) return CFFList() ;
783    // INTERRUPTHANDLER
784
[1a80b4]785    TIMING_START(truefactor_time);
786    Outputlist = Truefactors(ff, level(ff), Substitutionlist, Outputlist);
[e2ca88]787    DEBOUTLN(CERR, "Outputlist after Truefactors: ", Outputlist);
[1a80b4]788    TIMING_END(truefactor_time);
789
[3e55bc]790    // INTERRUPTHANDLER
791    if ( interrupt_handle() ) return CFFList() ;
792    // INTERRUPTHANDLER
793
[aa7480c]794    //if ( lt != f.genOne() )
795    if ( !lt.isOne() )
[52e543]796    {
[1a80b4]797      Outputlist = not_monic(Outputlist,lt,ff,level(ff));
[e2ca88]798      DEBOUTLN(CERR, "not_monic returned: ", Outputlist);
[1a80b4]799    }
800
801    // have to back-swapvar the factors....
[52e543]802    for ( CFFListIterator i=Outputlist; i.hasItem(); i++ )
803    {
804      copy=i.getItem();
805      Outputlist2.append(CFFactor(swapvar(copy.factor(),oldmainvar,mainvar),copy.exp()));
[1a80b4]806    }
807
808    return Outputlist2;
809  }
810}
811
[5299b6]812int cmpCF( const CFFactor & f, const CFFactor & g );
813
[1a80b4]814///////////////////////////////////////////////////////////////
815// The user front-end for a uni/multivariate factorization   //
816// routine. F needs not to be SqrFree.                       //
817// Option of * choosing a  main variable (n.y.i.)            //
818//           * choosing an algebraic extension (n.y.u.)      //
819//           * ensuring poly is sqrfree (n.y.i.)             //
[b4ea1d]820// use Factorize(F,alpha,is_SqrFree) if not over Zp[x]/Q[x]  //
[1a80b4]821///////////////////////////////////////////////////////////////
[b6249e]822int find_mvar(const CanonicalForm &f);
[38e7b3]823CFFList Factorize(const CanonicalForm & F, int is_SqrFree )
824{
[ee586a]825  //out_cf("Factorize ",F,"\n");
[1a80b4]826  CFFList Outputlist,SqrFreeList,Intermediatelist,Outputlist2;
827  ListIterator<CFFactor> i,j;
[0be2bc]828  CanonicalForm g=1,unit=1,r=1;
[b4ea1d]829  Variable minpoly; // dummy
[1a80b4]830  int exp;
831  CFMap m;
832
[3e55bc]833  // INTERRUPTHANDLER
834  if ( interrupt_handle() ) return CFFList() ;
835  // INTERRUPTHANDLER
836
[e2ca88]837  DEBINCLEVEL(CERR, "Factorize");
838  DEBOUTLN(CERR, "Called with F= ", F);
[9e9b7c]839  if (( getCharacteristic() == 0 ) || (F.isUnivariate()))
[38e7b3]840  { // char == 0
[1a80b4]841    TIMING_START(factorize_time);
[e2ca88]842    //CERR << "Factoring in char=0 of " << F << " = " << Outputlist << "\n";
[1a80b4]843    Outputlist= factorize(F);
[3e55bc]844    // Factorization in char=0 doesn't sometimes return at least two elements!!!
[0be2bc]845    if ( getNumVars(Outputlist.getFirst().factor()) != 0 )
[3e55bc]846      Outputlist.insert(CFFactor(1,1));
[e2ca88]847    //CERR << "  Factorize in char=0: returning with: " << Outputlist << "\n";
[3e55bc]848    TIMING_END(factorize_time);
[e2ca88]849    DEBDECLEVEL(CERR, "Factorize");
[3e55bc]850    TIMING_PRINT(factorize_time, "\ntime used for factorization   : ");
851    return Outputlist;
[1a80b4]852  }
853  TIMING_START(factorize_time);
[b6249e]854  // search an "optimal" main variavble
855  int mv=F.level();
[9e9b7c]856  if ((mv != LEVELBASE) /* && (! F.isUnivariate()) */)
[b6249e]857  {
858     mv=find_mvar(F);
859     if (mv!=F.level())
860     {
861       swapvar(F,Variable(mv),F.mvar());
862     }
863  }
864
[1a80b4]865  ///////
866  // Maybe it`s better to add a sqrfree-test before?
867  // (If gcd is fast...)
868  ///////
[e89e56]869  //  if ( ! SqrFreeTest(F) ){
[38e7b3]870  if ( ! is_SqrFree )
871  {
[3e55bc]872    TIMING_START(sqrfree_time);
[e89e56]873    SqrFreeList = SqrFreeMV(F) ; // first sqrfree the polynomial
874    // don't use sqrFree(F), factory's internal sqrFree for multiv.
875    // Polynomials; it's wrong!! Ex.: char=p   f= x^p*(y+1);
876    // SqrFreeMV(f)= ( y+1, (x)^p ), sqrFree(f)= ( y+1 ) .
[3e55bc]877    TIMING_END(sqrfree_time);
878
879    // INTERRUPTHANDLER
880    if ( interrupt_handle() ) return CFFList() ;
881    // INTERRUPTHANDLER
882
[1a80b4]883  }
[0be2bc]884  else
[3e55bc]885    SqrFreeList.append(CFFactor(F,1));
[9e9b7c]886
[e89e56]887  DEBOUTLN(CERR, "SqrFreeMV= ", SqrFreeList);
[38e7b3]888  for ( i=SqrFreeList; i.hasItem(); i++ )
889  {
[e2ca88]890    DEBOUTLN(CERR, "Factor under consideration: ", i.getItem().factor());
[1a80b4]891    // We need a compress on each list item ! Maybe we have less variables!
[0be2bc]892    g =compress(i.getItem().factor(),m);
[1a80b4]893    exp = i.getItem().exp();
894    if ( getNumVars(g) ==0 ) // a constant; Exp==1
895      Outputlist.append( CFFactor(g,1) ) ;
896    else// a real polynomial
[38e7b3]897      if ( g.isUnivariate() )
898      {
[ee586a]899        //out_cf("univ. poly: ",g,"\n");
[0be2bc]900        Intermediatelist=factorize(g,1); // poly is sqr-free!
901        for ( j=Intermediatelist; j.hasItem(); j++ )
902          //Normally j.getItem().exp() should be 1
903          Outputlist.append( CFFactor( m(j.getItem().factor()),exp*j.getItem().exp()));
[1a80b4]904      }
[38e7b3]905      else
906      { // multivariate polynomial
907        if ( g.isHomogeneous() )
908        {
[e2ca88]909          DEBOUTLN(CERR, "Poly is homogeneous! : ", g);
[0be2bc]910          // Now we can substitute one variable to 1, factorize and then
911          // look on the resulting factors and their monomials for
912          // backsubstitution of the substituted variable.
913          Intermediatelist = HomogFactor(g, minpoly, 0);
914        }
915        else // not homogeneous
916          Intermediatelist = Factorized(g, minpoly, 0);
917
918        // INTERRUPTHANDLER
919        if ( interrupt_handle() ) return CFFList() ;
920        // INTERRUPTHANDLER
921
922        for ( j=Intermediatelist; j.hasItem(); j++ )
923          //Normally j.getItem().exp() should be 1
[e89e56]924          Outputlist= myappend( Outputlist, CFFactor(m(j.getItem().factor()),exp*j.getItem().exp()));
[1a80b4]925      }
926  }
927  g=1; unit=1;
[e2ca88]928  DEBOUTLN(CERR, "Outputlist is ", Outputlist);
[1a80b4]929  for ( i=Outputlist; i.hasItem(); i++ )
[38e7b3]930    if ( level(i.getItem().factor()) > 0 )
931    {
[1a80b4]932      unit = lc(i.getItem().factor());
[38e7b3]933      if ( getNumVars(unit) == 0 )
934      { // a constant; possibly 1
[0be2bc]935        Outputlist2.append(CFFactor(i.getItem().factor()/unit , i.getItem().exp()));
936        g *=power(i.getItem().factor()/unit,i.getItem().exp());
[1a80b4]937      }
[38e7b3]938      else
939      {
[0be2bc]940        Outputlist2.append(i.getItem());
941        g *=power(i.getItem().factor(),i.getItem().exp());
[1a80b4]942      }
943    }
[0be2bc]944
945  r=F/g;
[1a80b4]946  Outputlist2.insert(CFFactor(r,1));
[0be2bc]947
[b6249e]948  if ((mv!=F.level()) && (! F.isUnivariate() ))
949  {
950    CFFListIterator J=Outputlist2;
951    for ( ; J.hasItem(); J++)
952    {
953      swapvar(J.getItem().factor(),Variable(mv),F.mvar());
954    }
955    swapvar(F,Variable(mv),F.mvar());
956  }
[e2ca88]957  DEBDECLEVEL(CERR, "Factorize");
[1a80b4]958  TIMING_END(factorize_time);
959
960  TIMING_PRINT(sqrfree_time, "\ntime used for sqrfree   : ");
961  TIMING_PRINT(discr_time, "time used for discriminante   : ");
962  TIMING_PRINT(evaluate_time, "time used for evaluation and univ. factorization  : ");
963  TIMING_PRINT(hensel_time, "time used for hensel-lift   : ");
964  TIMING_PRINT(truefactor_time, "time used for truefactors   : ");
965  TIMING_PRINT(factorize_time, "\ntime used for factorization   : ");
[5299b6]966
967  if(isOn(SW_USE_NTL_SORT)) Outputlist2.sort(cmpCF);
968
[1a80b4]969  return Outputlist2;
970}
971
[b4ea1d]972///////////////////////////////////////////////////////////////
973// The user front-end for a uni/multivariate factorization   //
974// routine. F needs not to be SqrFree.                       //
975// Option of * choosing a  main variable (n.y.i.)            //
976//           * choosing an algebraic extension (n.y.u.)      //
977//           * ensuring poly is sqrfree (n.y.i.)             //
978///////////////////////////////////////////////////////////////
[52e543]979static bool fdivides2(const CanonicalForm &F, const CanonicalForm &G, const CanonicalForm &minpoly)
980{
[8e0cdf]981  if (!minpoly.isZero())
[52e543]982  {
983  #if 0
984    Variable Alpha=minpoly.mvar();
985    Variable X=rootOf(minpoly);
986    CanonicalForm rF=replacevar(F,Alpha,X);
987    CanonicalForm rG=replacevar(G,Alpha,X);
988    return fdivides(rF,rG);;
989  #else
[304e26]990    if (degree(F,F.mvar()) > degree(G,F.mvar())) return false;
991    return true;
992    //CanonicalForm a,b;
993    //mydivrem(G,F,a,b);
994    //if (b.isZero()) return true;
995    //else return false;
[52e543]996  #endif
997  }
998  else
999   return fdivides(F,G);
1000}
[8de151]1001CFFList Factorize2(CanonicalForm F, const CanonicalForm & minpoly )
[10697c]1002{
[927b7e]1003#ifndef NDEBUG
[7cb56a9]1004  //printf("start Factorize2(int_flag=%d)\n",libfac_interruptflag);
[927b7e]1005#endif
[10697c]1006  CFFList G,H;
1007  CanonicalForm fac;
[52e543]1008  int d,e;
[10697c]1009  ListIterator<CFFactor> i,k;
[304e26]1010  libfac_interruptflag=0;
1011  CFFList iF=Factorize(F,minpoly);
[e89e56]1012  if ((libfac_interruptflag==0)&&(!iF.isEmpty()))
[927b7e]1013    H=iF;
1014  else
[52e543]1015  {
1016#ifndef NDEBUG
[7cb56a9]1017    //printf("variant 2(int_flag=%d)\n",libfac_interruptflag);
[52e543]1018#endif
[304e26]1019    libfac_interruptflag=0;
[52e543]1020    iF=Factorize(F);
[927b7e]1021    if (libfac_interruptflag==0)
[52e543]1022    {
[927b7e]1023      i = iF;
1024      while( i.hasItem())
[52e543]1025      {
[927b7e]1026        d = i.getItem().exp();
1027        fac = i.getItem().factor();
1028        if (fdivides(fac,F))
[52e543]1029        {
[927b7e]1030          if ((getNumVars(fac)==0)||(fac.degree()<=1))
1031          {
[52e543]1032#ifndef NOSTREAMIO
1033#ifndef NDEBUG
[7cb56a9]1034            //printf("append trivial factor\n");
[52e543]1035#endif
1036#endif
[927b7e]1037            H.append( CFFactor( fac, d));
1038            do {F/=fac; d--; } while (d>0);
1039          }
1040          else
[52e543]1041          {
[927b7e]1042            G = Factorize( fac, minpoly);
1043            if (libfac_interruptflag!=0)
[52e543]1044            {
[927b7e]1045              libfac_interruptflag=0;
1046              k = G;
1047              while( k.hasItem())
1048              {
1049                fac = k.getItem().factor();
1050                int dd = k.getItem().exp()*d;
1051                e=0;
1052                while ((!fac.isZero())&& fdivides2(fac,F,minpoly) && (dd>0))
1053                {
[52e543]1054#ifndef NOSTREAMIO
1055#ifndef NDEBUG
[7cb56a9]1056                  //out_cf("factor:",fac,"\n");
[52e543]1057#endif
1058#endif
[927b7e]1059                  e++;dd--;
1060                  F/=fac;
1061                }
1062                if (e>0) H.append( CFFactor( fac , e ) );
1063                ++k;
1064              }
[52e543]1065            }
1066          }
1067        }
[927b7e]1068        ++i;
[8de151]1069      }
[10697c]1070    }
1071  }
[927b7e]1072  //Outputlist = newfactoras( F, as, 1);
1073  if((isOn(SW_USE_NTL_SORT))&&(!H.isEmpty())) H.sort(cmpCF);
[8de151]1074#ifndef NDEBUG
[7cb56a9]1075  //printf("end Factorize2(%d)\n",libfac_interruptflag);
[8de151]1076#endif
[10697c]1077  return H;
1078}
[927b7e]1079
[b4ea1d]1080CFFList
[38e7b3]1081Factorize(const CanonicalForm & F, const CanonicalForm & minpoly, int is_SqrFree )
1082{
[a38d45]1083  //out_cf("Factorize: F=",F,"\n");
1084  //out_cf("           minpoly:",minpoly,"\n");
[b4ea1d]1085  CFFList Outputlist,SqrFreeList,Intermediatelist,Outputlist2;
1086  ListIterator<CFFactor> i,j;
1087  CanonicalForm g=1,unit=1,r=1;
1088  //Variable minpoly; // reserved (-> Factorisation over algebraic Extensions)
1089  int exp;
1090  CFMap m;
1091
1092  // INTERRUPTHANDLER
1093  if ( interrupt_handle() ) return CFFList() ;
1094  // INTERRUPTHANDLER
1095
[e2ca88]1096  DEBINCLEVEL(CERR, "Factorize");
1097  DEBOUTLN(CERR, "Called with F= ", F);
[639047e]1098  if ( getCharacteristic() == 0 )
1099  { // char == 0
[b4ea1d]1100    TIMING_START(factorize_time);
[e2ca88]1101    //CERR << "Factoring in char=0 of " << F << " = " << Outputlist << "\n";
[639047e]1102    #if 0
[93a6da3]1103    // SHOULD: Outputlist= factorize(F,minpoly);
1104    Outputlist= factorize(F);
[639047e]1105    #else
[8e0cdf]1106    if (!minpoly.isZero())
[639047e]1107    {
[a38d45]1108      if ( F.isHomogeneous() )
[6036eb2]1109      {
[a38d45]1110        DEBOUTLN(CERR, "Poly is homogeneous! : ", F);
1111        // Now we can substitute one variable to 1, factorize and then
1112        // look on the resulting factors and their monomials for
1113        // backsubstitution of the substituted variable.
1114        Outputlist=HomogFactor(F, minpoly, 0);
1115      }
1116      else
1117      {
1118        CFList as(minpoly);
[8e0cdf]1119        //CFFList sqF=sqrFree(F); // sqrFreeZ
1120        CFFList sqF=SqrFreeMV(F,minpoly);
1121        if (sqF.isEmpty()) sqF=sqrFree(F);
[a38d45]1122        CFFList G,H;
1123        CanonicalForm fac;
1124        int d;
1125        ListIterator<CFFactor> i,k;
1126        for ( i = sqF; i.hasItem(); ++i )
[6036eb2]1127        {
[a38d45]1128          d = i.getItem().exp();
1129          fac = i.getItem().factor();
[adfb22]1130          int success=1;
1131          G = newfactoras( fac, as, success);
[a38d45]1132          for ( k = G; k.hasItem(); ++k )
1133          {
1134            fac = k.getItem().factor();
1135            int dd = k.getItem().exp();
1136            H.append( CFFactor( fac , d*dd ) );
1137          }
[6036eb2]1138        }
[a38d45]1139        //Outputlist = newfactoras( F, as, 1);
1140        Outputlist = H;
[6036eb2]1141      }
[639047e]1142    }
[8e0cdf]1143    else // minpoly==0
[639047e]1144      Outputlist=factorize(F);
1145    #endif
[b4ea1d]1146    // Factorization in char=0 doesn't sometimes return at least two elements!!!
1147    if ( getNumVars(Outputlist.getFirst().factor()) != 0 )
1148      Outputlist.insert(CFFactor(1,1));
[e2ca88]1149    //CERR << "  Factorize in char=0: returning with: " << Outputlist << "\n";
[b4ea1d]1150    TIMING_END(factorize_time);
[e2ca88]1151    DEBDECLEVEL(CERR, "Factorize");
[b4ea1d]1152    TIMING_PRINT(factorize_time, "\ntime used for factorization   : ");
[a38d45]1153    //out_cff(Outputlist);
[b4ea1d]1154    return Outputlist;
1155  }
1156  TIMING_START(factorize_time);
1157  // search an "optimal" main variavble
1158  int mv=F.level();
1159  if (mv != LEVELBASE && ! F.isUnivariate() )
1160  {
1161     mv=find_mvar(F);
1162     if (mv!=F.level())
1163     {
1164       swapvar(F,Variable(mv),F.mvar());
1165     }
1166  }
1167
1168  ///////
1169  // Maybe it`s better to add a sqrfree-test before?
1170  // (If gcd is fast...)
1171  ///////
[e89e56]1172  //  if ( ! SqrFreeTest(F) ){
[10697c]1173  if ( ! is_SqrFree )
1174  {
[b4ea1d]1175    TIMING_START(sqrfree_time);
[e89e56]1176    SqrFreeList = SqrFreeMV(F, minpoly) ; // first sqrfree the polynomial
1177    // don't use sqrFree(F), factory's internal sqrFree for multiv.
1178    // Polynomials; it's wrong!! Ex.: char=p   f= x^p*(y+1);
1179    // SqrFreeMV(f)= ( y+1, (x)^p ), sqrFree(f)= ( y+1 ) .
[b4ea1d]1180    TIMING_END(sqrfree_time);
1181
1182    // INTERRUPTHANDLER
1183    if ( interrupt_handle() ) return CFFList() ;
1184    // INTERRUPTHANDLER
1185
1186  }
1187  else
1188    SqrFreeList.append(CFFactor(F,1));
[e89e56]1189  DEBOUTLN(CERR, "SqrFreeMV= ", SqrFreeList);
[10697c]1190  for ( i=SqrFreeList; i.hasItem(); i++ )
1191  {
[e2ca88]1192    DEBOUTLN(CERR, "Factor under consideration: ", i.getItem().factor());
[b4ea1d]1193    // We need a compress on each list item ! Maybe we have less variables!
1194    g =compress(i.getItem().factor(),m);
1195    exp = i.getItem().exp();
1196    if ( getNumVars(g) ==0 ) // a constant; Exp==1
1197      Outputlist.append( CFFactor(g,1) ) ;
1198    else// a real polynomial
[8de151]1199    {
[10697c]1200      if ( g.isUnivariate() )
1201      {
[639047e]1202        Variable alpha=rootOf(minpoly);
[1048e0c]1203        Intermediatelist=factorize2(g,alpha,minpoly); // poly is sqr-free!
[b4ea1d]1204        for ( j=Intermediatelist; j.hasItem(); j++ )
1205          //Normally j.getItem().exp() should be 1
[639047e]1206          Outputlist.append(
1207           CFFactor( m(replacevar(j.getItem().factor(),alpha,minpoly.mvar())),
1208             exp*j.getItem().exp()));
[b4ea1d]1209      }
[10697c]1210      else // multivariate polynomial
1211      {
1212        if ( g.isHomogeneous() )
[52e543]1213        {
[e2ca88]1214          DEBOUTLN(CERR, "Poly is homogeneous! : ", g);
[b4ea1d]1215          // Now we can substitute one variable to 1, factorize and then
1216          // look on the resulting factors and their monomials for
1217          // backsubstitution of the substituted variable.
1218          Intermediatelist = HomogFactor(g, minpoly, 0);
1219        }
1220        else // not homogeneous
1221          Intermediatelist = Factorized(g, minpoly, 0);
1222
1223        // INTERRUPTHANDLER
1224        if ( interrupt_handle() ) return CFFList() ;
1225        // INTERRUPTHANDLER
1226
1227        for ( j=Intermediatelist; j.hasItem(); j++ )
1228          //Normally j.getItem().exp() should be 1
[e89e56]1229          Outputlist= myappend( Outputlist, CFFactor(m(j.getItem().factor()),exp*j.getItem().exp()));
[b4ea1d]1230      }
[8de151]1231    }
[b4ea1d]1232  }
1233  g=1; unit=1;
[e2ca88]1234  DEBOUTLN(CERR, "Outputlist is ", Outputlist);
[b4ea1d]1235  for ( i=Outputlist; i.hasItem(); i++ )
[8e0cdf]1236    if ( level(i.getItem().factor()) > 0 )
1237    {
[b4ea1d]1238      unit = lc(i.getItem().factor());
1239      if ( getNumVars(unit) == 0 ){ // a constant; possibly 1
1240        Outputlist2.append(CFFactor(i.getItem().factor()/unit , i.getItem().exp()));
1241        g *=power(i.getItem().factor()/unit,i.getItem().exp());
1242      }
[8e0cdf]1243      else
1244      {
[b4ea1d]1245        Outputlist2.append(i.getItem());
1246        g *=power(i.getItem().factor(),i.getItem().exp());
1247      }
1248    }
1249
1250  r=F/g;
1251  Outputlist2.insert(CFFactor(r,1));
1252
1253  if ((mv!=F.level()) && (! F.isUnivariate() ))
1254  {
1255    CFFListIterator J=Outputlist2;
1256    for ( ; J.hasItem(); J++)
1257    {
1258      swapvar(J.getItem().factor(),Variable(mv),F.mvar());
1259    }
1260    swapvar(F,Variable(mv),F.mvar());
1261  }
[1048e0c]1262
[e2ca88]1263  DEBDECLEVEL(CERR, "Factorize");
[b4ea1d]1264  TIMING_END(factorize_time);
1265
1266  TIMING_PRINT(sqrfree_time, "\ntime used for sqrfree   : ");
1267  TIMING_PRINT(discr_time, "time used for discriminante   : ");
1268  TIMING_PRINT(evaluate_time, "time used for evaluation and univ. factorization  : ");
1269  TIMING_PRINT(hensel_time, "time used for hensel-lift   : ");
1270  TIMING_PRINT(truefactor_time, "time used for truefactors   : ");
1271  TIMING_PRINT(factorize_time, "\ntime used for factorization   : ");
[5299b6]1272
1273  if(isOn(SW_USE_NTL_SORT)) Outputlist2.sort(cmpCF);
1274
[a38d45]1275  //out_cff(Outputlist2);
[b4ea1d]1276  return Outputlist2;
1277}
1278
Note: See TracBrowser for help on using the repository browser.