source: git/factory/fieldGCD.cc @ ad8e1b

spielwiese
Last change on this file since ad8e1b was ad8e1b, checked in by Hans Schönemann <hannes@…>, 16 years ago
*hannes: QGCD, fieldGCD, etc git-svn-id: file:///usr/local/Singular/svn/trunk@10949 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 6.8 KB
Line 
1#include <stdio.h>
2#include <iostream.h>
3#include <config.h>
4
5#include "cf_defs.h"
6#include "canonicalform.h"
7#include "cf_iter.h"
8#include "cf_primes.h"
9#include "cf_algorithm.h"
10#include "algext.h"
11#include "fieldGCD.h"
12#include "cf_map.h"
13#include "cf_generator.h"
14
15void out_cf(char *s1,const CanonicalForm &f,char *s2);
16
17
18CanonicalForm fieldGCD( const CanonicalForm & F, const CanonicalForm & G );
19void CRA(const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew);
20
21
22CanonicalForm fieldGCD( const CanonicalForm & F, const CanonicalForm & G )
23{// this is the modular method by Brown
24 // assume F,G are multivariate polys over Z/p for big prime p
25  if(F.isZero())
26  {
27    if(G.isZero())
28      return G; // G is zero
29    if(G.inCoeffDomain())
30      return CanonicalForm(1);
31    return G/lc(G); // return monic G
32  }
33  if(G.isZero()) // F is non-zero
34  {
35    if(F.inCoeffDomain())
36      return CanonicalForm(1);
37    return F/lc(F); // return monic F
38  }
39  if(F.inCoeffDomain() || G.inCoeffDomain())
40    return CanonicalForm(1);
41  //out_cf("F=",F,"\n");
42  //out_cf("G=",G,"\n");
43  CFMap MM,NN;
44  CFArray ps(1,2);
45  ps[1] = F;
46  ps[2] = G;
47  compress(ps,MM,NN); // maps MM, NN are created
48  CanonicalForm f=MM(F);
49  CanonicalForm g=MM(G);
50  // here: f, g are compressed
51  // compute largest variable in f or g (least one is Variable(1))
52  int mv = f.level();
53  if(g.level() > mv)
54    mv = g.level();
55  // here: mv is level of the largest variable in f, g
56  if(mv == 1) // f,g univariate
57    return NN(gcd( f, g )); // do not forget to map back
58  // here: mv > 1
59  CanonicalForm cf = vcontent(f, Variable(2)); // cf is univariate poly in var(1)
60  CanonicalForm cg = vcontent(g, Variable(2));
61  CanonicalForm c = gcd( cf, cg );
62  f/=cf;
63  g/=cg;
64  if(f.inCoeffDomain() || g.inCoeffDomain())
65  {
66    //printf("=============== inCoeffDomain\n");
67    return NN(c);
68  }
69  int *L = new int[mv+1]; // L is addressed by i from 2 to mv
70  int *M = new int[mv+1];
71  for(int i=2; i<=mv; i++)
72    L[i] = M[i] = 0;
73  L = leadDeg(f, L);
74  M = leadDeg(g, M);
75  CanonicalForm gamma = gcd( firstLC(f), firstLC(g) );
76  for(int i=2; i<=mv; i++) // entry at i=1 is not visited
77    if(M[i] < L[i])
78      L[i] = M[i];
79  // L is now upper bound for leading degrees of gcd
80  int *dg_im = new int[mv+1]; // for the degree vector of the image we don't need any entry at i=1
81  for(int i=2; i<=mv; i++)
82    dg_im[i] = 0; // initialize
83  CanonicalForm gamma_image, m=1;
84  CanonicalForm gm=0;
85  CanonicalForm g_image, alpha, gnew, mnew;
86  FFGenerator gen = FFGenerator();
87  for(FFGenerator gen = FFGenerator(); gen.hasItems(); gen.next())
88  {
89    alpha = gen.item();
90    gamma_image = gamma(alpha, Variable(1)); // plug in alpha for var(1)
91    if(gamma_image.isZero()) // skip lc-bad points var(1)-alpha
92      continue;
93    g_image = gcd( f(alpha, Variable(1)), g(alpha, Variable(1)) ); // recursive call with one var less
94    if(g_image.inCoeffDomain()) // early termination
95    {
96      //printf("================== inCoeffDomain\n");
97      return NN(c);
98    }
99    for(int i=2; i<=mv; i++)
100      dg_im[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg)
101    dg_im = leadDeg(g_image, dg_im); // dg_im cannot be NIL-pointer
102    if(isEqual(dg_im, L, 2, mv))
103    {
104      g_image /= lc(g_image); // make g_image monic
105      g_image *= gamma_image; // multiply by multiple of image lc(gcd)
106      CRA( g_image, Variable(1)-alpha, gm, m, gnew, mnew );
107      // gnew = gm mod m
108      // gnew = g_image mod var(1)-alpha
109      // mnew = m * (var(1)-alpha)
110      m = mnew;
111      if(gnew == gm) // gnew did not change
112      {
113        g_image = gm / vcontent(gm, Variable(2));
114        //out_cf("=========== try ",g_image,"\n");
115        if(fdivides(g_image,f) && fdivides(g_image,g)) // trial division
116        {
117          //printf("=========== okay\n");
118          return NN(c*g_image);
119        }
120      }
121      gm = gnew;
122      continue;
123    }
124    if(isLess(L, dg_im, 2, mv)) // dg_im > L --> current point unlucky
125      continue;
126
127    // here: dg_im < L --> all previous points were unlucky
128    //printf("=========== reset\n");
129    m = CanonicalForm(1); // reset
130    gm = 0; // reset
131    for(int i=2; i<=mv; i++) // tighten bound
132      L[i] = dg_im[i];
133  }
134  // hopefully, we never reach this point
135  Off( SW_USE_fieldGCD );
136  g_image = gcd(f,g);
137  On( SW_USE_fieldGCD );
138  return g_image;
139}
140
141
142void CRA(const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew)
143{ // this is polynomial Chinese Remaindering. q1, q2 are assumed to be coprime.
144  // polynomials of level <= 1 are considered coefficients
145  // xnew = x1 mod q1 (coefficientwise in the above sense)
146  // xnew = x2 mod q2
147  // qnew = q1*q2
148  if(x1.level() <= 1 && x2.level() <= 1) // base case
149  {
150    (void) extgcd(q1,q2,xnew,qnew);
151    xnew = x1 + (x2-x1) * xnew * q1;
152    qnew = q1*q2;
153    xnew = mod(xnew,qnew);
154    return;
155  }
156  CanonicalForm tmp,tmp2;
157  xnew = 0;
158  qnew = q1 * q2;
159  // here: x1.level() > 1 || x2.level() > 1
160  if(x1.level() > x2.level())
161  {
162    for(CFIterator i=x1; i.hasTerms(); i++)
163    {
164      if(i.exp() == 0) // const. term
165      {
166        CRA(i.coeff(),q1,x2,q2,tmp,tmp2);
167        xnew += tmp;
168      }
169      else
170      {
171        CRA(i.coeff(),q1,0,q2,tmp,tmp2);
172        xnew += tmp * power(x1.mvar(),i.exp());
173      }
174    }
175    return;
176  }
177  // here: x1.level() <= x2.level() && ( x1.level() > 1 || x2.level() > 1 )
178  if(x2.level() > x1.level())
179  {
180    for(CFIterator j=x2; j.hasTerms(); j++)
181    {
182      if(j.exp() == 0) // const. term
183      {
184        CRA(x1,q1,j.coeff(),q2,tmp,tmp2);
185        xnew += tmp;
186      }
187      else
188      {
189        CRA(0,q1,j.coeff(),q2,tmp,tmp2);
190        xnew += tmp * power(x2.mvar(),j.exp());
191      }
192    }
193    return;
194  }
195  // here: x1.level() == x2.level() && x1.level() > 1 && x2.level() > 1
196  CFIterator i = x1;
197  CFIterator j = x2;
198  while(i.hasTerms() || j.hasTerms())
199  {
200    if(i.hasTerms())
201    {
202      if(j.hasTerms())
203      {
204        if(i.exp() == j.exp())
205        {
206          CRA(i.coeff(),q1,j.coeff(),q2,tmp,tmp2);
207          xnew += tmp * power(x1.mvar(),i.exp());
208          i++; j++;
209        }
210        else
211        {
212          if(i.exp() < j.exp())
213          {
214            CRA(i.coeff(),q1,0,q2,tmp,tmp2);
215            xnew += tmp * power(x1.mvar(),i.exp());
216            i++;
217          }
218          else // i.exp() > j.exp()
219          {
220            CRA(0,q1,j.coeff(),q2,tmp,tmp2);
221            xnew += tmp * power(x1.mvar(),j.exp());
222            j++;
223          }
224        }
225      }
226      else // j is out of terms
227      {
228        CRA(i.coeff(),q1,0,q2,tmp,tmp2);
229        xnew += tmp * power(x1.mvar(),i.exp());
230        i++;
231      }
232    }
233    else // i is out of terms
234    {
235      CRA(0,q1,j.coeff(),q2,tmp,tmp2);
236      xnew += tmp * power(x1.mvar(),j.exp());
237      j++;
238    }
239  }
240}
Note: See TracBrowser for help on using the repository browser.