source: git/factory/cf_factor.cc @ faa6c6

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