source: git/factory/algext.cc @ c99b6b

spielwiese
Last change on this file since c99b6b was c99b6b, checked in by Hans Schönemann <hannes@…>, 15 years ago
*** empty log message *** git-svn-id: file:///usr/local/Singular/svn/trunk@10763 2c84dea3-7e68-4137-9b89-c4e89433aadc
  • Property mode set to 100644
File size: 3.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
12
13void tryEuclid( const CanonicalForm & A, const CanonicalForm & B, const CanonicalForm M, CanonicalForm & result, bool & fail )
14{
15  CanonicalForm P;
16  if( degree(A) > degree(B) )
17  {
18    P = A; result = B;
19  }
20  else
21  {
22    P = B; result = A;
23  }
24  if( P.isZero() ) // then result is zero, too
25    return;
26  CanonicalForm inv;
27  if( result.isZero() )
28  {
29    tryInvert( Lc(P), M, inv, fail );
30    if(fail)
31      return;
32    result = inv*P; // monify result
33    return;
34  }
35  CanonicalForm rem;
36  // here: degree(P) >= degree(result)
37  while(true)
38  {
39    tryInvert( Lc(result), M, inv, fail );
40    if(fail)
41      return;
42    // here: Lc(result) is invertible modulo M
43    rem = P - Lc(P)*inv*result * power( P.mvar(), degree(P)-degree(result) );
44    if( rem.isZero() )
45    {
46      result *= inv; // monify result
47      return;
48    }
49    P = result;
50    result = rem;
51  }
52}
53
54
55void tryInvert( const CanonicalForm & F, const CanonicalForm & M, CanonicalForm & inv, bool & fail )
56{
57  // F, M are required to be "univariate" polynomials in an algebraic variable
58  // we try to invert F modulo M
59  CanonicalForm b;
60  Variable a = M.mvar();
61  Variable x = Variable(1);
62  if(!extgcd( replacevar( F, a, x ), replacevar( M, a, x ), inv, b ).isOne())
63    fail = true;
64  else
65    inv = replacevar( inv, a, x); // change back to alg var
66}
67
68
69bool hasFirstAlgVar( const CanonicalForm & f, Variable & a )
70{
71  if( f.inBaseDomain() ) // f has NO alg. variable
72    return false;
73
74  if( f.level()<0 ) // f has only alg. vars, so take the first one
75  {
76    a = f.mvar();
77    return true;
78  }
79  for(CFIterator i=f; i.hasTerms(); i++)
80    if( hasFirstAlgVar( i.coeff(), a ))
81      return true; // 'a' is already set
82
83  return false;
84}
85
86
87CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G )
88{
89  CanonicalForm f, g, tmp, M, q, D, Dp, cl, newD, newq;
90  int p, dp_deg, bound, i;
91  bool fail;
92  On(SW_RATIONAL);
93  f = F * bCommonDen(F);
94  g = G * bCommonDen(G);
95  Variable a,b;
96  if( !hasFirstAlgVar( f, a ) && !hasFirstAlgVar( g, b ))
97  {
98    // F and G are in Q[x], call...
99#ifdef HAVE_NTL
100    if ( isOn( SW_USE_NTL_GCD_0 ))
101      return gcd_univar_ntl0( f, g );
102#endif
103    return gcd_poly_univar0( f, g, false );
104  }
105  if( b.level() > a.level() )
106    a = b;
107  // here: a is the biggest alg. var in f and g
108  tmp = getMipo(a);
109  M = tmp * bCommonDen(tmp);
110  Off(SW_RATIONAL);
111  // calculate upper bound for degree of gcd
112  bound = degree(f);
113  i = degree(g);
114  if( i < bound )
115    bound = i;
116
117  cl = lc(M) * lc(f) * lc(g);
118  q = 1;
119  D = 0;
120  for(i=cf_getNumBigPrimes()-1; i>-1; i--)
121  {
122    p = cf_getBigPrime(i);
123    if( mod( cl, p ).isZero() ) // skip lc-bad primes
124      continue;
125
126    fail = false;
127    setCharacteristic(p);
128    tryEuclid( mapinto(f), mapinto(g), mapinto(M), Dp, fail );
129    setCharacteristic(0);
130    if( fail ) // M splits in char p
131      continue;
132
133    dp_deg = degree(Dp);
134
135    if( !dp_deg ) // early termination
136      return CanonicalForm(1);
137
138    if( dp_deg > bound ) // current prime unlucky
139      continue;
140
141    if( dp_deg < bound ) // all previous primes unlucky
142    {
143      q = p;
144      D = mapinto(Dp); // shortcut CRA
145      bound = dp_deg; // tighten bound
146      continue;
147    }
148    chineseRemainder( D, q, mapinto(Dp), p, newD, newq );
149    // newD = Dp mod p
150    // newD = D mod q
151    // newq = p*q
152    q = newq;
153    if( D != newD )
154    {
155      D = newD;
156      continue;
157    }
158    On( SW_RATIONAL );
159    tmp = Farey( D, q );
160    if( fdivides( tmp, f ) && fdivides( tmp, g )) // trial division
161    {
162      Off( SW_RATIONAL );
163      return tmp;
164    }
165    Off( SW_RATIONAL );
166  }
167  // hopefully, we never reach this point
168  Off( SW_USE_QGCD );
169  D = gcd( f, g );
170  On( SW_USE_QGCD );
171  return D;
172}
Note: See TracBrowser for help on using the repository browser.