static void
check_overflow (void)
{
  mpfr_t x, y, z1, z2;
  mpfr_exp_t emin, emax;

  emin = mpfr_get_emin ();
  emax = mpfr_get_emax ();

  set_emin (-1021);
  set_emax (1024);

  mpfr_inits (x, y, z1, z2, (mpfr_ptr) 0);

  mpfr_set_str1 (x, "8.00468257869324898448e+307");
  mpfr_set_str1 (y, "7.44784712422708645156e+307");
  mpfr_add1sp (z1, x, y, MPFR_RNDN);
  mpfr_add1   (z2, x, y, MPFR_RNDN);
  if (mpfr_cmp (z1, z2))
    {
      printf ("Overflow bug in add1sp.\n");
      exit (1);
    }
  mpfr_clears (x, y, z1, z2, (mpfr_ptr) 0);

  set_emin (emin);
  set_emax (emax);
}
static void
check_random (mpfr_prec_t p)
{
  mpfr_t a1,b,c,a2;
  int r;
  int i, inexact1, inexact2;

  mpfr_inits2 (p, a1, b, c, a2, (mpfr_ptr) 0);

  for (i = 0 ; i < 500 ; i++)
    {
      mpfr_urandomb (b, RANDS);
      mpfr_urandomb (c, RANDS);
      if (MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c))
        {
          if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
            mpfr_swap(b, c);
          if (MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c))
            for (r = 0 ; r < MPFR_RND_MAX ; r++)
              {
                inexact1 = mpfr_add1(a1, b, c, (mpfr_rnd_t) r);
                inexact2 = mpfr_add1sp(a2, b, c, (mpfr_rnd_t) r);
                if (mpfr_cmp(a1, a2))
                  STD_ERROR;
                if (inexact1 != inexact2)
                  STD_ERROR2;
              }
        }
    }

  mpfr_clears (a1, a2, b, c, (mpfr_ptr) 0);
}
static void
check_special (void)
{
  mpfr_t a1,a2,b,c;
  int r;
  mpfr_prec_t p;
  int i = -1, inexact1, inexact2;

  mpfr_inits (a1, a2, b, c, (mpfr_ptr) 0);

  for (r = 0 ; r < MPFR_RND_MAX ; r++)
    {
      SET_PREC(53);
      mpfr_set_str1 (b, "1@100");
      mpfr_set_str1 (c, "1@1");
      inexact1 = mpfr_add1(a1, b, c, (mpfr_rnd_t) r);
      inexact2 = mpfr_add1sp(a2, b, c, (mpfr_rnd_t) r);
      if (mpfr_cmp(a1, a2))
        STD_ERROR;
      if (inexact1 != inexact2)
        STD_ERROR2;
      mpfr_set_str_binary (b, "1E53");
      mpfr_set_str_binary (c, "1E0");
      inexact1 = mpfr_add1(a1, b, c, (mpfr_rnd_t) r);
      inexact2 = mpfr_add1sp(a2, b, c, (mpfr_rnd_t) r);
      if (mpfr_cmp(a1, a2))
        STD_ERROR;
      if (inexact1 != inexact2)
        STD_ERROR2;
    }

  mpfr_set_prec (c, 2);
  mpfr_set_prec (a1, 2);
  mpfr_set_prec (a2, 2);
  mpfr_set_str_binary (c, "1.0e1");
  mpfr_set_str_binary (a2, "1.1e-1");
  mpfr_set_str_binary (a1, "0.11E2");
  mpfr_add1sp (a2, c, a2, MPFR_RNDN);
  if (mpfr_cmp (a1, a2))
    {
      printf ("Regression reuse test failed!\n");
      exit (1);
    }

  mpfr_clears (a1, a2, b, c, (mpfr_ptr) 0);
}
Exemple #4
0
int
mpfr_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
{
  MPFR_LOG_FUNC (("b[%#R]=%R c[%#R]=%R rnd=%d", b, b, c, c, rnd_mode),
                 ("a[%#R]=%R", a, a));

  if (MPFR_ARE_SINGULAR (b,c))
    {
      if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
        {
          MPFR_SET_NAN (a);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (b))
        {
          if (!MPFR_IS_INF (c) || MPFR_SIGN (b) != MPFR_SIGN(c))
            {
              MPFR_SET_INF (a);
              MPFR_SET_SAME_SIGN (a, b);
              MPFR_RET (0); /* exact */
            }
          else
            {
              MPFR_SET_NAN (a); /* Inf - Inf */
              MPFR_RET_NAN;
            }
        }
      else if (MPFR_IS_INF (c))
        {
          MPFR_SET_INF (a);
          MPFR_SET_OPPOSITE_SIGN (a, c);
          MPFR_RET (0); /* exact */
        }
      else if (MPFR_IS_ZERO (b))
        {
          if (MPFR_IS_ZERO (c))
            {
              int sign = rnd_mode != MPFR_RNDD
                ? ((MPFR_IS_NEG(b) && MPFR_IS_POS(c)) ? -1 : 1)
                : ((MPFR_IS_POS(b) && MPFR_IS_NEG(c)) ? 1 : -1);
              MPFR_SET_SIGN (a, sign);
              MPFR_SET_ZERO (a);
              MPFR_RET(0); /* 0 - 0 is exact */
            }
          else
            return mpfr_neg (a, c, rnd_mode);
        }
      else
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (c));
          return mpfr_set (a, b, rnd_mode);
        }
    }
  MPFR_ASSERTD (MPFR_IS_PURE_FP (b) && MPFR_IS_PURE_FP (c));

  if (MPFR_LIKELY (MPFR_SIGN (b) == MPFR_SIGN (c)))
    { /* signs are equal, it's a real subtraction */
      if (MPFR_LIKELY (MPFR_PREC (a) == MPFR_PREC (b)
                       && MPFR_PREC (b) == MPFR_PREC (c)))
        return mpfr_sub1sp (a, b, c, rnd_mode);
      else
        return mpfr_sub1 (a, b, c, rnd_mode);
    }
  else
    { /* signs differ, it's an addition */
      if (MPFR_GET_EXP (b) < MPFR_GET_EXP (c))
         { /* exchange rounding modes toward +/- infinity */
          int inexact;
          rnd_mode = MPFR_INVERT_RND (rnd_mode);
          if (MPFR_LIKELY (MPFR_PREC (a) == MPFR_PREC (b)
                           && MPFR_PREC (b) == MPFR_PREC (c)))
            inexact = mpfr_add1sp (a, c, b, rnd_mode);
          else
            inexact = mpfr_add1 (a, c, b, rnd_mode);
          MPFR_CHANGE_SIGN (a);
          return -inexact;
        }
      else
        {
          if (MPFR_LIKELY (MPFR_PREC (a) == MPFR_PREC (b)
                           && MPFR_PREC (b) == MPFR_PREC (c)))
            return mpfr_add1sp (a, b, c, rnd_mode);
          else
            return mpfr_add1 (a, b, c, rnd_mode);
        }
    }
}
int
mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode)
{
  MPFR_LOG_FUNC (("b[%#R]=%R c[%#R]=%R rnd=%d", b, b, c, c, rnd_mode),
                 ("a[%#R]=%R", a, a));

  if (MPFR_ARE_SINGULAR(b,c))
    {
      if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c))
        {
          MPFR_SET_NAN(a);
          MPFR_RET_NAN;
        }
      /* neither b nor c is NaN here */
      else if (MPFR_IS_INF(b))
        {
          if (!MPFR_IS_INF(c) || MPFR_SIGN(b) == MPFR_SIGN(c))
            {
              MPFR_SET_INF(a);
              MPFR_SET_SAME_SIGN(a, b);
              MPFR_RET(0); /* exact */
            }
          else
            {
              MPFR_SET_NAN(a);
              MPFR_RET_NAN;
            }
        }
      else if (MPFR_IS_INF(c))
          {
            MPFR_SET_INF(a);
            MPFR_SET_SAME_SIGN(a, c);
            MPFR_RET(0); /* exact */
          }
      /* now either b or c is zero */
      else if (MPFR_IS_ZERO(b))
        {
          if (MPFR_IS_ZERO(c))
            {
              /* for round away, we take the same convention for 0 + 0
                 as for round to zero or to nearest: it always gives +0,
                 except (-0) + (-0) = -0. */
              MPFR_SET_SIGN(a,
                            (rnd_mode != MPFR_RNDD ?
                             ((MPFR_IS_NEG(b) && MPFR_IS_NEG(c)) ? -1 : 1) :
                             ((MPFR_IS_POS(b) && MPFR_IS_POS(c)) ? 1 : -1)));
              MPFR_SET_ZERO(a);
              MPFR_RET(0); /* 0 + 0 is exact */
            }
          return mpfr_set (a, c, rnd_mode);
        }
      else
        {
          MPFR_ASSERTD(MPFR_IS_ZERO(c));
          return mpfr_set (a, b, rnd_mode);
        }
    }

  MPFR_ASSERTD(MPFR_IS_PURE_FP(b) && MPFR_IS_PURE_FP(c));

  if (MPFR_UNLIKELY(MPFR_SIGN(b) != MPFR_SIGN(c)))
    { /* signs differ, it's a subtraction */
      if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b)
                      && MPFR_PREC(b) == MPFR_PREC(c)))
        return mpfr_sub1sp(a,b,c,rnd_mode);
      else
        return mpfr_sub1(a, b, c, rnd_mode);
    }
  else
    { /* signs are equal, it's an addition */
      if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b)
                      && MPFR_PREC(b) == MPFR_PREC(c)))
        if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
          return mpfr_add1sp(a, c, b, rnd_mode);
        else
          return mpfr_add1sp(a, b, c, rnd_mode);
      else
        if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c))
          return mpfr_add1(a, c, b, rnd_mode);
        else
          return mpfr_add1(a, b, c, rnd_mode);
    }
}