Ignore:
Timestamp:
Jul 6, 2011, 4:41:07 PM (13 years ago)
Author:
Frank Seelisch <seelisch@…>
Branches:
(u'spielwiese', '17f1d200f27c5bd38f5dfc6e8a0879242279d1d8')
Children:
6c19d854882ab99fd19b9b972a32606106c2f2ee
Parents:
2d3091c7bb239cd4787574560ab475ac88621da7
git-author:
Frank Seelisch <seelisch@mathematik.uni-kl.de>2011-07-06 16:41:07+02:00
git-committer:
Mohamed Barakat <mohamed.barakat@rwth-aachen.de>2011-11-09 12:39:12+01:00
Message:
handled nested fractions (when over Q), found bug in longrat.cc (see coeffs_test.h:507)
File:
1 edited

Legend:

Unmodified
Added
Removed
  • libpolys/polys/ext_fields/transext.cc

    r2d3091c r06df101  
    77*           transcendental variables t_1, ..., t_s, where s >= 1.
    88*           Denoting the implemented coeffs object by cf, then these numbers
    9 *           are represented as quotients of polynomials in the polynomial
    10 *           ring K[t_1, .., t_s] represented by cf->extring.
     9*           are represented as quotients of polynomials living in the
     10*           polynomial ring K[t_1, .., t_s] represented by cf->extring.
     11*
     12*           An element of K(t_1, .., t_s) may have numerous representations,
     13*           due to the possibility of common polynomial factors in the
     14*           numerator and denominator. This problem is handled by a
     15*           cancellation heuristic: Each number "knows" its complexity
     16*           which is 0 if and only if common factors have definitely been
     17*           cancelled, and some positive integer otherwise.
     18*           Each arithmetic operation of two numbers with complexities c1
     19*           and c2 will result in a number of complexity c1 + c2 + some
     20*           penalty (specific for each arithmetic operation; see constants
     21*           in the *.h file). Whenever the resulting complexity exceeds a
     22*           certain threshold (see constant in the *.h file), then the
     23*           cancellation heuristic will call 'factory' to compute the gcd
     24*           and cancel it out in the given number. (This definite cancel-
     25*           lation will also be performed at the beginning of ntWrite,
     26*           ensuring that any output is free of common factors.
     27*           For the special case of K = Q (i.e., when computing over the
     28*           rationals), this definite cancellation procedure will also take
     29*           care of nested fractions: If there are fractional coefficients
     30*           in the numerator or denominator of a number, then this number
     31*           is being replaced by a quotient of two polynomials over Z, or
     32*           - if the denominator is a constant - by a polynomial over Q.
    1133*/
    1234
     
    7193void heuristicGcdCancellation(number a, const coeffs cf);
    7294void definiteGcdCancellation(number a, const coeffs cf,
    73                              BOOLEAN skipSimpleTests);
     95                             BOOLEAN simpleTestsHaveAlreadyBeenPerformed);
     96void handleNestedFractionsOverQ(fraction f, const coeffs cf);
    7497
    7598#ifdef LDEBUG
     
    529552}
    530553
     554/* assumes that cf represents the rationals, i.e. Q, and will only
     555   be called in that case;
     556   assumes furthermore that f != NULL and that the denominator of f != 1;
     557   generally speaking, this method removes denominators in the rational
     558   coefficients of the numerator and denominator of 'a';
     559   more concretely, the following normalizations will be performed,
     560   where t^alpha denotes a monomial in the transcendental variables t_k
     561   (1) if 'a' is of the form
     562          (sum_alpha a_alpha/b_alpha * t^alpha)
     563          -------------------------------------
     564            (sum_beta c_beta/d_beta * t^beta)
     565       with integers a_alpha, b_alpha, c_beta, d_beta, then both the
     566       numerator and the denominator will be multiplied by the LCM of
     567       the b_alpha's and the d_beta's (if this LCM is != 1),
     568   (2) if 'a' is - e.g. after having performed step (1) - of the form
     569          (sum_alpha a_alpha * t^alpha)
     570          -----------------------------
     571            (sum_beta c_beta * t^beta)
     572       with integers a_alpha, c_beta, and with a non-constant denominator,
     573       then both the numerator and the denominator will be divided by the
     574       GCD of the a_alpha's and the c_beta's (if this GCD is != 1),
     575   (3) if 'a' is - e.g. after having performed steps (1) and (2) - of the
     576       form
     577          (sum_alpha a_alpha * t^alpha)
     578          -----------------------------
     579                        c
     580       with integers a_alpha, and c != 1, then 'a' will be replaced by
     581       (sum_alpha a_alpha/c * t^alpha);
     582   this procedure does not alter COM(f) (this has to be done by the
     583   calling procedure);
     584   modifies f */
     585void handleNestedFractionsOverQ(fraction f, const coeffs cf)
     586{
     587  assume(nCoeff_is_Q(ntCoeffs));
     588  assume(!IS0(f));
     589  assume(!DENIS1(f));
     590 
     591  if (!p_IsConstant(DEN(f), ntRing))
     592  { /* step (1); see documentation of this procedure above */
     593    number lcmOfDenominators = n_Init(1, ntCoeffs);
     594    number c; number tmp;
     595    poly p = NUM(f);
     596    /* careful when using n_Lcm!!! It computes the lcm of the numerator
     597       of the 1st argument and the denominator of the 2nd!!! */
     598    while (p != NULL)
     599    {
     600      c = p_GetCoeff(p, ntRing);
     601      tmp = n_Lcm(lcmOfDenominators, c, ntCoeffs);
     602      n_Delete(&lcmOfDenominators, ntCoeffs);
     603      lcmOfDenominators = tmp;
     604      pIter(p);
     605    }
     606    p = DEN(f);
     607    while (p != NULL)
     608    {
     609      c = p_GetCoeff(p, ntRing);
     610      tmp = n_Lcm(lcmOfDenominators, c, ntCoeffs);
     611      n_Delete(&lcmOfDenominators, ntCoeffs);
     612      lcmOfDenominators = tmp;
     613      pIter(p);
     614    }
     615    if (!n_IsOne(lcmOfDenominators, ntCoeffs))
     616    { /* multiply NUM(f) and DEN(f) with lcmOfDenominators */
     617      NUM(f) = p_Mult_nn(NUM(f), lcmOfDenominators, ntRing);
     618      DEN(f) = p_Mult_nn(DEN(f), lcmOfDenominators, ntRing);
     619    }
     620    n_Delete(&lcmOfDenominators, ntCoeffs);
     621    if (!p_IsConstant(DEN(f), ntRing))
     622    { /* step (2); see documentation of this procedure above */
     623      p = NUM(f);
     624      number gcdOfCoefficients = n_Copy(p_GetCoeff(p, ntRing), ntCoeffs);
     625      pIter(p);
     626      while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs)))
     627      {
     628        c = p_GetCoeff(p, ntRing);
     629        tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs);
     630        n_Delete(&gcdOfCoefficients, ntCoeffs);
     631        gcdOfCoefficients = tmp;
     632        pIter(p);
     633      }
     634      p = DEN(f);
     635      while ((p != NULL) && (!n_IsOne(gcdOfCoefficients, ntCoeffs)))
     636      {
     637        c = p_GetCoeff(p, ntRing);
     638        tmp = n_Gcd(c, gcdOfCoefficients, ntCoeffs);
     639        n_Delete(&gcdOfCoefficients, ntCoeffs);
     640        gcdOfCoefficients = tmp;
     641        pIter(p);
     642      }
     643      if (!n_IsOne(gcdOfCoefficients, ntCoeffs))
     644      { /* divide NUM(f) and DEN(f) by gcdOfCoefficients */
     645        number inverseOfGcdOfCoefficients = n_Invers(gcdOfCoefficients,
     646                                                     ntCoeffs);
     647        NUM(f) = p_Mult_nn(NUM(f), inverseOfGcdOfCoefficients, ntRing);
     648        DEN(f) = p_Mult_nn(DEN(f), inverseOfGcdOfCoefficients, ntRing);
     649        n_Delete(&inverseOfGcdOfCoefficients, ntCoeffs);
     650      }
     651      n_Delete(&gcdOfCoefficients, ntCoeffs);
     652    }
     653  }
     654  if (p_IsConstant(DEN(f), ntRing) &&
     655      (!n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs)))
     656  { /* step (3); see documentation of this procedure above */
     657    number inverseOfDen = n_Invers(p_GetCoeff(DEN(f), ntRing), ntCoeffs);
     658    NUM(f) = p_Mult_nn(NUM(f), inverseOfDen, ntRing);
     659    n_Delete(&inverseOfDen, ntCoeffs);
     660    p_Delete(&DEN(f), ntRing);
     661    DEN(f) = NULL;
     662  }
     663 
     664  /* Now, due to the above computations, DEN(f) may have become the
     665     1-polynomial which needs to be represented by NULL: */
     666  if ((DEN(f) != NULL) &&
     667      p_IsConstant(DEN(f), ntRing) &&
     668      n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
     669  {
     670    p_Delete(&DEN(f), ntRing); DEN(f) = NULL;
     671  }
     672}
     673
    531674/* modifies a */
    532675void heuristicGcdCancellation(number a, const coeffs cf)
     
    553696/* modifies a */
    554697void definiteGcdCancellation(number a, const coeffs cf,
    555                              BOOLEAN skipSimpleTests)
     698                             BOOLEAN simpleTestsHaveAlreadyBeenPerformed)
    556699{
    557700  ntTest(a);
     
    559702  fraction f = (fraction)a;
    560703 
    561   if (!skipSimpleTests)
     704  if (!simpleTestsHaveAlreadyBeenPerformed)
    562705  {
    563706    if (IS0(a)) return;
     
    574717  }
    575718 
    576 #ifdef HAVE_FACTORY
    577   /* singclap_gcd destroys its arguments. We hence need copies: */
     719#ifdef HAVE_FACTORY 
     720  /* singclap_gcd destroys its arguments; we hence need copies: */
    578721  poly pNum = p_Copy(NUM(f), ntRing);
    579722  poly pDen = p_Copy(DEN(f), ntRing);
     723 
     724  /* Note that, over Q, singclap_gcd will remove the denominators in all
     725     rational coefficients of pNum and pDen, before starting to compute
     726     the gcd. Thus, we do not need to ensure that the coefficients of
     727     pNum and pDen live in Z; they may well be elements of Q\Z. */
    580728  poly pGcd = singclap_gcd(pNum, pDen, cf->extRing);
    581729  if (p_IsConstant(pGcd, ntRing) &&
    582730      n_IsOne(p_GetCoeff(pGcd, ntRing), ntCoeffs))
    583   {
    584       /* gcd = 1; nothing to cancel */
     731  { /* gcd = 1; nothing to cancel;
     732       Suppose the given rational function field is over Q. Although the
     733       gcd is 1, we may have produced fractional coefficients in NUM(f),
     734       DEN(f), or both, due to previous arithmetics. The next call will
     735       remove those nested fractions, in case there are any. */
     736    if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf);
    585737  }
    586738  else
    587   {
    588       poly newNum = singclap_pdivide(NUM(f), pGcd, ntRing);
    589       p_Delete(&NUM(f), ntRing);
    590       NUM(f) = newNum;
    591       poly newDen = singclap_pdivide(DEN(f), pGcd, ntRing);
     739  { /* We divide both NUM(f) and DEN(f) by the gcd which is known
     740       to be != 1. */
     741    poly newNum = singclap_pdivide(NUM(f), pGcd, ntRing);
     742    p_Delete(&NUM(f), ntRing);
     743    NUM(f) = newNum;
     744    poly newDen = singclap_pdivide(DEN(f), pGcd, ntRing);
     745    p_Delete(&DEN(f), ntRing);
     746    DEN(f) = newDen;
     747    if (p_IsConstant(DEN(f), ntRing) &&
     748        n_IsOne(p_GetCoeff(DEN(f), ntRing), ntCoeffs))
     749    {
     750      /* DEN(f) = 1 needs to be represented by NULL! */
    592751      p_Delete(&DEN(f), ntRing);
    593       if (p_IsConstant(newDen, ntRing) &&
    594           n_IsOne(p_GetCoeff(newDen, ntRing), ntCoeffs))
    595       {
    596         /* newDen = 1 needs to be represented by NULL */
    597         p_Delete(&newDen, ntRing);
    598         newDen = NULL;
    599       }
    600       DEN(f) = newDen;
     752      newDen = NULL;
     753    }
     754    else
     755    { /* Note that over Q, by cancelling the gcd, we may have produced
     756         fractional coefficients in NUM(f), DEN(f), or both. The next
     757         call will remove those nested fractions, in case there are
     758         any. */
     759      if (nCoeff_is_Q(ntCoeffs)) handleNestedFractionsOverQ(f, cf);
     760    }
    601761  }
    602762  COM(f) = 0;
Note: See TracChangeset for help on using the changeset viewer.