source: git/factory/cf_factor.cc @ a8fbae

fieker-DuValspielwiese
Last change on this file since a8fbae was a8fbae, checked in by Hans Schoenemann <hannes@…>, 4 years ago
factory: multivariate over Z via flint 2.7.0
  • Property mode set to 100644
File size: 23.3 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2
3/**
4 *
5 * @file cf_factor.cc
6 *
7 * Interface to factorization and square free factorization algorithms.
8 *
9 * Used by: cf_irred.cc
10 *
11 * Header file: cf_algorithm.h
12 *
13**/
14
15
16#include "config.h"
17
18
19#include "cf_assert.h"
20
21#include "cf_defs.h"
22#include "canonicalform.h"
23#include "cf_iter.h"
24#include "fac_sqrfree.h"
25#include "cf_algorithm.h"
26#include "facFqFactorize.h"
27#include "facFqSquarefree.h"
28#include "cf_map.h"
29#include "facAlgExt.h"
30#include "facFactorize.h"
31#include "singext.h"
32#include "cf_util.h"
33#include "fac_berlekamp.h"
34#include "fac_cantzass.h"
35#include "fac_univar.h"
36#include "fac_multivar.h"
37
38#include "int_int.h"
39#ifdef HAVE_NTL
40#include "NTLconvert.h"
41#endif
42
43#include "factory/cf_gmp.h"
44#ifdef HAVE_FLINT
45#include "FLINTconvert.h"
46#if (__FLINT_RELEASE >= 20700)
47#include <flint/nmod_mpoly_factor.h>
48#include <flint/fmpq_mpoly_factor.h>
49#endif
50#endif
51
52//static bool isUnivariateBaseDomain( const CanonicalForm & f )
53//{
54//    CFIterator i = f;
55//    bool ok = i.coeff().inBaseDomain();
56//    i++;
57//    while ( i.hasTerms() && ( ok = ok && i.coeff().inBaseDomain() ) ) i++;
58//    return ok;
59//}
60
61void find_exp(const CanonicalForm & f, int * exp_f)
62{
63  if ( ! f.inCoeffDomain() )
64  {
65    int e=f.level();
66    CFIterator i = f;
67    if (e>=0)
68    {
69      if (i.exp() > exp_f[e]) exp_f[e]=i.exp();
70    }
71    for (; i.hasTerms(); i++ )
72    {
73      find_exp(i.coeff(), exp_f);
74    }
75  }
76}
77
78int find_mvar(const CanonicalForm & f)
79{
80  int mv=f.level();
81  int *exp_f=NEW_ARRAY(int,mv+1);
82  int i;
83  for(i=mv;i>0;i--) exp_f[i]=0;
84  find_exp(f,exp_f);
85  for(i=mv;i>0;i--)
86  {
87    if ((exp_f[i]>0) && (exp_f[i]<exp_f[mv]))
88    {
89      mv=i;
90    }
91  }
92  DELETE_ARRAY(exp_f);
93  return mv;
94}
95
96#if 1
97//#ifndef NOSTREAMIO
98void out_cf(const char *s1,const CanonicalForm &f,const char *s2)
99{
100  printf("%s",s1);
101  if (f.isZero()) printf("+0");
102  //else if (! f.inCoeffDomain() )
103  else if (! f.inBaseDomain() )
104  {
105    int l = f.level();
106    for ( CFIterator i = f; i.hasTerms(); i++ )
107    {
108      int e=i.exp();
109      if (i.coeff().isOne())
110      {
111        printf("+");
112        if (e==0) printf("1");
113        else
114        {
115          printf("%c",'a'+l-1);
116          if (e!=1) printf("^%d",e);
117        }
118      }
119      else
120      {
121        out_cf("+(",i.coeff(),")");
122        if (e!=0)
123        {
124          printf("*%c",'a'+l-1);
125          if (e!=1) printf("^%d",e);
126        }
127      }
128    }
129  }
130  else
131  {
132    if ( f.isImm() )
133    {
134      if (CFFactory::gettype()==GaloisFieldDomain)
135      {
136         long a= imm2int (f.getval());
137         if ( a == gf_q )
138           printf ("+%ld", a);
139         else  if ( a == 0L )
140           printf ("+1");
141         else  if ( a == 1L )
142           printf ("+%c",gf_name);
143         else
144         {
145           printf ("+%c",gf_name);
146           printf ("^%ld",a);
147         }
148      }
149      else
150      {
151        long l=f.intval();
152        if (l<0) printf("%ld",l);
153        else     printf("+%ld",l);
154      }
155    }
156    else
157    {
158    #ifdef NOSTREAMIO
159      if (f.inZ())
160      {
161        mpz_t m;
162        gmp_numerator(f,m);
163        char * str = new char[mpz_sizeinbase( m, 10 ) + 2];
164        str = mpz_get_str( str, 10, m );
165        puts(str);
166        delete[] str;
167        mpz_clear(m);
168      }
169      else if (f.inQ())
170      {
171        mpz_t m;
172        gmp_numerator(f,m);
173        char * str = new char[mpz_sizeinbase( m, 10 ) + 2];
174        str = mpz_get_str( str, 10, m );
175        while(str[strlen(str)]<' ') { str[strlen(str)]='\0'; }
176        puts(str);putchar('/');
177        delete[] str;
178        mpz_clear(m);
179        gmp_denominator(f,m);
180        str = new char[mpz_sizeinbase( m, 10 ) + 2];
181        str = mpz_get_str( str, 10, m );
182        while(str[strlen(str)]<' ') { str[strlen(str)]='\0'; }
183        puts(str);
184        delete[] str;
185        mpz_clear(m);
186      }
187    #else
188       std::cout << f;
189    #endif
190    }
191    //if (f.inZ()) printf("(Z)");
192    //else if (f.inQ()) printf("(Q)");
193    //else if (f.inFF()) printf("(FF)");
194    //else if (f.inPP()) printf("(PP)");
195    //else if (f.inGF()) printf("(PP)");
196    //else
197    if (f.inExtension()) printf("E(%d)",f.level());
198  }
199  printf("%s",s2);
200}
201void out_cff(CFFList &L)
202{
203  //int n = L.length();
204  CFFListIterator J=L;
205  int j=0;
206  for ( ; J.hasItem(); J++, j++ )
207  {
208    printf("F%d",j);out_cf(":",J.getItem().factor()," ^ ");
209    printf("%d\n", J.getItem().exp());
210  }
211}
212void test_cff(CFFList &L,const CanonicalForm & f)
213{
214  //int n = L.length();
215  CFFListIterator J=L;
216  CanonicalForm t=1;
217  int j=0;
218  if (!(L.getFirst().factor().inCoeffDomain()))
219    printf("first entry is not const\n");
220  for ( ; J.hasItem(); J++, j++ )
221  {
222    CanonicalForm tt=J.getItem().factor();
223    if (tt.inCoeffDomain() && (j!=0))
224      printf("other entry is const\n");
225    j=J.getItem().exp();
226    while(j>0) { t*=tt; j--; }
227  }
228  if (!(f-t).isZero()) { printf("problem:\n");out_cf("factor:",f," has problems\n");}
229}
230//#endif
231#endif
232
233bool isPurePoly_m(const CanonicalForm & f)
234{
235  if (f.inBaseDomain()) return true;
236  if (f.level()<0) return false;
237  for (CFIterator i=f;i.hasTerms();i++)
238  {
239    if (!isPurePoly_m(i.coeff())) return false;
240  }
241  return true;
242}
243bool isPurePoly(const CanonicalForm & f)
244{
245  if (f.level()<=0) return false;
246  for (CFIterator i=f;i.hasTerms();i++)
247  {
248    if (!(i.coeff().inBaseDomain())) return false;
249  }
250  return true;
251}
252
253
254/**
255 * get_max_degree_Variable returns Variable with
256 * highest degree. We assume f is *not* a constant!
257**/
258Variable
259get_max_degree_Variable(const CanonicalForm & f)
260{
261  ASSERT( ( ! f.inCoeffDomain() ), "no constants" );
262  int max=0, maxlevel=0, n=level(f);
263  for ( int i=1; i<=n; i++ )
264  {
265    if (degree(f,Variable(i)) >= max)
266    {
267      max= degree(f,Variable(i)); maxlevel= i;
268    }
269  }
270  return Variable(maxlevel);
271}
272
273/**
274 * get_Terms: Split the polynomial in the containing terms.
275 * getTerms: the real work is done here.
276**/
277void
278getTerms( const CanonicalForm & f, const CanonicalForm & t, CFList & result )
279{
280  if ( getNumVars(f) == 0 ) result.append(f*t);
281  else{
282    Variable x(level(f));
283    for ( CFIterator i=f; i.hasTerms(); i++ )
284      getTerms( i.coeff(), t*power(x,i.exp()), result);
285  }
286}
287CFList
288get_Terms( const CanonicalForm & f ){
289  CFList result,dummy,dummy2;
290  CFIterator i;
291  CFListIterator j;
292
293  if ( getNumVars(f) == 0 ) result.append(f);
294  else{
295    Variable _x(level(f));
296    for ( i=f; i.hasTerms(); i++ ){
297      getTerms(i.coeff(), 1, dummy);
298      for ( j=dummy; j.hasItem(); j++ )
299        result.append(j.getItem() * power(_x, i.exp()));
300
301      dummy= dummy2; // have to initalize new
302    }
303  }
304  return result;
305}
306
307
308/**
309 * homogenize homogenizes f with Variable x
310**/
311CanonicalForm
312homogenize( const CanonicalForm & f, const Variable & x)
313{
314#if 0
315  int maxdeg=totaldegree(f), deg;
316  CFIterator i;
317  CanonicalForm elem, result(0);
318
319  for (i=f; i.hasTerms(); i++)
320  {
321    elem= i.coeff()*power(f.mvar(),i.exp());
322    deg = totaldegree(elem);
323    if ( deg < maxdeg )
324      result += elem * power(x,maxdeg-deg);
325    else
326      result+=elem;
327  }
328  return result;
329#else
330  CFList Newlist, Termlist= get_Terms(f);
331  int maxdeg=totaldegree(f), deg;
332  CFListIterator i;
333  CanonicalForm elem, result(0);
334
335  for (i=Termlist; i.hasItem(); i++)
336  {
337    elem= i.getItem();
338    deg = totaldegree(elem);
339    if ( deg < maxdeg )
340      Newlist.append(elem * power(x,maxdeg-deg));
341    else
342      Newlist.append(elem);
343  }
344  for (i=Newlist; i.hasItem(); i++) // rebuild
345    result += i.getItem();
346
347  return result;
348#endif
349}
350
351CanonicalForm
352homogenize( const CanonicalForm & f, const Variable & x, const Variable & v1, const Variable & v2)
353{
354#if 0
355  int maxdeg=totaldegree(f), deg;
356  CFIterator i;
357  CanonicalForm elem, result(0);
358
359  for (i=f; i.hasTerms(); i++)
360  {
361    elem= i.coeff()*power(f.mvar(),i.exp());
362    deg = totaldegree(elem);
363    if ( deg < maxdeg )
364      result += elem * power(x,maxdeg-deg);
365    else
366      result+=elem;
367  }
368  return result;
369#else
370  CFList Newlist, Termlist= get_Terms(f);
371  int maxdeg=totaldegree(f), deg;
372  CFListIterator i;
373  CanonicalForm elem, result(0);
374
375  for (i=Termlist; i.hasItem(); i++)
376  {
377    elem= i.getItem();
378    deg = totaldegree(elem,v1,v2);
379    if ( deg < maxdeg )
380      Newlist.append(elem * power(x,maxdeg-deg));
381    else
382      Newlist.append(elem);
383  }
384  for (i=Newlist; i.hasItem(); i++) // rebuild
385    result += i.getItem();
386
387  return result;
388#endif
389}
390
391VAR int singular_homog_flag=1;
392
393int cmpCF( const CFFactor & f, const CFFactor & g )
394{
395  if (f.exp() > g.exp()) return 1;
396  if (f.exp() < g.exp()) return 0;
397  if (f.factor() > g.factor()) return 1;
398  return 0;
399}
400
401/**
402 * factorization over \f$ F_p \f$ or \f$ Q \f$
403**/
404CFFList factorize ( const CanonicalForm & f, bool issqrfree )
405{
406  if ( f.inCoeffDomain() )
407        return CFFList( f );
408#ifndef NOASSERT
409  Variable a;
410  ASSERT (!hasFirstAlgVar (f, a), "f has an algebraic variable use factorize \
411          ( const CanonicalForm & f, const Variable & alpha ) instead");
412#endif
413  //out_cf("factorize:",f,"==================================\n");
414  if (! f.isUnivariate() ) // preprocess homog. polys
415  {
416    if ( singular_homog_flag && f.isHomogeneous())
417    {
418      Variable xn = get_max_degree_Variable(f);
419      int d_xn = degree(f,xn);
420      CFMap n;
421      CanonicalForm F = compress(f(1,xn),n);
422      CFFList Intermediatelist;
423      Intermediatelist = factorize(F);
424      CFFList Homoglist;
425      CFFListIterator j;
426      for ( j=Intermediatelist; j.hasItem(); j++ )
427      {
428        Homoglist.append(
429            CFFactor( n(j.getItem().factor()), j.getItem().exp()) );
430      }
431      CFFList Unhomoglist;
432      CanonicalForm unhomogelem;
433      for ( j=Homoglist; j.hasItem(); j++ )
434      {
435        unhomogelem= homogenize(j.getItem().factor(),xn);
436        Unhomoglist.append(CFFactor(unhomogelem,j.getItem().exp()));
437        d_xn -= (degree(unhomogelem,xn)*j.getItem().exp());
438      }
439      if ( d_xn != 0 ) // have to append xn^(d_xn)
440        Unhomoglist.append(CFFactor(CanonicalForm(xn),d_xn));
441      if(isOn(SW_USE_NTL_SORT)) Unhomoglist.sort(cmpCF);
442      return Unhomoglist;
443    }
444  }
445  CFFList F;
446  if ( getCharacteristic() > 0 )
447  {
448    if (f.isUnivariate())
449    {
450#ifdef HAVE_FLINT
451#ifdef HAVE_NTL
452      if (degree (f) < 300)
453#endif
454      {
455        // use FLINT: char p, univariate
456        nmod_poly_t f1;
457        convertFacCF2nmod_poly_t (f1, f);
458        nmod_poly_factor_t result;
459        nmod_poly_factor_init (result);
460        mp_limb_t leadingCoeff= nmod_poly_factor (result, f1);
461        F= convertFLINTnmod_poly_factor2FacCFFList (result, leadingCoeff, f.mvar());
462        nmod_poly_factor_clear (result);
463        nmod_poly_clear (f1);
464        if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
465        return F;
466      }
467#endif
468#ifdef HAVE_NTL
469      { // NTL char 2, univariate
470        if (getCharacteristic()==2)
471        {
472          // Specialcase characteristic==2
473          if (fac_NTL_char != 2)
474          {
475            fac_NTL_char = 2;
476            zz_p::init(2);
477          }
478          // convert to NTL using the faster conversion routine for characteristic 2
479          GF2X f1=convertFacCF2NTLGF2X(f);
480          // no make monic necessary in GF2
481          //factorize
482          vec_pair_GF2X_long factors;
483          CanZass(factors,f1);
484
485          // convert back to factory again using the faster conversion routine for vectors over GF2X
486          F=convertNTLvec_pair_GF2X_long2FacCFFList(factors,LeadCoeff(f1),f.mvar());
487          if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
488          return F;
489        }
490      }
491#endif
492#ifdef HAVE_NTL
493      {
494        // use NTL char p, univariate
495        if (fac_NTL_char != getCharacteristic())
496        {
497          fac_NTL_char = getCharacteristic();
498          zz_p::init(getCharacteristic());
499        }
500
501        // convert to NTL
502        zz_pX f1=convertFacCF2NTLzzpX(f);
503        zz_p leadcoeff = LeadCoeff(f1);
504
505        //make monic
506        f1=f1 / LeadCoeff(f1);
507        // factorize
508        vec_pair_zz_pX_long factors;
509        CanZass(factors,f1);
510
511        F=convertNTLvec_pair_zzpX_long2FacCFFList(factors,leadcoeff,f.mvar());
512        //test_cff(F,f);
513        if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
514        return F;
515      }
516#endif
517#if !defined(HAVE_NTL) && !defined(HAVE_FLINT)
518      // Use Factory without NTL and without FLINT: char p, univariate
519      {
520        if ( isOn( SW_BERLEKAMP ) )
521          F=FpFactorizeUnivariateB( f, issqrfree );
522        else
523          F=FpFactorizeUnivariateCZ( f, issqrfree, 0, Variable(), Variable() );
524        return F;
525      }
526#endif
527    }
528    else // char p, multivariate
529    {
530      if (CFFactory::gettype() == GaloisFieldDomain)
531      {
532        #if defined(HAVE_NTL)
533        if (issqrfree)
534        {
535          CFList factors;
536          Variable alpha;
537          factors= GFSqrfFactorize (f);
538          for (CFListIterator i= factors; i.hasItem(); i++)
539            F.append (CFFactor (i.getItem(), 1));
540        }
541        else
542        {
543          Variable alpha;
544          F= GFFactorize (f);
545        }
546        #else
547        factoryError ("multivariate factorization depends on NTL(missing)");
548        return CFFList (CFFactor (f, 1));
549        #endif
550      }
551      else
552      {
553        #if defined(HAVE_NTL)
554        if (issqrfree)
555        {
556          CFList factors;
557          Variable alpha;
558          factors= FpSqrfFactorize (f);
559          for (CFListIterator i= factors; i.hasItem(); i++)
560            F.append (CFFactor (i.getItem(), 1));
561        }
562        else
563        {
564          Variable alpha;
565          F= FpFactorize (f);
566        }
567        #elif defined(HAVE_FLINT) && (__FLINT_RELEASE >= 20700)
568        nmod_mpoly_ctx_t ctx;
569        nmod_mpoly_ctx_init(ctx,f.level(),ORD_LEX,getCharacteristic());
570        nmod_mpoly_t Flint_f;
571        nmod_mpoly_init(Flint_f,ctx);
572        convFactoryPFlintMP(f,Flint_f,ctx,f.level());
573        nmod_mpoly_factor_t factors;
574        nmod_mpoly_factor_init(factors,ctx);
575        if (issqrfree) nmod_mpoly_factor_squarefree(factors,Flint_f,ctx);
576        else           nmod_mpoly_factor(factors,Flint_f,ctx);
577        nmod_mpoly_t fac;
578        nmod_mpoly_init(fac,ctx);
579        CanonicalForm cf_fac;
580        int cf_exp;
581        cf_fac=nmod_mpoly_factor_get_constant_ui(factors,ctx);
582        F.append(CFFactor(cf_fac,1));
583        for(int i=nmod_mpoly_factor_length(factors,ctx)-1; i>=0; i--)
584        {
585          nmod_mpoly_factor_get_base(fac,factors,i,ctx);
586          cf_fac=convFlintMPFactoryP(fac,ctx,f.level());
587          cf_exp=nmod_mpoly_factor_get_exp_si(factors,i,ctx);
588          F.append(CFFactor(cf_fac,cf_exp));
589        }
590        nmod_mpoly_factor_clear(factors,ctx);
591        nmod_mpoly_clear(Flint_f,ctx);
592        nmod_mpoly_ctx_clear(ctx);
593        #else
594        factoryError ("multivariate factorization depends on NTL(missing)");
595        return CFFList (CFFactor (f, 1));
596        #endif
597      }
598    }
599  }
600  else // char 0
601  {
602    bool on_rational = isOn(SW_RATIONAL);
603    On(SW_RATIONAL);
604    CanonicalForm cd = bCommonDen( f );
605    CanonicalForm fz = f * cd;
606    Off(SW_RATIONAL);
607    if ( f.isUnivariate() )
608    {
609      CanonicalForm ic=icontent(fz);
610      fz/=ic;
611      if (fz.degree()==1)
612      {
613        F=CFFList(CFFactor(fz,1));
614        F.insert(CFFactor(ic,1));
615      }
616      else
617      #if defined(HAVE_FLINT) && (__FLINT_RELEASE>=20503)  && (__FLINT_RELEASE!= 20600)
618      {
619        // FLINT 2.6.0 has a bug:
620        // factorize x^12-13*x^10-13*x^8+13*x^4+13*x^2-1 runs forever
621        // use FLINT: char 0, univariate
622        fmpz_poly_t f1;
623        convertFacCF2Fmpz_poly_t (f1, fz);
624        fmpz_poly_factor_t result;
625        fmpz_poly_factor_init (result);
626        fmpz_poly_factor(result, f1);
627        F= convertFLINTfmpz_poly_factor2FacCFFList (result, fz.mvar());
628        fmpz_poly_factor_clear (result);
629        fmpz_poly_clear (f1);
630        if ( ! ic.isOne() )
631        {
632           // according to convertFLINTfmpz_polyfactor2FcaCFFlist,
633           //  first entry is in CoeffDomain
634          CFFactor new_first( F.getFirst().factor() * ic );
635          F.removeFirst();
636          F.insert( new_first );
637        }
638      }
639      goto end_char0;
640      #elif defined(HAVE_NTL)
641      {
642        //use NTL
643        ZZ c;
644        vec_pair_ZZX_long factors;
645        //factorize the converted polynomial
646        factor(c,factors,convertFacCF2NTLZZX(fz));
647
648        //convert the result back to Factory
649        F=convertNTLvec_pair_ZZX_long2FacCFFList(factors,c,fz.mvar());
650        if ( ! ic.isOne() )
651        {
652           // according to convertNTLvec_pair_ZZX_long2FacCFFList
653           //  first entry is in CoeffDomain
654          CFFactor new_first( F.getFirst().factor() * ic );
655          F.removeFirst();
656          F.insert( new_first );
657        }
658      }
659      goto end_char0;
660      #else
661      {
662        //Use Factory without NTL: char 0, univariate
663        F = ZFactorizeUnivariate( fz, issqrfree );
664        goto end_char0;
665      }
666      #endif
667    }
668    else // multivariate,  char 0
669    {
670      #if defined(HAVE_FLINT) && (__FLINT_RELEASE >= 20700)
671      On (SW_RATIONAL);
672      fmpz_mpoly_ctx_t ctx;
673      fmpz_mpoly_ctx_init(ctx,f.level(),ORD_LEX);
674      fmpz_mpoly_t Flint_f;
675      fmpz_mpoly_init(Flint_f,ctx);
676      convFactoryPFlintMP(fz,Flint_f,ctx,fz.level());
677      fmpz_mpoly_factor_t factors;
678      fmpz_mpoly_factor_init(factors,ctx);
679      int rr;
680      if (issqrfree) rr=fmpz_mpoly_factor_squarefree(factors,Flint_f,ctx);
681      else           rr=fmpz_mpoly_factor(factors,Flint_f,ctx);
682      if (rr==0) printf("fail\n");
683      fmpz_mpoly_t fac;
684      fmpz_mpoly_init(fac,ctx);
685      CanonicalForm cf_fac;
686      int cf_exp;
687      fmpz_t c;
688      fmpz_init(c);
689      fmpz_mpoly_factor_get_constant_fmpz(c,factors,ctx);
690      cf_fac=convertFmpz2CF(c);
691      fmpz_clear(c);
692      F.append(CFFactor(cf_fac,1));
693      for(int i=fmpz_mpoly_factor_length(factors,ctx)-1; i>=0; i--)
694      {
695         fmpz_mpoly_factor_get_base(fac,factors,i,ctx);
696         cf_fac=convFlintMPFactoryP(fac,ctx,f.level());
697         cf_exp=fmpz_mpoly_factor_get_exp_si(factors,i,ctx);
698         F.append(CFFactor(cf_fac,cf_exp));
699      }
700      fmpz_mpoly_factor_clear(factors,ctx);
701      fmpz_mpoly_clear(Flint_f,ctx);
702      fmpz_mpoly_ctx_clear(ctx);
703      #elif defined(HAVE_NTL)
704      On (SW_RATIONAL);
705      if (issqrfree)
706      {
707        CFList factors= ratSqrfFactorize (fz);
708        for (CFListIterator i= factors; i.hasItem(); i++)
709          F.append (CFFactor (i.getItem(), 1));
710      }
711      else
712      {
713        F = ratFactorize (fz);
714      }
715      #else
716      F=ZFactorizeMultivariate(fz, issqrfree);
717      #endif
718    }
719
720end_char0:
721    if ( on_rational )
722      On(SW_RATIONAL);
723    else
724      Off(SW_RATIONAL);
725    if ( ! cd.isOne() )
726    {
727      CFFactor new_first( F.getFirst().factor() / cd );
728      F.removeFirst();
729      F.insert( new_first );
730    }
731  }
732
733  if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
734  return F;
735}
736
737/**
738 * factorization over \f$ F_p(\alpha) \f$ or \f$ Q(\alpha) \f$
739**/
740CFFList factorize ( const CanonicalForm & f, const Variable & alpha )
741{
742  if ( f.inCoeffDomain() )
743    return CFFList( f );
744  //out_cf("factorize:",f,"==================================\n");
745  //out_cf("mipo:",getMipo(alpha),"\n");
746
747  CFFList F;
748  ASSERT( alpha.level() < 0 && getReduce (alpha), "not an algebraic extension" );
749#ifndef NOASSERT
750  Variable beta;
751  if (hasFirstAlgVar(f, beta))
752    ASSERT (beta == alpha, "f has an algebraic variable that \
753                            does not coincide with alpha");
754#endif
755  int ch=getCharacteristic();
756  if (ch>0)
757  {
758    if (f.isUnivariate())
759    {
760#ifdef HAVE_NTL
761      if (/*getCharacteristic()*/ch==2)
762      {
763        // special case : GF2
764
765        // remainder is two ==> nothing to do
766
767        // set minimal polynomial in NTL using the optimized conversion routines for characteristic 2
768        GF2X minPo=convertFacCF2NTLGF2X(getMipo(alpha,f.mvar()));
769        GF2E::init (minPo);
770
771        // convert to NTL again using the faster conversion routines
772        GF2EX f1;
773        if (isPurePoly(f))
774        {
775          GF2X f_tmp=convertFacCF2NTLGF2X(f);
776          f1=to_GF2EX(f_tmp);
777        }
778        else
779          f1=convertFacCF2NTLGF2EX(f,minPo);
780
781        // make monic (in Z/2(a))
782        GF2E f1_coef=LeadCoeff(f1);
783        MakeMonic(f1);
784
785        // factorize using NTL
786        vec_pair_GF2EX_long factors;
787        CanZass(factors,f1);
788
789        // return converted result
790        F=convertNTLvec_pair_GF2EX_long2FacCFFList(factors,f1_coef,f.mvar(),alpha);
791        if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
792        return F;
793      }
794#endif
795#if (HAVE_FLINT && __FLINT_RELEASE >= 20400)
796      {
797        // use FLINT
798        nmod_poly_t FLINTmipo, leadingCoeff;
799        fq_nmod_ctx_t fq_con;
800
801        nmod_poly_init (FLINTmipo, ch);
802        nmod_poly_init (leadingCoeff, ch);
803        convertFacCF2nmod_poly_t (FLINTmipo, getMipo (alpha));
804
805        fq_nmod_ctx_init_modulus (fq_con, FLINTmipo, "Z");
806        fq_nmod_poly_t FLINTF;
807        convertFacCF2Fq_nmod_poly_t (FLINTF, f, fq_con);
808        fq_nmod_poly_factor_t res;
809        fq_nmod_poly_factor_init (res, fq_con);
810        fq_nmod_poly_factor (res, leadingCoeff, FLINTF, fq_con);
811        F= convertFLINTFq_nmod_poly_factor2FacCFFList (res, f.mvar(), alpha, fq_con);
812        F.insert (CFFactor (Lc (f), 1));
813
814        fq_nmod_poly_factor_clear (res, fq_con);
815        fq_nmod_poly_clear (FLINTF, fq_con);
816        nmod_poly_clear (FLINTmipo);
817        nmod_poly_clear (leadingCoeff);
818        fq_nmod_ctx_clear (fq_con);
819        if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
820        return F;
821      }
822#endif
823#ifdef HAVE_NTL
824      {
825        // use NTL
826        if (fac_NTL_char != ch)
827        {
828          fac_NTL_char = ch;
829          zz_p::init(ch);
830        }
831
832        // set minimal polynomial in NTL
833        zz_pX minPo=convertFacCF2NTLzzpX(getMipo(alpha));
834        zz_pE::init (minPo);
835
836        // convert to NTL
837        zz_pEX f1=convertFacCF2NTLzz_pEX(f,minPo);
838        zz_pE leadcoeff= LeadCoeff(f1);
839
840        //make monic
841        f1=f1 / leadcoeff; //leadcoeff==LeadCoeff(f1);
842
843        // factorize
844        vec_pair_zz_pEX_long factors;
845        CanZass(factors,f1);
846
847        // return converted result
848        F=convertNTLvec_pair_zzpEX_long2FacCFFList(factors,leadcoeff,f.mvar(),alpha);
849        //test_cff(F,f);
850        if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
851        return F;
852      }
853#endif
854#if !defined(HAVE_NTL) && !defined(HAVE_FLINT)
855      // char p, extension, univariate
856      CanonicalForm c=Lc(f);
857      CanonicalForm fc=f/c;
858      F=FpFactorizeUnivariateCZ( fc, false, 1, alpha, Variable() );
859      F.insert (CFFactor (c, 1));
860#endif
861    }
862    else // char p, multivariate
863    {
864      #ifdef HAVE_NTL
865      F= FqFactorize (f, alpha);
866      #else
867      factoryError ("univariate factorization  depends on NTL(missing)");
868      return CFFList (CFFactor (f, 1));
869      #endif
870    }
871  }
872  else // Q(a)[x]
873  {
874    if (f.isUnivariate())
875    {
876      F= AlgExtFactorize (f, alpha);
877    }
878    else //Q(a)[x1,...,xn]
879    {
880      #ifdef HAVE_NTL
881      F= ratFactorize (f, alpha);
882      #else
883      factoryError ("multivariate factorization  depends on NTL(missing)");
884      return CFFList (CFFactor (f, 1));
885      #endif
886    }
887  }
888  if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF);
889  return F;
890}
891
892/**
893 * squarefree factorization
894**/
895CFFList sqrFree ( const CanonicalForm & f, bool sort )
896{
897//    ASSERT( f.isUnivariate(), "multivariate factorization not implemented" );
898    CFFList result;
899
900    if ( getCharacteristic() == 0 )
901        result = sqrFreeZ( f );
902    else
903    {
904        Variable alpha;
905        if (hasFirstAlgVar (f, alpha))
906          result = FqSqrf( f, alpha );
907        else
908          result= FpSqrf (f);
909    }
910    if (sort)
911    {
912      CFFactor buf= result.getFirst();
913      result.removeFirst();
914      result= sortCFFList (result);
915      result.insert (buf);
916    }
917    return result;
918}
919
Note: See TracBrowser for help on using the repository browser.