Home | History | Annotate | Line # | Download | only in src
      1 /* mpfr_cmp2 -- exponent shift when subtracting two numbers.
      2 
      3 Copyright 1999-2004, 2006-2023 Free Software Foundation, Inc.
      4 Contributed by the AriC and Caramba projects, INRIA.
      5 
      6 This file is part of the GNU MPFR Library.
      7 
      8 The GNU MPFR Library is free software; you can redistribute it and/or modify
      9 it under the terms of the GNU Lesser General Public License as published by
     10 the Free Software Foundation; either version 3 of the License, or (at your
     11 option) any later version.
     12 
     13 The GNU MPFR Library is distributed in the hope that it will be useful, but
     14 WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     15 or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
     16 License for more details.
     17 
     18 You should have received a copy of the GNU Lesser General Public License
     19 along with the GNU MPFR Library; see the file COPYING.LESSER.  If not, see
     20 https://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc.,
     21 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */
     22 
     23 
     24 #define MPFR_NEED_LONGLONG_H
     25 #include "mpfr-impl.h"
     26 
     27 /* If |b| != |c|, puts the number of canceled bits when one subtracts |c|
     28    from |b| in *cancel. Returns the sign of the difference (-1, 0, 1).
     29 
     30    Assumes neither of b or c is NaN, +/- infinity, or +/- 0.
     31 
     32    In other terms, if |b| != |c|, mpfr_cmp2 (b, c) stores
     33    EXP(max(|b|,|c|)) - EXP(|b| - |c|) in *cancel.
     34 
     35    One necessarily has 0 <= cancel <= max(PREC(b),PREC(c)), so that this
     36    value is representable in a mpfr_prec_t. Note that in the code, the
     37    maximum intermediate value is cancel + 1, but since MPFR_PREC_MAX is
     38    not the maximum value of mpfr_prec_t, there is no integer overflow.
     39 */
     40 
     41 int
     42 mpfr_cmp2 (mpfr_srcptr b, mpfr_srcptr c, mpfr_prec_t *cancel)
     43 {
     44   mp_limb_t *bp, *cp, bb, cc, lastc, dif;
     45   int high_dif;  /* manipulated like a boolean */
     46   mp_size_t bn, cn;
     47   mpfr_exp_t sdiff_exp;
     48   mpfr_uexp_t diff_exp;
     49   mpfr_prec_t res = 0;  /* will be the number of canceled bits (*cancel) */
     50   int sign;
     51 
     52   /* b=c should not happen, since cmp2 is called only from agm (with
     53      different variables) and from sub1 (if b=c, then sub1sp would be
     54      called instead). So, no need for a particular optimization here. */
     55 
     56   /* the cases b=0 or c=0 are also treated apart in agm and sub
     57      (which calls sub1) */
     58   MPFR_ASSERTD (MPFR_IS_PURE_UBF (b));
     59   MPFR_ASSERTD (MPFR_IS_PURE_UBF (c));
     60 
     61   sdiff_exp = MPFR_UNLIKELY (MPFR_IS_UBF (b) || MPFR_IS_UBF (c)) ?
     62     mpfr_ubf_diff_exp (b, c) : MPFR_GET_EXP (b) - MPFR_GET_EXP (c);
     63 
     64   /* The returned result is saturated to [MPFR_EXP_MIN,MPFR_EXP_MAX],
     65      which is the range of the mpfr_exp_t type. But under the condition
     66      below, since |MPFR_EXP_MIN| >= MPFR_EXP_MAX, the value of cancel
     67      will not be affected: by symmetry (as done in the code), assume
     68      |b| >= |c|; if EXP(b) - EXP(c) >= MPFR_EXP_MAX, then |c| < ulp(b),
     69      so that the value of cancel is 0, or 1 if |b| is a power of 2,
     70      whatever the exact value of EXP(b) - EXP(c). */
     71   MPFR_STAT_STATIC_ASSERT (MPFR_EXP_MAX > MPFR_PREC_MAX);
     72 
     73   if (sdiff_exp >= 0)
     74     {
     75       sign = 1;  /* assumes |b| > |c|; will be changed if not. */
     76       diff_exp = sdiff_exp;
     77 
     78       bp = MPFR_MANT(b);
     79       cp = MPFR_MANT(c);
     80 
     81       /* index of the most significant limb of b and c */
     82       bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
     83       cn = (MPFR_PREC(c) - 1) / GMP_NUMB_BITS;
     84 
     85       /* If diff_exp != 0, i.e. diff_exp > 0, then |b| > |c|. Otherwise... */
     86       if (diff_exp == 0)
     87         {
     88           /* Skip the identical most significant limbs, adding GMP_NUMB_BITS
     89              to the number of canceled bits at each iteration. */
     90           while (bn >= 0 && cn >= 0 && bp[bn] == cp[cn])
     91             {
     92               bn--;
     93               cn--;
     94               res += GMP_NUMB_BITS;
     95             }
     96 
     97           if (MPFR_UNLIKELY (bn < 0))
     98             {
     99               if (MPFR_LIKELY (cn < 0)) /* |b| = |c| */
    100                 return 0;
    101 
    102               /* b has been read entirely, but not c. Thus |b| <= |c|.
    103                  Swap (bp,bn) and (cp,cn), and take the opposite sign
    104                  for the symmetric case below (simulating a swap).
    105                  Note: cp will not be used, thus is not assigned; and
    106                  "cn = -1;" is necessary to enter the following "if"
    107                  (probably less confusing than a "goto"). */
    108               bp = cp;
    109               bn = cn;
    110               cn = -1;
    111               sign = -1;
    112             }
    113 
    114           if (MPFR_UNLIKELY (cn < 0))
    115             /* c discards exactly the upper part of b */
    116             {
    117               int z;
    118 
    119               MPFR_ASSERTD (bn >= 0);
    120 
    121               /* Skip null limbs of b (= non-represented null limbs of c),
    122                  adding GMP_NUMB_BITS to the number of canceled bits at
    123                  each iteration. */
    124               while (bp[bn] == 0)
    125                 {
    126                   if (--bn < 0) /* |b| = |c| */
    127                     return 0;
    128                   res += GMP_NUMB_BITS;
    129                 }
    130 
    131               count_leading_zeros (z, bp[bn]); /* bp[bn] != 0 */
    132               *cancel = res + z;
    133               return sign;
    134             }
    135 
    136           MPFR_ASSERTD (bn >= 0);
    137           MPFR_ASSERTD (cn >= 0);
    138           MPFR_ASSERTD (bp[bn] != cp[cn]);
    139 
    140           /* |b| != |c|. If |b| < |c|: swap (bp,bn) and (cp,cn),
    141              and take the opposite sign. */
    142           if (bp[bn] < cp[cn])
    143             {
    144               mp_limb_t *tp;
    145               mp_size_t tn;
    146 
    147               tp = bp; bp = cp; cp = tp;
    148               tn = bn; bn = cn; cn = tn;
    149               sign = -1;
    150             }
    151         }
    152     } /* MPFR_EXP(b) >= MPFR_EXP(c) */
    153   else /* MPFR_EXP(b) < MPFR_EXP(c) */
    154     {
    155       /* We necessarily have |b| < |c|. Simulate a swap by reading the
    156          parameters so that |(bp,bn)| > |(cp,cn)|. */
    157 
    158       sign = -1;
    159       diff_exp = - (mpfr_uexp_t) sdiff_exp;
    160 
    161       bp = MPFR_MANT(c);
    162       cp = MPFR_MANT(b);
    163 
    164       bn = (MPFR_PREC(c) - 1) / GMP_NUMB_BITS;
    165       cn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
    166     }
    167 
    168   /* Now we have removed the identical upper limbs of b and c
    169      (when diff_exp = 0), and after the possible swap, we have |b| > |c|,
    170      where b is represented by (bp,bn) and c is represented by (cp,cn).
    171      The value diff_exp = EXP(b) - EXP(c) can be regarded as the number
    172      of leading zeros of c, when aligned with b. */
    173 
    174   /* When a limb of c is read from memory, the part that is not taken
    175      into account for the operation with a limb bp[bn] of b will be put
    176      in lastc, shifted to the leftmost part (for alignment with b):
    177        [-------- bp[bn] --------][------- bp[bn-1] -------]
    178        [-- old_lastc --][-------- cp[cn] --------]
    179                                  [-- new_lastc --]
    180      Note: if diff_exp == 0, then lastc will always remain 0. */
    181   lastc = 0;
    182 
    183   /* Compute the next limb difference, which cannot be 0 (dif >= 1). */
    184 
    185   if (MPFR_LIKELY (diff_exp < GMP_NUMB_BITS))
    186     {
    187       cc = cp[cn] >> diff_exp;
    188       /* warning: a shift by GMP_NUMB_BITS is not allowed by ISO C */
    189       if (diff_exp != 0)
    190         lastc = cp[cn] << (GMP_NUMB_BITS - diff_exp);
    191       cn--;
    192     }
    193   else
    194     {
    195       cc = 0;
    196       diff_exp -= GMP_NUMB_BITS;  /* remove GMP_NUMB_BITS leading zeros */
    197     }
    198 
    199   MPFR_ASSERTD (bp[bn] >= cc);  /* no borrow out in subtraction below */
    200   dif = bp[bn--] - cc;
    201   MPFR_ASSERTD (dif >= 1);
    202   high_dif = 0;
    203 
    204   /* The current difference, here and later, is expressed under the form
    205      [high_dif][dif], where high_dif is 0 or 1, and dif is a limb.
    206      Here, since we have computed a difference of limbs (with b >= c),
    207      high_dif = 0. */
    208 
    209   /* One needs to accumulate canceled bits for the remaining case where
    210      b and c are close to each other due to a long borrow propagation:
    211        b = [common part]1000...000[low(b)]
    212        c = [common part]0111...111[low(c)]
    213      After eliminating the common part above, we have computed a difference
    214      of the most significant parts, which has been stored in [high_dif][dif]
    215      with high_dif = 0. We will loop as long as the currently computed
    216      difference [high_dif][dif] = 1 (it is >= 1 by construction). The
    217      computation of the difference will be:
    218         1bbb...bbb
    219        - ccc...ccc
    220      where the leading 1 before bbb...bbb corresponds to [high_dif][dif]
    221      at the beginning of the loop. We will exit the loop also when c has
    222      entirely been taken into account as cancellation is no longer possible
    223      in this case (it is no longer possible to cancel the leading 1).
    224      Note: We can enter the loop only with diff_exp = 0 (with a non-empty
    225      common part, partly or entirely removed) or with diff_exp = 1 (with
    226      an empty common part). Indeed, if diff_exp > 1, then no limbs have
    227      been skipped, so that bp[bn] had its MSB equal to 1 and the most two
    228      significant bits of cc are 0, which implies that dif > 1. */
    229 
    230   while (MPFR_UNLIKELY ((cn >= 0 || lastc != 0)
    231                         && high_dif == 0 && dif == 1))
    232     {
    233       /* Since we consider the next limb, we assume a cancellation of
    234          GMP_NUMB_BITS (the new exponent of the difference now being the
    235          one of the MSB of the next limb). But if the leading 1 remains
    236          1 in the difference (i.e. high_dif = 1 at the end of the loop),
    237          then we will need to decrease res. */
    238       res += GMP_NUMB_BITS;
    239       MPFR_ASSERTD (diff_exp <= 1);  /* see comment before the loop */
    240       bb = bn >= 0 ? bp[bn--] : 0;  /* next limb of b or non-represented 0 */
    241       if (MPFR_UNLIKELY (cn < 0))
    242         {
    243           cc = lastc;
    244           lastc = 0;
    245         }
    246       else if (diff_exp == 0)
    247         {
    248           cc = cp[cn--];
    249         }
    250       else
    251         {
    252           MPFR_ASSERTD (diff_exp == 1);
    253           MPFR_ASSERTD (lastc == 0 || lastc == MPFR_LIMB_HIGHBIT);
    254           cc = lastc + (cp[cn] >> 1);
    255           lastc = cp[cn--] << (GMP_NUMB_BITS - 1);
    256         }
    257       dif = bb - cc;
    258       high_dif = bb >= cc;
    259     }
    260 
    261   /* Now, c has entirely been taken into account or [high_dif][dif] > 1.
    262      In any case, [high_dif][dif] >= 1 by construction.
    263      First, we determine the currently number of canceled bits,
    264      corresponding to the exponent of the current difference.
    265      The trailing bits of c, if any, can still decrease the exponent of
    266      the difference when [high_dif][dif] is a power of two, but since
    267      [high_dif][dif] > 1 in this case, by not more than 1. */
    268 
    269   if (high_dif != 0) /* high_dif == 1 */
    270     {
    271       res--;  /* see comment at the beginning of the above loop */
    272       MPFR_ASSERTD (res >= 0);
    273       /* Terminate if [high_dif][dif] is not a power of two. */
    274       if (MPFR_LIKELY (dif != 0))
    275         goto end;
    276     }
    277   else /* high_dif == 0 */
    278     {
    279       int z;
    280 
    281       MPFR_ASSERTD (dif >= 1);  /* [high_dif][dif] >= 1 */
    282       count_leading_zeros (z, dif);
    283       res += z;
    284       /* Terminate if [high_dif][dif] is not a power of two. */
    285       if (MPFR_LIKELY (NOT_POW2 (dif)))
    286         goto end;
    287     }
    288 
    289   /* Now, the result will be res + (low(b) < low(c)). */
    290 
    291   /* If c has entirely been taken into account, it can no longer modify
    292      the current result. */
    293   if (cn < 0 && lastc == 0)
    294     goto end;
    295 
    296   for (; bn >= 0 ; bn--)
    297     {
    298       if (diff_exp >= GMP_NUMB_BITS)
    299         {
    300           diff_exp -= GMP_NUMB_BITS;
    301           MPFR_ASSERTD (cc == 0);
    302         }
    303       else if (MPFR_UNLIKELY (cn < 0))
    304         {
    305           cc = lastc;
    306           lastc = 0;
    307         }
    308       else if (diff_exp == 0)
    309         {
    310           cc = cp[cn--];
    311         }
    312       else
    313         {
    314           MPFR_ASSERTD (diff_exp >= 1 && diff_exp < GMP_NUMB_BITS);
    315           cc = lastc + (cp[cn] >> diff_exp);
    316           lastc = cp[cn--] << (GMP_NUMB_BITS - diff_exp);
    317         }
    318 
    319       if (bp[bn] != cc)
    320         {
    321           res += bp[bn] < cc;
    322           goto end;
    323         }
    324     }
    325 
    326   /* b has entirely been read. Determine whether the trailing part of c
    327      is non-zero. */
    328 
    329   if (lastc != 0)
    330     res++;
    331   else
    332     {
    333       while (cn >= 0 && cp[cn] == 0)
    334         cn--;
    335       if (cn >= 0)
    336         res++;
    337     }
    338 
    339  end:
    340   *cancel = res;
    341   return sign;
    342 }
    343