Exemple #1
0
static void
test_reuse (void)
{
  mpc_t z;
  mpfr_t y;
  int inex;

  mpfr_init2 (y, 2);
  mpc_init2 (z, 2);
  mpc_set_si_si (z, 0, -1, MPC_RNDNN);
  mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
  mpc_div_2ui (z, z, 4, MPC_RNDNN);
  mpfr_set_ui (y, 512, MPFR_RNDN);
  inex = mpc_pow_fr (z, z, y, MPC_RNDNN);
  if (MPC_INEX_RE(inex) != 0 || MPC_INEX_IM(inex) != 0 ||
      mpfr_cmp_ui_2exp (mpc_realref(z), 1, -2048) != 0 ||
      mpfr_cmp_ui (mpc_imagref(z), 0) != 0 || mpfr_signbit (mpc_imagref(z)) == 0)
    {
      printf ("Error in test_reuse, wrong ternary value or output\n");
      printf ("inex=(%d %d)\n", MPC_INEX_RE(inex), MPC_INEX_IM(inex));
      printf ("z="); mpc_out_str (stdout, 2, 0, z, MPC_RNDNN); printf ("\n");
      exit (1);
    }
  mpfr_clear (y);
  mpc_clear (z);
}
static void
check_different_precisions(void)
{
  /* check reuse when real and imaginary part have different precisions. */
  mpc_t z, expected, got;
  int res;

  mpc_init2(z, 128);
  mpc_init2(expected, 128);
  mpc_init2(got, 128);

  /* change precision of one part */
  mpfr_set_prec (mpc_imagref (z), 32);
  mpfr_set_prec (mpc_imagref (expected), 32);
  mpfr_set_prec (mpc_imagref (got), 32);

  mpfr_set_str (mpc_realref (z), "0x100000000fp-32", 16, GMP_RNDN);
  mpfr_set_str (mpc_imagref (z), "-1", 2, GMP_RNDN);
  mpfr_set_str (mpc_realref (expected), "+1", 2, GMP_RNDN);
  mpfr_set_str (mpc_imagref (expected), "0x100000000fp-32", 16, GMP_RNDN);

  mpc_set (got, z, MPC_RNDNN);
  res = mpc_mul_i (got, got, +1, MPC_RNDNN);
  if (MPC_INEX_RE(res) != 0 || MPC_INEX_IM(res) >=0)
    {
      printf("Wrong inexact flag for mpc_mul_i(z, z, n)\n"
             "     got (re=%2d, im=%2d)\nexpected (re= 0, im=-1)\n",
             MPC_INEX_RE(res), MPC_INEX_IM(res));
      exit(1);
    }
  if (mpc_cmp(got, expected) != 0)
    {
      printf ("Error for mpc_mul_i(z, z, n) for\n");
      MPC_OUT (z);
      printf ("n=+1\n");
      MPC_OUT (expected);
      MPC_OUT (got);

      exit (1);
    }

  mpc_neg (expected, expected, MPC_RNDNN);
  mpc_set (got, z, MPC_RNDNN);
  mpc_mul_i (got, got, -1, MPC_RNDNN);
  if (mpc_cmp(got, expected) != 0)
    {
      printf ("Error for mpc_mul_i(z, z, n) for\n");
      MPC_OUT (z);
      printf ("n=-1\n");
      MPC_OUT (expected);
      MPC_OUT (got);

      exit (1);
    }

  mpc_clear (z);
  mpc_clear (expected);
  mpc_clear (got);
}
Exemple #3
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;
}
Exemple #4
0
int
mpc_tanh (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  /* tanh(op) = -i*tan(i*op) = conj(-i*tan(conj(-i*op))) */
  mpc_t z;
  mpc_t tan_z;
  int inex;

  /* z := conj(-i * op) and rop = conj(-i * tan(z)), in other words, we have
     to switch real and imaginary parts. Let us set them without copying
     significands. */
  mpc_realref (z)[0] = mpc_imagref (op)[0];
  mpc_imagref (z)[0] = mpc_realref (op)[0];
  mpc_realref (tan_z)[0] = mpc_imagref (rop)[0];
  mpc_imagref (tan_z)[0] = mpc_realref (rop)[0];

  inex = mpc_tan (tan_z, z, MPC_RND (MPC_RND_IM (rnd), MPC_RND_RE (rnd)));

  /* tan_z and rop parts share the same significands, copy the rest now. */
  mpc_realref (rop)[0] = mpc_imagref (tan_z)[0];
  mpc_imagref (rop)[0] = mpc_realref (tan_z)[0];

  /* swap inexact flags for real and imaginary parts */
  return MPC_INEX (MPC_INEX_IM (inex), MPC_INEX_RE (inex));
}
Exemple #5
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));
}
Exemple #6
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));
}
Exemple #7
0
int main() {
	
	mpc_t z;
	int inex;
	mpc_init2(z, 128);
	mpc_set_ui_ui(z, 0, 1, MPC_RNDNN);

	inex = mpc_sqrt(z, z, MPC_RNDNN);
	mpc_out_str(stdout, 10, 3, z, MPC_RNDNN);
	printf("\n%i %i\n", MPC_INEX_RE(inex), MPC_INEX_IM(inex));

	mpc_clear(z);

}
Exemple #8
0
int
mpc_log10 (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
   int ok = 0, loops = 0, check_exact = 0, special_re, special_im,
       inex, inex_re, inex_im;
   mpfr_prec_t prec;
   mpfr_t log10;
   mpc_t log;

   mpfr_init2 (log10, 2);
   mpc_init2 (log, 2);
   prec = MPC_MAX_PREC (rop);
   /* compute log(op)/log(10) */
   while (ok == 0) {
      loops ++;
      prec += (loops <= 2) ? mpc_ceil_log2 (prec) + 4 : prec / 2;
      mpfr_set_prec (log10, prec);
      mpc_set_prec (log, prec);

      inex = mpc_log (log, op, rnd); /* error <= 1 ulp */

      if (!mpfr_number_p (mpc_imagref (log))
         || mpfr_zero_p (mpc_imagref (log))) {
         /* no need to divide by log(10) */
         special_im = 1;
         ok = 1;
      }
      else {
         special_im = 0;
         mpfr_const_log10 (log10);
         mpfr_div (mpc_imagref (log), mpc_imagref (log), log10, MPFR_RNDN);

         ok = mpfr_can_round (mpc_imagref (log), prec - 2,
                  MPFR_RNDN, MPFR_RNDZ,
                  MPC_PREC_IM(rop) + (MPC_RND_IM (rnd) == MPFR_RNDN));
      }

      if (ok) {
         if (!mpfr_number_p (mpc_realref (log))
            || mpfr_zero_p (mpc_realref (log)))
            special_re = 1;
         else {
            special_re = 0;
            if (special_im)
               /* log10 not yet computed */
               mpfr_const_log10 (log10);
            mpfr_div (mpc_realref (log), mpc_realref (log), log10, MPFR_RNDN);
               /* error <= 24/7 ulp < 4 ulp for prec >= 4, see algorithms.tex */

            ok = mpfr_can_round (mpc_realref (log), prec - 2,
                     MPFR_RNDN, MPFR_RNDZ,
                     MPC_PREC_RE(rop) + (MPC_RND_RE (rnd) == MPFR_RNDN));
         }

         /* Special code to deal with cases where the real part of log10(x+i*y)
            is exact, like x=3 and y=1. Since Re(log10(x+i*y)) = log10(x^2+y^2)/2
            this happens whenever x^2+y^2 is a nonnegative power of 10.
            Indeed x^2+y^2 cannot equal 10^(a/2^b) for a, b integers, a odd, b>0,
            since x^2+y^2 is rational, and 10^(a/2^b) is irrational.
            Similarly, for b=0, x^2+y^2 cannot equal 10^a for a < 0 since x^2+y^2
            is a rational with denominator a power of 2.
            Now let x^2+y^2 = 10^s. Without loss of generality we can assume
            x = u/2^e and y = v/2^e with u, v, e integers: u^2+v^2 = 10^s*2^(2e)
            thus u^2+v^2 = 0 mod 2^(2e). By recurrence on e, necessarily
            u = v = 0 mod 2^e, thus x and y are necessarily integers.
         */
         if (!ok && !check_exact && mpfr_integer_p (mpc_realref (op)) &&
            mpfr_integer_p (mpc_imagref (op))) {
            mpz_t x, y;
            unsigned long s, v;

            check_exact = 1;
            mpz_init (x);
            mpz_init (y);
            mpfr_get_z (x, mpc_realref (op), MPFR_RNDN); /* exact */
            mpfr_get_z (y, mpc_imagref (op), MPFR_RNDN); /* exact */
            mpz_mul (x, x, x);
            mpz_mul (y, y, y);
            mpz_add (x, x, y); /* x^2+y^2 */
            v = mpz_scan1 (x, 0);
            /* if x = 10^s then necessarily s = v */
            s = mpz_sizeinbase (x, 10);
            /* since s is either the number of digits of x or one more,
               then x = 10^(s-1) or 10^(s-2) */
            if (s == v + 1 || s == v + 2) {
               mpz_div_2exp (x, x, v);
               mpz_ui_pow_ui (y, 5, v);
               if (mpz_cmp (y, x) == 0) {
                  /* Re(log10(x+i*y)) is exactly v/2
                     we reset the precision of Re(log) so that v can be
                     represented exactly */
                  mpfr_set_prec (mpc_realref (log),
                                 sizeof(unsigned long)*CHAR_BIT);
                  mpfr_set_ui_2exp (mpc_realref (log), v, -1, MPFR_RNDN);
                     /* exact */
                  ok = 1;
               }
            }
            mpz_clear (x);
            mpz_clear (y);
         }
      }
   }

   inex_re = mpfr_set (mpc_realref(rop), mpc_realref (log), MPC_RND_RE (rnd));
   if (special_re)
      inex_re = MPC_INEX_RE (inex);
      /* recover flag from call to mpc_log above */
   inex_im = mpfr_set (mpc_imagref(rop), mpc_imagref (log), MPC_RND_IM (rnd));
   if (special_im)
      inex_im = MPC_INEX_IM (inex);
   mpfr_clear (log10);
   mpc_clear (log);

   return MPC_INEX(inex_re, inex_im);
}
Exemple #9
0
int
mpc_div (mpc_ptr a, mpc_srcptr b, mpc_srcptr c, mpc_rnd_t rnd)
{
   int ok_re = 0, ok_im = 0;
   mpc_t res, c_conj;
   mpfr_t q;
   mpfr_prec_t prec;
   int inex, inexact_prod, inexact_norm, inexact_re, inexact_im, loops = 0;
   int underflow_norm, overflow_norm, underflow_prod, overflow_prod;
   int underflow_re = 0, overflow_re = 0, underflow_im = 0, overflow_im = 0;
   mpfr_rnd_t rnd_re = MPC_RND_RE (rnd), rnd_im = MPC_RND_IM (rnd);
   int saved_underflow, saved_overflow;
   int tmpsgn;
   mpfr_exp_t e, emin, emax, emid; /* for scaling of exponents */
   mpc_t b_scaled, c_scaled;
   mpfr_t b_re, b_im, c_re, c_im;

   /* According to the C standard G.3, there are three types of numbers:   */
   /* finite (both parts are usual real numbers; contains 0), infinite     */
   /* (at least one part is a real infinity) and all others; the latter    */
   /* are numbers containing a nan, but no infinity, and could reasonably  */
   /* be called nan.                                                       */
   /* By G.5.1.4, infinite/finite=infinite; finite/infinite=0;             */
   /* all other divisions that are not finite/finite return nan+i*nan.     */
   /* Division by 0 could be handled by the following case of division by  */
   /* a real; we handle it separately instead.                             */
   if (mpc_zero_p (c)) /* both Re(c) and Im(c) are zero */
      return mpc_div_zero (a, b, c, rnd);
   else if (mpc_inf_p (b) && mpc_fin_p (c)) /* either Re(b) or Im(b) is infinite
                                               and both Re(c) and Im(c) are ordinary */
         return mpc_div_inf_fin (a, b, c);
   else if (mpc_fin_p (b) && mpc_inf_p (c))
         return mpc_div_fin_inf (a, b, c);
   else if (!mpc_fin_p (b) || !mpc_fin_p (c)) {
      mpc_set_nan (a);
      return MPC_INEX (0, 0);
   }
   else if (mpfr_zero_p(mpc_imagref(c)))
      return mpc_div_real (a, b, c, rnd);
   else if (mpfr_zero_p(mpc_realref(c)))
      return mpc_div_imag (a, b, c, rnd);

   prec = MPC_MAX_PREC(a);

   mpc_init2 (res, 2);
   mpfr_init (q);

   /* compute scaling of exponents: none of Re(c) and Im(c) can be zero,
      but one of Re(b) or Im(b) could be zero */

   e = mpfr_get_exp (mpc_realref (c));
   emin = emax = e;
   e = mpfr_get_exp (mpc_imagref (c));
   if (e > emax)
     emax = e;
   else if (e < emin)
     emin = e;
   if (!mpfr_zero_p (mpc_realref (b)))
     {
       e = mpfr_get_exp (mpc_realref (b));
       if (e > emax)
         emax = e;
       else if (e < emin)
         emin = e;
     }
   if (!mpfr_zero_p (mpc_imagref (b)))
     {
       e = mpfr_get_exp (mpc_imagref (b));
       if (e > emax)
         emax = e;
       else if (e < emin)
         emin = e;
     }

   /* all input exponents are in [emin, emax] */
   emid = emin / 2 + emax / 2;

   /* scale the inputs */
   b_re[0] = mpc_realref (b)[0];
   if (!mpfr_zero_p (mpc_realref (b)))
     MPFR_EXP(b_re) = MPFR_EXP(mpc_realref (b)) - emid;
   b_im[0] = mpc_imagref (b)[0];
   if (!mpfr_zero_p (mpc_imagref (b)))
     MPFR_EXP(b_im) = MPFR_EXP(mpc_imagref (b)) - emid;
   c_re[0] = mpc_realref (c)[0];
   MPFR_EXP(c_re) = MPFR_EXP(mpc_realref (c)) - emid;
   c_im[0] = mpc_imagref (c)[0];
   MPFR_EXP(c_im) = MPFR_EXP(mpc_imagref (c)) - emid;

   /* create the scaled inputs without allocating new memory */
   mpc_realref (b_scaled)[0] = b_re[0];
   mpc_imagref (b_scaled)[0] = b_im[0];
   mpc_realref (c_scaled)[0] = c_re[0];
   mpc_imagref (c_scaled)[0] = c_im[0];

   /* create the conjugate of c in c_conj without allocating new memory */
   mpc_realref (c_conj)[0] = mpc_realref (c_scaled)[0];
   mpc_imagref (c_conj)[0] = mpc_imagref (c_scaled)[0];
   MPFR_CHANGE_SIGN (mpc_imagref (c_conj));

   /* save the underflow or overflow flags from MPFR */
   saved_underflow = mpfr_underflow_p ();
   saved_overflow = mpfr_overflow_p ();

   do {
      loops ++;
      prec += loops <= 2 ? mpc_ceil_log2 (prec) + 5 : prec / 2;

      mpc_set_prec (res, prec);
      mpfr_set_prec (q, prec);

      /* first compute norm(c_scaled) */
      mpfr_clear_underflow ();
      mpfr_clear_overflow ();
      inexact_norm = mpc_norm (q, c_scaled, MPFR_RNDU);
      underflow_norm = mpfr_underflow_p ();
      overflow_norm = mpfr_overflow_p ();
      if (underflow_norm)
         mpfr_set_ui (q, 0ul, MPFR_RNDN);
         /* to obtain divisions by 0 later on */

      /* now compute b_scaled*conjugate(c_scaled) */
      mpfr_clear_underflow ();
      mpfr_clear_overflow ();
      inexact_prod = mpc_mul (res, b_scaled, c_conj, MPC_RNDZZ);
      inexact_re = MPC_INEX_RE (inexact_prod);
      inexact_im = MPC_INEX_IM (inexact_prod);
      underflow_prod = mpfr_underflow_p ();
      overflow_prod = mpfr_overflow_p ();
         /* unfortunately, does not distinguish between under-/overflow
            in real or imaginary parts
            hopefully, the side-effects of mpc_mul do indeed raise the
            mpfr exceptions */
      if (overflow_prod) {
        /* FIXME: in case overflow_norm is also true, the code below is wrong,
           since the after division by the norm, we might end up with finite
           real and/or imaginary parts. A workaround would be to scale the
           inputs (in case the exponents are within the same range). */
         int isinf = 0;
         /* determine if the real part of res is the maximum or the minimum
            representable number */
         tmpsgn = mpfr_sgn (mpc_realref(res));
         if (tmpsgn > 0)
           {
             mpfr_nextabove (mpc_realref(res));
             isinf = mpfr_inf_p (mpc_realref(res));
             mpfr_nextbelow (mpc_realref(res));
           }
         else if (tmpsgn < 0)
           {
             mpfr_nextbelow (mpc_realref(res));
             isinf = mpfr_inf_p (mpc_realref(res));
             mpfr_nextabove (mpc_realref(res));
           }
         if (isinf)
           {
             mpfr_set_inf (mpc_realref(res), tmpsgn);
             overflow_re = 1;
           }
         /* same for the imaginary part */
         tmpsgn = mpfr_sgn (mpc_imagref(res));
         isinf = 0;
         if (tmpsgn > 0)
           {
             mpfr_nextabove (mpc_imagref(res));
             isinf = mpfr_inf_p (mpc_imagref(res));
             mpfr_nextbelow (mpc_imagref(res));
           }
         else if (tmpsgn < 0)
           {
             mpfr_nextbelow (mpc_imagref(res));
             isinf = mpfr_inf_p (mpc_imagref(res));
             mpfr_nextabove (mpc_imagref(res));
           }
         if (isinf)
           {
             mpfr_set_inf (mpc_imagref(res), tmpsgn);
             overflow_im = 1;
           }
         mpc_set (a, res, rnd);
         goto end;
      }

      /* divide the product by the norm */
      if (inexact_norm == 0 && (inexact_re == 0 || inexact_im == 0)) {
         /* The division has good chances to be exact in at least one part.  */
         /* Since this can cause problems when not rounding to the nearest,  */
         /* we use the division code of mpfr, which handles the situation.   */
         mpfr_clear_underflow ();
         mpfr_clear_overflow ();
         inexact_re |= mpfr_div (mpc_realref (res), mpc_realref (res), q, MPFR_RNDZ);
         underflow_re = mpfr_underflow_p ();
         overflow_re = mpfr_overflow_p ();
         ok_re = !inexact_re || underflow_re || overflow_re
                 || mpfr_can_round (mpc_realref (res), prec - 4, MPFR_RNDN,
                    MPFR_RNDZ, MPC_PREC_RE(a) + (rnd_re == MPFR_RNDN));

         if (ok_re) /* compute imaginary part */ {
            mpfr_clear_underflow ();
            mpfr_clear_overflow ();
            inexact_im |= mpfr_div (mpc_imagref (res), mpc_imagref (res), q, MPFR_RNDZ);
            underflow_im = mpfr_underflow_p ();
            overflow_im = mpfr_overflow_p ();
            ok_im = !inexact_im || underflow_im || overflow_im
                    || mpfr_can_round (mpc_imagref (res), prec - 4, MPFR_RNDN,
                       MPFR_RNDZ, MPC_PREC_IM(a) + (rnd_im == MPFR_RNDN));
         }
      }
      else {
         /* The division is inexact, so for efficiency reasons we invert q */
         /* only once and multiply by the inverse. */
         if (mpfr_ui_div (q, 1ul, q, MPFR_RNDZ) || inexact_norm) {
             /* if 1/q is inexact, the approximations of the real and
                imaginary part below will be inexact, unless RE(res)
                or IM(res) is zero */
             inexact_re |= !mpfr_zero_p (mpc_realref (res));
             inexact_im |= !mpfr_zero_p (mpc_imagref (res));
         }
         mpfr_clear_underflow ();
         mpfr_clear_overflow ();
         inexact_re |= mpfr_mul (mpc_realref (res), mpc_realref (res), q, MPFR_RNDZ);
         underflow_re = mpfr_underflow_p ();
         overflow_re = mpfr_overflow_p ();
         ok_re = !inexact_re || underflow_re || overflow_re
                 || mpfr_can_round (mpc_realref (res), prec - 4, MPFR_RNDN,
                    MPFR_RNDZ, MPC_PREC_RE(a) + (rnd_re == MPFR_RNDN));

         if (ok_re) /* compute imaginary part */ {
            mpfr_clear_underflow ();
            mpfr_clear_overflow ();
            inexact_im |= mpfr_mul (mpc_imagref (res), mpc_imagref (res), q, MPFR_RNDZ);
            underflow_im = mpfr_underflow_p ();
            overflow_im = mpfr_overflow_p ();
            ok_im = !inexact_im || underflow_im || overflow_im
                    || mpfr_can_round (mpc_imagref (res), prec - 4, MPFR_RNDN,
                       MPFR_RNDZ, MPC_PREC_IM(a) + (rnd_im == MPFR_RNDN));
         }
      }
   } while ((!ok_re || !ok_im) && !underflow_norm && !overflow_norm
                               && !underflow_prod && !overflow_prod);

   inex = mpc_set (a, res, rnd);
   inexact_re = MPC_INEX_RE (inex);
   inexact_im = MPC_INEX_IM (inex);

 end:
   /* fix values and inexact flags in case of overflow/underflow */
   /* FIXME: heuristic, certainly does not cover all cases */
   if (overflow_re || (underflow_norm && !underflow_prod)) {
      mpfr_set_inf (mpc_realref (a), mpfr_sgn (mpc_realref (res)));
      inexact_re = mpfr_sgn (mpc_realref (res));
   }
   else if (underflow_re || (overflow_norm && !overflow_prod)) {
      inexact_re = mpfr_signbit (mpc_realref (res)) ? 1 : -1;
      mpfr_set_zero (mpc_realref (a), -inexact_re);
   }
   if (overflow_im || (underflow_norm && !underflow_prod)) {
      mpfr_set_inf (mpc_imagref (a), mpfr_sgn (mpc_imagref (res)));
      inexact_im = mpfr_sgn (mpc_imagref (res));
   }
   else if (underflow_im || (overflow_norm && !overflow_prod)) {
      inexact_im = mpfr_signbit (mpc_imagref (res)) ? 1 : -1;
      mpfr_set_zero (mpc_imagref (a), -inexact_im);
   }

   mpc_clear (res);
   mpfr_clear (q);

   /* restore underflow and overflow flags from MPFR */
   if (saved_underflow)
     mpfr_set_underflow ();
   if (saved_overflow)
     mpfr_set_overflow ();

   return MPC_INEX (inexact_re, inexact_im);
}
Exemple #10
0
static void
foo (int f(mpc_ptr, mpc_srcptr, mpc_rnd_t), char *s)
{
  mpc_t z, t;
  int rnd_re, rnd_im, rnd;
#define N 5
  mpfr_exp_t exy[N][2] = {{200, 800}, {800, 200}, {-50, 50}, {-10, 1000},
                          {0, 1000}};
  int n, inex, inex_re, inex_im, sgn;

  mpc_init2 (z, MPFR_PREC_MIN);
  mpc_init2 (t, MPFR_PREC_MIN);
  for (n = 0; n < N; n++)
    for (sgn = 0; sgn < 4; sgn++)
    {
      if (exy[n][0])
        mpfr_set_ui_2exp (mpc_realref (z), 1, exy[n][0], MPFR_RNDN);
      else
        mpfr_set_ui (mpc_realref (z), 0, MPFR_RNDN);
      if (sgn & 1)
        mpfr_neg (mpc_realref (z), mpc_realref (z), MPFR_RNDN);
      if (exy[n][1])
        mpfr_set_ui_2exp (mpc_imagref (z), 1, exy[n][1], MPFR_RNDN);
      else
        mpfr_set_ui (mpc_imagref (z), 0, MPFR_RNDN);
      if (sgn & 2)
        mpfr_neg (mpc_imagref (z), mpc_imagref (z), MPFR_RNDN);

      inex = f (t, z, MPC_RNDZZ);
      inex_re = MPC_INEX_RE(inex);
      inex_im = MPC_INEX_IM(inex);

      if (inex_re != 0 && mpfr_inf_p (mpc_realref (t)))
        {
          fprintf (stderr, "Error, wrong real part with rounding towards zero\n");
          fprintf (stderr, "f = %s\n", s);
          fprintf (stderr, "z=");
          mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
          fprintf (stderr, "\nt=");
          mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
          fprintf (stderr, "\n");
          exit (1);
        }

      if (inex_im != 0 && mpfr_inf_p (mpc_imagref (t)))
        {
          fprintf (stderr, "Error, wrong imag part with rounding towards zero\n");
          fprintf (stderr, "f = %s\n", s);
          fprintf (stderr, "z=");
          mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
          fprintf (stderr, "\nt=");
          mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
          fprintf (stderr, "\n");
          exit (1);
        }

      rnd_re = mpfr_signbit (mpc_realref (t)) == 0 ? MPFR_RNDU : MPFR_RNDD;
      rnd_im = mpfr_signbit (mpc_imagref (t)) == 0 ? MPFR_RNDU : MPFR_RNDD;
      rnd = MPC_RND(rnd_re,rnd_im); /* round away */

      inex = f (t, z, rnd);
      inex_re = MPC_INEX_RE(inex);
      inex_im = MPC_INEX_IM(inex);

      if (inex_re != 0 && mpfr_zero_p (mpc_realref (t)))
        {
          fprintf (stderr, "Error, wrong real part with rounding away from zero\n");
          fprintf (stderr, "f = %s\n", s);
          fprintf (stderr, "z=");
          mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
          fprintf (stderr, "\nt=");
          mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
          fprintf (stderr, "\n");
          fprintf (stderr, "rnd=%s\n", mpfr_print_rnd_mode (rnd_re));
          exit (1);
        }

      if (inex_im != 0 && mpfr_zero_p (mpc_imagref (t)))
        {
          fprintf (stderr, "Error, wrong imag part with rounding away from zero\n");
          fprintf (stderr, "f = %s\n", s);
          fprintf (stderr, "z=");
          mpc_out_str (stderr, 2, 0, z, MPC_RNDNN);
          fprintf (stderr, "\nt=");
          mpc_out_str (stderr, 2, 0, t, MPC_RNDNN);
          fprintf (stderr, "\n");
          fprintf (stderr, "rnd=%s\n", mpfr_print_rnd_mode (rnd_im));
          exit (1);
        }
    }

  mpc_clear (z);
  mpc_clear (t);
}
Exemple #11
0
int
mpc_tan (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  mpc_t x, y;
  mpfr_prec_t prec;
  mpfr_exp_t err;
  int ok = 0;
  int inex;

  /* special values */
  if (!mpc_fin_p (op))
    {
      if (mpfr_nan_p (mpc_realref (op)))
        {
          if (mpfr_inf_p (mpc_imagref (op)))
            /* tan(NaN -i*Inf) = +/-0 -i */
            /* tan(NaN +i*Inf) = +/-0 +i */
            {
              /* exact unless 1 is not in exponent range */
              inex = mpc_set_si_si (rop, 0,
                                    (MPFR_SIGN (mpc_imagref (op)) < 0) ? -1 : +1,
                                    rnd);
            }
          else
            /* tan(NaN +i*y) = NaN +i*NaN, when y is finite */
            /* tan(NaN +i*NaN) = NaN +i*NaN */
            {
              mpfr_set_nan (mpc_realref (rop));
              mpfr_set_nan (mpc_imagref (rop));
              inex = MPC_INEX (0, 0); /* always exact */
            }
        }
      else if (mpfr_nan_p (mpc_imagref (op)))
        {
          if (mpfr_cmp_ui (mpc_realref (op), 0) == 0)
            /* tan(-0 +i*NaN) = -0 +i*NaN */
            /* tan(+0 +i*NaN) = +0 +i*NaN */
            {
              mpc_set (rop, op, rnd);
              inex = MPC_INEX (0, 0); /* always exact */
            }
          else
            /* tan(x +i*NaN) = NaN +i*NaN, when x != 0 */
            {
              mpfr_set_nan (mpc_realref (rop));
              mpfr_set_nan (mpc_imagref (rop));
              inex = MPC_INEX (0, 0); /* always exact */
            }
        }
      else if (mpfr_inf_p (mpc_realref (op)))
        {
          if (mpfr_inf_p (mpc_imagref (op)))
            /* tan(-Inf -i*Inf) = -/+0 -i */
            /* tan(-Inf +i*Inf) = -/+0 +i */
            /* tan(+Inf -i*Inf) = +/-0 -i */
            /* tan(+Inf +i*Inf) = +/-0 +i */
            {
              const int sign_re = mpfr_signbit (mpc_realref (op));
              int inex_im;

              mpfr_set_ui (mpc_realref (rop), 0, MPC_RND_RE (rnd));
              mpfr_setsign (mpc_realref (rop), mpc_realref (rop), sign_re, MPFR_RNDN);

              /* exact, unless 1 is not in exponent range */
              inex_im = mpfr_set_si (mpc_imagref (rop),
                                     mpfr_signbit (mpc_imagref (op)) ? -1 : +1,
                                     MPC_RND_IM (rnd));
              inex = MPC_INEX (0, inex_im);
            }
          else
            /* tan(-Inf +i*y) = tan(+Inf +i*y) = NaN +i*NaN, when y is
               finite */
            {
              mpfr_set_nan (mpc_realref (rop));
              mpfr_set_nan (mpc_imagref (rop));
              inex = MPC_INEX (0, 0); /* always exact */
            }
        }
      else
        /* tan(x -i*Inf) = +0*sin(x)*cos(x) -i, when x is finite */
        /* tan(x +i*Inf) = +0*sin(x)*cos(x) +i, when x is finite */
        {
          mpfr_t c;
          mpfr_t s;
          int inex_im;

          mpfr_init (c);
          mpfr_init (s);

          mpfr_sin_cos (s, c, mpc_realref (op), MPFR_RNDN);
          mpfr_set_ui (mpc_realref (rop), 0, MPC_RND_RE (rnd));
          mpfr_setsign (mpc_realref (rop), mpc_realref (rop),
                        mpfr_signbit (c) != mpfr_signbit (s), MPFR_RNDN);
          /* exact, unless 1 is not in exponent range */
          inex_im = mpfr_set_si (mpc_imagref (rop),
                                 (mpfr_signbit (mpc_imagref (op)) ? -1 : +1),
                                 MPC_RND_IM (rnd));
          inex = MPC_INEX (0, inex_im);

          mpfr_clear (s);
          mpfr_clear (c);
        }

      return inex;
    }

  if (mpfr_zero_p (mpc_realref (op)))
    /* tan(-0 -i*y) = -0 +i*tanh(y), when y is finite. */
    /* tan(+0 +i*y) = +0 +i*tanh(y), when y is finite. */
    {
      int inex_im;

      mpfr_set (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));
      inex_im = mpfr_tanh (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd));

      return MPC_INEX (0, inex_im);
    }

  if (mpfr_zero_p (mpc_imagref (op)))
    /* tan(x -i*0) = tan(x) -i*0, when x is finite. */
    /* tan(x +i*0) = tan(x) +i*0, when x is finite. */
    {
      int inex_re;

      inex_re = mpfr_tan (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));
      mpfr_set (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd));

      return MPC_INEX (inex_re, 0);
    }

  /* ordinary (non-zero) numbers */

  /* tan(op) = sin(op) / cos(op).

     We use the following algorithm with rounding away from 0 for all
     operations, and working precision w:

     (1) x = A(sin(op))
     (2) y = A(cos(op))
     (3) z = A(x/y)

     the error on Im(z) is at most 81 ulp,
     the error on Re(z) is at most
     7 ulp if k < 2,
     8 ulp if k = 2,
     else 5+k ulp, where
     k = Exp(Re(x))+Exp(Re(y))-2min{Exp(Re(y)), Exp(Im(y))}-Exp(Re(x/y))
     see proof in algorithms.tex.
  */

  prec = MPC_MAX_PREC(rop);

  mpc_init2 (x, 2);
  mpc_init2 (y, 2);

  err = 7;

  do
    {
      mpfr_exp_t k, exr, eyr, eyi, ezr;

      ok = 0;

      /* FIXME: prevent addition overflow */
      prec += mpc_ceil_log2 (prec) + err;
      mpc_set_prec (x, prec);
      mpc_set_prec (y, prec);

      /* rounding away from zero: except in the cases x=0 or y=0 (processed
         above), sin x and cos y are never exact, so rounding away from 0 is
         rounding towards 0 and adding one ulp to the absolute value */
      mpc_sin_cos (x, y, op, MPC_RNDZZ, MPC_RNDZZ);
      MPFR_ADD_ONE_ULP (mpc_realref (x));
      MPFR_ADD_ONE_ULP (mpc_imagref (x));
      MPFR_ADD_ONE_ULP (mpc_realref (y));
      MPFR_ADD_ONE_ULP (mpc_imagref (y));
      MPC_ASSERT (mpfr_zero_p (mpc_realref (x)) == 0);

      if (   mpfr_inf_p (mpc_realref (x)) || mpfr_inf_p (mpc_imagref (x))
          || mpfr_inf_p (mpc_realref (y)) || mpfr_inf_p (mpc_imagref (y))) {
         /* If the real or imaginary part of x is infinite, it means that
            Im(op) was large, in which case the result is
            sign(tan(Re(op)))*0 + sign(Im(op))*I,
            where sign(tan(Re(op))) = sign(Re(x))*sign(Re(y)). */
          int inex_re, inex_im;
          mpfr_set_ui (mpc_realref (rop), 0, MPFR_RNDN);
          if (mpfr_sgn (mpc_realref (x)) * mpfr_sgn (mpc_realref (y)) < 0)
            {
              mpfr_neg (mpc_realref (rop), mpc_realref (rop), MPFR_RNDN);
              inex_re = 1;
            }
          else
            inex_re = -1; /* +0 is rounded down */
          if (mpfr_sgn (mpc_imagref (op)) > 0)
            {
              mpfr_set_ui (mpc_imagref (rop), 1, MPFR_RNDN);
              inex_im = 1;
            }
          else
            {
              mpfr_set_si (mpc_imagref (rop), -1, MPFR_RNDN);
              inex_im = -1;
            }
          inex = MPC_INEX(inex_re, inex_im);
          goto end;
        }

      exr = mpfr_get_exp (mpc_realref (x));
      eyr = mpfr_get_exp (mpc_realref (y));
      eyi = mpfr_get_exp (mpc_imagref (y));

      /* some parts of the quotient may be exact */
      inex = mpc_div (x, x, y, MPC_RNDZZ);
      /* OP is no pure real nor pure imaginary, so in theory the real and
         imaginary parts of its tangent cannot be null. However due to
         rouding errors this might happen. Consider for example
         tan(1+14*I) = 1.26e-10 + 1.00*I. For small precision sin(op) and
         cos(op) differ only by a factor I, thus after mpc_div x = I and
         its real part is zero. */
      if (mpfr_zero_p (mpc_realref (x)) || mpfr_zero_p (mpc_imagref (x)))
        {
          err = prec; /* double precision */
          continue;
        }
      if (MPC_INEX_RE (inex))
         MPFR_ADD_ONE_ULP (mpc_realref (x));
      if (MPC_INEX_IM (inex))
         MPFR_ADD_ONE_ULP (mpc_imagref (x));
      MPC_ASSERT (mpfr_zero_p (mpc_realref (x)) == 0);
      ezr = mpfr_get_exp (mpc_realref (x));

      /* FIXME: compute
         k = Exp(Re(x))+Exp(Re(y))-2min{Exp(Re(y)), Exp(Im(y))}-Exp(Re(x/y))
         avoiding overflow */
      k = exr - ezr + MPC_MAX(-eyr, eyr - 2 * eyi);
      err = k < 2 ? 7 : (k == 2 ? 8 : (5 + k));

      /* Can the real part be rounded? */
      ok = (!mpfr_number_p (mpc_realref (x)))
           || mpfr_can_round (mpc_realref(x), prec - err, MPFR_RNDN, MPFR_RNDZ,
                      MPC_PREC_RE(rop) + (MPC_RND_RE(rnd) == MPFR_RNDN));

      if (ok)
        {
          /* Can the imaginary part be rounded? */
          ok = (!mpfr_number_p (mpc_imagref (x)))
               || mpfr_can_round (mpc_imagref(x), prec - 6, MPFR_RNDN, MPFR_RNDZ,
                      MPC_PREC_IM(rop) + (MPC_RND_IM(rnd) == MPFR_RNDN));
        }
    }
  while (ok == 0);

  inex = mpc_set (rop, x, rnd);

 end:
  mpc_clear (x);
  mpc_clear (y);

  return inex;
}
Exemple #12
0
static PyObject *
GMPy_MPC_GetRc_Attrib(MPC_Object *self, void *closure)
{
    return Py_BuildValue("(ii)", MPC_INEX_RE(self->rc), MPC_INEX_IM(self->rc));
}
Exemple #13
0
int
mpc_acos (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
  int inex_re, inex_im, inex;
  mpfr_prec_t p_re, p_im, p;
  mpc_t z1;
  mpfr_t pi_over_2;
  mpfr_exp_t e1, e2;
  mpfr_rnd_t rnd_im;
  mpc_rnd_t rnd1;

  inex_re = 0;
  inex_im = 0;

  /* 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_inf (mpc_imagref (rop), mpfr_signbit (mpc_imagref (op)) ? +1 : -1);
          mpfr_set_nan (mpc_realref (rop));
        }
      else if (mpfr_zero_p (mpc_realref (op)))
        {
          inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd));
          mpfr_set_nan (mpc_imagref (rop));
        }
      else
        {
          mpfr_set_nan (mpc_realref (rop));
          mpfr_set_nan (mpc_imagref (rop));
        }

      return MPC_INEX (inex_re, 0);
    }

  if (mpfr_inf_p (mpc_realref (op)) || mpfr_inf_p (mpc_imagref (op)))
    {
      if (mpfr_inf_p (mpc_realref (op)))
        {
          if (mpfr_inf_p (mpc_imagref (op)))
            {
              if (mpfr_sgn (mpc_realref (op)) > 0)
                {
                  inex_re =
                    set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd));
                  mpfr_div_2ui (mpc_realref (rop), mpc_realref (rop), 1, GMP_RNDN);
                }
              else
                {

                  /* the real part of the result is 3*pi/4
                     a = o(pi)  error(a) < 1 ulp(a)
                     b = o(3*a) error(b) < 2 ulp(b)
                     c = b/4    exact
                     thus 1 bit is lost */
                  mpfr_t x;
                  mpfr_prec_t prec;
                  int ok;
                  mpfr_init (x);
                  prec = mpfr_get_prec (mpc_realref (rop));
                  p = prec;

                  do
                    {
                      p += mpc_ceil_log2 (p);
                      mpfr_set_prec (x, p);
                      mpfr_const_pi (x, GMP_RNDD);
                      mpfr_mul_ui (x, x, 3, GMP_RNDD);
                      ok =
                        mpfr_can_round (x, p - 1, GMP_RNDD, MPC_RND_RE (rnd),
                                        prec+(MPC_RND_RE (rnd) == GMP_RNDN));

                    } while (ok == 0);
                  inex_re =
                    mpfr_div_2ui (mpc_realref (rop), x, 2, MPC_RND_RE (rnd));
                  mpfr_clear (x);
                }
            }
          else
            {
              if (mpfr_sgn (mpc_realref (op)) > 0)
                mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN);
              else
                inex_re = mpfr_const_pi (mpc_realref (rop), MPC_RND_RE (rnd));
            }
        }
      else
        inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd));

      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 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),
                                  MPC_RND_IM (rnd));
          else
            inex_im = -mpfr_acosh (mpc_imagref (rop), mpc_realref (op),
                                   INV_RND (MPC_RND_IM (rnd)));

          mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN);
        }
      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,
                                  MPC_RND_IM (rnd));
          else
            inex_im = -mpfr_acosh (mpc_imagref (rop), minus_op_re,
                                   INV_RND (MPC_RND_IM (rnd)));
          inex_re = mpfr_const_pi (mpc_realref (rop), MPC_RND_RE (rnd));
        }
      else
        {
          inex_re = mpfr_acos (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));
          mpfr_set_ui (mpc_imagref (rop), 0, MPC_RND_IM (rnd));
        }

      if (!s_im)
        mpc_conj (rop, rop, MPC_RNDNN);

      return MPC_INEX (inex_re, inex_im);
    }

  /* pure imaginary argument */
  if (mpfr_zero_p (mpc_realref (op)))
    {
      inex_re = set_pi_over_2 (mpc_realref (rop), +1, MPC_RND_RE (rnd));
      inex_im = -mpfr_asinh (mpc_imagref (rop), mpc_imagref (op),
                             INV_RND (MPC_RND_IM (rnd)));
      mpc_conj (rop,rop, MPC_RNDNN);

      return MPC_INEX (inex_re, inex_im);
    }

  /* regular complex argument: acos(z) = Pi/2 - asin(z) */
  p_re = mpfr_get_prec (mpc_realref(rop));
  p_im = mpfr_get_prec (mpc_imagref(rop));
  p = p_re;
  mpc_init3 (z1, p, p_im); /* we round directly the imaginary part to p_im,
                              with rounding mode opposite to rnd_im */
  rnd_im = MPC_RND_IM(rnd);
  /* the imaginary part of asin(z) has the same sign as Im(z), thus if
     Im(z) > 0 and rnd_im = RNDZ, we want to round the Im(asin(z)) to -Inf
     so that -Im(asin(z)) is rounded to zero */
  if (rnd_im == GMP_RNDZ)
    rnd_im = mpfr_sgn (mpc_imagref(op)) > 0 ? GMP_RNDD : GMP_RNDU;
  else
    rnd_im = rnd_im == GMP_RNDU ? GMP_RNDD
      : rnd_im == GMP_RNDD ? GMP_RNDU
      : rnd_im; /* both RNDZ and RNDA map to themselves for -asin(z) */
  rnd1 = MPC_RND (GMP_RNDN, rnd_im);
  mpfr_init2 (pi_over_2, p);
  for (;;)
    {
      p += mpc_ceil_log2 (p) + 3;

      mpfr_set_prec (mpc_realref(z1), p);
      mpfr_set_prec (pi_over_2, p);

      set_pi_over_2 (pi_over_2, +1, GMP_RNDN);
      e1 = 1; /* Exp(pi_over_2) */
      inex = mpc_asin (z1, op, rnd1); /* asin(z) */
      MPC_ASSERT (mpfr_sgn (mpc_imagref(z1)) * mpfr_sgn (mpc_imagref(op)) > 0);
      inex_im = MPC_INEX_IM(inex); /* inex_im is in {-1, 0, 1} */
      e2 = mpfr_get_exp (mpc_realref(z1));
      mpfr_sub (mpc_realref(z1), pi_over_2, mpc_realref(z1), GMP_RNDN);
      if (!mpfr_zero_p (mpc_realref(z1)))
        {
          /* the error on x=Re(z1) is bounded by 1/2 ulp(x) + 2^(e1-p-1) +
             2^(e2-p-1) */
          e1 = e1 >= e2 ? e1 + 1 : e2 + 1;
          /* the error on x is bounded by 1/2 ulp(x) + 2^(e1-p-1) */
          e1 -= mpfr_get_exp (mpc_realref(z1));
          /* the error on x is bounded by 1/2 ulp(x) [1 + 2^e1] */
          e1 = e1 <= 0 ? 0 : e1;
          /* the error on x is bounded by 2^e1 * ulp(x) */
          mpfr_neg (mpc_imagref(z1), mpc_imagref(z1), GMP_RNDN); /* exact */
          inex_im = -inex_im;
          if (mpfr_can_round (mpc_realref(z1), p - e1, GMP_RNDN, GMP_RNDZ,
                              p_re + (MPC_RND_RE(rnd) == GMP_RNDN)))
            break;
        }
    }
  inex = mpc_set (rop, z1, rnd);
  inex_re = MPC_INEX_RE(inex);
  mpc_clear (z1);
  mpfr_clear (pi_over_2);

  return MPC_INEX(inex_re, inex_im);
}
Exemple #14
0
bool operator>=(const mpcomplex& a, const mpcomplex& b) {
    int result = mpc_cmp(a.mpc_val,b.mpc_val);
    return MPC_INEX_RE(result)>=0;
}