source: git/factory/algext.cc @ 2156ec

spielwiese
Last change on this file since 2156ec was 2156ec, checked in by Martin Lee <martinlee84@…>, 12 years ago
chg: compute content in QGCD
  • Property mode set to 100644
File size: 28.9 KB
Line 
1#include <factory/factoryconf.h>
2
3#ifndef NOSTREAMIO
4#ifdef HAVE_CSTDIO
5#include <cstdio>
6#else
7#include <stdio.h>
8#endif
9#ifdef HAVE_IOSTREAM_H
10#include <iostream.h>
11#elif defined(HAVE_IOSTREAM)
12#include <iostream>
13#endif
14#endif
15
16#include "templates/ftmpl_functions.h"
17#include "cf_defs.h"
18#include "canonicalform.h"
19#include "cf_iter.h"
20#include "cf_primes.h"
21#include "cf_algorithm.h"
22#include "algext.h"
23#include "fieldGCD.h"
24#include "cf_map.h"
25#include "cf_generator.h"
26
27#ifdef HAVE_NTL
28#include "NTLconvert.h"
29#endif
30
31/// compressing two polynomials F and G, M is used for compressing,
32/// N to reverse the compression
33static
34int myCompress (const CanonicalForm& F, const CanonicalForm& G, CFMap & M,
35                CFMap & N, bool topLevel)
36{
37  int n= tmax (F.level(), G.level());
38  int * degsf= new int [n + 1];
39  int * degsg= new int [n + 1];
40
41  for (int i = 0; i <= n; i++)
42    degsf[i]= degsg[i]= 0;
43
44  degsf= degrees (F, degsf);
45  degsg= degrees (G, degsg);
46
47  int both_non_zero= 0;
48  int f_zero= 0;
49  int g_zero= 0;
50  int both_zero= 0;
51
52  if (topLevel)
53  {
54    for (int i= 1; i <= n; i++)
55    {
56      if (degsf[i] != 0 && degsg[i] != 0)
57      {
58        both_non_zero++;
59        continue;
60      }
61      if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
62      {
63        f_zero++;
64        continue;
65      }
66      if (degsg[i] == 0 && degsf[i] && i <= F.level())
67      {
68        g_zero++;
69        continue;
70      }
71    }
72
73    if (both_non_zero == 0)
74    {
75      delete [] degsf;
76      delete [] degsg;
77      return 0;
78    }
79
80    // map Variables which do not occur in both polynomials to higher levels
81    int k= 1;
82    int l= 1;
83    for (int i= 1; i <= n; i++)
84    {
85      if (degsf[i] != 0 && degsg[i] == 0 && i <= F.level())
86      {
87        if (k + both_non_zero != i)
88        {
89          M.newpair (Variable (i), Variable (k + both_non_zero));
90          N.newpair (Variable (k + both_non_zero), Variable (i));
91        }
92        k++;
93      }
94      if (degsf[i] == 0 && degsg[i] != 0 && i <= G.level())
95      {
96        if (l + g_zero + both_non_zero != i)
97        {
98          M.newpair (Variable (i), Variable (l + g_zero + both_non_zero));
99          N.newpair (Variable (l + g_zero + both_non_zero), Variable (i));
100        }
101        l++;
102      }
103    }
104
105    // sort Variables x_{i} in increasing order of
106    // min(deg_{x_{i}}(f),deg_{x_{i}}(g))
107    int m= tmax (F.level(), G.level());
108    int min_max_deg;
109    k= both_non_zero;
110    l= 0;
111    int i= 1;
112    while (k > 0)
113    {
114      if (degsf [i] != 0 && degsg [i] != 0)
115        min_max_deg= tmax (degsf[i], degsg[i]);
116      else
117        min_max_deg= 0;
118      while (min_max_deg == 0)
119      {
120        i++;
121        min_max_deg= tmax (degsf[i], degsg[i]);
122        if (degsf [i] != 0 && degsg [i] != 0)
123          min_max_deg= tmax (degsf[i], degsg[i]);
124        else
125          min_max_deg= 0;
126      }
127      for (int j= i + 1; j <=  m; j++)
128      {
129        if (tmax (degsf[j],degsg[j]) <= min_max_deg && degsf[j] != 0 && degsg [j] != 0)
130        {
131          min_max_deg= tmax (degsf[j], degsg[j]);
132          l= j;
133        }
134      }
135      if (l != 0)
136      {
137        if (l != k)
138        {
139          M.newpair (Variable (l), Variable(k));
140          N.newpair (Variable (k), Variable(l));
141          degsf[l]= 0;
142          degsg[l]= 0;
143          l= 0;
144        }
145        else
146        {
147          degsf[l]= 0;
148          degsg[l]= 0;
149          l= 0;
150        }
151      }
152      else if (l == 0)
153      {
154        if (i != k)
155        {
156          M.newpair (Variable (i), Variable (k));
157          N.newpair (Variable (k), Variable (i));
158          degsf[i]= 0;
159          degsg[i]= 0;
160        }
161        else
162        {
163          degsf[i]= 0;
164          degsg[i]= 0;
165        }
166        i++;
167      }
168      k--;
169    }
170  }
171  else
172  {
173    //arrange Variables such that no gaps occur
174    for (int i= 1; i <= n; i++)
175    {
176      if (degsf[i] == 0 && degsg[i] == 0)
177      {
178        both_zero++;
179        continue;
180      }
181      else
182      {
183        if (both_zero != 0)
184        {
185          M.newpair (Variable (i), Variable (i - both_zero));
186          N.newpair (Variable (i - both_zero), Variable (i));
187        }
188      }
189    }
190  }
191
192  delete [] degsf;
193  delete [] degsg;
194
195  return 1;
196}
197
198void tryInvert( const CanonicalForm & F, const CanonicalForm & M, CanonicalForm & inv, bool & fail )
199{ // F, M are required to be "univariate" polynomials in an algebraic variable
200  // we try to invert F modulo M
201  if(F.inBaseDomain())
202  {
203    if(F.isZero())
204    {
205      fail = true;
206      return;
207    }
208    inv = 1/F;
209    return;
210  }
211  CanonicalForm b;
212  Variable a = M.mvar();
213  Variable x = Variable(1);
214  if(!extgcd( replacevar( F, a, x ), replacevar( M, a, x ), inv, b ).isOne())
215    fail = true;
216  else
217    inv = replacevar( inv, x, a ); // change back to alg var
218}
219
220void tryDivrem (const CanonicalForm& F, const CanonicalForm& G, CanonicalForm& Q,
221                CanonicalForm& R, CanonicalForm& inv, const CanonicalForm& mipo,
222                bool& fail)
223{
224  if (F.inCoeffDomain())
225  {
226    Q= 0;
227    R= F;
228    return;
229  }
230
231  CanonicalForm A, B;
232  Variable x= F.mvar();
233  A= F;
234  B= G;
235  int degA= degree (A, x);
236  int degB= degree (B, x);
237
238  if (degA < degB)
239  {
240    R= A;
241    Q= 0;
242    return;
243  }
244
245  tryInvert (Lc (B), mipo, inv, fail);
246  if (fail)
247    return;
248
249  R= A;
250  Q= 0;
251  CanonicalForm Qi;
252  for (int i= degA -degB; i >= 0; i--)
253  {
254    if (degree (R, x) == i + degB)
255    {
256      Qi= Lc (R)*inv*power (x, i);
257      Qi= reduce (Qi, mipo);
258      R -= Qi*B;
259      R= reduce (R, mipo);
260      Q += Qi;
261    }
262  }
263}
264
265void tryEuclid( const CanonicalForm & A, const CanonicalForm & B, const CanonicalForm & M, CanonicalForm & result, bool & fail )
266{
267  CanonicalForm P;
268  if(A.inCoeffDomain())
269  {
270    tryInvert( A, M, P, fail );
271    if(fail)
272      return;
273    result = 1;
274    return;
275  }
276  if(B.inCoeffDomain())
277  {
278    tryInvert( B, M, P, fail );
279    if(fail)
280      return;
281    result = 1;
282    return;
283  }
284  // here: both not inCoeffDomain
285  if( A.degree() > B.degree() )
286  {
287    P = A; result = B;
288  }
289  else
290  {
291    P = B; result = A;
292  }
293  CanonicalForm inv;
294  if( result.isZero() )
295  {
296    tryInvert( Lc(P), M, inv, fail );
297    if(fail)
298      return;
299    result = inv*P; // monify result (not reduced, yet)
300    result= reduce (result, M);
301    return;
302  }
303  Variable x = P.mvar();
304  CanonicalForm rem, Q;
305  // here: degree(P) >= degree(result)
306  while(true)
307  {
308    tryDivrem (P, result, Q, rem, inv, M, fail);
309    if (fail)
310      return;
311    if( rem.isZero() )
312    {
313      result *= inv;
314      result= reduce (result, M);
315      return;
316    }
317    if(result.degree(x) >= rem.degree(x))
318    {
319      P = result;
320      result = rem;
321    }
322    else
323      P = rem;
324  }
325}
326
327bool hasFirstAlgVar( const CanonicalForm & f, Variable & a )
328{
329  if( f.inBaseDomain() ) // f has NO alg. variable
330    return false;
331  if( f.level()<0 ) // f has only alg. vars, so take the first one
332  {
333    a = f.mvar();
334    return true;
335  }
336  for(CFIterator i=f; i.hasTerms(); i++)
337    if( hasFirstAlgVar( i.coeff(), a ))
338      return true; // 'a' is already set
339  return false;
340}
341
342CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G );
343int * leadDeg(const CanonicalForm & f, int *degs);
344bool isLess(int *a, int *b, int lower, int upper);
345bool isEqual(int *a, int *b, int lower, int upper);
346CanonicalForm firstLC(const CanonicalForm & f);
347static CanonicalForm trycontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail );
348static CanonicalForm tryvcontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail );
349static CanonicalForm trycf_content ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, bool & fail );
350static void tryDivide( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, CanonicalForm & result, bool & divides, bool & fail );
351
352static inline CanonicalForm
353tryNewtonInterp (const CanonicalForm alpha, const CanonicalForm u,
354              const CanonicalForm newtonPoly, const CanonicalForm oldInterPoly,
355              const Variable & x, const CanonicalForm& M, bool& fail)
356{
357  CanonicalForm interPoly;
358
359  CanonicalForm inv;
360  tryInvert (newtonPoly (alpha, x), M, inv, fail);
361  if (fail)
362    return 0;
363
364  interPoly= oldInterPoly+reduce ((u - oldInterPoly (alpha, x))*inv*newtonPoly, M);
365  return interPoly;
366}
367
368void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail, bool topLevel )
369{ // assume F,G are multivariate polys over Z/p(a) for big prime p, M "univariate" polynomial in an algebraic variable
370  // M is assumed to be monic
371  if(F.isZero())
372  {
373    if(G.isZero())
374    {
375      result = G; // G is zero
376      return;
377    }
378    if(G.inCoeffDomain())
379    {
380      tryInvert(G,M,result,fail);
381      if(fail)
382        return;
383      result = 1;
384      return;
385    }
386    // try to make G monic modulo M
387    CanonicalForm inv;
388    tryInvert(Lc(G),M,inv,fail);
389    if(fail)
390      return;
391    result = inv*G;
392    result= reduce (result, M);
393    return;
394  }
395  if(G.isZero()) // F is non-zero
396  {
397    if(F.inCoeffDomain())
398    {
399      tryInvert(F,M,result,fail);
400      if(fail)
401        return;
402      result = 1;
403      return;
404    }
405    // try to make F monic modulo M
406    CanonicalForm inv;
407    tryInvert(Lc(F),M,inv,fail);
408    if(fail)
409      return;
410    result = inv*F;
411    result= reduce (result, M);
412    return;
413  }
414  // here: F,G both nonzero
415  if(F.inCoeffDomain())
416  {
417    tryInvert(F,M,result,fail);
418    if(fail)
419      return;
420    result = 1;
421    return;
422  }
423  if(G.inCoeffDomain())
424  {
425    tryInvert(G,M,result,fail);
426    if(fail)
427      return;
428    result = 1;
429    return;
430  }
431  CFMap MM,NN;
432  int lev= myCompress (F, G, MM, NN, topLevel);
433  if (lev == 0)
434  {
435    result= 1;
436    return;
437  }
438  CanonicalForm f=MM(F);
439  CanonicalForm g=MM(G);
440  // here: f,g are compressed
441  // compute largest variable in f or g (least one is Variable(1))
442  int mv = f.level();
443  if(g.level() > mv)
444    mv = g.level();
445  // here: mv is level of the largest variable in f, g
446  if(mv == 1) // f,g univariate
447  {
448    tryEuclid(f,g,M,result,fail);
449    if(fail)
450      return;
451    result= NN (reduce (result, M)); // do not forget to map back
452    return;
453  }
454  // here: mv > 1
455  CanonicalForm cf = tryvcontent(f, Variable(2), M, fail); // cf is univariate poly in var(1)
456  if(fail)
457    return;
458  CanonicalForm cg = tryvcontent(g, Variable(2), M, fail);
459  if(fail)
460    return;
461  CanonicalForm c;
462  tryEuclid(cf,cg,M,c,fail);
463  if(fail)
464    return;
465  // f /= cf
466  f.tryDiv (cf, M, fail);
467  if(fail)
468    return;
469  // g /= cg
470  g.tryDiv (cg, M, fail);
471  if(fail)
472    return;
473  if(f.inCoeffDomain())
474  {
475    tryInvert(f,M,result,fail);
476    if(fail)
477      return;
478    result = NN(c);
479    return;
480  }
481  if(g.inCoeffDomain())
482  {
483    tryInvert(g,M,result,fail);
484    if(fail)
485      return;
486    result = NN(c);
487    return;
488  }
489  int *L = new int[mv+1]; // L is addressed by i from 2 to mv
490  int *N = new int[mv+1];
491  for(int i=2; i<=mv; i++)
492    L[i] = N[i] = 0;
493  L = leadDeg(f, L);
494  N = leadDeg(g, N);
495  CanonicalForm gamma;
496  tryEuclid( firstLC(f), firstLC(g), M, gamma, fail );
497  if(fail)
498    return;
499  for(int i=2; i<=mv; i++) // entries at i=0,1 not visited
500    if(N[i] < L[i])
501      L[i] = N[i];
502  // L is now upper bound for degrees of gcd
503  int *dg_im = new int[mv+1]; // for the degree vector of the image we don't need any entry at i=1
504  for(int i=2; i<=mv; i++)
505    dg_im[i] = 0; // initialize
506  CanonicalForm gamma_image, m=1;
507  CanonicalForm gm=0;
508  CanonicalForm g_image, alpha, gnew;
509  FFGenerator gen = FFGenerator();
510  Variable x= Variable (1);
511  bool divides= true;
512  for(FFGenerator gen = FFGenerator(); gen.hasItems(); gen.next())
513  {
514    alpha = gen.item();
515    gamma_image = reduce(gamma(alpha, x),M); // plug in alpha for var(1)
516    if(gamma_image.isZero()) // skip lc-bad points var(1)-alpha
517      continue;
518    tryBrownGCD( f(alpha, x), g(alpha, x), M, g_image, fail, false ); // recursive call with one var less
519    if(fail)
520      return;
521    g_image = reduce(g_image, M);
522    if(g_image.inCoeffDomain()) // early termination
523    {
524      tryInvert(g_image,M,result,fail);
525      if(fail)
526        return;
527      result = NN(c);
528      return;
529    }
530    for(int i=2; i<=mv; i++)
531      dg_im[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg)
532    dg_im = leadDeg(g_image, dg_im); // dg_im cannot be NIL-pointer
533    if(isEqual(dg_im, L, 2, mv))
534    {
535      CanonicalForm inv;
536      tryInvert (firstLC (g_image), M, inv, fail);
537      if (fail)
538        return;
539      g_image *= inv;
540      g_image *= gamma_image; // multiply by multiple of image lc(gcd)
541      g_image= reduce (g_image, M);
542      gnew= tryNewtonInterp (alpha, g_image, m, gm, x, M, fail);
543      // gnew = gm mod m
544      // gnew = g_image mod var(1)-alpha
545      // mnew = m * (var(1)-alpha)
546      if(fail)
547        return;
548      m *= (x - alpha);
549      if(gnew == gm) // gnew did not change
550      {
551        cf = tryvcontent(gm, Variable(2), M, fail);
552        if(fail)
553          return;
554        divides = true;
555        g_image= gm;
556        g_image.tryDiv (cf, M, fail);
557        if(fail)
558          return;
559        divides= tryFdivides (g_image,f, M, fail); // trial division (f)
560        if(fail)
561          return;
562        if(divides)
563        {
564          bool divides2= tryFdivides (g_image,g, M, fail); // trial division (g)
565          if(fail)
566            return;
567          if(divides2)
568          {
569            result = NN(reduce (c*g_image, M));
570            return;
571          }
572        }
573      }
574      gm = gnew;
575      continue;
576    }
577
578    if(isLess(L, dg_im, 2, mv)) // dg_im > L --> current point unlucky
579      continue;
580
581    // here: isLess(dg_im, L, 2, mv) --> all previous points were unlucky
582    m = CanonicalForm(1); // reset
583    gm = 0; // reset
584    for(int i=2; i<=mv; i++) // tighten bound
585      L[i] = dg_im[i];
586  }
587  // we are out of evaluation points
588  fail = true;
589}
590
591#ifdef HAVE_NTL
592static CanonicalForm
593myicontent ( const CanonicalForm & f, const CanonicalForm & c )
594{
595    if (f.isOne() || c.isOne())
596      return 1;
597    if ( f.inBaseDomain() && c.inBaseDomain())
598    {
599      if (c.isZero()) return abs(f);
600      return bgcd( f, c );
601    }
602    else if ( (f.inCoeffDomain() && c.inCoeffDomain()) ||
603              (f.inCoeffDomain() && c.inBaseDomain()) ||
604              (f.inBaseDomain() && c.inCoeffDomain()))
605    {
606      if (c.isZero()) return abs (f);
607      ZZX NTLf= convertFacCF2NTLZZX (f);
608      ZZX NTLc= convertFacCF2NTLZZX (c);
609      NTLc= GCD (NTLc, NTLf);
610      if (f.inCoeffDomain())
611        return convertNTLZZX2CF(NTLc,f.mvar());
612      else
613        return convertNTLZZX2CF(NTLc,c.mvar());
614    }
615    else
616    {
617        CanonicalForm g = c;
618        for ( CFIterator i = f; i.hasTerms() && ! g.isOne(); i++ )
619            g = myicontent( i.coeff(), g );
620        return g;
621    }
622}
623#endif
624
625CanonicalForm
626myicontent ( const CanonicalForm & f )
627{
628#ifdef HAVE_NTL
629    return myicontent( f, 0 );
630#else
631    return 1;
632#endif
633}
634
635CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G )
636{ // f,g in Q(a)[x1,...,xn]
637  if(F.isZero())
638  {
639    if(G.isZero())
640      return G; // G is zero
641    if(G.inCoeffDomain())
642      return CanonicalForm(1);
643    return G/Lc(G); // return monic G
644  }
645  if(G.isZero()) // F is non-zero
646  {
647    if(F.inCoeffDomain())
648      return CanonicalForm(1);
649    return F/Lc(F); // return monic F
650  }
651  if(F.inCoeffDomain() || G.inCoeffDomain())
652    return CanonicalForm(1);
653  // here: both NOT inCoeffDomain
654  CanonicalForm f, g, tmp, M, q, D, Dp, cl, newq, mipo;
655  int p, i;
656  int *bound, *other; // degree vectors
657  bool fail;
658  bool off_rational=!isOn(SW_RATIONAL);
659  On( SW_RATIONAL ); // needed by bCommonDen
660  f = F * bCommonDen(F);
661  g = G * bCommonDen(G);
662  CanonicalForm contf= myicontent (f);
663  CanonicalForm contg= myicontent (g);
664  f /= contf;
665  g /= contg;
666  CanonicalForm gcdcfcg= myicontent (contf, contg);
667  Variable a, b;
668  if(hasFirstAlgVar(f,a))
669  {
670    if(hasFirstAlgVar(g,b))
671    {
672      if(b.level() > a.level())
673        a = b;
674    }
675  }
676  else
677  {
678    if(!hasFirstAlgVar(g,a))// both not in extension
679    {
680      Off( SW_RATIONAL );
681      Off( SW_USE_QGCD );
682      tmp = gcdcfcg*gcd( f, g );
683      On( SW_USE_QGCD );
684      if (off_rational) Off(SW_RATIONAL);
685      return tmp;
686    }
687  }
688  // here: a is the biggest alg. var in f and g AND some of f,g is in extension
689  // (in the sequel b is used to swap alg/poly vars)
690  setReduce(a,false); // do not reduce expressions modulo mipo
691  tmp = getMipo(a);
692  M = tmp * bCommonDen(tmp);
693  // here: f, g in Z[a][x1,...,xn], M in Z[a] not necessarily monic
694  Off( SW_RATIONAL ); // needed by mod
695  // calculate upper bound for degree vector of gcd
696  int mv = f.level(); i = g.level();
697  if(i > mv)
698    mv = i;
699  // here: mv is level of the largest variable in f, g
700  b = Variable(mv+1);
701  bound = new int[mv+1]; // 'bound' could be indexed from 0 to mv, but we will only use from 1 to mv
702  other = new int[mv+1];
703  for(int i=1; i<=mv; i++) // initialize 'bound', 'other' with zeros
704    bound[i] = other[i] = 0;
705  bound = leadDeg(f,bound); // 'bound' is set the leading degree vector of f
706  other = leadDeg(g,other);
707  for(int i=1; i<=mv; i++) // entry at i=0 not visited
708    if(other[i] < bound[i])
709      bound[i] = other[i];
710  // now 'bound' is the smaller vector
711  cl = lc(M) * lc(f) * lc(g);
712  q = 1;
713  D = 0;
714  CanonicalForm test= 0;
715  bool equal= false;
716  for( i=cf_getNumBigPrimes()-1; i>-1; i-- )
717  {
718    p = cf_getBigPrime(i);
719    if( mod( cl, p ).isZero() ) // skip lc-bad primes
720      continue;
721    fail = false;
722    setCharacteristic(p);
723    mipo = mapinto(M);
724    mipo /= mipo.lc();
725    // here: mipo is monic
726    tryBrownGCD( mapinto(f), mapinto(g), mipo, Dp, fail );
727    if( fail ) // mipo splits in char p
728      continue;
729    if( Dp.inCoeffDomain() ) // early termination
730    {
731      tryInvert(Dp,mipo,tmp,fail); // check if zero divisor
732      if(fail)
733        continue;
734      setReduce(a,true);
735      if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL);
736      setCharacteristic(0);
737      return gcdcfcg;
738    }
739    setCharacteristic(0);
740    // here: Dp NOT inCoeffDomain
741    for(int i=1; i<=mv; i++)
742      other[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg)
743    other = leadDeg(Dp,other);
744
745    if(isEqual(bound, other, 1, mv)) // equal
746    {
747      chineseRemainder( D, q, replacevar( mapinto(Dp), a, b ), p, tmp, newq );
748      // tmp = Dp mod p
749      // tmp = D mod q
750      // newq = p*q
751      q = newq;
752      if( D != tmp )
753        D = tmp;
754      On( SW_RATIONAL );
755      tmp = replacevar( Farey( D, q ), b, a ); // Farey and switch back to alg var
756      setReduce(a,true); // reduce expressions modulo mipo
757      On( SW_RATIONAL ); // needed by fdivides
758      if (test != tmp)
759        test= tmp;
760      else
761        equal= true; // modular image did not add any new information
762      if(equal && fdivides( tmp, f ) && fdivides( tmp, g )) // trial division
763      {
764        Off( SW_RATIONAL );
765        setReduce(a,true);
766        if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL);
767        return tmp*gcdcfcg;
768      }
769      Off( SW_RATIONAL );
770      setReduce(a,false); // do not reduce expressions modulo mipo
771      continue;
772    }
773    if( isLess(bound, other, 1, mv) ) // current prime unlucky
774      continue;
775    // here: isLess(other, bound, 1, mv) ) ==> all previous primes unlucky
776    q = p;
777    D = replacevar( mapinto(Dp), a, b ); // shortcut CRA // shortcut CRA
778    for(int i=1; i<=mv; i++) // tighten bound
779      bound[i] = other[i];
780  }
781  // hopefully, we never reach this point
782  setReduce(a,true);
783  Off( SW_USE_QGCD );
784  D = gcdcfcg*gcd( f, g );
785  On( SW_USE_QGCD );
786  if (off_rational) Off(SW_RATIONAL); else On(SW_RATIONAL);
787  return D;
788}
789
790
791int * leadDeg(const CanonicalForm & f, int *degs)
792{ // leading degree vector w.r.t. lex. monomial order x(i+1) > x(i)
793  // if f is in a coeff domain, the zero pointer is returned
794  // 'a' should point to an array of sufficient size level(f)+1
795  if(f.inCoeffDomain())
796    return 0;
797  CanonicalForm tmp = f;
798  do
799  {
800    degs[tmp.level()] = tmp.degree();
801    tmp = LC(tmp);
802  }
803  while(!tmp.inCoeffDomain());
804  return degs;
805}
806
807
808bool isLess(int *a, int *b, int lower, int upper)
809{ // compares the degree vectors a,b on the specified part. Note: x(i+1) > x(i)
810  for(int i=upper; i>=lower; i--)
811    if(a[i] == b[i])
812      continue;
813    else
814      return a[i] < b[i];
815  return true;
816}
817
818
819bool isEqual(int *a, int *b, int lower, int upper)
820{ // compares the degree vectors a,b on the specified part. Note: x(i+1) > x(i)
821  for(int i=lower; i<=upper; i++)
822    if(a[i] != b[i])
823      return false;
824  return true;
825}
826
827
828CanonicalForm firstLC(const CanonicalForm & f)
829{ // returns the leading coefficient (LC) of level <= 1
830  CanonicalForm ret = f;
831  while(ret.level() > 1)
832    ret = LC(ret);
833  return ret;
834}
835
836void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail )
837{ // F, G are univariate polynomials (i.e. they have exactly one polynomial variable)
838  // F and G must have the same level AND level > 0
839  // we try to calculate gcd(F,G) = s*F + t*G
840  // if a zero divisor is encontered, 'fail' is set to one
841  // M is assumed to be monic
842  CanonicalForm P;
843  if(F.inCoeffDomain())
844  {
845    tryInvert( F, M, P, fail );
846    if(fail)
847      return;
848    result = 1;
849    s = P; t = 0;
850    return;
851  }
852  if(G.inCoeffDomain())
853  {
854    tryInvert( G, M, P, fail );
855    if(fail)
856      return;
857    result = 1;
858    s = 0; t = P;
859    return;
860  }
861  // here: both not inCoeffDomain
862  CanonicalForm inv, rem, tmp, u, v, q, sum=0;
863  if( F.degree() > G.degree() )
864  {
865    P = F; result = G;  s=v=0; t=u=1;
866  }
867  else
868  {
869    P = G; result = F; s=v=1; t=u=0;
870  }
871  Variable x = P.mvar();
872  // here: degree(P) >= degree(result)
873  while(true)
874  {
875    tryDivrem (P, result, q, rem, inv, M, fail);
876    if(fail)
877      return;
878    if( rem.isZero() )
879    {
880      s*=inv;
881      s= reduce (s, M);
882      t*=inv;
883      t= reduce (t, M);
884      result *= inv; // monify result
885      result= reduce (result, M);
886      return;
887    }
888    sum += q;
889    if(result.degree(x) >= rem.degree(x))
890    {
891      P=result;
892      result=rem;
893      tmp=u-sum*s;
894      u=s;
895      s=tmp;
896      tmp=v-sum*t;
897      v=t;
898      t=tmp;
899      sum = 0; // reset
900    }
901    else
902      P = rem;
903  }
904}
905
906
907static CanonicalForm trycontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail )
908{ // as 'content', but takes care of zero divisors
909  ASSERT( x.level() > 0, "cannot calculate content with respect to algebraic variable" );
910  Variable y = f.mvar();
911  if ( y == x )
912    return trycf_content( f, 0, M, fail );
913  if ( y < x )
914     return f;
915  return swapvar( trycontent( swapvar( f, y, x ), y, M, fail ), y, x );
916}
917
918
919static CanonicalForm tryvcontent ( const CanonicalForm & f, const Variable & x, const CanonicalForm & M, bool & fail )
920{ // as vcontent, but takes care of zero divisors
921  ASSERT( x.level() > 0, "cannot calculate vcontent with respect to algebraic variable" );
922  if ( f.mvar() <= x )
923    return trycontent( f, x, M, fail );
924  CFIterator i;
925  CanonicalForm d = 0, e, ret;
926  for ( i = f; i.hasTerms() && ! d.isOne() && ! fail; i++ )
927  {
928    e = tryvcontent( i.coeff(), x, M, fail );
929    if(fail)
930      break;
931    tryBrownGCD( d, e, M, ret, fail );
932    d = ret;
933  }
934  return d;
935}
936
937
938static CanonicalForm trycf_content ( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, bool & fail )
939{ // as cf_content, but takes care of zero divisors
940  if ( f.inPolyDomain() || ( f.inExtension() && ! getReduce( f.mvar() ) ) )
941  {
942    CFIterator i = f;
943    CanonicalForm tmp = g, result;
944    while ( i.hasTerms() && ! tmp.isOne() && ! fail )
945    {
946      tryBrownGCD( i.coeff(), tmp, M, result, fail );
947      tmp = result;
948      i++;
949    }
950    return result;
951  }
952  return abs( f );
953}
954
955
956static void tryDivide( const CanonicalForm & f, const CanonicalForm & g, const CanonicalForm & M, CanonicalForm & result, bool & divides, bool & fail )
957{ // M "univariate" monic polynomial
958  // f, g polynomials with coeffs modulo M.
959  // if f is divisible by g, 'divides' is set to 1 and 'result' == f/g mod M coefficientwise.
960  // 'fail' is set to 1, iff a zero divisor is encountered.
961  // divides==1 implies fail==0
962  // required: getReduce(M.mvar())==0
963  if(g.inBaseDomain())
964  {
965    result = f/g;
966    divides = true;
967    return;
968  }
969  if(g.inCoeffDomain())
970  {
971    tryInvert(g,M,result,fail);
972    if(fail)
973      return;
974    result = reduce(f*result, M);
975    divides = true;
976    return;
977  }
978  // here: g NOT inCoeffDomain
979  Variable x = g.mvar();
980  if(f.degree(x) < g.degree(x))
981  {
982    divides = false;
983    return;
984  }
985  // here: f.degree(x) > 0 and f.degree(x) >= g.degree(x)
986  CanonicalForm F = f;
987  CanonicalForm q, leadG = LC(g);
988  result = 0;
989  while(!F.isZero())
990  {
991    tryDivide(F.LC(x),leadG,M,q,divides,fail);
992    if(fail || !divides)
993      return;
994    if(F.degree(x)<g.degree(x))
995    {
996      divides = false;
997      return;
998    }
999    q *= power(x,F.degree(x)-g.degree(x));
1000    result += q;
1001    F = reduce(F-q*g, M);
1002  }
1003  result = reduce(result, M);
1004  divides = true;
1005}
1006
1007void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail )
1008{
1009  // F, G are univariate polynomials (i.e. they have exactly one polynomial variable)
1010  // F and G must have the same level AND level > 0
1011  // we try to calculate gcd(f,g) = s*F + t*G
1012  // if a zero divisor is encontered, 'fail' is set to one
1013  Variable a, b;
1014  if( !hasFirstAlgVar(F,a) && !hasFirstAlgVar(G,b) ) // note lazy evaluation
1015  {
1016    result = extgcd( F, G, s, t ); // no zero divisors possible
1017    return;
1018  }
1019  if( b.level() > a.level() )
1020    a = b;
1021  // here: a is the biggest alg. var in F and G
1022  CanonicalForm M = getMipo(a);
1023  CanonicalForm P;
1024  if( degree(F) > degree(G) )
1025  {
1026    P=F; result=G; s=0; t=1;
1027  }
1028  else
1029  {
1030    P=G; result=F; s=1; t=0;
1031  }
1032  CanonicalForm inv, rem, q, u, v;
1033  // here: degree(P) >= degree(result)
1034  while(true)
1035  {
1036    tryInvert( Lc(result), M, inv, fail );
1037    if(fail)
1038      return;
1039    // here: Lc(result) is invertible modulo M
1040    q = Lc(P)*inv * power( P.mvar(), degree(P)-degree(result) );
1041    rem = P - q*result;
1042    // here: s*F + t*G = result
1043    if( rem.isZero() )
1044    {
1045      s*=inv;
1046      t*=inv;
1047      result *= inv; // monify result
1048      return;
1049    }
1050    P=result;
1051    result=rem;
1052    rem=u-q*s;
1053    u=s;
1054    s=rem;
1055    rem=v-q*t;
1056    v=t;
1057    t=rem;
1058  }
1059}
1060
1061void tryCRA( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew, bool & fail )
1062{ // polys of level <= 1 are considered coefficients. q1,q2 are assumed to be coprime
1063  // xnew = x1 mod q1 (coefficientwise in the above sense)
1064  // xnew = x2 mod q2
1065  // qnew = q1*q2
1066  CanonicalForm tmp;
1067  if(x1.level() <= 1 && x2.level() <= 1) // base case
1068  {
1069    tryExtgcd(q1,q2,tmp,xnew,qnew,fail);
1070    if(fail)
1071      return;
1072    xnew = x1 + (x2-x1) * xnew * q1;
1073    qnew = q1*q2;
1074    xnew = mod(xnew,qnew);
1075    return;
1076  }
1077  CanonicalForm tmp2;
1078  xnew = 0;
1079  qnew = q1 * q2;
1080  // here: x1.level() > 1 || x2.level() > 1
1081  if(x1.level() > x2.level())
1082  {
1083    for(CFIterator i=x1; i.hasTerms(); i++)
1084    {
1085      if(i.exp() == 0) // const. term
1086      {
1087        tryCRA(i.coeff(),q1,x2,q2,tmp,tmp2,fail);
1088        if(fail)
1089          return;
1090        xnew += tmp;
1091      }
1092      else
1093      {
1094        tryCRA(i.coeff(),q1,0,q2,tmp,tmp2,fail);
1095        if(fail)
1096          return;
1097        xnew += tmp * power(x1.mvar(),i.exp());
1098      }
1099    }
1100    return;
1101  }
1102  // here: x1.level() <= x2.level() && ( x1.level() > 1 || x2.level() > 1 )
1103  if(x2.level() > x1.level())
1104  {
1105    for(CFIterator j=x2; j.hasTerms(); j++)
1106    {
1107      if(j.exp() == 0) // const. term
1108      {
1109        tryCRA(x1,q1,j.coeff(),q2,tmp,tmp2,fail);
1110        if(fail)
1111          return;
1112        xnew += tmp;
1113      }
1114      else
1115      {
1116        tryCRA(0,q1,j.coeff(),q2,tmp,tmp2,fail);
1117        if(fail)
1118          return;
1119        xnew += tmp * power(x2.mvar(),j.exp());
1120      }
1121    }
1122    return;
1123  }
1124  // here: x1.level() == x2.level() && x1.level() > 1 && x2.level() > 1
1125  CFIterator i = x1;
1126  CFIterator j = x2;
1127  while(i.hasTerms() || j.hasTerms())
1128  {
1129    if(i.hasTerms())
1130    {
1131      if(j.hasTerms())
1132      {
1133        if(i.exp() == j.exp())
1134        {
1135          tryCRA(i.coeff(),q1,j.coeff(),q2,tmp,tmp2,fail);
1136          if(fail)
1137            return;
1138          xnew += tmp * power(x1.mvar(),i.exp());
1139          i++; j++;
1140        }
1141        else
1142        {
1143          if(i.exp() < j.exp())
1144          {
1145            tryCRA(i.coeff(),q1,0,q2,tmp,tmp2,fail);
1146            if(fail)
1147              return;
1148            xnew += tmp * power(x1.mvar(),i.exp());
1149            i++;
1150          }
1151          else // i.exp() > j.exp()
1152          {
1153            tryCRA(0,q1,j.coeff(),q2,tmp,tmp2,fail);
1154            if(fail)
1155              return;
1156            xnew += tmp * power(x1.mvar(),j.exp());
1157            j++;
1158          }
1159        }
1160      }
1161      else // j is out of terms
1162      {
1163        tryCRA(i.coeff(),q1,0,q2,tmp,tmp2,fail);
1164        if(fail)
1165          return;
1166        xnew += tmp * power(x1.mvar(),i.exp());
1167        i++;
1168      }
1169    }
1170    else // i is out of terms
1171    {
1172      tryCRA(0,q1,j.coeff(),q2,tmp,tmp2,fail);
1173      if(fail)
1174        return;
1175      xnew += tmp * power(x1.mvar(),j.exp());
1176      j++;
1177    }
1178  }
1179}
1180
Note: See TracBrowser for help on using the repository browser.