source: git/factory/cfUnivarGcd.cc

spielwiese
Last change on this file was 3edea1, checked in by Hans Schoenemann <hannes@…>, 3 years ago
cygwin port: shared lib libfactory
  • Property mode set to 100644
File size: 8.1 KB
Line 
1#include "config.h"
2
3#include "debug.h"
4
5#include "cf_algorithm.h"
6#include "templates/ftmpl_functions.h"
7#include "cf_primes.h"
8#include "cfGcdUtil.h"
9#include "cfUnivarGcd.h"
10
11#ifdef HAVE_NTL
12#include "NTLconvert.h"
13#endif
14
15#ifdef HAVE_FLINT
16#include "FLINTconvert.h"
17#endif
18
19#ifdef HAVE_NTL
20#ifndef HAVE_FLINT
21CanonicalForm
22gcd_univar_ntl0( const CanonicalForm & F, const CanonicalForm & G )
23{
24    ZZX F1=convertFacCF2NTLZZX(F);
25    ZZX G1=convertFacCF2NTLZZX(G);
26    ZZX R=GCD(F1,G1);
27    return convertNTLZZX2CF(R,F.mvar());
28}
29
30CanonicalForm
31gcd_univar_ntlp( const CanonicalForm & F, const CanonicalForm & G )
32{
33  if (fac_NTL_char!=getCharacteristic())
34  {
35    fac_NTL_char=getCharacteristic();
36    zz_p::init(getCharacteristic());
37  }
38  zz_pX F1=convertFacCF2NTLzzpX(F);
39  zz_pX G1=convertFacCF2NTLzzpX(G);
40  zz_pX R=GCD(F1,G1);
41  return  convertNTLzzpX2CF(R,F.mvar());
42}
43#endif
44#endif
45
46#ifdef HAVE_FLINT
47CanonicalForm
48gcd_univar_flintp (const CanonicalForm& F, const CanonicalForm& G)
49{
50  nmod_poly_t F1, G1;
51  convertFacCF2nmod_poly_t (F1, F);
52  convertFacCF2nmod_poly_t (G1, G);
53  nmod_poly_gcd (F1, F1, G1);
54  CanonicalForm result= convertnmod_poly_t2FacCF (F1, F.mvar());
55  nmod_poly_clear (F1);
56  nmod_poly_clear (G1);
57  return result;
58}
59
60CanonicalForm
61gcd_univar_flint0( const CanonicalForm & F, const CanonicalForm & G )
62{
63  fmpz_poly_t F1, G1;
64  convertFacCF2Fmpz_poly_t(F1, F);
65  convertFacCF2Fmpz_poly_t(G1, G);
66  fmpz_poly_gcd (F1, F1, G1);
67  CanonicalForm result= convertFmpz_poly_t2FacCF (F1, F.mvar());
68  fmpz_poly_clear (F1);
69  fmpz_poly_clear (G1);
70  return result;
71}
72#endif
73
74#ifndef HAVE_NTL
75CanonicalForm gcd_poly_univar0( const CanonicalForm & F, const CanonicalForm & G, bool primitive )
76{
77  CanonicalForm f, g, c, cg, cl, BB, B, M, q, Dp, newD, D, newq;
78  int p, i;
79
80  if ( primitive )
81  {
82    f = F;
83    g = G;
84    c = 1;
85  }
86  else
87  {
88    CanonicalForm cF = content( F ), cG = content( G );
89    f = F / cF;
90    g = G / cG;
91    c = bgcd( cF, cG );
92  }
93  cg = gcd( f.lc(), g.lc() );
94  cl = ( f.lc() / cg ) * g.lc();
95//     B = 2 * cg * tmin(
96//         maxnorm(f)*power(CanonicalForm(2),f.degree())*isqrt(f.degree()+1),
97//         maxnorm(g)*power(CanonicalForm(2),g.degree())*isqrt(g.degree()+1)
98//         )+1;
99  M = tmin( maxNorm(f), maxNorm(g) );
100  BB = power(CanonicalForm(2),tmin(f.degree(),g.degree()))*M;
101  q = 0;
102  i = cf_getNumSmallPrimes() - 1;
103  while ( true )
104  {
105    B = BB;
106    while ( i >= 0 && q < B )
107    {
108      p = cf_getSmallPrime( i );
109      i--;
110      while ( i >= 0 && mod( cl, p ) == 0 )
111      {
112        p = cf_getSmallPrime( i );
113        i--;
114      }
115      setCharacteristic( p );
116      Dp = gcd( mapinto( f ), mapinto( g ) );
117      Dp = ( Dp / Dp.lc() ) * mapinto( cg );
118      setCharacteristic( 0 );
119      if ( Dp.degree() == 0 )
120        return c;
121      if ( q.isZero() )
122      {
123        D = mapinto( Dp );
124        q = p;
125        B = power(CanonicalForm(2),D.degree())*M+1;
126      }
127      else
128      {
129        if ( Dp.degree() == D.degree() )
130        {
131          chineseRemainder( D, q, mapinto( Dp ), p, newD, newq );
132          q = newq;
133          D = newD;
134        }
135        else if ( Dp.degree() < D.degree() )
136        {
137          // all previous p's are bad primes
138          q = p;
139          D = mapinto( Dp );
140          B = power(CanonicalForm(2),D.degree())*M+1;
141        }
142        // else p is a bad prime
143      }
144    }
145    if ( i >= 0 )
146    {
147      // now balance D mod q
148      D = pp( balance_p( D, q ) );
149      if ( fdivides( D, f ) && fdivides( D, g ) )
150        return D * c;
151      else
152        q = 0;
153    }
154    else
155      return gcd_poly( F, G );
156    DEBOUTLN( cerr, "another try ..." );
157  }
158}
159#endif
160
161/** CanonicalForm extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
162 *
163 * extgcd() - returns polynomial extended gcd of f and g.
164 *
165 * Returns gcd(f, g) and a and b sucht that f*a+g*b=gcd(f, g).
166 * The gcd is calculated using an extended euclidean polynomial
167 * remainder sequence, so f and g should be polynomials over an
168 * euclidean domain.  Normalizes result.
169 *
170 * Note: be sure that f and g have the same level!
171 *
172**/
173CanonicalForm
174extgcd ( const CanonicalForm & f, const CanonicalForm & g, CanonicalForm & a, CanonicalForm & b )
175{
176  if (f.isZero())
177  {
178    a= 0;
179    b= 1;
180    return g;
181  }
182  else if (g.isZero())
183  {
184    a= 1;
185    b= 0;
186    return f;
187  }
188#ifdef HAVE_FLINT
189  if (( getCharacteristic() > 0 ) && (CFFactory::gettype() != GaloisFieldDomain)
190  &&  (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g))
191  {
192    nmod_poly_t F1, G1, A, B, R;
193    convertFacCF2nmod_poly_t (F1, f);
194    convertFacCF2nmod_poly_t (G1, g);
195    nmod_poly_init (R, getCharacteristic());
196    nmod_poly_init (A, getCharacteristic());
197    nmod_poly_init (B, getCharacteristic());
198    nmod_poly_xgcd (R, A, B, F1, G1);
199    a= convertnmod_poly_t2FacCF (A, f.mvar());
200    b= convertnmod_poly_t2FacCF (B, f.mvar());
201    CanonicalForm r= convertnmod_poly_t2FacCF (R, f.mvar());
202    nmod_poly_clear (F1);
203    nmod_poly_clear (G1);
204    nmod_poly_clear (A);
205    nmod_poly_clear (B);
206    nmod_poly_clear (R);
207    return r;
208  }
209#elif defined(HAVE_NTL)
210  if (( getCharacteristic() > 0 ) && (CFFactory::gettype() != GaloisFieldDomain)
211  &&  (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g))
212  {
213    if (fac_NTL_char!=getCharacteristic())
214    {
215      fac_NTL_char=getCharacteristic();
216      zz_p::init(getCharacteristic());
217    }
218    zz_pX F1=convertFacCF2NTLzzpX(f);
219    zz_pX G1=convertFacCF2NTLzzpX(g);
220    zz_pX R;
221    zz_pX A,B;
222    XGCD(R,A,B,F1,G1);
223    a=convertNTLzzpX2CF(A,f.mvar());
224    b=convertNTLzzpX2CF(B,f.mvar());
225    return convertNTLzzpX2CF(R,f.mvar());
226  }
227#endif
228#ifdef HAVE_FLINT
229  if (( getCharacteristic() ==0) && (f.level()==g.level())
230       && isPurePoly(f) && isPurePoly(g))
231  {
232    fmpq_poly_t F1, G1;
233    convertFacCF2Fmpq_poly_t (F1, f);
234    convertFacCF2Fmpq_poly_t (G1, g);
235    fmpq_poly_t R, A, B;
236    fmpq_poly_init (R);
237    fmpq_poly_init (A);
238    fmpq_poly_init (B);
239    fmpq_poly_xgcd (R, A, B, F1, G1);
240    a= convertFmpq_poly_t2FacCF (A, f.mvar());
241    b= convertFmpq_poly_t2FacCF (B, f.mvar());
242    CanonicalForm r= convertFmpq_poly_t2FacCF (R, f.mvar());
243    fmpq_poly_clear (F1);
244    fmpq_poly_clear (G1);
245    fmpq_poly_clear (A);
246    fmpq_poly_clear (B);
247    fmpq_poly_clear (R);
248    return r;
249  }
250#elif defined(HAVE_NTL)
251  if (( getCharacteristic() ==0)
252  && (f.level()==g.level()) && isPurePoly(f) && isPurePoly(g))
253  {
254    CanonicalForm fc=bCommonDen(f);
255    CanonicalForm gc=bCommonDen(g);
256    ZZX F1=convertFacCF2NTLZZX(f*fc);
257    ZZX G1=convertFacCF2NTLZZX(g*gc);
258    ZZX R=GCD(F1,G1);
259    CanonicalForm r=convertNTLZZX2CF(R,f.mvar());
260    ZZ RR;
261    ZZX A,B;
262    if (r.inCoeffDomain())
263    {
264      XGCD(RR,A,B,F1,G1,1);
265      CanonicalForm rr=convertZZ2CF(RR);
266      if(!rr.isZero())
267      {
268        a=convertNTLZZX2CF(A,f.mvar())*fc/rr;
269        b=convertNTLZZX2CF(B,f.mvar())*gc/rr;
270        return CanonicalForm(1);
271      }
272      else
273      {
274        F1 /= R;
275        G1 /= R;
276        XGCD (RR, A,B,F1,G1,1);
277        rr=convertZZ2CF(RR);
278        a=convertNTLZZX2CF(A,f.mvar())*(fc/rr);
279        b=convertNTLZZX2CF(B,f.mvar())*(gc/rr);
280      }
281    }
282    else
283    {
284      XGCD(RR,A,B,F1,G1,1);
285      CanonicalForm rr=convertZZ2CF(RR);
286      if (!rr.isZero())
287      {
288        a=convertNTLZZX2CF(A,f.mvar())*fc;
289        b=convertNTLZZX2CF(B,f.mvar())*gc;
290      }
291      else
292      {
293        F1 /= R;
294        G1 /= R;
295        XGCD (RR, A,B,F1,G1,1);
296        rr=convertZZ2CF(RR);
297        a=convertNTLZZX2CF(A,f.mvar())*(fc/rr);
298        b=convertNTLZZX2CF(B,f.mvar())*(gc/rr);
299      }
300      return r;
301    }
302  }
303#endif
304  // may contain bug in the co-factors, see track 107
305  CanonicalForm contf = content( f );
306  CanonicalForm contg = content( g );
307
308  CanonicalForm p0 = f / contf, p1 = g / contg;
309  CanonicalForm f0 = 1, f1 = 0, g0 = 0, g1 = 1, q, r;
310
311  while ( ! p1.isZero() )
312  {
313      divrem( p0, p1, q, r );
314      p0 = p1; p1 = r;
315      r = g0 - g1 * q;
316      g0 = g1; g1 = r;
317      r = f0 - f1 * q;
318      f0 = f1; f1 = r;
319  }
320  CanonicalForm contp0 = content( p0 );
321  a = f0 / ( contf * contp0 );
322  b = g0 / ( contg * contp0 );
323  p0 /= contp0;
324  if ( p0.sign() < 0 )
325  {
326      p0 = -p0;
327      a = -a;
328      b = -b;
329  }
330  return p0;
331}
Note: See TracBrowser for help on using the repository browser.