Example #1
0
int
mpc_atanh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  /* atanh(op) = -i*atan(i*op) */
  int inex;
  mpfr_t tmp;
  mpc_t z, a;

  MPC_RE (z)[0] = MPC_IM (op)[0];
  MPC_IM (z)[0] = MPC_RE (op)[0];
  MPFR_CHANGE_SIGN (MPC_RE (z));

  /* Note reversal of precisions due to later multiplication by -i */
  mpc_init3 (a, MPC_PREC_IM(rop), MPC_PREC_RE(rop));

  inex = mpc_atan (a, z,
                   RNDC (INV_RND (MPC_RND_IM (rnd)), MPC_RND_RE (rnd)));

  /* change a to -i*a, i.e., x+i*y to y-i*x */
  tmp[0] = MPC_RE (a)[0];
  MPC_RE (a)[0] = MPC_IM (a)[0];
  MPC_IM (a)[0] = tmp[0];
  MPFR_CHANGE_SIGN (MPC_IM (a));

  mpc_set (rop, a, rnd);

  mpc_clear (a);

  return MPC_INEX (MPC_INEX_IM (inex), -MPC_INEX_RE (inex));
}
Example #2
0
int
mpc_asinh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  /* asinh(op) = -i*asin(i*op) */
  int inex;
  mpc_t z, a;
  mpfr_t tmp;

  /* z = i*op */
  MPC_RE (z)[0] = MPC_IM (op)[0];
  MPC_IM (z)[0] = MPC_RE (op)[0];
  MPFR_CHANGE_SIGN (MPC_RE (z));

  /* Note reversal of precisions due to later multiplication by -i */
  mpc_init3 (a, MPC_PREC_IM(rop), MPC_PREC_RE(rop));

  inex = mpc_asin (a, z,
                   RNDC (INV_RND (MPC_RND_IM (rnd)), MPC_RND_RE (rnd)));

  /* if a = asin(i*op) = x+i*y, and we want y-i*x */

  /* change a to -i*a */
  tmp[0] = MPC_RE (a)[0];
  MPC_RE (a)[0] = MPC_IM (a)[0];
  MPC_IM (a)[0] = tmp[0];
  MPFR_CHANGE_SIGN (MPC_IM (a));

  mpc_set (rop, a, MPC_RNDNN);   /* exact */

  mpc_clear (a);

  return MPC_INEX (MPC_INEX_IM (inex), -MPC_INEX_RE (inex));
}
static int
mpc_sin_cos_real (mpc_ptr rop_sin, mpc_ptr rop_cos, mpc_srcptr op,
   mpc_rnd_t rnd_sin, mpc_rnd_t rnd_cos)
   /* assumes that op is real */
{
   int inex_sin_re = 0, inex_cos_re = 0;
      /* Until further notice, assume computations exact; in particular,
         by definition, for not computed values.                         */
   mpfr_t s, c;
   int inex_s, inex_c;
   int sign_im_op = mpfr_signbit (MPC_IM (op));

   /* sin(x +-0*i) = sin(x) +-0*i*sign(cos(x)) */
   /* cos(x +-i*0) = cos(x) -+i*0*sign(sin(x)) */
   if (rop_sin != 0)
      mpfr_init2 (s, MPC_PREC_RE (rop_sin));
   else
      mpfr_init2 (s, 2); /* We need only the sign. */
   if (rop_cos != NULL)
      mpfr_init2 (c, MPC_PREC_RE (rop_cos));
   else
      mpfr_init2 (c, 2);
   inex_s = mpfr_sin (s, MPC_RE (op), MPC_RND_RE (rnd_sin));
   inex_c = mpfr_cos (c, MPC_RE (op), MPC_RND_RE (rnd_cos));
      /* We cannot use mpfr_sin_cos since we may need two distinct rounding
         modes and the exact return values. If we need only the sign, an
         arbitrary rounding mode will work.                                 */

   if (rop_sin != NULL) {
      mpfr_set (MPC_RE (rop_sin), s, GMP_RNDN); /* exact */
      inex_sin_re = inex_s;
      mpfr_set_ui (MPC_IM (rop_sin), 0ul, GMP_RNDN);
      if (   ( sign_im_op && !mpfr_signbit (c))
          || (!sign_im_op &&  mpfr_signbit (c)))
         MPFR_CHANGE_SIGN (MPC_IM (rop_sin));
      /* FIXME: simpler implementation with mpfr-3:
         mpfr_set_zero (MPC_IM (rop_sin),
            (   ( mpfr_signbit (MPC_IM(op)) && !mpfr_signbit(c))
             || (!mpfr_signbit (MPC_IM(op)) &&  mpfr_signbit(c)) ? -1 : 1);
         there is no need to use the variable sign_im_op then, needed now in
         the case rop_sin == op                                              */
   }

   if (rop_cos != NULL) {
      mpfr_set (MPC_RE (rop_cos), c, GMP_RNDN); /* exact */
      inex_cos_re = inex_c;
      mpfr_set_ui (MPC_IM (rop_cos), 0ul, GMP_RNDN);
      if (   ( sign_im_op &&  mpfr_signbit (s))
          || (!sign_im_op && !mpfr_signbit (s)))
         MPFR_CHANGE_SIGN (MPC_IM (rop_cos));
      /* FIXME: see previous MPFR_CHANGE_SIGN */
   }

   mpfr_clear (s);
   mpfr_clear (c);

   return MPC_INEX12 (MPC_INEX (inex_sin_re, 0), MPC_INEX (inex_cos_re, 0));
}
Example #4
0
int
mpc_mul_i (mpc_ptr a, mpc_srcptr b, int sign, mpc_rnd_t rnd)
/* if sign is >= 0, multiply by i, otherwise by -i */
{
  int   inex_re, inex_im;
  mpfr_t tmp;

  /* Treat the most probable case of compatible precisions first */
  if (     MPFR_PREC (MPC_RE (b)) == MPFR_PREC (MPC_IM (a))
        && MPFR_PREC (MPC_IM (b)) == MPFR_PREC (MPC_RE (a)))
  {
     if (a == b)
        mpfr_swap (MPC_RE (a), MPC_IM (a));
     else
     {
        mpfr_set (MPC_RE (a), MPC_IM (b), GMP_RNDN);
        mpfr_set (MPC_IM (a), MPC_RE (b), GMP_RNDN);
     }
     if (sign >= 0)
        MPFR_CHANGE_SIGN (MPC_RE (a));
     else
        MPFR_CHANGE_SIGN (MPC_IM (a));
     inex_re = 0;
     inex_im = 0;
  }
  else
  {
     if (a == b)
     {
        mpfr_init2 (tmp, MPFR_PREC (MPC_RE (a)));
        if (sign >= 0)
        {
           inex_re = mpfr_neg (tmp, MPC_IM (b), MPC_RND_RE (rnd));
           inex_im = mpfr_set (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd));
        }
        else
        {
           inex_re = mpfr_set (tmp, MPC_IM (b), MPC_RND_RE (rnd));
           inex_im = mpfr_neg (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd));
        }
        mpfr_clear (MPC_RE (a));
        MPC_RE (a)[0] = tmp [0];
     }
     else
        if (sign >= 0)
        {
           inex_re = mpfr_neg (MPC_RE (a), MPC_IM (b), MPC_RND_RE (rnd));
           inex_im = mpfr_set (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd));
        }
        else
        {
           inex_re = mpfr_set (MPC_RE (a), MPC_IM (b), MPC_RND_RE (rnd));
           inex_im = mpfr_neg (MPC_IM (a), MPC_RE (b), MPC_RND_IM (rnd));
        }
  }

  return MPC_INEX(inex_re, inex_im);
}
Example #5
0
int
mpc_acosh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  /* acosh(z) =
      NaN + i*NaN, if z=0+i*NaN
     -i*acos(z), if sign(Im(z)) = -
      i*acos(z), if sign(Im(z)) = +
      http://functions.wolfram.com/ElementaryFunctions/ArcCosh/27/02/03/01/01/
  */
  mpc_t a;
  mpfr_t tmp;
  int inex;

  if (mpfr_zero_p (MPC_RE (op)) && mpfr_nan_p (MPC_IM (op)))
    {
      mpfr_set_nan (MPC_RE (rop));
      mpfr_set_nan (MPC_IM (rop));
      return 0;
    }
  
  /* Note reversal of precisions due to later multiplication by i or -i */
  mpc_init3 (a, MPC_PREC_IM(rop), MPC_PREC_RE(rop));

  if (mpfr_signbit (MPC_IM (op)))
    {
      inex = mpc_acos (a, op,
                       RNDC (INV_RND (MPC_RND_IM (rnd)), MPC_RND_RE (rnd)));

      /* change a to -i*a, i.e., -y+i*x to x+i*y */
      tmp[0] = MPC_RE (a)[0];
      MPC_RE (a)[0] = MPC_IM (a)[0];
      MPC_IM (a)[0] = tmp[0];
      MPFR_CHANGE_SIGN (MPC_IM (a));
      inex = MPC_INEX (MPC_INEX_IM (inex), -MPC_INEX_RE (inex));
    }
  else
    {
      inex = mpc_acos (a, op,
                       RNDC (MPC_RND_IM (rnd), INV_RND(MPC_RND_RE (rnd))));

      /* change a to i*a, i.e., y-i*x to x+i*y */
      tmp[0] = MPC_RE (a)[0];
      MPC_RE (a)[0] = MPC_IM (a)[0];
      MPC_IM (a)[0] = tmp[0];
      MPFR_CHANGE_SIGN (MPC_RE (a));
      inex = MPC_INEX (-MPC_INEX_IM (inex), MPC_INEX_RE (inex));
    }

  mpc_set (rop, a, rnd);

  mpc_clear (a);

  return inex;
}
Example #6
0
int
mpfr_set_underflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign)
{
  int inex;

  MPFR_CLEAR_FLAGS(x);
  if ((rnd_mode == GMP_RNDU && sign > 0)
   || (rnd_mode == GMP_RNDD && sign < 0))
    {
      mp_size_t xn;
      mp_limb_t *xp;

      MPFR_EXP(x) = __mpfr_emin;
      xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
      xp = MPFR_MANT(x);
      xp[xn] = GMP_LIMB_HIGHBIT;
      MPN_ZERO(xp, xn);
      inex = 1;
    }
  else
    {
      MPFR_SET_ZERO(x);
      inex = -1;
    }
  if (MPFR_SIGN(x) != sign)
    MPFR_CHANGE_SIGN(x);
  __mpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_UNDERFLOW;
  return sign > 0 ? inex : -inex;
}
Example #7
0
int
mpfr_set_overflow (mpfr_ptr x, mp_rnd_t rnd_mode, int sign)
{
  int inex;

  MPFR_CLEAR_FLAGS(x);
  if ((rnd_mode == GMP_RNDU && sign < 0)
   || (rnd_mode == GMP_RNDD && sign > 0))
    {
      mp_size_t xn, i;
      int sh;
      mp_limb_t *xp;

      MPFR_EXP(x) = __mpfr_emax;
      xn = 1 + (MPFR_PREC(x) - 1) / BITS_PER_MP_LIMB;
      sh = xn * BITS_PER_MP_LIMB - MPFR_PREC(x);
      xp = MPFR_MANT(x);
      xp[0] = MP_LIMB_T_MAX << sh;
      for (i = 1; i < xn; i++)
        xp[i] = MP_LIMB_T_MAX;
      inex = -1;
    }
  else
    {
      MPFR_SET_INF(x);
      inex = 1;
    }
  if (MPFR_SIGN(x) != sign)
    MPFR_CHANGE_SIGN(x);
  __mpfr_flags |= MPFR_FLAGS_INEXACT | MPFR_FLAGS_OVERFLOW;
  return sign > 0 ? inex : -inex;
}
Example #8
0
/* Input: p - an integer
   Output: fills tc[1..p], tc[i] = bernoulli(2i)/(2i)!
   tc[1]=1/12, tc[2]=-1/720, tc[3]=1/30240, ...
*/
static void
mpfr_zeta_c (int p, mpfr_t *tc)
{
  mpfr_t d;
  int k, l;

  if (p > 0)
    {
      mpfr_init2 (d, MPFR_PREC (tc[1]));
      mpfr_div_ui (tc[1], __gmpfr_one, 12, GMP_RNDN);
      for (k = 2; k <= p; k++)
        {
          mpfr_set_ui (d, k-1, GMP_RNDN);
          mpfr_div_ui (d, d, 12*k+6, GMP_RNDN);
          for (l=2; l < k; l++)
            {
              mpfr_div_ui (d, d, 4*(2*k-2*l+3)*(2*k-2*l+2), GMP_RNDN);
              mpfr_add (d, d, tc[l], GMP_RNDN);
            }
          mpfr_div_ui (tc[k], d, 24, GMP_RNDN);
          MPFR_CHANGE_SIGN (tc[k]);
        }
      mpfr_clear (d);
    }
}
Example #9
0
File: neg.c Project: mahdiz/mpclib
int
mpfr_neg (mpfr_ptr a, mpfr_srcptr b, mp_rnd_t rnd_mode)
{
  if (a != b)
    return mpfr_set4 (a, b, rnd_mode, -MPFR_SIGN(b));
  else
    {
      MPFR_CHANGE_SIGN(a);
      MPFR_RET(0);
    }
}
Example #10
0
int
mpfr_set_si (mpfr_ptr x, long i, mp_rnd_t rnd_mode)
{
  int inex;
  mp_size_t xn;
  unsigned int cnt, nbits;
  mp_limb_t ai, *xp;

  MPFR_CLEAR_FLAGS(x);
  if (i == 0)
    {
      MPFR_SET_ZERO(x);
      MPFR_SET_POS(x);
      MPFR_RET(0);
    }

  xn = (MPFR_PREC(x)-1)/BITS_PER_MP_LIMB;
  ai = SAFE_ABS(long, i);
  count_leading_zeros(cnt, ai);

  xp = MPFR_MANT(x);
  xp[xn] = ai << cnt;
  /* don't forget to put zero in lower limbs */
  MPN_ZERO(xp, xn);
  /* set sign */
  if ((i < 0) ^ (MPFR_SIGN(x) < 0))
    MPFR_CHANGE_SIGN(x);

  MPFR_EXP(x) = nbits = BITS_PER_MP_LIMB - cnt;
  inex = mpfr_check_range(x, rnd_mode);
  if (inex)
    return inex; /* underflow or overflow */

  /* round if MPFR_PREC(x) smaller than length of i */
  if (MPFR_PREC(x) < nbits)
    {
      int carry;

      carry = mpfr_round_raw(xp+xn, xp+xn, nbits, (i < 0), MPFR_PREC(x),
                             rnd_mode, &inex);
      if (carry)
        {
          mp_exp_t exp = MPFR_EXP(x);

          if (exp == __mpfr_emax)
            return mpfr_set_overflow(x, rnd_mode, (i < 0 ? -1 : 1));

          MPFR_EXP(x)++;
          xp[xn] = GMP_LIMB_HIGHBIT;
        }
    }

  MPFR_RET(inex);
}
Example #11
0
int
mpfr_si_sub (mpfr_ptr y, long int u, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  if (u >= 0)
    return mpfr_ui_sub (y, u, x, rnd_mode);
  else
    {
    int res = -mpfr_add_ui (y, x, -u, MPFR_INVERT_RND (rnd_mode));
    MPFR_CHANGE_SIGN (y);
    return res;
    }
}
Example #12
0
int mpfr_mul_si (mpfr_ptr y, mpfr_srcptr x, long int u, mpfr_rnd_t rnd_mode)
{
  int res;

  if (u >= 0)
    res = mpfr_mul_ui (y, x, u, rnd_mode);
  else
    {
      res = -mpfr_mul_ui (y, x, -u, MPFR_INVERT_RND (rnd_mode));
      MPFR_CHANGE_SIGN (y);
    }
  return res;
}
Example #13
0
int
mpc_cosh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  /* cosh(op) = cos(i*op) */
  mpc_t z;

  /* z = i*op without copying significand */
  MPC_RE (z)[0] = MPC_IM (op)[0];
  MPC_IM (z)[0] = MPC_RE (op)[0];
  MPFR_CHANGE_SIGN (MPC_RE (z));

  return mpc_cos (rop, z, rnd);
}
Example #14
0
int
mpfr_set_sj_2exp (mpfr_t x, intmax_t j, intmax_t e, mp_rnd_t rnd)
{
  if (j>=0)
    return mpfr_set_uj_2exp (x, j, e, rnd);
  else
    {
      int inex;
      inex = mpfr_set_uj_2exp (x, - (uintmax_t) j, e, MPFR_INVERT_RND (rnd));
      MPFR_CHANGE_SIGN (x);
      return -inex;
    }
}
Example #15
0
int mpfr_si_div (mpfr_ptr y, long int u, mpfr_srcptr x,mp_rnd_t rnd_mode)
{
  int res;

  if (u >= 0)
    res = mpfr_ui_div (y, u, x, rnd_mode);
  else
    {
      res = -mpfr_ui_div (y, -u, x, MPFR_INVERT_RND(rnd_mode));
      MPFR_CHANGE_SIGN (y);
    }
  return res;
}
Example #16
0
int
mpfr_neg (mpfr_ptr a, mpfr_srcptr b, mpfr_rnd_t rnd_mode)
{
  if (MPFR_UNLIKELY(a != b))
    return mpfr_set4 (a, b, rnd_mode, -MPFR_SIGN(b));
  else if (MPFR_UNLIKELY(MPFR_IS_NAN (b)))
    {
      MPFR_RET_NAN;
    }
  else
    {
      MPFR_CHANGE_SIGN(a);
      MPFR_RET(0);
    }
}
Example #17
0
/* set f to the integer z */
int 
mpfr_set_z (mpfr_ptr f, mpz_srcptr z, mp_rnd_t rnd_mode)
{
  mp_size_t fn, zn, dif;
  int k, sign_z, inex;
  mp_limb_t *fp, *zp;
  mp_exp_t exp;

  MPFR_CLEAR_FLAGS (f); /* z cannot be NaN nor Inf */

  sign_z = mpz_cmp_ui (z, 0);

  if (sign_z == 0)
    {
      MPFR_SET_ZERO(f);
      MPFR_SET_POS(f);
      MPFR_RET(0);
    }

  fp = MPFR_MANT(f);
  fn = 1 + (MPFR_PREC(f) - 1) / BITS_PER_MP_LIMB;
  zn = ABS(SIZ(z));
  dif = zn - fn;
  zp = PTR(z);
  count_leading_zeros(k, zp[zn-1]);

  exp = (mp_prec_t) zn * BITS_PER_MP_LIMB - k;
  /* The exponent will be exp or exp + 1 (due to rounding) */
  if (exp > __mpfr_emax)
    return mpfr_set_overflow(f, rnd_mode, sign_z);
  if (exp + 1 < __mpfr_emin)
    return mpfr_set_underflow(f, rnd_mode, sign_z);

  if (MPFR_SIGN(f) * sign_z < 0)
    MPFR_CHANGE_SIGN(f);

  if (dif >= 0)
    {
      mp_limb_t cc;
      int sh;

      /* number has to be truncated */
      if (k != 0)
        {
          mpn_lshift(fp, zp + dif, fn, k);
          if (dif != 0)
            fp[0] += zp[dif - 1] >> (BITS_PER_MP_LIMB - k);
        }
static int
mpc_sin_cos_imag (mpc_ptr rop_sin, mpc_ptr rop_cos, mpc_srcptr op,
   mpc_rnd_t rnd_sin, mpc_rnd_t rnd_cos)
   /* assumes that op is purely imaginary */
{
   int inex_sin_im = 0, inex_cos_re = 0;
      /* assume exact if not computed */
   int overlap;
   mpc_t op_loc;

   overlap = (rop_sin == op || rop_cos == op);
   if (overlap) {
      mpc_init3 (op_loc, MPC_PREC_RE (op), MPC_PREC_IM (op));
      mpc_set (op_loc, op, MPC_RNDNN);
   }
   else
      op_loc [0] = op [0];

   if (rop_sin != NULL) {
      /* sin(+-O +i*y) = +-0 +i*sinh(y) */
      mpfr_set (MPC_RE(rop_sin), MPC_RE(op_loc), GMP_RNDN);
      inex_sin_im = mpfr_sinh (MPC_IM(rop_sin), MPC_IM(op_loc), MPC_RND_IM(rnd_sin));
   }

   if (rop_cos != NULL) {
      /* cos(-0 - i * y) = cos(+0 + i * y) = cosh(y) - i * 0,
         cos(-0 + i * y) = cos(+0 - i * y) = cosh(y) + i * 0,
         where y >= 0 */

      if (mpfr_zero_p (MPC_IM (op_loc)))
        inex_cos_re = mpfr_set_ui (MPC_RE (rop_cos), 1ul, MPC_RND_RE (rnd_cos));
      else
        inex_cos_re = mpfr_cosh (MPC_RE (rop_cos), MPC_IM (op_loc), MPC_RND_RE (rnd_cos));

      mpfr_set_ui (MPC_IM (rop_cos), 0ul, MPC_RND_IM (rnd_cos));
      if (mpfr_signbit (MPC_RE (op_loc)) ==  mpfr_signbit (MPC_IM (op_loc)))
         MPFR_CHANGE_SIGN (MPC_IM (rop_cos));
   }

   if (overlap)
      mpc_clear (op_loc);

   return MPC_INEX12 (MPC_INEX (0, inex_sin_im), MPC_INEX (inex_cos_re, 0));
}
Example #19
0
static int
pi_div_2ui (mpfr_ptr dest, int i, int neg, mpfr_rnd_t rnd_mode)
{
  int inexact;
  MPFR_SAVE_EXPO_DECL (expo);

  MPFR_SAVE_EXPO_MARK (expo);
  if (neg) /* -PI/2^i */
    {
      inexact = - mpfr_const_pi (dest, MPFR_INVERT_RND (rnd_mode));
      MPFR_CHANGE_SIGN (dest);
    }
  else /* PI/2^i */
    {
      inexact = mpfr_const_pi (dest, rnd_mode);
    }
  mpfr_div_2ui (dest, dest, i, rnd_mode);  /* exact */
  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (dest, inexact, rnd_mode);
}
Example #20
0
int
mpfr_asin (mpfr_ptr asin, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpfr_t xp;
  int compared, inexact;
  mpfr_prec_t prec;
  mpfr_exp_t xp_exp;
  MPFR_SAVE_EXPO_DECL (expo);
  MPFR_ZIV_DECL (loop);

  MPFR_LOG_FUNC (
    ("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
    ("asin[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (asin), mpfr_log_prec, asin,
     inexact));

  /* Special cases */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x) || MPFR_IS_INF (x))
        {
          MPFR_SET_NAN (asin);
          MPFR_RET_NAN;
        }
      else /* x = 0 */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          MPFR_SET_ZERO (asin);
          MPFR_SET_SAME_SIGN (asin, x);
          MPFR_RET (0); /* exact result */
        }
    }

  /* asin(x) = x + x^3/6 + ... so the error is < 2^(3*EXP(x)-2) */
  MPFR_FAST_COMPUTE_IF_SMALL_INPUT (asin, x, -2 * MPFR_GET_EXP (x), 2, 1,
                                    rnd_mode, {});

  /* Set x_p=|x| (x is a normal number) */
  mpfr_init2 (xp, MPFR_PREC (x));
  inexact = mpfr_abs (xp, x, MPFR_RNDN);
  MPFR_ASSERTD (inexact == 0);

  compared = mpfr_cmp_ui (xp, 1);

  MPFR_SAVE_EXPO_MARK (expo);

  if (MPFR_UNLIKELY (compared >= 0))
    {
      mpfr_clear (xp);
      if (compared > 0)                  /* asin(x) = NaN for |x| > 1 */
        {
          MPFR_SAVE_EXPO_FREE (expo);
          MPFR_SET_NAN (asin);
          MPFR_RET_NAN;
        }
      else                              /* x = 1 or x = -1 */
        {
          if (MPFR_IS_POS (x)) /* asin(+1) = Pi/2 */
            inexact = mpfr_const_pi (asin, rnd_mode);
          else /* asin(-1) = -Pi/2 */
            {
              inexact = -mpfr_const_pi (asin, MPFR_INVERT_RND(rnd_mode));
              MPFR_CHANGE_SIGN (asin);
            }
          mpfr_div_2ui (asin, asin, 1, rnd_mode);
        }
    }
  else
    {
      /* Compute exponent of 1 - ABS(x) */
      mpfr_ui_sub (xp, 1, xp, MPFR_RNDD);
      MPFR_ASSERTD (MPFR_GET_EXP (xp) <= 0);
      MPFR_ASSERTD (MPFR_GET_EXP (x) <= 0);
      xp_exp = 2 - MPFR_GET_EXP (xp);

      /* Set up initial prec */
      prec = MPFR_PREC (asin) + 10 + xp_exp;

      /* use asin(x) = atan(x/sqrt(1-x^2)) */
      MPFR_ZIV_INIT (loop, prec);
      for (;;)
        {
          mpfr_set_prec (xp, prec);
          mpfr_sqr (xp, x, MPFR_RNDN);
          mpfr_ui_sub (xp, 1, xp, MPFR_RNDN);
          mpfr_sqrt (xp, xp, MPFR_RNDN);
          mpfr_div (xp, x, xp, MPFR_RNDN);
          mpfr_atan (xp, xp, MPFR_RNDN);
          if (MPFR_LIKELY (MPFR_CAN_ROUND (xp, prec - xp_exp,
                                           MPFR_PREC (asin), rnd_mode)))
            break;
          MPFR_ZIV_NEXT (loop, prec);
        }
      MPFR_ZIV_FREE (loop);
      inexact = mpfr_set (asin, xp, rnd_mode);

      mpfr_clear (xp);
    }

  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (asin, inexact, rnd_mode);
}
Example #21
0
int
mpfr_cbrt (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode)
{
  mpz_t m;
  mpfr_exp_t e, r, sh;
  mpfr_prec_t n, size_m, tmp;
  int inexact, negative;
  MPFR_SAVE_EXPO_DECL (expo);

  MPFR_LOG_FUNC (
    ("x[%Pu]=%.*Rg rnd=%d", mpfr_get_prec (x), mpfr_log_prec, x, rnd_mode),
    ("y[%Pu]=%.*Rg inexact=%d", mpfr_get_prec (y), mpfr_log_prec, y,
     inexact));

  /* special values */
  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN (x))
        {
          MPFR_SET_NAN (y);
          MPFR_RET_NAN;
        }
      else if (MPFR_IS_INF (x))
        {
          MPFR_SET_INF (y);
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
      /* case 0: cbrt(+/- 0) = +/- 0 */
      else /* x is necessarily 0 */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          MPFR_SET_ZERO (y);
          MPFR_SET_SAME_SIGN (y, x);
          MPFR_RET (0);
        }
    }

  /* General case */
  MPFR_SAVE_EXPO_MARK (expo);
  mpz_init (m);

  e = mpfr_get_z_2exp (m, x);                /* x = m * 2^e */
  if ((negative = MPFR_IS_NEG(x)))
    mpz_neg (m, m);
  r = e % 3;
  if (r < 0)
    r += 3;
  /* x = (m*2^r) * 2^(e-r) = (m*2^r) * 2^(3*q) */

  MPFR_MPZ_SIZEINBASE2 (size_m, m);
  n = MPFR_PREC (y) + (rnd_mode == MPFR_RNDN);

  /* we want 3*n-2 <= size_m + 3*sh + r <= 3*n
     i.e. 3*sh + size_m + r <= 3*n */
  sh = (3 * (mpfr_exp_t) n - (mpfr_exp_t) size_m - r) / 3;
  sh = 3 * sh + r;
  if (sh >= 0)
    {
      mpz_mul_2exp (m, m, sh);
      e = e - sh;
    }
  else if (r > 0)
    {
      mpz_mul_2exp (m, m, r);
      e = e - r;
    }

  /* invariant: x = m*2^e, with e divisible by 3 */

  /* we reuse the variable m to store the cube root, since it is not needed
     any more: we just need to know if the root is exact */
  inexact = mpz_root (m, m, 3) == 0;

  MPFR_MPZ_SIZEINBASE2 (tmp, m);
  sh = tmp - n;
  if (sh > 0) /* we have to flush to 0 the last sh bits from m */
    {
      inexact = inexact || ((mpfr_exp_t) mpz_scan1 (m, 0) < sh);
      mpz_fdiv_q_2exp (m, m, sh);
      e += 3 * sh;
    }

  if (inexact)
    {
      if (negative)
        rnd_mode = MPFR_INVERT_RND (rnd_mode);
      if (rnd_mode == MPFR_RNDU || rnd_mode == MPFR_RNDA
          || (rnd_mode == MPFR_RNDN && mpz_tstbit (m, 0)))
        inexact = 1, mpz_add_ui (m, m, 1);
      else
        inexact = -1;
    }

  /* either inexact is not zero, and the conversion is exact, i.e. inexact
     is not changed; or inexact=0, and inexact is set only when
     rnd_mode=MPFR_RNDN and bit (n+1) from m is 1 */
  inexact += mpfr_set_z (y, m, MPFR_RNDN);
  MPFR_SET_EXP (y, MPFR_GET_EXP (y) + e / 3);

  if (negative)
    {
      MPFR_CHANGE_SIGN (y);
      inexact = -inexact;
    }

  mpz_clear (m);
  MPFR_SAVE_EXPO_FREE (expo);
  return mpfr_check_range (y, inexact, rnd_mode);
}
Example #22
0
int
mpc_asin (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  mpfr_prec_t p, p_re, p_im, incr_p = 0;
  mpfr_rnd_t rnd_re, rnd_im;
  mpc_t z1;
  int inex;

  /* special values */
  if (mpfr_nan_p (mpc_realref (op)) || mpfr_nan_p (mpc_imagref (op)))
    {
      if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op)))
        {
          mpfr_set_nan (mpc_realref (rop));
          mpfr_set_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? -1 : +1);
        }
      else if (mpfr_zero_p (mpc_realref (op)))
        {
          mpfr_set (mpc_realref (rop), mpc_realref (op), GMP_RNDN);
          mpfr_set_nan (mpc_imagref (rop));
        }
      else
        {
          mpfr_set_nan (mpc_realref (rop));
          mpfr_set_nan (mpc_imagref (rop));
        }

      return 0;
    }

  if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op)))
    {
      int inex_re;
      if (mpfr_inf_p (mpc_realref (op)))
        {
          int inf_im = mpfr_inf_p (mpc_imagref (op));

          inex_re = set_pi_over_2 (mpc_realref (rop),
             (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd));
          mpfr_set_inf (mpc_imagref (rop), (mpfr_signbit (mpc_imagref (op)) ? -1 : 1));

          if (inf_im)
            mpfr_div_2ui (mpc_realref (rop), mpc_realref (rop), 1, GMP_RNDN);
        }
      else
        {
          mpfr_set_zero (mpc_realref (rop), (mpfr_signbit (mpc_realref (op)) ? -1 : 1));
          inex_re = 0;
          mpfr_set_inf (mpc_imagref (rop), (mpfr_signbit (mpc_imagref (op)) ? -1 : 1));
        }

      return MPC_INEX (inex_re, 0);
    }

  /* pure real argument */
  if (mpfr_zero_p (mpc_imagref (op)))
    {
      int inex_re;
      int inex_im;
      int s_im;
      s_im = mpfr_signbit (mpc_imagref (op));

      if (mpfr_cmp_ui (mpc_realref (op), 1) > 0)
        {
          if (s_im)
            inex_im = -mpfr_acosh (mpc_imagref (rop), mpc_realref (op),
                                   INV_RND (MPC_RND_IM (rnd)));
          else
            inex_im = mpfr_acosh (mpc_imagref (rop), mpc_realref (op),
                                  MPC_RND_IM (rnd));
          inex_re = set_pi_over_2 (mpc_realref (rop),
             (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd));
          if (s_im)
            mpc_conj (rop, rop, MPC_RNDNN);
        }
      else if (mpfr_cmp_si (mpc_realref (op), -1) < 0)
        {
          mpfr_t minus_op_re;
          minus_op_re[0] = mpc_realref (op)[0];
          MPFR_CHANGE_SIGN (minus_op_re);

          if (s_im)
            inex_im = -mpfr_acosh (mpc_imagref (rop), minus_op_re,
                                   INV_RND (MPC_RND_IM (rnd)));
          else
            inex_im = mpfr_acosh (mpc_imagref (rop), minus_op_re,
                                  MPC_RND_IM (rnd));
          inex_re = set_pi_over_2 (mpc_realref (rop),
             (mpfr_signbit (mpc_realref (op)) ? -1 : 1), MPC_RND_RE (rnd));
          if (s_im)
            mpc_conj (rop, rop, MPC_RNDNN);
        }
      else
        {
          inex_im = mpfr_set_ui (mpc_imagref (rop), 0, MPC_RND_IM (rnd));
          if (s_im)
            mpfr_neg (mpc_imagref (rop), mpc_imagref (rop), GMP_RNDN);
          inex_re = mpfr_asin (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));
        }

      return MPC_INEX (inex_re, inex_im);
    }

  /* pure imaginary argument */
  if (mpfr_zero_p (mpc_realref (op)))
    {
      int inex_im;
      int s;
      s = mpfr_signbit (mpc_realref (op));
      mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN);
      if (s)
        mpfr_neg (mpc_realref (rop), mpc_realref (rop), GMP_RNDN);
      inex_im = mpfr_asinh (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd));

      return MPC_INEX (0, inex_im);
    }

  /* regular complex: asin(z) = -i*log(i*z+sqrt(1-z^2)) */
  p_re = mpfr_get_prec (mpc_realref(rop));
  p_im = mpfr_get_prec (mpc_imagref(rop));
  rnd_re = MPC_RND_RE(rnd);
  rnd_im = MPC_RND_IM(rnd);
  p = p_re >= p_im ? p_re : p_im;
  mpc_init2 (z1, p);
  while (1)
  {
    mpfr_exp_t ex, ey, err;

    p += mpc_ceil_log2 (p) + 3 + incr_p; /* incr_p is zero initially */
    incr_p = p / 2;
    mpfr_set_prec (mpc_realref(z1), p);
    mpfr_set_prec (mpc_imagref(z1), p);

    /* z1 <- z^2 */
    mpc_sqr (z1, op, MPC_RNDNN);
    /* err(x) <= 1/2 ulp(x), err(y) <= 1/2 ulp(y) */
    /* z1 <- 1-z1 */
    ex = mpfr_get_exp (mpc_realref(z1));
    mpfr_ui_sub (mpc_realref(z1), 1, mpc_realref(z1), GMP_RNDN);
    mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN);
    ex = ex - mpfr_get_exp (mpc_realref(z1));
    ex = (ex <= 0) ? 0 : ex;
    /* err(x) <= 2^ex * ulp(x) */
    ex = ex + mpfr_get_exp (mpc_realref(z1)) - p;
    /* err(x) <= 2^ex */
    ey = mpfr_get_exp (mpc_imagref(z1)) - p - 1;
    /* err(y) <= 2^ey */
    ex = (ex >= ey) ? ex : ey; /* err(x), err(y) <= 2^ex, i.e., the norm
                                  of the error is bounded by |h|<=2^(ex+1/2) */
    /* z1 <- sqrt(z1): if z1 = z + h, then sqrt(z1) = sqrt(z) + h/2/sqrt(t) */
    ey = mpfr_get_exp (mpc_realref(z1)) >= mpfr_get_exp (mpc_imagref(z1))
      ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1));
    /* we have |z1| >= 2^(ey-1) thus 1/|z1| <= 2^(1-ey) */
    mpc_sqrt (z1, z1, MPC_RNDNN);
    ex = (2 * ex + 1) - 2 - (ey - 1); /* |h^2/4/|t| <= 2^ex */
    ex = (ex + 1) / 2; /* ceil(ex/2) */
    /* express ex in terms of ulp(z1) */
    ey = mpfr_get_exp (mpc_realref(z1)) <= mpfr_get_exp (mpc_imagref(z1))
      ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1));
    ex = ex - ey + p;
    /* take into account the rounding error in the mpc_sqrt call */
    err = (ex <= 0) ? 1 : ex + 1;
    /* err(x) <= 2^err * ulp(x), err(y) <= 2^err * ulp(y) */
    /* z1 <- i*z + z1 */
    ex = mpfr_get_exp (mpc_realref(z1));
    ey = mpfr_get_exp (mpc_imagref(z1));
    mpfr_sub (mpc_realref(z1), mpc_realref(z1), mpc_imagref(op), GMP_RNDN);
    mpfr_add (mpc_imagref(z1), mpc_imagref(z1), mpc_realref(op), GMP_RNDN);
    if (mpfr_cmp_ui (mpc_realref(z1), 0) == 0 || mpfr_cmp_ui (mpc_imagref(z1), 0) == 0)
      continue;
    ex -= mpfr_get_exp (mpc_realref(z1)); /* cancellation in x */
    ey -= mpfr_get_exp (mpc_imagref(z1)); /* cancellation in y */
    ex = (ex >= ey) ? ex : ey; /* maximum cancellation */
    err += ex;
    err = (err <= 0) ? 1 : err + 1; /* rounding error in sub/add */
    /* z1 <- log(z1): if z1 = z + h, then log(z1) = log(z) + h/t with
       |t| >= min(|z1|,|z|) */
    ex = mpfr_get_exp (mpc_realref(z1));
    ey = mpfr_get_exp (mpc_imagref(z1));
    ex = (ex >= ey) ? ex : ey;
    err += ex - p; /* revert to absolute error <= 2^err */
    mpc_log (z1, z1, GMP_RNDN);
    err -= ex - 1; /* 1/|t| <= 1/|z| <= 2^(1-ex) */
    /* express err in terms of ulp(z1) */
    ey = mpfr_get_exp (mpc_realref(z1)) <= mpfr_get_exp (mpc_imagref(z1))
      ? mpfr_get_exp (mpc_realref(z1)) : mpfr_get_exp (mpc_imagref(z1));
    err = err - ey + p;
    /* take into account the rounding error in the mpc_log call */
    err = (err <= 0) ? 1 : err + 1;
    /* z1 <- -i*z1 */
    mpfr_swap (mpc_realref(z1), mpc_imagref(z1));
    mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN);
    if (mpfr_can_round (mpc_realref(z1), p - err, GMP_RNDN, GMP_RNDZ,
                        p_re + (rnd_re == GMP_RNDN)) &&
        mpfr_can_round (mpc_imagref(z1), p - err, GMP_RNDN, GMP_RNDZ,
                        p_im + (rnd_im == GMP_RNDN)))
      break;
  }

  inex = mpc_set (rop, z1, rnd);
  mpc_clear (z1);

  return inex;
}
Example #23
0
int
main (int argc, char *argv[])
{
  mpfr_t x, y;
  unsigned long int n;

  tests_start_mpfr ();

  mpfr_init (x);
  mpfr_init (y);

  n = randlimb ();

  MPFR_SET_INF(x);
  mpfr_ui_pow (y, n, x, MPFR_RNDN);
  if(!MPFR_IS_INF(y))
    {
      printf ("evaluation of function in INF does not return INF\n");
      exit (1);
    }

  MPFR_CHANGE_SIGN(x);
  mpfr_ui_pow (y, n, x, MPFR_RNDN);
  if(!MPFR_IS_ZERO(y))
    {
      printf ("evaluation of function in -INF does not return 0");
      exit (1);
    }

  MPFR_SET_NAN(x);
  mpfr_ui_pow (y, n, x, MPFR_RNDN);
  if(!MPFR_IS_NAN(y))
    {
      printf ("evaluation of function in NAN does not return NAN");
      exit (1);
    }

  test1 ();

  {
  mpfr_t z, t;
  mpfr_prec_t prec;
  mpfr_rnd_t rnd;
  unsigned int n;

  mpfr_prec_t p0=2, p1=100;
  unsigned int N=20;

  mpfr_init2 (z, 38);
  mpfr_init2 (t, 6);

  /* check exact power */
  mpfr_set_str_binary (t, "0.110000E5");
  mpfr_ui_pow (z, 3, t, MPFR_RNDN);

  mpfr_set_prec (x, 2);
  mpfr_set_prec (y, 2);
  mpfr_set_str (x, "-0.5", 10, MPFR_RNDZ);
  mpfr_ui_pow (y, 4, x, MPFR_RNDD);
  if (mpfr_cmp_ui_2exp(y, 1, -1))
    {
      fprintf (stderr, "Error for 4^(-0.5), prec=2, MPFR_RNDD\n");
      fprintf (stderr, "expected 0.5, got ");
      mpfr_out_str (stderr, 2, 0, y, MPFR_RNDN);
      fprintf (stderr, "\n");
      exit (1);
    }

  /* problem found by Kevin on spe175.testdrive.compaq.com
     (03 Sep 2003), ia64 under HP-UX */
  mpfr_set_prec (x, 2);
  mpfr_set_prec (y, 2);
  mpfr_set_str (x, "0.5", 10, MPFR_RNDN);
  mpfr_ui_pow (y, 398441521, x, MPFR_RNDN);
  if (mpfr_cmp_ui_2exp(y, 1, 14))
    {
      fprintf (stderr, "Error for 398441521^(0.5), prec=2, MPFR_RNDN\n");
      fprintf (stderr, "expected 1.0e14, got ");
      mpfr_out_str (stderr, 2, 0, y, MPFR_RNDN);
      fprintf (stderr, "\n");
      exit (1);
    }

  mpfr_clear (z);
  mpfr_clear (t);

  mpfr_set_prec (x, 2);
  mpfr_set_str (x, "0.5", 10, MPFR_RNDN);
  check1 (x, 2, 398441521, MPFR_RNDN);  /* 398441521 = 19961^2 */

  /* generic test */
  for (prec = p0; prec <= p1; prec++)
    {
      mpfr_set_prec (x, prec);
      for (n=0; n<N; n++)
        {
          int nt;
          nt = randlimb () & INT_MAX;
          mpfr_urandomb (x, RANDS);
          rnd = RND_RAND ();
          check1 (x, prec, nt, rnd);
        }
    }
  }

  mpfr_clear (x);
  mpfr_clear (y);

  tests_end_mpfr ();
  return 0;
}
Example #24
0
File: tatan.c Project: Canar/mpfr
static void
special_atan2 (void)
{
    mpfr_t x, y, z;

    mpfr_inits2 (4, x, y, z, (mpfr_ptr) 0);

    /* Anything with NAN should be set to NAN */
    mpfr_set_ui (y, 0, MPFR_RNDN);
    mpfr_set_nan (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_NAN (z));
    mpfr_swap (x, y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_NAN (z));

    /* 0+ 0+ --> 0+ */
    mpfr_set_ui (y, 0, MPFR_RNDN);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z));
    /* 0- 0+ --> 0- */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_NEG (z));
    /* 0- 0- --> -PI */
    MPFR_CHANGE_SIGN (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-3.1415", 10, MPFR_RNDN) == 0);
    /* 0+ 0- --> +PI */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "3.1415", 10, MPFR_RNDN) == 0);
    /* 0+ -1 --> PI */
    mpfr_set_si (x, -1, MPFR_RNDN);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "3.1415", 10, MPFR_RNDN) == 0);
    /* 0- -1 --> -PI */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-3.1415", 10, MPFR_RNDN) == 0);
    /* 0- +1 --> 0- */
    mpfr_set_ui (x, 1, MPFR_RNDN);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_NEG (z));
    /* 0+ +1 --> 0+ */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z));
    /* +1 0+ --> PI/2 */
    mpfr_swap (x, y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "1.57075", 10, MPFR_RNDN) == 0);
    /* +1 0- --> PI/2 */
    MPFR_CHANGE_SIGN (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "1.57075", 10, MPFR_RNDN) == 0);
    /* -1 0- --> -PI/2 */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-1.57075", 10, MPFR_RNDN) == 0);
    /* -1 0+ --> -PI/2 */
    MPFR_CHANGE_SIGN (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-1.57075", 10, MPFR_RNDN) == 0);

    /* -1 +INF --> -0 */
    MPFR_SET_INF (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_NEG (z));
    /* +1 +INF --> +0 */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z));
    /* +1 -INF --> +PI */
    MPFR_CHANGE_SIGN (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "3.1415", 10, MPFR_RNDN) == 0);
    /* -1 -INF --> -PI */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-3.1415", 10, MPFR_RNDN) == 0);
    /* -INF -1 --> -PI/2 */
    mpfr_swap (x, y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-1.57075", 10, MPFR_RNDN) == 0);
    /* +INF -1  --> PI/2 */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "1.57075", 10, MPFR_RNDN) == 0);
    /* +INF -INF --> 3*PI/4 */
    MPFR_SET_INF (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "2.356194490192344928", 10, MPFR_RNDN) == 0);
    /* +INF +INF --> PI/4 */
    MPFR_CHANGE_SIGN (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "0.785375", 10, MPFR_RNDN) == 0);
    /* -INF +INF --> -PI/4 */
    MPFR_CHANGE_SIGN (y);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-0.785375", 10, MPFR_RNDN) == 0);
    /* -INF -INF --> -3*PI/4 */
    MPFR_CHANGE_SIGN (x);
    mpfr_atan2 (z, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-2.356194490192344928", 10, MPFR_RNDN) == 0);
    mpfr_set_prec (z, 905); /* exercises Ziv's loop */
    mpfr_atan2 (z, y, x, MPFR_RNDZ);
    MPFR_ASSERTN (mpfr_cmp_str (z, "-2.35619449019234492884698253745962716314787704953132936573120844423086230471465674897102611900658780098661106488496172998532038345716293667379401955609636083808771307702645389082916973346721171619778647332160823174945008459635673617534008737395340143185923642519259526145784", 10, MPFR_RNDN) == 0);

    mpfr_clears (x, y, z, (mpfr_ptr) 0);
}
Example #25
0
static void
special (void)
{
  mpfr_t x, y;
  int i;

  mpfr_init (x);
  mpfr_init (y);

  /* root(NaN) = NaN */
  mpfr_set_nan (x);
  mpfr_root (y, x, 17, GMP_RNDN);
  if (!mpfr_nan_p (y))
    {
      printf ("Error: root(NaN,17) <> NaN\n");
      exit (1);
    }

  /* root(+Inf) = +Inf */
  mpfr_set_inf (x, 1);
  mpfr_root (y, x, 42, GMP_RNDN);
  if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0)
    {
      printf ("Error: root(+Inf,42) <> +Inf\n");
      exit (1);
    }

  /* root(-Inf, 17) =  -Inf */
  mpfr_set_inf (x, -1);
  mpfr_root (y, x, 17, GMP_RNDN);
  if (!mpfr_inf_p (y) || mpfr_sgn (y) > 0)
    {
      printf ("Error: root(-Inf,17) <> -Inf\n");
      exit (1);
    }
  /* root(-Inf, 42) =  NaN */
  mpfr_set_inf (x, -1);
  mpfr_root (y, x, 42, GMP_RNDN);
  if (!mpfr_nan_p (y))
    {
      printf ("Error: root(-Inf,42) <> -Inf\n");
      exit (1);
    }

  /* root(+/-0) =  +/-0 */
  mpfr_set_ui (x, 0, GMP_RNDN);
  mpfr_root (y, x, 17, GMP_RNDN);
  if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0)
    {
      printf ("Error: root(+0,17) <> +0\n");
      exit (1);
    }
  mpfr_neg (x, x, GMP_RNDN);
  mpfr_root (y, x, 42, GMP_RNDN);
  if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) > 0)
    {
      printf ("Error: root(-0,42) <> -0\n");
      exit (1);
    }

  mpfr_set_prec (x, 53);
  mpfr_set_str (x, "8.39005285514734966412e-01", 10, GMP_RNDN);
  mpfr_root (x, x, 3, GMP_RNDN);
  if (mpfr_cmp_str1 (x, "9.43166207799662426048e-01"))
    {
      printf ("Error in root3 (1)\n");
      printf ("expected 9.43166207799662426048e-01\n");
      printf ("got      ");
      mpfr_dump (x);
      exit (1);
    }

  mpfr_set_prec (x, 32);
  mpfr_set_prec (y, 32);
  mpfr_set_str_binary (x, "0.10000100001100101001001001011001");
  mpfr_root (x, x, 3, GMP_RNDN);
  mpfr_set_str_binary (y, "0.11001101011000100111000111111001");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in root3 (2)\n");
      exit (1);
    }

  mpfr_set_prec (x, 32);
  mpfr_set_prec (y, 32);
  mpfr_set_str_binary (x, "-0.1100001110110000010101011001011");
  mpfr_root (x, x, 3, GMP_RNDD);
  mpfr_set_str_binary (y, "-0.11101010000100100101000101011001");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in root3 (3)\n");
      exit (1);
    }

  mpfr_set_prec (x, 82);
  mpfr_set_prec (y, 27);
  mpfr_set_str_binary (x, "0.1010001111011101011011000111001011001101100011110110010011011011011010011001100101e-7");
  mpfr_root (y, x, 3, GMP_RNDD);
  mpfr_set_str_binary (x, "0.101011110001110001000100011E-2");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in root3 (4)\n");
      exit (1);
    }

  mpfr_set_prec (x, 204);
  mpfr_set_prec (y, 38);
  mpfr_set_str_binary (x, "0.101000000001101000000001100111111011111001110110100001111000100110100111001101100111110001110001011011010110010011100101111001111100001010010100111011101100000011011000101100010000000011000101001010001001E-5");
  mpfr_root (y, x, 3, GMP_RNDD);
  mpfr_set_str_binary (x, "0.10001001111010011011101000010110110010E-1");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in root3 (5)\n");
      exit (1);
    }

  /* Worst case found on 2006-11-25 */
  mpfr_set_prec (x, 53);
  mpfr_set_prec (y, 53);
  mpfr_set_str_binary (x, "1.0100001101101101001100110001001000000101001101100011E28");
  mpfr_root (y, x, 35, GMP_RNDN);
  mpfr_set_str_binary (x, "1.1100000010110101100011101011000010100001101100100011E0");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in mpfr_root (y, x, 35, GMP_RNDN) for\n"
              "x = 1.0100001101101101001100110001001000000101001101100011E28\n"
              "Expected ");
      mpfr_dump (x);
      printf ("Got      ");
      mpfr_dump (y);
      exit (1);
    }
  /* Worst cases found on 2006-11-26 */
  mpfr_set_str_binary (x, "1.1111010011101110001111010110000101110000110110101100E17");
  mpfr_root (y, x, 36, GMP_RNDD);
  mpfr_set_str_binary (x, "1.0110100111010001101001010111001110010100111111000010E0");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in mpfr_root (y, x, 36, GMP_RNDD) for\n"
              "x = 1.1111010011101110001111010110000101110000110110101100E17\n"
              "Expected ");
      mpfr_dump (x);
      printf ("Got      ");
      mpfr_dump (y);
      exit (1);
    }
  mpfr_set_str_binary (x, "1.1100011101101101100010110001000001110001111110010000E23");
  mpfr_root (y, x, 36, GMP_RNDU);
  mpfr_set_str_binary (x, "1.1001010100001110000110111111100011011101110011000100E0");
  if (mpfr_cmp (x, y))
    {
      printf ("Error in mpfr_root (y, x, 36, GMP_RNDU) for\n"
              "x = 1.1100011101101101100010110001000001110001111110010000E23\n"
              "Expected ");
      mpfr_dump (x);
      printf ("Got      ");
      mpfr_dump (y);
      exit (1);
    }

  /* Check for k = 1 */
  mpfr_set_ui (x, 17, GMP_RNDN);
  i = mpfr_root (y, x, 1, GMP_RNDN);
  if (mpfr_cmp_ui (x, 17) || i != 0)
    {
      printf ("Error in root (17^(1/1))\n");
      exit (1);
    }

#if 0
  /* Check for k == 0:
     For 0 <= x < 1 => +0.
     For x = 1      => 1.
     For x > 1,     => +Inf.
     For x < 0      => NaN.   */
  i = mpfr_root (y, x, 0, GMP_RNDN);
  if (!MPFR_IS_INF (y) || !MPFR_IS_POS (y) || i != 0)
    {
      printf ("Error in root 17^(1/0)\n");
      exit (1);
    }
  mpfr_set_ui (x, 1, GMP_RNDN);
  i = mpfr_root (y, x, 0, GMP_RNDN);
  if (mpfr_cmp_ui (y, 1) || i != 0)
    {
      printf ("Error in root 1^(1/0)\n");
      exit (1);
    }
  mpfr_set_ui (x, 0, GMP_RNDN);
  i = mpfr_root (y, x, 0, GMP_RNDN);
  if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0)
    {
      printf ("Error in root 0+^(1/0)\n");
      exit (1);
    }
  MPFR_CHANGE_SIGN (x);
  i = mpfr_root (y, x, 0, GMP_RNDN);
  if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0)
    {
      printf ("Error in root 0-^(1/0)\n");
      exit (1);
    }
  mpfr_set_ui_2exp (x, 17, -5, GMP_RNDD);
  i = mpfr_root (y, x, 0, GMP_RNDN);
  if (!MPFR_IS_ZERO (y) || !MPFR_IS_POS (y) || i != 0)
    {
      printf ("Error in root (17/2^5)^(1/0)\n");
      exit (1);
    }
#endif
  mpfr_set_ui (x, 0, GMP_RNDN);
  i = mpfr_root (y, x, 0, GMP_RNDN);
  if (!MPFR_IS_NAN (y) || i != 0)
    {
      printf ("Error in root 0+^(1/0)\n");
      exit (1);
    }
  /* Check for k==2 */
  mpfr_set_si (x, -17, GMP_RNDD);
  i = mpfr_root (y, x, 2, GMP_RNDN);
  if (!MPFR_IS_NAN (y) || i != 0)
    {
      printf ("Error in root (-17)^(1/2)\n");
      exit (1);
    }

  mpfr_clear (x);
  mpfr_clear (y);
}
Example #26
0
int
main (int argc, char *argv[])
{
  mpfr_t x, y;
  mpfr_exp_t emin, emax;

  tests_start_mpfr ();

  special_overflow ();
  emax_m_eps ();
  exp_range ();

  mpfr_init (x);
  mpfr_init (y);

  mpfr_set_ui (x, 4, MPFR_RNDN);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if (mpfr_cmp_ui (y, 16) != 0)
    {
      printf ("Error for 2^4, MPFR_RNDN\n");
      exit (1);
    }
  mpfr_exp2 (y, x, MPFR_RNDD);
  if (mpfr_cmp_ui (y, 16) != 0)
    {
      printf ("Error for 2^4, MPFR_RNDD\n");
      exit (1);
    }
  mpfr_exp2 (y, x, MPFR_RNDU);
  if (mpfr_cmp_ui (y, 16) != 0)
    {
      printf ("Error for 2^4, MPFR_RNDU\n");
      exit (1);
    }

  mpfr_set_si (x, -4, MPFR_RNDN);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if (mpfr_cmp_ui_2exp (y, 1, -4) != 0)
    {
      printf ("Error for 2^(-4), MPFR_RNDN\n");
      exit (1);
    }
  mpfr_exp2 (y, x, MPFR_RNDD);
  if (mpfr_cmp_ui_2exp (y, 1, -4) != 0)
    {
      printf ("Error for 2^(-4), MPFR_RNDD\n");
      exit (1);
    }
  mpfr_exp2 (y, x, MPFR_RNDU);
  if (mpfr_cmp_ui_2exp (y, 1, -4) != 0)
    {
      printf ("Error for 2^(-4), MPFR_RNDU\n");
      exit (1);
    }

  mpfr_set_prec (x, 53);
  mpfr_set_prec (y, 53);
  mpfr_set_str (x, /*-1683977482443233.0 / 2199023255552.0*/
                "-7.6578429909351734750089235603809357e2", 10, MPFR_RNDN);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if (mpfr_cmp_str1 (y, "2.991959870867646566478e-231"))
    {
      printf ("Error for x=-1683977482443233/2^41\n");
      exit (1);
    }

  mpfr_set_prec (x, 10);
  mpfr_set_prec (y, 10);
  /* save emin */
  emin = mpfr_get_emin ();
  set_emin (-10);
  mpfr_set_si (x, -12, MPFR_RNDN);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if (mpfr_cmp_ui (y, 0) || mpfr_sgn (y) < 0)
    {
      printf ("Error for x=emin-2, RNDN\n");
      printf ("Expected +0\n");
      printf ("Got      "); mpfr_print_binary (y); puts ("");
      exit (1);
    }
  /* restore emin */
  set_emin (emin);

  /* save emax */
  emax = mpfr_get_emax ();
  set_emax (10);
  mpfr_set_ui (x, 11, MPFR_RNDN);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if (!mpfr_inf_p (y) || mpfr_sgn (y) < 0)
    {
      printf ("Error for x=emax+1, RNDN\n");
      exit (1);
    }
  /* restore emax */
  set_emax (emax);

  MPFR_SET_INF(x);
  MPFR_SET_POS(x);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if(!MPFR_IS_INF(y))
    {
      printf ("evaluation of function in INF does not return INF\n");
      exit (1);
    }

  MPFR_CHANGE_SIGN(x);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if(!MPFR_IS_ZERO(y))
    {
      printf ("evaluation of function in -INF does not return 0\n");
      exit (1);
    }

  MPFR_SET_NAN(x);
  mpfr_exp2 (y, x, MPFR_RNDN);
  if(!MPFR_IS_NAN(y))
    {
      printf ("evaluation of function in NaN does not return NaN\n");
      exit (1);
    }

  if ((mpfr_uexp_t) 8 << 31 != 0 ||
      mpfr_get_emax () <= (mpfr_uexp_t) 100000 * 100000)
    {
      /* emax <= 10000000000 */
      mpfr_set_prec (x, 40);
      mpfr_set_prec (y, 40);
      mpfr_set_str (x, "10000000000.5", 10, MPFR_RNDN);
      mpfr_clear_flags ();
      mpfr_exp2 (y, x, MPFR_RNDN);
      if (!(MPFR_IS_INF (y) && MPFR_IS_POS (y) && mpfr_overflow_p ()))
        {
          printf ("exp2(10000000000.5) should overflow.\n");
          exit (1);
        }
    }

  mpfr_set_prec (x, 2);
  mpfr_set_prec (y, 2);
  mpfr_set_str_binary (x, "-1.0E-26");
  mpfr_exp2 (y, x, MPFR_RNDD);
  mpfr_set_str_binary (x, "1.1E-1");
  if (mpfr_cmp (x, y))
    {
      printf ("Error for exp(-2^(-26)) for prec=2\n");
      exit (1);
    }

  test_generic (2, 100, 100);

  mpfr_clear (x);
  mpfr_clear (y);

  overflowed_exp2_0 ();

  data_check ("data/exp2", mpfr_exp2, "mpfr_exp2");

  tests_end_mpfr ();
  return 0;
}
Example #27
0
static int
check_INF (void)
{
  mpfr_t t, ch, sh, th, ach, ash, ath;
  int tester;
  int fail = 0;

  mpfr_init2 (t, 200);
  mpfr_init2 (ch, 200);
  mpfr_init2 (sh, 200);
  mpfr_init2 (th, 200);
  mpfr_init2 (ach, 200);
  mpfr_init2 (ash, 200);
  mpfr_init2 (ath, 200);

  MPFR_SET_INF(t);

  if(MPFR_IS_NEG (t))
    MPFR_CHANGE_SIGN(t);

  /******cosh********/

  tester = mpfr_cosh(ch,t,MPFR_RNDD);
  if (!MPFR_IS_INF(ch) || MPFR_IS_NEG (ch) || tester!=0)
    {
      printf("cosh(INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******sinh********/

  tester=mpfr_sinh(sh,t,MPFR_RNDD);
  if (!MPFR_IS_INF(sh) || MPFR_IS_NEG (sh)  || tester!=0)
    {
      printf("sinh(INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******tanh********/

  tester=mpfr_tanh(th,t,MPFR_RNDD);
  if (mpfr_cmp_ui(th,1) != 0 || tester!=0)
    {
      printf("tanh(INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******acosh********/

  tester=mpfr_acosh(ach,t,MPFR_RNDD);
  if (!MPFR_IS_INF(ach) || MPFR_IS_NEG (ach)  || tester!=0)
    {
      printf("acosh(INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******asinh********/

  tester=mpfr_asinh(ash,t,MPFR_RNDD);
  if (!MPFR_IS_INF(ash) || MPFR_IS_NEG (ash)  || tester!=0)
    {
      printf("asinh(INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******atanh********/

  tester = mpfr_atanh (ath, t, MPFR_RNDD);
  if (!MPFR_IS_NAN(ath) || tester != 0)
    {
      printf("atanh(INF) \n");
      fail = 1;
      goto clean_up;
    }

  MPFR_CHANGE_SIGN(t);

  /******cosh********/

  tester=mpfr_cosh(ch,t,MPFR_RNDD);
  if (!MPFR_IS_INF(ch) || MPFR_IS_NEG (ch)  || tester!=0)
    {
      printf("cosh(-INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******sinh********/

  tester=mpfr_sinh(sh,t,MPFR_RNDD);
  if (!MPFR_IS_INF(sh)  || MPFR_IS_POS (sh) || tester!=0)
    {
      printf("sinh(-INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******tanh********/

  tester=mpfr_tanh(th,t,MPFR_RNDD);
  if (!mpfr_cmp_ui(th,-1) || tester!=0)
    {
      printf("tanh(-INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******acosh********/

  tester=mpfr_acosh(ach,t,MPFR_RNDD);
  if (!MPFR_IS_NAN(ach) || tester!=0)
    {
      printf("acosh(-INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******asinh********/

  tester=mpfr_asinh(ash,t,MPFR_RNDD);
  if (!MPFR_IS_INF(ash) || MPFR_IS_POS (ash)  || tester!=0)
    {
      printf("asinh(-INF) \n");
      fail = 1;
      goto clean_up;
    }

  /******atanh********/

  tester = mpfr_atanh (ath, t, MPFR_RNDD);
  if (!MPFR_IS_NAN(ath) || tester != 0)
    {
      printf("atanh(-INF) \n");
      fail = 1;
      goto clean_up;
    }

 clean_up:
  mpfr_clear(t);
  mpfr_clear(ch);
  mpfr_clear(sh);
  mpfr_clear(th);
  mpfr_clear(ach);
  mpfr_clear(ash);
  mpfr_clear(ath);

  return fail;
}
Example #28
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);
        }
    }
}
Example #29
0
/* return mpfr_cmp (mpc_abs (a), mpc_abs (b)) */
int
mpc_cmp_abs (mpc_srcptr a, mpc_srcptr b)
{
   mpc_t z1, z2;
   mpfr_t n1, n2;
   mpfr_prec_t prec;
   int inex1, inex2, ret;

   /* Handle numbers containing one NaN as mpfr_cmp. */
   if (   mpfr_nan_p (mpc_realref (a)) || mpfr_nan_p (mpc_imagref (a))
       || mpfr_nan_p (mpc_realref (b)) || mpfr_nan_p (mpc_imagref (b)))
     {
       mpfr_t nan;
       mpfr_init (nan);
       mpfr_set_nan (nan);
       ret = mpfr_cmp (nan, nan);
       mpfr_clear (nan);
       return ret;
     }

   /* Handle infinities. */
   if (mpc_inf_p (a))
      if (mpc_inf_p (b))
         return 0;
      else
         return 1;
   else if (mpc_inf_p (b))
      return -1;

   /* Replace all parts of a and b by their absolute values, then order
      them by size. */
   z1 [0] = a [0];
   z2 [0] = b [0];
   if (mpfr_signbit (mpc_realref (a)))
      MPFR_CHANGE_SIGN (mpc_realref (z1));
   if (mpfr_signbit (mpc_imagref (a)))
      MPFR_CHANGE_SIGN (mpc_imagref (z1));
   if (mpfr_signbit (mpc_realref (b)))
      MPFR_CHANGE_SIGN (mpc_realref (z2));
   if (mpfr_signbit (mpc_imagref (b)))
      MPFR_CHANGE_SIGN (mpc_imagref (z2));
   if (mpfr_cmp (mpc_realref (z1), mpc_imagref (z1)) > 0)
      mpfr_swap (mpc_realref (z1), mpc_imagref (z1));
   if (mpfr_cmp (mpc_realref (z2), mpc_imagref (z2)) > 0)
      mpfr_swap (mpc_realref (z2), mpc_imagref (z2));

   /* Handle cases in which only one part differs. */
   if (mpfr_cmp (mpc_realref (z1), mpc_realref (z2)) == 0)
      return mpfr_cmp (mpc_imagref (z1), mpc_imagref (z2));
   if (mpfr_cmp (mpc_imagref (z1), mpc_imagref (z2)) == 0)
      return mpfr_cmp (mpc_realref (z1), mpc_realref (z2));

   /* Implement the algorithm in algorithms.tex. */
   mpfr_init (n1);
   mpfr_init (n2);
   prec = MPC_MAX (50, MPC_MAX (MPC_MAX_PREC (z1), MPC_MAX_PREC (z2)) / 100);
   do {
      mpfr_set_prec (n1, prec);
      mpfr_set_prec (n2, prec);
      inex1 = mpc_norm (n1, z1, MPFR_RNDD);
      inex2 = mpc_norm (n2, z2, MPFR_RNDD);
      ret = mpfr_cmp (n1, n2);
      if (ret != 0)
        goto end;
      else
         if (inex1 == 0) /* n1 = norm(z1) */
            if (inex2)   /* n2 < norm(z2) */
              {
                ret = -1;
                goto end;
              }
            else /* n2 = norm(z2) */
              {
                ret = 0;
                goto end;
              }
         else /* n1 < norm(z1) */
            if (inex2 == 0)
              {
                ret = 1;
                goto end;
              }
      prec *= 2;
   } while (1);
 end:
   mpfr_clear (n1);
   mpfr_clear (n2);
   return ret;
}
Example #30
0
/* (y, z) <- (sin(x), cos(x)), return value is 0 iff both results are exact
   ie, iff x = 0 */
int
mpfr_sin_cos (mpfr_ptr y, mpfr_ptr z, mpfr_srcptr x, mp_rnd_t rnd_mode)
{
  mp_prec_t prec, m;
  int neg, reduce;
  mpfr_t c, xr;
  mpfr_srcptr xx;
  mp_exp_t err, expx;
  MPFR_ZIV_DECL (loop);

  if (MPFR_UNLIKELY (MPFR_IS_SINGULAR (x)))
    {
      if (MPFR_IS_NAN(x) || MPFR_IS_INF(x))
        {
          MPFR_SET_NAN (y);
          MPFR_SET_NAN (z);
          MPFR_RET_NAN;
        }
      else /* x is zero */
        {
          MPFR_ASSERTD (MPFR_IS_ZERO (x));
          MPFR_SET_ZERO (y);
          MPFR_SET_SAME_SIGN (y, x);
          /* y = 0, thus exact, but z is inexact in case of underflow
             or overflow */
          return mpfr_set_ui (z, 1, rnd_mode);
        }
    }

  MPFR_LOG_FUNC (("x[%#R]=%R rnd=%d", x, x, rnd_mode),
                  ("sin[%#R]=%R cos[%#R]=%R", y, y, z, z));

  prec = MAX (MPFR_PREC (y), MPFR_PREC (z));
  m = prec + MPFR_INT_CEIL_LOG2 (prec) + 13;
  expx = MPFR_GET_EXP (x);

  mpfr_init (c);
  mpfr_init (xr);

  MPFR_ZIV_INIT (loop, m);
  for (;;)
    {
      /* the following is copied from sin.c */
      if (expx >= 2) /* reduce the argument */
        {
          reduce = 1;
          mpfr_set_prec (c, expx + m - 1);
          mpfr_set_prec (xr, m);
          mpfr_const_pi (c, GMP_RNDN);
          mpfr_mul_2ui (c, c, 1, GMP_RNDN);
          mpfr_remainder (xr, x, c, GMP_RNDN);
          mpfr_div_2ui (c, c, 1, GMP_RNDN);
          if (MPFR_SIGN (xr) > 0)
            mpfr_sub (c, c, xr, GMP_RNDZ);
          else
            mpfr_add (c, c, xr, GMP_RNDZ);
          if (MPFR_IS_ZERO(xr) || MPFR_EXP(xr) < (mp_exp_t) 3 - (mp_exp_t) m
              || MPFR_EXP(c) < (mp_exp_t) 3 - (mp_exp_t) m)
            goto next_step;
          xx = xr;
        }
      else /* the input argument is already reduced */
        {
          reduce = 0;
          xx = x;
        }

      neg = MPFR_IS_NEG (xx); /* gives sign of sin(x) */
      mpfr_set_prec (c, m);
      mpfr_cos (c, xx, GMP_RNDZ);
      /* If no argument reduction was performed, the error is at most ulp(c),
         otherwise it is at most ulp(c) + 2^(2-m). Since |c| < 1, we have
         ulp(c) <= 2^(-m), thus the error is bounded by 2^(3-m) in that later
         case. */
      if (reduce == 0)
        err = m;
      else
        err = MPFR_GET_EXP (c) + (mp_exp_t) (m - 3);
      if (!mpfr_can_round (c, err, GMP_RNDN, rnd_mode,
                           MPFR_PREC (z) + (rnd_mode == GMP_RNDN)))
        goto next_step;

      mpfr_set (z, c, rnd_mode);
      mpfr_sqr (c, c, GMP_RNDU);
      mpfr_ui_sub (c, 1, c, GMP_RNDN);
      err = 2 + (- MPFR_GET_EXP (c)) / 2;
      mpfr_sqrt (c, c, GMP_RNDN);
      if (neg)
        MPFR_CHANGE_SIGN (c);

      /* the absolute error on c is at most 2^(err-m), which we must put
         in the form 2^(EXP(c)-err). If there was an argument reduction,
         we need to add 2^(2-m); since err >= 2, the error is bounded by
         2^(err+1-m) in that case. */
      err = MPFR_GET_EXP (c) + (mp_exp_t) m - (err + reduce);
      if (mpfr_can_round (c, err, GMP_RNDN, rnd_mode,
                          MPFR_PREC (y) + (rnd_mode == GMP_RNDN)))
        break;
      /* check for huge cancellation */
      if (err < (mp_exp_t) MPFR_PREC (y))
        m += MPFR_PREC (y) - err;
      /* Check if near 1 */
      if (MPFR_GET_EXP (c) == 1
          && MPFR_MANT (c)[MPFR_LIMB_SIZE (c)-1] == MPFR_LIMB_HIGHBIT)
        m += m;

    next_step:
      MPFR_ZIV_NEXT (loop, m);
      mpfr_set_prec (c, m);
    }
  MPFR_ZIV_FREE (loop);

  mpfr_set (y, c, rnd_mode);

  mpfr_clear (c);
  mpfr_clear (xr);

  MPFR_RET (1); /* Always inexact */
}