Exemplo n.º 1
0
uintmax_t
mpfr_get_uj (mpfr_srcptr f, mpfr_rnd_t rnd)
{
  uintmax_t r;
  mpfr_prec_t prec;
  mpfr_t x;

  if (MPFR_UNLIKELY (!mpfr_fits_uintmax_p (f, rnd)))
    {
      MPFR_SET_ERANGEFLAG ();
      return MPFR_IS_NAN (f) || MPFR_IS_NEG (f) ?
        (uintmax_t) 0 : MPFR_UINTMAX_MAX;
    }

  if (MPFR_IS_ZERO (f))
    return (uintmax_t) 0;

  /* determine the precision of uintmax_t */
  for (r = MPFR_UINTMAX_MAX, prec = 0; r != 0; r /= 2, prec++)
    { }

  /* Now, r = 0. */

  mpfr_init2 (x, prec);
  mpfr_rint (x, f, rnd);
  MPFR_ASSERTN (MPFR_IS_FP (x));

  if (MPFR_NOTZERO (x))
    {
      mp_limb_t *xp;
      int sh, n;  /* An int should be sufficient in this context. */

      MPFR_ASSERTN (MPFR_IS_POS (x));
      xp = MPFR_MANT (x);
      sh = MPFR_GET_EXP (x);
      MPFR_ASSERTN ((mpfr_prec_t) sh <= prec);
      for (n = MPFR_LIMB_SIZE(x) - 1; n >= 0; n--)
        {
          sh -= GMP_NUMB_BITS;
          r += (sh >= 0
                ? (uintmax_t) xp[n] << sh
                : (uintmax_t) xp[n] >> (- sh));
        }
    }

  mpfr_clear (x);

  return r;
}
Exemplo n.º 2
0
Arquivo: sgn.c Projeto: epowers/mpfr
int
(mpfr_sgn) (mpfr_srcptr a)
{
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (a)))
    {
      if (MPFR_LIKELY (MPFR_IS_ZERO (a)))
        return 0;
      if (MPFR_UNLIKELY (MPFR_IS_NAN (a)))
        {
          MPFR_SET_ERANGEFLAG ();
          return 0;
        }
      /* Remains infinity, handled by the return below. */
    }
  return MPFR_INT_SIGN (a);
}
Exemplo n.º 3
0
int
mpfr_get_z (mpz_ptr z, mpfr_srcptr f, mpfr_rnd_t rnd)
{
  int inex;
  mpfr_t r;
  mpfr_exp_t exp;
  MPFR_SAVE_EXPO_DECL (expo);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (f)))
    {
      if (MPFR_UNLIKELY (MPFR_NOTZERO (f)))
        MPFR_SET_ERANGEFLAG ();
      mpz_set_ui (z, 0);
      /* The ternary value is 0 even for infinity. Giving the rounding
         direction in this case would not make much sense anyway, and
         the direction would not necessarily match rnd. */
      return 0;
    }

  MPFR_SAVE_EXPO_MARK (expo);

  exp = MPFR_GET_EXP (f);
  /* if exp <= 0, then |f|<1, thus |o(f)|<=1 */
  MPFR_ASSERTN (exp < 0 || exp <= MPFR_PREC_MAX);
  mpfr_init2 (r, (exp < (mpfr_exp_t) MPFR_PREC_MIN ?
                  MPFR_PREC_MIN : (mpfr_prec_t) exp));
  inex = mpfr_rint (r, f, rnd);
  MPFR_ASSERTN (inex != 1 && inex != -1); /* integral part of f is
                                             representable in r */
  MPFR_ASSERTN (MPFR_IS_FP (r));

  /* The flags from mpfr_rint are the wanted ones. In particular,
     it sets the inexact flag when necessary. */
  MPFR_SAVE_EXPO_UPDATE_FLAGS (expo, __gmpfr_flags);

  exp = mpfr_get_z_2exp (z, r);
  if (exp >= 0)
    mpz_mul_2exp (z, z, exp);
  else
    mpz_fdiv_q_2exp (z, z, -exp);
  mpfr_clear (r);

  MPFR_SAVE_EXPO_FREE (expo);

  return inex;
}
Exemplo n.º 4
0
/* Since MPFR-3.0, return the usual inexact value.
   The erange flag is set if an error occurred in the conversion
   (y is NaN, +Inf, or -Inf that have no equivalent in mpf)
*/
int
mpfr_get_f (mpf_ptr x, mpfr_srcptr y, mpfr_rnd_t rnd_mode)
{
  int inex;
  mp_size_t sx, sy;
  mpfr_prec_t precx, precy;
  mp_limb_t *xp;
  int sh;

  if (MPFR_UNLIKELY(MPFR_IS_SINGULAR(y)))
    {
      if (MPFR_IS_ZERO(y))
        {
          mpf_set_ui (x, 0);
          return 0;
        }
      else if (MPFR_IS_NAN (y))
        {
          MPFR_SET_ERANGEFLAG ();
          return 0;
        }
      else /* y is plus infinity (resp. minus infinity), set x to the maximum
              value (resp. the minimum value) in precision PREC(x) */
        {
          int i;
          mp_limb_t *xp;

          MPFR_SET_ERANGEFLAG ();

          /* To this day, [mp_exp_t] and mp_size_t are #defined as the same
             type */
          EXP (x) = MP_SIZE_T_MAX;

          sx = PREC (x);
          SIZ (x) = sx;
          xp = PTR (x);
          for (i = 0; i < sx; i++)
            xp[i] = MPFR_LIMB_MAX;

          if (MPFR_IS_POS (y))
            return -1;
          else
            {
              mpf_neg (x, x);
              return +1;
            }
        }
    }

  sx = PREC(x); /* number of limbs of the mantissa of x */

  precy = MPFR_PREC(y);
  precx = (mpfr_prec_t) sx * GMP_NUMB_BITS;
  sy = MPFR_LIMB_SIZE (y);

  xp = PTR (x);

  /* since mpf numbers are represented in base 2^GMP_NUMB_BITS,
     we loose -EXP(y) % GMP_NUMB_BITS bits in the most significant limb */
  sh = MPFR_GET_EXP(y) % GMP_NUMB_BITS;
  sh = sh <= 0 ? - sh : GMP_NUMB_BITS - sh;
  MPFR_ASSERTD (sh >= 0);
  if (precy + sh <= precx) /* we can copy directly */
    {
      mp_size_t ds;

      MPFR_ASSERTN (sx >= sy);
      ds = sx - sy;

      if (sh != 0)
        {
          mp_limb_t out;
          out = mpn_rshift (xp + ds, MPFR_MANT(y), sy, sh);
          MPFR_ASSERTN (ds > 0 || out == 0);
          if (ds > 0)
            xp[--ds] = out;
        }
      else
        MPN_COPY (xp + ds, MPFR_MANT (y), sy);
      if (ds > 0)
        MPN_ZERO (xp, ds);
      EXP(x) = (MPFR_GET_EXP(y) + sh) / GMP_NUMB_BITS;
      inex = 0;
    }
  else /* we have to round to precx - sh bits */
    {
      mpfr_t z;
      mp_size_t sz;

      /* Recall that precx = (mpfr_prec_t) sx * GMP_NUMB_BITS, thus removing
         sh bits (sh < GMP_NUMB_BITSS) won't reduce the number of limbs. */
      mpfr_init2 (z, precx - sh);
      sz = MPFR_LIMB_SIZE (z);
      MPFR_ASSERTN (sx == sz);

      inex = mpfr_set (z, y, rnd_mode);
      /* warning, sh may change due to rounding, but then z is a power of two,
         thus we can safely ignore its last bit which is 0 */
      sh = MPFR_GET_EXP(z) % GMP_NUMB_BITS;
      sh = sh <= 0 ? - sh : GMP_NUMB_BITS - sh;
      MPFR_ASSERTD (sh >= 0);
      if (sh != 0)
        {
          mp_limb_t out;
          out = mpn_rshift (xp, MPFR_MANT(z), sz, sh);
          /* If sh hasn't changed, it is the number of the non-significant
             bits in the lowest limb of z. Therefore out == 0. */
          MPFR_ASSERTD (out == 0);  (void) out; /* avoid a warning */
        }
      else
        MPN_COPY (xp, MPFR_MANT(z), sz);
      EXP(x) = (MPFR_GET_EXP(z) + sh) / GMP_NUMB_BITS;
      mpfr_clear (z);
    }

  /* set size and sign */
  SIZ(x) = (MPFR_FROM_SIGN_TO_INT(MPFR_SIGN(y)) < 0) ? -sx : sx;

  return inex;
}
Exemplo n.º 5
0
Arquivo: cmp_abs.c Projeto: Canar/mpfr
int
mpfr_cmpabs (mpfr_srcptr b, mpfr_srcptr c)
{
  mpfr_exp_t be, ce;
  mp_size_t bn, cn;
  mp_limb_t *bp, *cp;

  if (MPFR_ARE_SINGULAR (b, c))
    {
      if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
        {
          MPFR_SET_ERANGEFLAG ();
          return 0;
        }
      else if (MPFR_IS_INF (b))
        return ! MPFR_IS_INF (c);
      else if (MPFR_IS_INF (c))
        return -1;
      else if (MPFR_IS_ZERO (c))
        return ! MPFR_IS_ZERO (b);
      else /* b == 0 */
        return -1;
    }

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

  /* Now that we know that b and c are pure FP numbers (i.e. they have
     a meaningful exponent), we use MPFR_EXP instead of MPFR_GET_EXP to
     allow exponents outside the current exponent range. For instance,
     this is useful for mpfr_pow, which compares values to __gmpfr_one.
     This is for internal use only! For compatibility with other MPFR
     versions, the user must still provide values that are representable
     in the current exponent range. */
  be = MPFR_EXP (b);
  ce = MPFR_EXP (c);
  if (be > ce)
    return 1;
  if (be < ce)
    return -1;

  /* exponents are equal */

  bn = MPFR_LIMB_SIZE(b)-1;
  cn = MPFR_LIMB_SIZE(c)-1;

  bp = MPFR_MANT(b);
  cp = MPFR_MANT(c);

  for ( ; bn >= 0 && cn >= 0; bn--, cn--)
    {
      if (bp[bn] > cp[cn])
        return 1;
      if (bp[bn] < cp[cn])
        return -1;
    }

  for ( ; bn >= 0; bn--)
    if (bp[bn])
      return 1;

  for ( ; cn >= 0; cn--)
    if (cp[cn])
      return -1;

   return 0;
}
Exemplo n.º 6
0
int
mpfr_cmp_ui_2exp (mpfr_srcptr b, unsigned long int i, mpfr_exp_t f)
{
  if (MPFR_UNLIKELY( MPFR_IS_SINGULAR(b) ))
    {
      if (MPFR_IS_NAN (b))
        {
          MPFR_SET_ERANGEFLAG ();
          return 0;
        }
      else if (MPFR_IS_INF(b))
        return MPFR_INT_SIGN (b);
      else /* since b cannot be NaN, b=0 here */
        return i != 0 ? -1 : 0;
    }

  if (MPFR_IS_NEG (b))
    return -1;
  /* now b > 0 */
  else if (MPFR_UNLIKELY(i == 0))
    return 1;
  else /* b > 0, i > 0 */
    {
      mpfr_exp_t e;
      int k;
      mp_size_t bn;
      mp_limb_t c, *bp;

      /* i must be representable in a mp_limb_t */
      MPFR_ASSERTN(i == (mp_limb_t) i);

      e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */
      if (e <= f)
        return -1;
      if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS &&
          e > f + GMP_NUMB_BITS)
        return 1;

      /* now f < e <= f + GMP_NUMB_BITS */
      c = (mp_limb_t) i;
      count_leading_zeros(k, c);
      if ((int) (e - f) > GMP_NUMB_BITS - k)
        return 1;
      if ((int) (e - f) < GMP_NUMB_BITS - k)
        return -1;

      /* now b and i*2^f have the same exponent */
      c <<= k;
      bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
      bp = MPFR_MANT(b);
      if (bp[bn] > c)
        return 1;
      if (bp[bn] < c)
        return -1;

      /* most significant limbs agree, check remaining limbs from b */
      while (bn > 0)
        if (bp[--bn] != 0)
          return 1;
      return 0;
    }
}
Exemplo n.º 7
0
Arquivo: cmp_si.c Projeto: Canar/mpfr
int
mpfr_cmp_si_2exp (mpfr_srcptr b, long int i, mpfr_exp_t f)
{
  int si;

  si = i < 0 ? -1 : 1; /* sign of i */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (b)))
    {
      if (MPFR_IS_INF(b))
        return MPFR_INT_SIGN(b);
      else if (MPFR_IS_ZERO(b))
        return i != 0 ? -si : 0;
      /* NAN */
      MPFR_SET_ERANGEFLAG ();
      return 0;
    }
  else if (MPFR_SIGN(b) != si || i == 0)
    return MPFR_INT_SIGN (b);
  else /* b and i are of same sign si */
    {
      mpfr_exp_t e;
      unsigned long ai;
      int k;
      mp_size_t bn;
      mp_limb_t c, *bp;

      ai = SAFE_ABS(unsigned long, i);

      /* ai must be representable in a mp_limb_t */
      MPFR_ASSERTN(ai == (mp_limb_t) ai);

      e = MPFR_GET_EXP (b); /* 2^(e-1) <= b < 2^e */
      if (e <= f)
        return -si;
      if (f < MPFR_EMAX_MAX - GMP_NUMB_BITS &&
          e > f + GMP_NUMB_BITS)
        return si;

      /* now f < e <= f + GMP_NUMB_BITS */
      c = (mp_limb_t) ai;
      count_leading_zeros(k, c);
      if ((int) (e - f) > GMP_NUMB_BITS - k)
        return si;
      if ((int) (e - f) < GMP_NUMB_BITS - k)
        return -si;

      /* now b and i*2^f have the same exponent */
      c <<= k;
      bn = (MPFR_PREC(b) - 1) / GMP_NUMB_BITS;
      bp = MPFR_MANT(b);
      if (bp[bn] > c)
        return si;
      if (bp[bn] < c)
        return -si;

      /* most significant limbs agree, check remaining limbs from b */
      while (bn > 0)
        if (bp[--bn])
          return si;
      return 0;
    }
}
Exemplo n.º 8
0
Arquivo: cmp.c Projeto: MiKTeX/miktex
MPFR_HOT_FUNCTION_ATTR int
mpfr_cmp3 (mpfr_srcptr b, mpfr_srcptr c, int s)
{
  mpfr_exp_t be, ce;
  mp_size_t bn, cn;
  mp_limb_t *bp, *cp;

  s = MPFR_MULT_SIGN( s , MPFR_SIGN(c) );

  if (MPFR_ARE_SINGULAR(b, c))
    {
      if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c))
        {
          MPFR_SET_ERANGEFLAG ();
          return 0;
        }
      else if (MPFR_IS_INF(b))
        {
          if (MPFR_IS_INF(c) && s == MPFR_SIGN(b) )
            return 0;
          else
            return MPFR_SIGN(b);
        }
      else if (MPFR_IS_INF(c))
        return -s;
      else if (MPFR_IS_ZERO(b))
        return MPFR_IS_ZERO(c) ? 0 : -s;
      else /* necessarily c=0 */
        return MPFR_SIGN(b);
    }
  /* b and c are real numbers */
  if (s != MPFR_SIGN(b))
    return MPFR_SIGN(b);

  /* now signs are equal */

  be = MPFR_GET_EXP (b);
  ce = MPFR_GET_EXP (c);
  if (be > ce)
    return s;
  if (be < ce)
    return -s;

  /* both signs and exponents are equal */

  bn = MPFR_LAST_LIMB (b);
  cn = MPFR_LAST_LIMB (c);

  bp = MPFR_MANT(b);
  cp = MPFR_MANT(c);

  for ( ; bn >= 0 && cn >= 0; bn--, cn--)
    {
      if (bp[bn] > cp[cn])
        return s;
      if (bp[bn] < cp[cn])
        return -s;
    }
  for ( ; bn >= 0; bn--)
    if (bp[bn])
      return s;
  for ( ; cn >= 0; cn--)
    if (cp[cn])
      return -s;

   return 0;
}