source: git/factory/cf_factor.cc @ a1ab2a

spielwiese
Last change on this file since a1ab2a was a1ab2a, checked in by Hans Schönemann <hannes@…>, 17 years ago
*hannes: SAGE/libsingular git-svn-id: file:///usr/local/Singular/svn/trunk@10284 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 15.7 KB
Line 
1/* emacs edit mode for this file is -*- C++ -*- */
2/* $Id: cf_factor.cc,v 1.33 2007-08-03 11:32:04 Singular Exp $ */
3
4//{{{ docu
5//
6// cf_factor.cc - factorization and square free algorithms.
7//
8// Used by: fac_multivar.cc, fac_univar.cc, cf_irred.cc
9//
10// Header file: cf_algorithm.h
11//
12//}}}
13
14#include <config.h>
15
16#include "cf_gmp.h"
17
18#include "assert.h"
19
20#include "cf_defs.h"
21#include "canonicalform.h"
22#include "cf_iter.h"
23#include "fac_berlekamp.h"
24#include "fac_cantzass.h"
25#include "fac_univar.h"
26#include "fac_multivar.h"
27#include "fac_sqrfree.h"
28#include "cf_algorithm.h"
29#include "cf_map.h"
30
31#include "int_int.h"
32#ifdef HAVE_NTL
33#include "NTLconvert.h"
34#endif
35
36int getExp(); /* cf_char.cc */
37
38static bool isUnivariateBaseDomain( const CanonicalForm & f )
39{
40    CFIterator i = f;
41    bool ok = i.coeff().inBaseDomain();
42    i++;
43    while ( i.hasTerms() && ( ok = ok && i.coeff().inBaseDomain() ) ) i++;
44    return ok;
45}
46
47void find_exp(const CanonicalForm & f, int * exp_f)
48{
49  if ( ! f.inCoeffDomain() )
50  {
51    int e=f.level();
52    CFIterator i = f;
53    if (e>=0)
54    {
55      if (i.exp() > exp_f[e]) exp_f[e]=i.exp();
56    }
57    for (; i.hasTerms(); i++ )
58    {
59      find_exp(i.coeff(), exp_f);
60    }
61  }
62}
63
64int find_mvar(const CanonicalForm & f)
65{
66  int mv=f.level();
67  int *exp_f=new int[mv+1];
68  int i;
69  for(i=mv;i>0;i--) exp_f[i]=0;
70  find_exp(f,exp_f);
71  for(i=mv;i>0;i--)
72  {
73    if ((exp_f[i]>0) && (exp_f[i]<exp_f[mv]))
74    {
75      mv=i;
76    }
77  }
78  delete[] exp_f;
79  return mv;
80}
81
82#if 1
83#ifndef NOSTREAMIO
84void out_cf(char *s1,const CanonicalForm &f,char *s2)
85{
86  printf("%s",s1);
87  if (f==0) printf("+0");
88  //else if (! f.inCoeffDomain() )
89  else if (! f.inBaseDomain() )
90  {
91    int l = f.level();
92    for ( CFIterator i = f; i.hasTerms(); i++ )
93    {
94      int e=i.exp();
95      if (i.coeff().isOne())
96      {
97        printf("+");
98        if (e==0) printf("1");
99        else
100        {
101          printf("v(%d)",l);
102          if (e!=1) printf("^%d",e);
103        }
104      }
105      else
106      {
107        out_cf("+(",i.coeff(),")");
108        if (e!=0)
109        {
110          printf("*v(%d)",l);
111          if (e!=1) printf("^%d",e);
112        }
113      }
114    }
115  }
116  else
117  {
118    if ( f.isImm() )
119    {
120      printf("+%d",f.intval());
121    }
122    else //printf("+...");
123       std::cout << f;
124    //if (f.inZ()) printf("(Z)");
125    //else if (f.inQ()) printf("(Q)");
126    //else if (f.inFF()) printf("(FF)");
127    //else if (f.inPP()) printf("(PP)");
128    //else if (f.inGF()) printf("(PP)");
129    //else
130    if (f.inExtension()) printf("E(%d)",f.level());
131  }
132  printf("%s",s2);
133}
134void out_cff(CFFList &L)
135{
136  int n = L.length();
137  CFFListIterator J=L;
138  int j=0;
139  for ( ; J.hasItem(); J++, j++ )
140  {
141    printf("F%d",j);out_cf(":",J.getItem().factor()," ^ ");
142    printf("%d\n", J.getItem().exp());
143  }
144}
145void test_cff(CFFList &L,const CanonicalForm & f)
146{
147  int n = L.length();
148  CFFListIterator J=L;
149  CanonicalForm t=1;
150  int j=0;
151  if (!(L.getFirst().factor().inCoeffDomain()))
152    printf("first entry is not const\n");
153  for ( ; J.hasItem(); J++, j++ )
154  {
155    CanonicalForm tt=J.getItem().factor();
156    if (tt.inCoeffDomain() && (j!=0))
157      printf("other entry is const\n");
158    j=J.getItem().exp();
159    while(j>0) { t*=tt; j--; }
160  }
161  if ((f-t)!=0) { printf("problem:\n");out_cf("factor:",f," has problems\n");}
162}
163#endif
164#endif
165
166bool isPurePoly(const CanonicalForm & f)
167{
168  if (f.level()<=0) return false;
169  for (CFIterator i=f;i.hasTerms();i++)
170  {
171    if (!(i.coeff().inBaseDomain())) return false;
172  }
173  return true;
174}
175
176///////////////////////////////////////////////////////////////
177// get_max_degree_Variable returns Variable with             //
178// highest degree. We assume f is *not* a constant!          //
179///////////////////////////////////////////////////////////////
180Variable
181get_max_degree_Variable(const CanonicalForm & f)
182{
183  ASSERT( ( ! f.inCoeffDomain() ), "no constants" );
184  int max=0, maxlevel=0, n=level(f);
185  for ( int i=1; i<=n; i++ )
186  {
187    if (degree(f,Variable(i)) >= max)
188    {
189      max= degree(f,Variable(i)); maxlevel= i;
190    }
191  }
192  return Variable(maxlevel);
193}
194
195///////////////////////////////////////////////////////////////
196// get_Terms: Split the polynomial in the containing terms.  //
197// getTerms: the real work is done here.                     //
198///////////////////////////////////////////////////////////////
199void
200getTerms( const CanonicalForm & f, const CanonicalForm & t, CFList & result )
201{
202  if ( getNumVars(f) == 0 ) result.append(f*t);
203  else{
204    Variable x(level(f));
205    for ( CFIterator i=f; i.hasTerms(); i++ )
206      getTerms( i.coeff(), t*power(x,i.exp()), result);
207  }
208}
209CFList
210get_Terms( const CanonicalForm & f ){
211  CFList result,dummy,dummy2;
212  CFIterator i;
213  CFListIterator j;
214
215  if ( getNumVars(f) == 0 ) result.append(f);
216  else{
217    Variable _x(level(f));
218    for ( i=f; i.hasTerms(); i++ ){
219      getTerms(i.coeff(), 1, dummy);
220      for ( j=dummy; j.hasItem(); j++ )
221        result.append(j.getItem() * power(_x, i.exp()));
222
223      dummy= dummy2; // have to initalize new
224    }
225  }
226  return result;
227}
228
229
230///////////////////////////////////////////////////////////////
231// homogenize homogenizes f with Variable x                  //
232///////////////////////////////////////////////////////////////
233
234CanonicalForm
235homogenize( const CanonicalForm & f, const Variable & x)
236{
237#if 0
238  int maxdeg=totaldegree(f), deg;
239  CFIterator i;
240  CanonicalForm elem, result(0);
241 
242  for (i=f; i.hasTerms(); i++)
243  {
244    elem= i.coeff()*power(f.mvar(),i.exp());
245    deg = totaldegree(elem);
246    if ( deg < maxdeg )
247      result += elem * power(x,maxdeg-deg);
248    else
249      result+=elem;
250  }
251  return result;
252#else
253  CFList Newlist, Termlist= get_Terms(f);
254  int maxdeg=totaldegree(f), deg;
255  CFListIterator i;
256  CanonicalForm elem, result(0);
257
258  for (i=Termlist; i.hasItem(); i++){
259    elem= i.getItem();
260    deg = totaldegree(elem);
261    if ( deg < maxdeg )
262      Newlist.append(elem * power(x,maxdeg-deg));
263    else
264      Newlist.append(elem);
265  }
266  for (i=Newlist; i.hasItem(); i++) // rebuild
267    result += i.getItem();
268
269  return result;
270#endif
271}
272
273#ifdef SINGULAR
274extern int singular_homog_flag;
275#else
276#define singular_homog_flag 1
277#endif
278int cmpCF( const CFFactor & f, const CFFactor & g )
279{
280  if (f.exp() > g.exp()) return 1;
281  if (f.exp() < g.exp()) return 0;
282  if (f.factor() > g.factor()) return 1;
283  return 0;
284}
285
286CFFList factorize ( const CanonicalForm & f, bool issqrfree )
287{
288  if ( f.inCoeffDomain() )
289        return CFFList( f );
290  int mv=f.level();
291  int org_v=mv;
292  //out_cf("factorize:",f,"==================================\n");
293  if (! f.isUnivariate() )
294  {
295    if ( singular_homog_flag && f.isHomogeneous())
296    {
297      Variable xn = get_max_degree_Variable(f);
298      int d_xn = degree(f,xn);
299      CFMap n;
300      CanonicalForm F = compress(f(1,xn),n);
301      CFFList Intermediatelist;
302      Intermediatelist = factorize(F);
303      CFFList Homoglist;
304      CFFListIterator j;
305      for ( j=Intermediatelist; j.hasItem(); j++ )
306      {
307        Homoglist.append(
308            CFFactor( n(j.getItem().factor()), j.getItem().exp()) );
309      }
310      CFFList Unhomoglist;
311      CanonicalForm unhomogelem;
312      for ( j=Homoglist; j.hasItem(); j++ )
313      {
314        unhomogelem= homogenize(j.getItem().factor(),xn);
315        Unhomoglist.append(CFFactor(unhomogelem,j.getItem().exp()));
316        d_xn -= (degree(unhomogelem,xn)*j.getItem().exp());
317      }
318      if ( d_xn != 0 ) // have to append xn^(d_xn)
319        Unhomoglist.append(CFFactor(CanonicalForm(xn),d_xn)); 
320      if(isOn(SW_USE_NTL_SORT)) Unhomoglist.sort(cmpCF); 
321      return Unhomoglist;
322    }
323    mv=find_mvar(f);
324    if ( getCharacteristic() == 0 )
325    {
326      if (mv!=f.level())
327      {
328        swapvar(f,Variable(mv),f.mvar());
329      }
330    }
331    else
332    {
333      if (mv!=1)
334      {
335        swapvar(f,Variable(mv),Variable(1));
336        org_v=1;
337      }
338    }
339  }
340  CFFList F;
341  if ( getCharacteristic() > 0 )
342  {
343    ASSERT( f.isUnivariate(), "multivariate factorization not implemented" );
344    #ifdef HAVE_NTL
345    if (isOn(SW_USE_NTL) && (isPurePoly(f)))
346    {
347      // USE NTL
348      if (getCharacteristic()!=2)
349      {
350        // set remainder
351        if (fac_NTL_char!=getCharacteristic())
352        {
353          fac_NTL_char=getCharacteristic();
354          #ifdef NTL_ZZ
355          ZZ r;
356          r=getCharacteristic();
357          ZZ_pContext ccc(r);
358          #else
359          zz_pContext ccc(getCharacteristic());
360          #endif
361          ccc.restore();
362          #ifdef NTL_ZZ
363          ZZ_p::init(r);
364          #else
365          zz_p::init(getCharacteristic());
366          #endif
367        }
368        // convert to NTL
369        #ifdef NTL_ZZ
370        ZZ_pX f1=convertFacCF2NTLZZpX(f);
371        ZZ_p leadcoeff = LeadCoeff(f1);
372        #else
373        zz_pX f1=convertFacCF2NTLzzpX(f);
374        zz_p leadcoeff = LeadCoeff(f1);
375        #endif
376        //make monic
377        f1=f1 / LeadCoeff(f1);
378
379        // factorize
380        #ifdef NTL_ZZ
381        vec_pair_ZZ_pX_long factors;
382        #else
383        vec_pair_zz_pX_long factors;
384        #endif
385        CanZass(factors,f1);
386
387        // convert back to factory
388        #ifdef NTL_ZZ
389        F=convertNTLvec_pair_ZZpX_long2FacCFFList(factors,leadcoeff,f.mvar());
390        #else
391        F=convertNTLvec_pair_zzpX_long2FacCFFList(factors,leadcoeff,f.mvar());
392        #endif
393        //test_cff(F,f);
394      }
395      else
396      {
397        // Specialcase characteristic==2
398        if (fac_NTL_char!=2)
399        {
400          fac_NTL_char=2;
401          zz_p::init(2);
402        }
403        // convert to NTL using the faster conversion routine for characteristic 2
404        GF2X f1=convertFacCF2NTLGF2X(f);
405        // no make monic necessary in GF2
406        //factorize
407        vec_pair_GF2X_long factors;
408        CanZass(factors,f1);
409
410        // convert back to factory again using the faster conversion routine for vectors over GF2X
411        F=convertNTLvec_pair_GF2X_long2FacCFFList(factors,LeadCoeff(f1),f.mvar());
412      }
413    }
414    else
415    #endif
416    {  // Use Factory without NTL
417      if ( isOn( SW_BERLEKAMP ) )
418         F=FpFactorizeUnivariateB( f, issqrfree );
419      else
420        F=FpFactorizeUnivariateCZ( f, issqrfree, 0, Variable(), Variable() );
421    }
422  }
423  else
424  {
425    bool on_rational = isOn(SW_RATIONAL);
426    On(SW_RATIONAL);
427    CanonicalForm cd = bCommonDen( f );
428    CanonicalForm fz = f * cd;
429    Off(SW_RATIONAL);
430    if ( f.isUnivariate() )
431    {
432      #ifdef HAVE_NTL
433      if ((isOn(SW_USE_NTL)) && (isPurePoly(f)))
434      {
435        //USE NTL
436        CanonicalForm ic=icontent(fz);
437        fz/=ic;
438        ZZ c;
439        vec_pair_ZZX_long factors;
440        //factorize the converted polynomial
441        factor(c,factors,convertFacCF2NTLZZX(fz));
442
443        //convert the result back to Factory
444        F=convertNTLvec_pair_ZZX_long2FacCFFList(factors,c,fz.mvar());
445        if ( ! ic.isOne() )
446        {
447          if ( F.getFirst().factor().inCoeffDomain() )
448          {
449            CFFactor new_first( F.getFirst().factor() * ic );
450            F.removeFirst();
451            F.insert( new_first );
452          }
453          else
454            F.insert( CFFactor( ic ) );
455        }
456        else
457        {
458          if ( !F.getFirst().factor().inCoeffDomain() )
459          {
460            CFFactor new_first( 1 );
461            F.insert( new_first );
462          }
463        }
464        //if ( F.getFirst().factor().isOne() )
465        //{
466        //  F.removeFirst();
467        //}
468        //printf("NTL:\n");out_cff(F);
469        //F=ZFactorizeUnivariate( fz, issqrfree );
470        //printf("fac.:\n");out_cff(F);
471      }
472      else
473      #endif
474      {
475        //Use Factory without NTL
476        F = ZFactorizeUnivariate( fz, issqrfree );
477      }
478    }
479    else
480    {
481      F = ZFactorizeMultivariate( fz, issqrfree );
482    }
483
484    if ( on_rational )
485      On(SW_RATIONAL);
486    if ( ! cd.isOne() )
487    {
488      if ( F.getFirst().factor().inCoeffDomain() )
489      {
490        CFFactor new_first( F.getFirst().factor() / cd );
491        F.removeFirst();
492        F.insert( new_first );
493      }
494      else
495      {
496        F.insert( CFFactor( 1/cd ) );
497      }
498    }
499  }
500
501  if ((mv!=org_v) && (! f.isUnivariate() ))
502  {
503    CFFListIterator J=F;
504    for ( ; J.hasItem(); J++)
505    {
506      swapvar(J.getItem().factor(),Variable(mv),Variable(org_v));
507    }
508    swapvar(f,Variable(mv),Variable(org_v));
509  }
510  //out_cff(F);
511  if(isOn(SW_USE_NTL_SORT)) F.sort(cmpCF); 
512  return F;
513}
514
515#ifdef HAVE_NTL
516CanonicalForm fntl ( const CanonicalForm & f, int j )
517{
518  ZZX f1=convertFacCF2NTLZZX(f);
519  return convertZZ2CF(coeff(f1,j));
520}
521#endif
522
523CFFList factorize ( const CanonicalForm & f, const Variable & alpha )
524{
525  //out_cf("factorize:",f,"==================================\n");
526  //out_cf("mipo:",getMipo(alpha),"\n");
527  CFFList F;
528  ASSERT( alpha.level() < 0, "not an algebraic extension" );
529  ASSERT( f.isUnivariate(), "multivariate factorization not implemented" );
530  ASSERT( getCharacteristic() > 0, "char 0 factorization not implemented" );
531  #ifdef HAVE_NTL
532  if  (isOn(SW_USE_NTL))
533  {
534    //USE NTL
535    if (getCharacteristic()!=2)
536    {
537      // First all cases with characteristic !=2
538      // set remainder
539      if (fac_NTL_char!=getCharacteristic())
540      {
541        fac_NTL_char=getCharacteristic();
542        #ifdef NTL_ZZ
543        ZZ r;
544        r=getCharacteristic();
545        ZZ_pContext ccc(r);
546        #else
547        zz_pContext ccc(getCharacteristic());
548        #endif
549        ccc.restore();
550        #ifdef NTL_ZZ
551        ZZ_p::init(r);
552        #else
553        zz_p::init(getCharacteristic());
554        #endif
555      }
556
557      // set minimal polynomial in NTL
558      #ifdef NTL_ZZ
559      ZZ_pX minPo=convertFacCF2NTLZZpX(getMipo(alpha));
560      ZZ_pEContext c(minPo);
561      #else
562      zz_pX minPo=convertFacCF2NTLzzpX(getMipo(alpha));
563      zz_pEContext c(minPo);
564      #endif
565
566      c.restore();
567
568      // convert to NTL
569      #ifdef NTL_ZZ
570      ZZ_pEX f1=convertFacCF2NTLZZ_pEX(f,minPo);
571      ZZ_pE leadcoeff= LeadCoeff(f1);
572      #else
573      zz_pEX f1=convertFacCF2NTLzz_pEX(f,minPo);
574      zz_pE leadcoeff= LeadCoeff(f1);
575      #endif
576
577      //make monic
578      f1=f1 / leadcoeff;
579
580      // factorize using NTL
581      #ifdef NTL_ZZ
582      vec_pair_ZZ_pEX_long factors;
583      #else
584      vec_pair_zz_pEX_long factors;
585      #endif
586      CanZass(factors,f1);
587
588      // return converted result
589      F=convertNTLvec_pair_zzpEX_long2FacCFFList(factors,leadcoeff,f.mvar(),alpha);
590    }
591    else
592    {
593      // special case : GF2
594
595      // remainder is two ==> nothing to do
596      // set remainder
597      ZZ r;
598      r=getCharacteristic();
599      ZZ_pContext ccc(r);
600      ccc.restore();
601
602      // set minimal polynomial in NTL using the optimized conversion routines for characteristic 2
603      GF2X minPo=convertFacCF2NTLGF2X(getMipo(alpha,f.mvar()));
604      GF2EContext c(minPo);
605      c.restore();
606
607      // convert to NTL again using the faster conversion routines
608      GF2EX f1;
609      if (isPurePoly(f))
610      {
611        GF2X f_tmp=convertFacCF2NTLGF2X(f);
612        f1=to_GF2EX(f_tmp);
613      }
614      else
615      {
616        f1=convertFacCF2NTLGF2EX(f,minPo);
617      }
618
619      // make monic (in Z/2(a))
620      GF2E f1_coef=LeadCoeff(f1);
621      MakeMonic(f1);
622
623      // factorize using NTL
624      vec_pair_GF2EX_long factors;
625      CanZass(factors,f1);
626
627      // return converted result
628      F=convertNTLvec_pair_GF2EX_long2FacCFFList(factors,f1_coef,f.mvar(),alpha);
629    }
630
631  }
632  else
633  #endif
634  {
635    F=FpFactorizeUnivariateCZ( f, false, 1, alpha, Variable() );
636  }
637  return F;
638}
639
640CFFList sqrFree ( const CanonicalForm & f, bool sort )
641{
642//    ASSERT( f.isUnivariate(), "multivariate factorization not implemented" );
643    CFFList result;
644
645    if ( getCharacteristic() == 0 )
646        result = sqrFreeZ( f );
647    else
648        result = sqrFreeFp( f );
649
650    return ( sort ? sortCFFList( result ) : result );
651}
652
653bool isSqrFree ( const CanonicalForm & f )
654{
655//    ASSERT( f.isUnivariate(), "multivariate factorization not implemented" );
656    if ( getCharacteristic() == 0 )
657        return isSqrFreeZ( f );
658    else
659        return isSqrFreeFp( f );
660}
661
Note: See TracBrowser for help on using the repository browser.