Changeset 359d742 in git


Ignore:
Timestamp:
Jun 24, 2008, 2:52:44 PM (16 years ago)
Author:
Hans Schönemann <hannes@…>
Branches:
(u'fieker-DuVal', '117eb8c30fc9e991c4decca4832b1d19036c4c65')(u'spielwiese', 'b4f17ed1d25f93d46dbe29e4b499baecc2fd51bb')
Children:
18c7a3e40a89b378bb7b4666e1f16148b663f9e8
Parents:
863f53819a571f2381b1eac36056dff30adc1904
Message:
*hannens: new versions:EZGCD_P,QGCD


git-svn-id: file:///usr/local/Singular/svn/trunk@10782 2c84dea3-7e68-4137-9b89-c4e89433aadc
Location:
factory
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • factory/algext.cc

    r863f53 r359d742  
    99#include "cf_algorithm.h"
    1010#include "algext.h"
    11 
     11#include "fieldGCD.h"
     12#include "cf_map.h"
     13#include "cf_generator.h"
    1214
    1315void tryEuclid( const CanonicalForm & A, const CanonicalForm & B, const CanonicalForm M, CanonicalForm & result, bool & fail )
     
    6163  Variable x = Variable(1);
    6264  if(!extgcd( replacevar( F, a, x ), replacevar( M, a, x ), inv, b ).isOne())
     65  {
     66    printf("failed ");
    6367    fail = true;
     68  }
    6469  else
    6570    inv = replacevar( inv, a, x); // change back to alg var
     
    8489}
    8590
    86 
    87 CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G )
    88 {
     91CanonicalForm univarQGCD( const CanonicalForm & F, const CanonicalForm & G )
     92{ // F,G in Q(a)[x]
    8993  CanonicalForm f, g, tmp, M, q, D, Dp, cl, newD, newq;
    9094  int p, dp_deg, bound, i;
     
    133137    dp_deg = degree(Dp);
    134138
    135     if( !dp_deg ) // early termination
     139    if( dp_deg == 0 ) // early termination
     140    {
     141      CanonicalForm inv;
     142      tryInvert(Dp, M, inv, fail);
     143      if(fail)
     144        continue;
    136145      return CanonicalForm(1);
     146    }
    137147
    138148    if( dp_deg > bound ) // current prime unlucky
     
    171181  return D;
    172182}
     183
     184
     185CanonicalForm QGCD( const CanonicalForm & F, const CanonicalForm & G )
     186{ // F,G in Q(a)[x1,...,xn]
     187  if(F.isZero())
     188  {
     189    if(G.isZero())
     190      return G; // G is zero
     191    if(G.inCoeffDomain())
     192      return CanonicalForm(1);
     193    return G/Lc(G); // return monic G
     194  }
     195  if(G.isZero()) // F is non-zero
     196  {
     197    if(F.inCoeffDomain())
     198      return CanonicalForm(1);
     199    return F/Lc(F); // return monic F
     200  }
     201  if(F.inCoeffDomain() || G.inCoeffDomain())
     202    return CanonicalForm(1);
     203
     204  CanonicalForm D;
     205  if (getCharacteristic()==0)
     206  {
     207    CanonicalForm f,g,tmp, M, q, Dp, cl, newD, newq;
     208    int p, i;
     209    int *bound, *other; // degree vectors
     210    bool fail;
     211    On(SW_RATIONAL);
     212    f = F * bCommonDen(F);
     213    g = G * bCommonDen(G);
     214    Variable a,b;
     215    if( !hasFirstAlgVar( f, a ) && !hasFirstAlgVar( g, b ))
     216    {
     217      // F and G are in Q[x1,...,xn], call...
     218      return gcd_poly_0( f, g );
     219    }
     220    if( b.level() > a.level() )
     221      a = b;
     222    // here: a is the biggest alg. var in f and g
     223    tmp = getMipo(a);
     224    M = tmp * bCommonDen(tmp);
     225    Off( SW_RATIONAL );
     226    // here: f, g in Z[y][x1,...,xn], M in Z[y] not necessarily monic
     227    // calculate upper bound for degree of gcd
     228    int mv = f.level();
     229    if(g.level() > mv)
     230      mv = g.level();
     231    // here: mv is level of the largest variable in f, g
     232    bound = new int[mv+1];
     233    other = new int[mv+1];
     234    for(int i=1; i<=mv; i++)
     235      bound[i] = other[i] = 0;
     236    bound = leadDeg(f,bound);
     237    other = leadDeg(g,other);
     238    for(int i=1; i<=mv; i++) // entry at i=0 is not visited
     239      if(other[i] < bound[i])
     240        bound[i] = other[i];
     241    // now bound points on the smaller vector
     242    cl = lc(M) * lc(f) * lc(g);
     243    q = 1;
     244    D = 0;
     245    for(int i=cf_getNumBigPrimes()-1; i>-1; i--)
     246    {
     247      p = cf_getBigPrime(i);
     248      if( mod( cl, p ).isZero() ) // skip lc-bad primes
     249        continue;
     250
     251      fail = false;
     252      setCharacteristic(p);
     253      tryBrownGCD( mapinto(f), mapinto(g), mapinto(M), Dp, fail );
     254      setCharacteristic(0);
     255      if( fail ) // M splits in char p
     256        continue;
     257
     258      for(int i=1; i<=mv; i++)
     259        other[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg)
     260      other = leadDeg(Dp,other);
     261
     262      if( other==0 ) // early termination
     263      {
     264        // Dp is in coeff domain
     265        CanonicalForm inv;
     266        tryInvert(Dp,M,inv,fail); // check if zero-divisor
     267        if(fail)
     268          continue;
     269        return CanonicalForm(1);
     270      }
     271
     272      if( isLess(bound, other, 1, mv) ) // current prime unlucky
     273        continue;
     274
     275      if( isLess(other, bound, 1, mv) ) // all previous primes unlucky
     276      {
     277        q = p;
     278        D = mapinto(Dp); // shortcut CRA
     279        for(int i=1; i<=mv; i++) // tighten bound
     280          bound[i] = other[i];
     281        continue;
     282      }
     283      chineseRemainder( D, q, mapinto(Dp), p, newD, newq );
     284      // newD = Dp mod p
     285      // newD = D mod q
     286      // newq = p*q
     287      q = newq;
     288      if( D != newD )
     289      {
     290        D = newD;
     291        continue;
     292      }
     293      On( SW_RATIONAL );
     294      tmp = Farey( D, q );
     295      if( fdivides( tmp, f ) && fdivides( tmp, g )) // trial division
     296      {
     297        Off( SW_RATIONAL );
     298        return tmp;
     299      }
     300      Off( SW_RATIONAL );
     301    }
     302  }
     303  // hopefully, we never reach this point
     304  Off( SW_USE_QGCD );
     305  D = gcd( F, G );
     306  On( SW_USE_QGCD );
     307  return D;
     308}
     309
     310void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail )
     311{// assume F,G are multivariate polys over Z/p(a) for big prime p, M "univariate" polynomial in an algebraic variable
     312  printf("Brown ");
     313  if(F.isZero())
     314  {
     315    if(G.isZero())
     316    {
     317      result = G; // G is zero
     318      return;
     319    }
     320    if(G.inCoeffDomain())
     321    {
     322      tryInvert(G,M,result,fail);
     323      return;
     324    }
     325    // try to make G monic modulo M
     326    CanonicalForm inv;
     327    tryInvert(Lc(G),M,inv,fail);
     328    if(fail)
     329      return;
     330    result = inv*G;
     331    return;
     332  }
     333  if(G.isZero()) // F is non-zero
     334  {
     335    if(F.inCoeffDomain())
     336    {
     337      tryInvert(F,M,result,fail);
     338      return;
     339    }
     340    // try to make F monic modulo M
     341    CanonicalForm inv;
     342    tryInvert(Lc(F),M,inv,fail);
     343    if(fail)
     344      return;
     345    result = inv*F;
     346    return;
     347  }
     348  if(F.inCoeffDomain())
     349  {
     350    tryInvert(F,M,result,fail);
     351    return;
     352  }
     353  if(G.inCoeffDomain())
     354  {
     355    tryInvert(G,M,result,fail);
     356    return;
     357  }
     358  CFMap MM,NN;
     359  CFArray ps(1,2);
     360  ps[1] = F;
     361  ps[2] = G;
     362  compress(ps,MM,NN); // maps MM, NN are created
     363  CanonicalForm f=MM(F);
     364  CanonicalForm g=MM(G);
     365  // here: f, g are compressed
     366  // compute largest variable in f or g (least one is Variable(1))
     367  int mv = f.level();
     368  if(g.level() > mv)
     369    mv = g.level();
     370  // here: mv is level of the largest variable in f, g
     371  if(mv == 1) // f,g univariate
     372  {
     373    tryEuclid(f,g,M,result,fail);
     374    if(fail)
     375      return;
     376    result = NN(result); // do not forget to map back
     377    return;
     378  }
     379  // here: mv > 1
     380  CanonicalForm cf = vcontent(f, Variable(2)); // cf is univariate poly in var(1)
     381  CanonicalForm cg = vcontent(g, Variable(2));
     382  CanonicalForm c;
     383  tryEuclid(cf,cg,M,c,fail);
     384  if(fail)
     385    return;
     386  f/=cf;
     387  g/=cg;
     388  if(f.inCoeffDomain())
     389  {
     390    tryInvert(f,M,result,fail);
     391    if(fail)
     392      return;
     393    result = NN(result);
     394    return;
     395  }
     396  if(g.inCoeffDomain())
     397  {
     398    tryInvert(g,M,result,fail);
     399    if(fail)
     400      return;
     401    result = NN(result);
     402    return;
     403  }
     404  int *L = new int[mv+1]; // L is addressed by i from 2 to mv
     405  int *N = new int[mv+1];
     406  for(int i=2; i<=mv; i++)
     407    L[i] = N[i] = 0;
     408  L = leadDeg(f, L);
     409  N = leadDeg(g, N);
     410  CanonicalForm gamma;
     411  tryEuclid( firstLC(f), firstLC(g), M, gamma, fail );
     412  if(fail)
     413    return;
     414  for(int i=2; i<=mv; i++) // entry at i=1 is not visited
     415    if(N[i] < L[i])
     416      L[i] = N[i];
     417  // L is now upper bound for degrees of gcd
     418  int *dg_im = new int[mv+1]; // for the degree vector of the image we don't need any entry at i=1
     419  for(int i=2; i<=mv; i++)
     420    dg_im[i] = 0; // initialize
     421  CanonicalForm gamma_image, m=1;
     422  CanonicalForm gm=0;
     423  CanonicalForm g_image, alpha, gnew, mnew;
     424  FFGenerator gen = FFGenerator();
     425  for(FFGenerator gen = FFGenerator(); gen.hasItems(); gen.next())
     426  {
     427    alpha = gen.item();
     428    gamma_image = gamma(alpha, Variable(1)); // plug in alpha for var(1)
     429    if(gamma_image.isZero()) // skip lc-bad points var(1)-alpha
     430      continue;
     431    tryBrownGCD( f(alpha, Variable(1)), g(alpha, Variable(1)), M, g_image, fail ); // recursive call with one var less
     432    if(fail)
     433      return;
     434    if(g_image.inCoeffDomain()) // early termination
     435    {
     436      tryInvert(g_image,M,result,fail);
     437      if(fail)
     438        return;
     439      result = NN(c);
     440      return;
     441    }
     442    for(int i=2; i<=mv; i++)
     443      dg_im[i] = 0; // reset (this is necessary, because some entries may not be updated by call to leadDeg)
     444    dg_im = leadDeg(g_image, dg_im); // dg_im cannot be NIL-pointer
     445    if(isEqual(dg_im, L, 2, mv))
     446    {
     447      g_image /= lc(g_image); // make g_image monic over Z/p
     448      g_image *= gamma_image; // multiply by multiple of image lc(gcd)
     449      tryCRA( g_image, Variable(1)-alpha, gm, m, gnew, mnew, fail );
     450      // gnew = gm mod m
     451      // gnew = g_image mod var(1)-alpha
     452      // mnew = m * (var(1)-alpha)
     453      if(fail)
     454        return;
     455      m = mnew;
     456      if(gnew == gm) // gnew did not change
     457      {
     458        g_image = gm / vcontent(gm, Variable(2));
     459        if(fdivides(g_image,f) && fdivides(g_image,g)) // trial division
     460        {
     461          result = NN(c*g_image);
     462          return;
     463        }
     464      }
     465      gm = gnew;
     466      continue;
     467    }
     468
     469    if(isLess(L, dg_im, 2, mv)) // dg_im > L --> current point unlucky
     470      continue;
     471
     472    if(isLess(dg_im, L, 2, mv)) // dg_im < L --> all previous points were unlucky
     473    {
     474      m = CanonicalForm(1); // reset
     475      gm = 0; // reset
     476      for(int i=2; i<=mv; i++) // tighten bound
     477        L[i] = dg_im[i];
     478    }
     479  }
     480  // we are out of evaluation points
     481  fail = true;
     482}
     483
     484
     485void tryCRA( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew, bool & fail )
     486{ // polys of level <= 1 are considered coefficients. q1,q2 are assumed to be coprime
     487  // xnew = x1 mod q1 (coefficientwise in the above sense)
     488  // xnew = x2 mod q2
     489  // qnew = q1*q2
     490  CanonicalForm tmp;
     491  if(x1.level() <= 1 && x2.level() <= 1) // base case
     492  {
     493    tryExtgcd(q1,q2,tmp,xnew,qnew,fail);
     494    if(fail)
     495      return;
     496    xnew = x1 + (x2-x1) * xnew * q1;
     497    qnew = q1*q2;
     498    xnew = mod(xnew,qnew);
     499    return;
     500  }
     501  CanonicalForm tmp2;
     502  xnew = 0;
     503  qnew = q1 * q2;
     504  // here: x1.level() > 1 || x2.level() > 1
     505  if(x1.level() > x2.level())
     506  {
     507    for(CFIterator i=x1; i.hasTerms(); i++)
     508    {
     509      if(i.exp() == 0) // const. term
     510      {
     511        tryCRA(i.coeff(),q1,x2,q2,tmp,tmp2,fail);
     512        if(fail)
     513          return;
     514        xnew += tmp;
     515      }
     516      else
     517      {
     518        tryCRA(i.coeff(),q1,0,q2,tmp,tmp2,fail);
     519        if(fail)
     520          return;
     521        xnew += tmp * power(x1.mvar(),i.exp());
     522      }
     523    }
     524    return;
     525  }
     526  // here: x1.level() <= x2.level() && ( x1.level() > 1 || x2.level() > 1 )
     527  if(x2.level() > x1.level())
     528  {
     529    for(CFIterator j=x2; j.hasTerms(); j++)
     530    {
     531      if(j.exp() == 0) // const. term
     532      {
     533        tryCRA(x1,q1,j.coeff(),q2,tmp,tmp2,fail);
     534        if(fail)
     535          return;
     536        xnew += tmp;
     537      }
     538      else
     539      {
     540        tryCRA(0,q1,j.coeff(),q2,tmp,tmp2,fail);
     541        if(fail)
     542          return;
     543        xnew += tmp * power(x2.mvar(),j.exp());
     544      }
     545    }
     546    return;
     547  }
     548  // here: x1.level() == x2.level() && x1.level() > 1 && x2.level() > 1
     549  CFIterator i = x1;
     550  CFIterator j = x2;
     551  while(i.hasTerms() || j.hasTerms())
     552  {
     553    if(i.hasTerms())
     554    {
     555      if(j.hasTerms())
     556      {
     557        if(i.exp() == j.exp())
     558        {
     559          tryCRA(i.coeff(),q1,j.coeff(),q2,tmp,tmp2,fail);
     560          if(fail)
     561            return;
     562          xnew += tmp * power(x1.mvar(),i.exp());
     563          i++; j++;
     564        }
     565        else
     566        {
     567          if(i.exp() < j.exp())
     568          {
     569            tryCRA(i.coeff(),q1,0,q2,tmp,tmp2,fail);
     570            if(fail)
     571              return;
     572            xnew += tmp * power(x1.mvar(),i.exp());
     573            i++;
     574          }
     575          else // i.exp() > j.exp()
     576          {
     577            tryCRA(0,q1,j.coeff(),q2,tmp,tmp2,fail);
     578            if(fail)
     579              return;
     580            xnew += tmp * power(x1.mvar(),j.exp());
     581            j++;
     582          }
     583        }
     584      }
     585      else // j is out of terms
     586      {
     587        tryCRA(i.coeff(),q1,0,q2,tmp,tmp2,fail);
     588        if(fail)
     589          return;
     590        xnew += tmp * power(x1.mvar(),i.exp());
     591        i++;
     592      }
     593    }
     594    else // i is out of terms
     595    {
     596      tryCRA(0,q1,j.coeff(),q2,tmp,tmp2,fail);
     597      if(fail)
     598        return;
     599      xnew += tmp * power(x1.mvar(),j.exp());
     600      j++;
     601    }
     602  }
     603}
     604
     605
     606void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail )
     607{
     608  // F, G are univariate polynomials (i.e. they have exactly one polynomial variable)
     609  // F and G must have the same level AND level > 0
     610  // we try to calculate gcd(f,g) = s*F + t*G
     611  // if a zero divisor is encontered, 'fail' is set to one
     612  Variable a, b;
     613  if( !hasFirstAlgVar(F,a) && !hasFirstAlgVar(G,b) ) // note lazy evaluation
     614  {
     615    result = extgcd( F, G, s, t ); // no zero divisors possible
     616    return;
     617  }
     618  if( b.level() > a.level() )
     619    a = b;
     620  // here: a is the biggest alg. var in F and G
     621  CanonicalForm M = getMipo(a);
     622  CanonicalForm P;
     623  if( degree(F) > degree(G) )
     624  {
     625    P=F; result=G; s=0; t=1;
     626  }
     627  else
     628  {
     629    P=G; result=F; s=1; t=0;
     630  }
     631  CanonicalForm inv, rem, q, u, v;
     632  // here: degree(P) >= degree(result)
     633  while(true)
     634  {
     635    tryInvert( Lc(result), M, inv, fail );
     636    if(fail)
     637      return;
     638    // here: Lc(result) is invertible modulo M
     639    q = Lc(P)*inv * power( P.mvar(), degree(P)-degree(result) );
     640    rem = P - q*result;
     641    // here: s*F + t*G = result
     642    if( rem.isZero() )
     643    {
     644      s*=inv;
     645      t*=inv;
     646      result *= inv; // monify result
     647      return;
     648    }
     649    P=result;
     650    result=rem;
     651    rem=u-q*s;
     652    u=s;
     653    s=rem;
     654    rem=v-q*t;
     655    v=t;
     656    t=rem;
     657  }
     658}
  • factory/algext.h

    r863f53 r359d742  
    55
    66CanonicalForm QGCD( const CanonicalForm &, const CanonicalForm & );
     7CanonicalForm univarQGCD( const CanonicalForm & F, const CanonicalForm & G );
    78void tryEuclid( const CanonicalForm &, const CanonicalForm &, const CanonicalForm, CanonicalForm &, bool & );
    89void tryInvert( const CanonicalForm &, const CanonicalForm &, CanonicalForm &, bool & );
    910bool hasFirstAlgVar( const CanonicalForm &, Variable & );
     11void tryBrownGCD( const CanonicalForm & F, const CanonicalForm & G, const CanonicalForm & M, CanonicalForm & result, bool & fail );
     12void tryCRA( const CanonicalForm & x1, const CanonicalForm & q1, const CanonicalForm & x2, const CanonicalForm & q2, CanonicalForm & xnew, CanonicalForm & qnew, bool & fail );
     13void tryExtgcd( const CanonicalForm & F, const CanonicalForm & G, CanonicalForm & result, CanonicalForm & s, CanonicalForm & t, bool & fail );
     14
     15
     16
  • factory/cf_defs.h

    r863f53 r359d742  
    11/* emacs edit mode for this file is -*- C++ -*- */
    2 /* $Id: cf_defs.h,v 1.14 2008-06-16 12:55:08 Singular Exp $ */
     2/* $Id: cf_defs.h,v 1.15 2008-06-24 12:52:44 Singular Exp $ */
    33
    44#ifndef INCL_CF_DEFS_H
     
    4343const int SW_USE_GCD_P=14;
    4444const int SW_USE_QGCD=15;
     45const int SW_USE_fieldGCD=16;
    4546//}}}
    4647
  • factory/cf_switches.cc

    r863f53 r359d742  
    11/* emacs edit mode for this file is -*- C++ -*- */
    2 /* $Id: cf_switches.cc,v 1.10 2008-06-16 12:54:25 Singular Exp $ */
     2/* $Id: cf_switches.cc,v 1.11 2008-06-24 12:52:44 Singular Exp $ */
    33
    44//{{{ docu
     
    3737  On(SW_USE_EZGCD);
    3838  //On(SW_USE_EZGCD_P); // still testing
    39   //On(SW_USE_QGCD);
     39  On(SW_USE_QGCD);
     40  On(SW_USE_fieldGCD);
    4041}
    4142//}}}
  • factory/cf_switches.h

    r863f53 r359d742  
    11/* emacs edit mode for this file is -*- C++ -*- */
    2 /* $Id: cf_switches.h,v 1.13 2008-06-16 12:54:05 Singular Exp $ */
     2/* $Id: cf_switches.h,v 1.14 2008-06-24 12:52:44 Singular Exp $ */
    33
    44#ifndef INCL_CF_SWITCHES_H
     
    1919//
    2020//}}}
    21 const int CFSwitchesMax = 16;
     21const int CFSwitchesMax = 17;
    2222//}}}
    2323
Note: See TracChangeset for help on using the changeset viewer.