Exemple #1
0
MpfrFloat MpfrFloat::atan2(const MpfrFloat& value1, const MpfrFloat& value2)
{
    MpfrFloat retval(MpfrFloat::kNoInitialization);
    mpfr_atan2(retval.mData->mFloat,
               value1.mData->mFloat, value2.mData->mFloat, GMP_RNDN);
    return retval;
}
Exemple #2
0
real atan2(const real & b, const real & a)
{
	real x;
	
	mpfr_atan2(x.r, b.r, a.r, MPFR_RNDN);
	return x;
}
Exemple #3
0
/* Bug found by Robert Bajema (regression in MPFR 2.3.0).
   The cause is the underflow flag set before the mpfr_atan2 call. */
static void
atan2_bug_20071003 (void)
{
    mpfr_t a, x, y, z;

    mpfr_inits (a, x, y, z, (mpfr_ptr) 0);

    mpfr_set_underflow ();
    mpfr_set_str_binary (y,
                         "-0.10100110110100110111010110111111100110100010001110110E2");
    mpfr_set_str_binary (x,
                         "0.10100101010110010100010010111000110110011110001011110E3");
    mpfr_set_str_binary (z,
                         "-0.11101111001101101100111011001101000010010111101110110E-1");
    mpfr_atan2 (a, y, x, MPFR_RNDN);
    if (! mpfr_equal_p (a, z))
    {
        printf ("mpfr_atan2 fails on:\n");
        printf ("  y = ");
        mpfr_dump (y);
        printf ("  x = ");
        mpfr_dump (x);
        printf ("Expected ");
        mpfr_dump (z);
        printf ("Got      ");
        mpfr_dump (a);
        exit (1);
    }

    mpfr_clears (a, x, y, z, (mpfr_ptr) 0);
}
Exemple #4
0
static void
atan2_pow_of_2 (void)
{
  mpfr_t x, y, r, g;
  int i;
  int d[] = { 0, -1, 1 };
  int ntests = sizeof (d) / sizeof (int);

  mpfr_init2 (x, 53);
  mpfr_init2 (y, 53);
  mpfr_init2 (r, 53);
  mpfr_init2 (g, 53);

  /* atan(42) */
  mpfr_set_str_binary (g, "1100011000000011110011111001100110101000011010010011E-51");

  for (i = 0; i < ntests; ++i)
    {
      mpfr_set_ui (y, 42, MPFR_RNDN);
      mpfr_mul_2si (y, y, d[i], MPFR_RNDN);
      mpfr_set_ui_2exp (x, 1, d[i], MPFR_RNDN);
      mpfr_atan2 (r, y, x, MPFR_RNDN);
      if (mpfr_equal_p (r, g) == 0)
        {
          printf ("Error in mpfr_atan2 (5)\n");
          printf ("Expected "); mpfr_print_binary (g); printf ("\n");
          printf ("Got      "); mpfr_print_binary (r); printf ("\n");
          exit (1);
        }
    }
  mpfr_clear (x);
  mpfr_clear (y);
  mpfr_clear (r);
  mpfr_clear (g);
}
Exemple #5
0
/* from Christopher Creutzig, 18 Jul 2007 */
static void
smallvals_atan2 (void)
{
    mpfr_t a, x, y;
    mpfr_exp_t old_emin;

    mpfr_inits (a, x, y, (mpfr_ptr) 0);
    mpfr_set_ui (y, 0, MPFR_RNDN);
    mpfr_nextbelow (y);
    mpfr_set_ui (x, 1, MPFR_RNDN);
    /* y=-2^(-emin-1), x=1 */

    mpfr_atan2 (a, y, x, MPFR_RNDD);
    MPFR_ASSERTN (mpfr_equal_p (a, y));

    mpfr_atan2 (a, y, x, MPFR_RNDU);
    MPFR_ASSERTN (mpfr_zero_p (a) && MPFR_IS_NEG(a));

    mpfr_set_prec (x, 8);
    mpfr_set_prec (y, 8);
    mpfr_set_prec (a, 8);
    old_emin = mpfr_get_emin ();
    mpfr_set_emin (MPFR_EMIN_MIN);

    mpfr_set_si (y, 3, MPFR_RNDN);
    mpfr_set_exp (y, mpfr_get_emin ());
    mpfr_set_str_binary (x, "1.1");
    mpfr_atan2 (a, y, x, MPFR_RNDU);
    mpfr_set_si (y, 1, MPFR_RNDN);
    mpfr_set_exp (y, mpfr_get_emin ());
    MPFR_ASSERTN (mpfr_equal_p (a, y));

    /* From a bug reported by Christopher Creutzig on 2007-08-28.
       Added test in each rounding mode.
       Segmentation fault or assertion failure due to an infinite Ziv loop. */
    mpfr_set_si (y, 1, MPFR_RNDN);
    mpfr_set_exp (y, mpfr_get_emin ());
    mpfr_set_str_binary (x, "1.01");
    mpfr_atan2 (a, y, x, MPFR_RNDZ);
    MPFR_ASSERTN (mpfr_zero_p (a));
    mpfr_atan2 (a, y, x, MPFR_RNDD);
    MPFR_ASSERTN (mpfr_zero_p (a));
    mpfr_atan2 (a, y, x, MPFR_RNDU);
    MPFR_ASSERTN (mpfr_equal_p (a, y));
    mpfr_atan2 (a, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_equal_p (a, y));

    /* trigger underflow with rounding to nearest */
    mpfr_set_ui (x, 4, MPFR_RNDN);
    mpfr_atan2 (a, y, x, MPFR_RNDN);
    MPFR_ASSERTN (mpfr_zero_p (a));

    mpfr_set_emin (old_emin);

    mpfr_clears (a, x, y, (mpfr_ptr) 0);
}
Exemple #6
0
decimal r_atan2(const decimal& a,const decimal& b,bool round)
{
#ifdef USE_CGAL
	CGAL::Gmpfr m;
	CGAL::Gmpfr n=to_gmpfr(a);
	CGAL::Gmpfr o=to_gmpfr(b);
	mpfr_atan2(m.fr(),n.fr(),o.fr(),MPFR_RNDN);
	return r_round_preference(decimal(m),round);
#else
	return r_round_preference(atan2(a,b),round);
#endif
}
Exemple #7
0
/* Bug found on 2009-04-29 by Christopher Creutzig.
 * With r6179: atan.c:62: MPFR assertion failed: r > n
 */
static void
atan2_different_prec (void)
{
    mpfr_t a, x, y;

    mpfr_init2 (a, 59);
    mpfr_init2 (x, 59);
    mpfr_init2 (y, 86);

    mpfr_set_ui (x, 1, MPFR_RNDN);
    mpfr_set_ui (y, 1, MPFR_RNDN);
    mpfr_nextbelow (y);
    mpfr_atan2 (a, y, x, MPFR_RNDN);

    mpfr_clears (a, x, y, (mpfr_ptr) 0);
}
Exemple #8
0
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);
}
Exemple #9
0
int main()
{
    long iter;
    flint_rand_t state;

    printf("atan2....");
    fflush(stdout);

    flint_randinit(state);

    for (iter = 0; iter < 100000; iter++)
    {
        arb_t a, b, c;
        fmpq_t q, r;
        mpfr_t t, u;
        long prec = 2 + n_randint(state, 200);

        arb_init(a);
        arb_init(b);
        arb_init(c);
        fmpq_init(q);
        fmpq_init(r);
        mpfr_init2(t, prec + 100);
        mpfr_init2(u, prec + 100);

        arb_randtest(a, state, 1 + n_randint(state, 200), 3);
        arb_randtest(b, state, 1 + n_randint(state, 200), 3);
        arb_randtest(c, state, 1 + n_randint(state, 200), 3);

        arb_get_rand_fmpq(q, state, a, 1 + n_randint(state, 200));
        arb_get_rand_fmpq(r, state, b, 1 + n_randint(state, 200));

        fmpq_get_mpfr(t, q, MPFR_RNDN);
        fmpq_get_mpfr(u, r, MPFR_RNDN);
        mpfr_atan2(t, u, t, MPFR_RNDN);

        arb_atan2(c, b, a, prec);

        if (!arb_contains_mpfr(c, t))
        {
            printf("FAIL: containment\n\n");
            printf("a = "); arb_print(a); printf("\n\n");
            printf("b = "); arb_print(b); printf("\n\n");
            printf("c = "); arb_print(c); printf("\n\n");
            abort();
        }

        arb_clear(a);
        arb_clear(b);
        arb_clear(c);
        fmpq_clear(q);
        fmpq_clear(r);
        mpfr_clear(t);
        mpfr_clear(u);
    }

    flint_randclear(state);
    flint_cleanup();
    printf("PASS\n");
    return EXIT_SUCCESS;
}
Exemple #10
0
int
mpc_log (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd){
   int ok, underflow = 0;
   mpfr_srcptr x, y;
   mpfr_t v, w;
   mpfr_prec_t prec;
   int loops;
   int re_cmp, im_cmp;
   int inex_re, inex_im;
   int err;
   mpfr_exp_t expw;
   int sgnw;

   /* special values: NaN and infinities */
   if (!mpc_fin_p (op)) {
      if (mpfr_nan_p (mpc_realref (op))) {
         if (mpfr_inf_p (mpc_imagref (op)))
            mpfr_set_inf (mpc_realref (rop), +1);
         else
            mpfr_set_nan (mpc_realref (rop));
         mpfr_set_nan (mpc_imagref (rop));
         inex_im = 0; /* Inf/NaN is exact */
      }
      else if (mpfr_nan_p (mpc_imagref (op))) {
         if (mpfr_inf_p (mpc_realref (op)))
            mpfr_set_inf (mpc_realref (rop), +1);
         else
            mpfr_set_nan (mpc_realref (rop));
         mpfr_set_nan (mpc_imagref (rop));
         inex_im = 0; /* Inf/NaN is exact */
      }
      else /* We have an infinity in at least one part. */ {
         inex_im = mpfr_atan2 (mpc_imagref (rop), mpc_imagref (op), mpc_realref (op),
                               MPC_RND_IM (rnd));
         mpfr_set_inf (mpc_realref (rop), +1);
      }
      return MPC_INEX(0, inex_im);
   }

   /* special cases: real and purely imaginary numbers */
   re_cmp = mpfr_cmp_ui (mpc_realref (op), 0);
   im_cmp = mpfr_cmp_ui (mpc_imagref (op), 0);
   if (im_cmp == 0) {
      if (re_cmp == 0) {
         inex_im = mpfr_atan2 (mpc_imagref (rop), mpc_imagref (op), mpc_realref (op),
                               MPC_RND_IM (rnd));
         mpfr_set_inf (mpc_realref (rop), -1);
         inex_re = 0; /* -Inf is exact */
      }
      else if (re_cmp > 0) {
         inex_re = mpfr_log (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));
         inex_im = mpfr_set (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd));
      }
      else {
         /* op = x + 0*y; let w = -x = |x| */
         int negative_zero;
         mpfr_rnd_t rnd_im;

         negative_zero = mpfr_signbit (mpc_imagref (op));
         if (negative_zero)
            rnd_im = INV_RND (MPC_RND_IM (rnd));
         else
            rnd_im = MPC_RND_IM (rnd);
         w [0] = *mpc_realref (op);
         MPFR_CHANGE_SIGN (w);
         inex_re = mpfr_log (mpc_realref (rop), w, MPC_RND_RE (rnd));
         inex_im = mpfr_const_pi (mpc_imagref (rop), rnd_im);
         if (negative_zero) {
            mpc_conj (rop, rop, MPC_RNDNN);
            inex_im = -inex_im;
         }
      }
      return MPC_INEX(inex_re, inex_im);
   }
   else if (re_cmp == 0) {
      if (im_cmp > 0) {
         inex_re = mpfr_log (mpc_realref (rop), mpc_imagref (op), MPC_RND_RE (rnd));
         inex_im = mpfr_const_pi (mpc_imagref (rop), MPC_RND_IM (rnd));
         /* division by 2 does not change the ternary flag */
         mpfr_div_2ui (mpc_imagref (rop), mpc_imagref (rop), 1, GMP_RNDN);
      }
      else {
         w [0] = *mpc_imagref (op);
         MPFR_CHANGE_SIGN (w);
         inex_re = mpfr_log (mpc_realref (rop), w, MPC_RND_RE (rnd));
         inex_im = mpfr_const_pi (mpc_imagref (rop), INV_RND (MPC_RND_IM (rnd)));
         /* division by 2 does not change the ternary flag */
         mpfr_div_2ui (mpc_imagref (rop), mpc_imagref (rop), 1, GMP_RNDN);
         mpfr_neg (mpc_imagref (rop), mpc_imagref (rop), GMP_RNDN);
         inex_im = -inex_im; /* negate the ternary flag */
      }
      return MPC_INEX(inex_re, inex_im);
   }

   prec = MPC_PREC_RE(rop);
   mpfr_init2 (w, 2);
   /* let op = x + iy; log = 1/2 log (x^2 + y^2) + i atan2 (y, x)   */
   /* loop for the real part: 1/2 log (x^2 + y^2), fast, but unsafe */
   /* implementation                                                */
   ok = 0;
   for (loops = 1; !ok && loops <= 2; loops++) {
      prec += mpc_ceil_log2 (prec) + 4;
      mpfr_set_prec (w, prec);

      mpc_abs (w, op, GMP_RNDN);
         /* error 0.5 ulp */
      if (mpfr_inf_p (w))
         /* intermediate overflow; the logarithm may be representable.
            Intermediate underflow is impossible.                      */
         break;

      mpfr_log (w, w, GMP_RNDN);
         /* generic error of log: (2^(- exp(w)) + 0.5) ulp */

      if (mpfr_zero_p (w))
         /* impossible to round, switch to second algorithm */
         break;

      err = MPC_MAX (-mpfr_get_exp (w), 0) + 1;
         /* number of lost digits */
      ok = mpfr_can_round (w, prec - err, GMP_RNDN, GMP_RNDZ,
         mpfr_get_prec (mpc_realref (rop)) + (MPC_RND_RE (rnd) == GMP_RNDN));
   }

   if (!ok) {
      prec = MPC_PREC_RE(rop);
      mpfr_init2 (v, 2);
      /* compute 1/2 log (x^2 + y^2) = log |x| + 1/2 * log (1 + (y/x)^2)
            if |x| >= |y|; otherwise, exchange x and y                   */
      if (mpfr_cmpabs (mpc_realref (op), mpc_imagref (op)) >= 0) {
         x = mpc_realref (op);
         y = mpc_imagref (op);
      }
      else {
         x = mpc_imagref (op);
         y = mpc_realref (op);
      }

      do {
         prec += mpc_ceil_log2 (prec) + 4;
         mpfr_set_prec (v, prec);
         mpfr_set_prec (w, prec);

         mpfr_div (v, y, x, GMP_RNDD); /* error 1 ulp */
         mpfr_sqr (v, v, GMP_RNDD);
            /* generic error of multiplication:
               1 + 2*1*(2+1*2^(1-prec)) <= 5.0625 since prec >= 6 */
         mpfr_log1p (v, v, GMP_RNDD);
            /* error 1 + 4*5.0625 = 21.25 , see algorithms.tex */
         mpfr_div_2ui (v, v, 1, GMP_RNDD);
            /* If the result is 0, then there has been an underflow somewhere. */

         mpfr_abs (w, x, GMP_RNDN); /* exact */
         mpfr_log (w, w, GMP_RNDN); /* error 0.5 ulp */
         expw = mpfr_get_exp (w);
         sgnw = mpfr_signbit (w);

         mpfr_add (w, w, v, GMP_RNDN);
         if (!sgnw) /* v is positive, so no cancellation;
                       error 22.25 ulp; error counts lost bits */
            err = 5;
         else
            err =   MPC_MAX (5 + mpfr_get_exp (v),
                  /* 21.25 ulp (v) rewritten in ulp (result, now in w) */
                           -1 + expw             - mpfr_get_exp (w)
                  /* 0.5 ulp (previous w), rewritten in ulp (result) */
                  ) + 2;

         /* handle one special case: |x|=1, and (y/x)^2 underflows;
            then 1/2*log(x^2+y^2) \approx 1/2*y^2 also underflows.  */
         if (   (mpfr_cmp_si (x, -1) == 0 || mpfr_cmp_ui (x, 1) == 0)
             && mpfr_zero_p (w))
            underflow = 1;

      } while (!underflow &&
               !mpfr_can_round (w, prec - err, GMP_RNDN, GMP_RNDZ,
               mpfr_get_prec (mpc_realref (rop)) + (MPC_RND_RE (rnd) == GMP_RNDN)));
      mpfr_clear (v);
   }

   /* imaginary part */
   inex_im = mpfr_atan2 (mpc_imagref (rop), mpc_imagref (op), mpc_realref (op),
                         MPC_RND_IM (rnd));

   /* set the real part; cannot be done before if rop==op */
   if (underflow)
      /* create underflow in result */
      inex_re = mpfr_set_ui_2exp (mpc_realref (rop), 1,
                                  mpfr_get_emin_min () - 2, MPC_RND_RE (rnd));
   else
      inex_re = mpfr_set (mpc_realref (rop), w, MPC_RND_RE (rnd));
   mpfr_clear (w);
   return MPC_INEX(inex_re, inex_im);
}
Exemple #11
0
void
ovm_q_atan2(oregister_t *l, oregister_t *r)
{
    switch (r->t) {
	case t_void:
	    if (!cfg_float_format) {
		l->t = t_float;
		l->v.d = atan2(mpq_get_d(oqr(l)), 0.0);
	    }
	    else {
		mpfr_set_ui(orr(r), 0, thr_rnd);
		goto mpr;
	    }
	    break;
	case t_word:
	    if (!cfg_float_format) {
		l->t = t_float;
		l->v.d = atan2(mpq_get_d(oqr(l)), r->v.w);
	    }
	    else {
		mpfr_set_si(orr(r), r->v.w, thr_rnd);
		goto mpr;
	    }
	    break;
	case t_float:
	    l->t = t_float;
	    l->v.d = atan2(mpq_get_d(oqr(l)), r->v.d);
	    break;
	case t_mpz:
	    if (!cfg_float_format) {
		l->t = t_float;
		l->v.d = atan2(mpq_get_d(oqr(l)), mpz_get_d(ozr(r)));
	    }
	    else {
		mpfr_set_z(orr(r), ozr(r), thr_rnd);
		goto mpr;
	    }
	    break;
	case t_rat:
	    if (!cfg_float_format) {
		l->t = t_float;
		l->v.d = atan2(mpq_get_d(oqr(l)), rat_get_d(r->v.r));
	    }
	    else {
		mpq_set_si(oqr(r), rat_num(r->v.r), rat_den(r->v.r));
		mpfr_set_q(orr(r), oqr(r), thr_rnd);
		goto mpr;
	    }
	    break;
	case t_mpq:
	    if (!cfg_float_format) {
		l->t = t_float;
		l->v.d = atan2(mpq_get_d(oqr(l)), mpq_get_d(oqr(r)));
	    }
	    else {
		mpfr_set_q(orr(r), oqr(r), thr_rnd);
		goto mpr;
	    }
	    break;
	case t_mpr:
	mpr:
	    mpfr_set_q(orr(l), oqr(l), thr_rnd);
	    l->t = t_mpr;
	    mpfr_atan2(orr(l), orr(l), orr(r), thr_rnd);
	    break;
	case t_cdd:
	cdd:
	    l->t = t_cdd;
	    real(l->v.dd) = mpq_get_d(oqr(l));
	    imag(l->v.dd) = 0.0;
	    l->v.dd = catan(l->v.dd / r->v.dd);
	    check_cdd(l);
	    break;
	case t_cqq:
	    if (!cfg_float_format) {
		real(r->v.dd) = mpq_get_d(oqr(r));
		imag(r->v.dd) = mpq_get_d(oqi(r));
		goto cdd;
	    }
	    mpc_set_q_q(occ(r), oqr(r), oqi(r), thr_rndc);
	case t_mpc:
	    l->t = t_mpc;
	    mpc_set_q(occ(l), oqr(l), thr_rndc);
	    mpc_div(occ(l), occ(l), occ(r), thr_rndc);
	    mpc_atan(occ(l), occ(l), thr_rndc);
	    check_mpc(l);
	    break;
	default:
	    ovm_raise(except_not_a_number);
    }
}
Exemple #12
0
int
mpc_atan (mpc_ptr rop, mpc_srcptr op, mpc_rnd_t rnd)
{
    int s_re;
    int s_im;
    int inex_re;
    int inex_im;
    int inex;

    inex_re = 0;
    inex_im = 0;
    s_re = mpfr_signbit (mpc_realref (op));
    s_im = mpfr_signbit (mpc_imagref (op));

    /* special values */
    if (mpfr_nan_p (mpc_realref (op)) || mpfr_nan_p (mpc_imagref (op)))
    {
        if (mpfr_nan_p (mpc_realref (op)))
        {
            mpfr_set_nan (mpc_realref (rop));
            if (mpfr_zero_p (mpc_imagref (op)) || mpfr_inf_p (mpc_imagref (op)))
            {
                mpfr_set_ui (mpc_imagref (rop), 0, GMP_RNDN);
                if (s_im)
                    mpc_conj (rop, rop, MPC_RNDNN);
            }
            else
                mpfr_set_nan (mpc_imagref (rop));
        }
        else
        {
            if (mpfr_inf_p (mpc_realref (op)))
            {
                inex_re = set_pi_over_2 (mpc_realref (rop), -s_re, MPC_RND_RE (rnd));
                mpfr_set_ui (mpc_imagref (rop), 0, GMP_RNDN);
            }
            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)))
    {
        inex_re = set_pi_over_2 (mpc_realref (rop), -s_re, MPC_RND_RE (rnd));

        mpfr_set_ui (mpc_imagref (rop), 0, GMP_RNDN);
        if (s_im)
            mpc_conj (rop, rop, GMP_RNDN);

        return MPC_INEX (inex_re, 0);
    }

    /* pure real argument */
    if (mpfr_zero_p (mpc_imagref (op)))
    {
        inex_re = mpfr_atan (mpc_realref (rop), mpc_realref (op), MPC_RND_RE (rnd));

        mpfr_set_ui (mpc_imagref (rop), 0, GMP_RNDN);
        if (s_im)
            mpc_conj (rop, rop, GMP_RNDN);

        return MPC_INEX (inex_re, 0);
    }

    /* pure imaginary argument */
    if (mpfr_zero_p (mpc_realref (op)))
    {
        int cmp_1;

        if (s_im)
            cmp_1 = -mpfr_cmp_si (mpc_imagref (op), -1);
        else
            cmp_1 = mpfr_cmp_ui (mpc_imagref (op), +1);

        if (cmp_1 < 0)
        {
            /* atan(+0+iy) = +0 +i*atanh(y), if |y| < 1
               atan(-0+iy) = -0 +i*atanh(y), if |y| < 1 */

            mpfr_set_ui (mpc_realref (rop), 0, GMP_RNDN);
            if (s_re)
                mpfr_neg (mpc_realref (rop), mpc_realref (rop), GMP_RNDN);

            inex_im = mpfr_atanh (mpc_imagref (rop), mpc_imagref (op), MPC_RND_IM (rnd));
        }
        else if (cmp_1 == 0)
        {
            /* atan(+/-0+i) = NaN +i*inf
               atan(+/-0-i) = NaN -i*inf */
            mpfr_set_nan (mpc_realref (rop));
            mpfr_set_inf (mpc_imagref (rop), s_im ? -1 : +1);
        }
        else
        {
            /* atan(+0+iy) = +pi/2 +i*atanh(1/y), if |y| > 1
               atan(-0+iy) = -pi/2 +i*atanh(1/y), if |y| > 1 */
            mpfr_rnd_t rnd_im, rnd_away;
            mpfr_t y;
            mpfr_prec_t p, p_im;
            int ok;

            rnd_im = MPC_RND_IM (rnd);
            mpfr_init (y);
            p_im = mpfr_get_prec (mpc_imagref (rop));
            p = p_im;

            /* a = o(1/y)      with error(a) < 1 ulp(a)
               b = o(atanh(a)) with error(b) < (1+2^{1+Exp(a)-Exp(b)}) ulp(b)

               As |atanh (1/y)| > |1/y| we have Exp(a)-Exp(b) <=0 so, at most,
               2 bits of precision are lost.

               We round atanh(1/y) away from 0.
            */
            do
            {
                p += mpc_ceil_log2 (p) + 2;
                mpfr_set_prec (y, p);
                rnd_away = s_im == 0 ? GMP_RNDU : GMP_RNDD;
                inex_im = mpfr_ui_div (y, 1, mpc_imagref (op), rnd_away);
                /* FIXME: should we consider the case with unreasonably huge
                   precision prec(y)>3*exp_min, where atanh(1/Im(op)) could be
                   representable while 1/Im(op) underflows ?
                   This corresponds to |y| = 0.5*2^emin, in which case the
                   result may be wrong. */

                /* atanh cannot underflow: |atanh(x)| > |x| for |x| < 1 */
                inex_im |= mpfr_atanh (y, y, rnd_away);

                ok = inex_im == 0
                     || mpfr_can_round (y, p - 2, rnd_away, GMP_RNDZ,
                                        p_im + (rnd_im == GMP_RNDN));
            } while (ok == 0);

            inex_re = set_pi_over_2 (mpc_realref (rop), -s_re, MPC_RND_RE (rnd));
            inex_im = mpfr_set (mpc_imagref (rop), y, rnd_im);
            mpfr_clear (y);
        }
        return MPC_INEX (inex_re, inex_im);
    }

    /* regular number argument */
    {
        mpfr_t a, b, x, y;
        mpfr_prec_t prec, p;
        mpfr_exp_t err, expo;
        int ok = 0;
        mpfr_t minus_op_re;
        mpfr_exp_t op_re_exp, op_im_exp;
        mpfr_rnd_t rnd1, rnd2;

        mpfr_inits2 (MPFR_PREC_MIN, a, b, x, y, (mpfr_ptr) 0);

        /* real part: Re(arctan(x+i*y)) = [arctan2(x,1-y) - arctan2(-x,1+y)]/2 */
        minus_op_re[0] = mpc_realref (op)[0];
        MPFR_CHANGE_SIGN (minus_op_re);
        op_re_exp = mpfr_get_exp (mpc_realref (op));
        op_im_exp = mpfr_get_exp (mpc_imagref (op));

        prec = mpfr_get_prec (mpc_realref (rop)); /* result precision */

        /* a = o(1-y)         error(a) < 1 ulp(a)
           b = o(atan2(x,a))  error(b) < [1+2^{3+Exp(x)-Exp(a)-Exp(b)}] ulp(b)
                                         = kb ulp(b)
           c = o(1+y)         error(c) < 1 ulp(c)
           d = o(atan2(-x,c)) error(d) < [1+2^{3+Exp(x)-Exp(c)-Exp(d)}] ulp(d)
                                         = kd ulp(d)
           e = o(b - d)       error(e) < [1 + kb*2^{Exp(b}-Exp(e)}
                                            + kd*2^{Exp(d)-Exp(e)}] ulp(e)
                              error(e) < [1 + 2^{4+Exp(x)-Exp(a)-Exp(e)}
                                            + 2^{4+Exp(x)-Exp(c)-Exp(e)}] ulp(e)
                              because |atan(u)| < |u|
                                       < [1 + 2^{5+Exp(x)-min(Exp(a),Exp(c))
                                                 -Exp(e)}] ulp(e)
           f = e/2            exact
        */

        /* p: working precision */
        p = (op_im_exp > 0 || prec > SAFE_ABS (mpfr_prec_t, op_im_exp)) ? prec
            : (prec - op_im_exp);
        rnd1 = mpfr_sgn (mpc_realref (op)) > 0 ? GMP_RNDD : GMP_RNDU;
        rnd2 = mpfr_sgn (mpc_realref (op)) < 0 ? GMP_RNDU : GMP_RNDD;

        do
        {
            p += mpc_ceil_log2 (p) + 2;
            mpfr_set_prec (a, p);
            mpfr_set_prec (b, p);
            mpfr_set_prec (x, p);

            /* x = upper bound for atan (x/(1-y)). Since atan is increasing, we
               need an upper bound on x/(1-y), i.e., a lower bound on 1-y for
               x positive, and an upper bound on 1-y for x negative */
            mpfr_ui_sub (a, 1, mpc_imagref (op), rnd1);
            if (mpfr_sgn (a) == 0) /* y is near 1, thus 1+y is near 2, and
                                  expo will be 1 or 2 below */
            {
                MPC_ASSERT (mpfr_cmp_ui (mpc_imagref(op), 1) == 0);
                /* check for intermediate underflow */
                err = 2; /* ensures err will be expo below */
            }
            else
                err = mpfr_get_exp (a); /* err = Exp(a) with the notations above */
            mpfr_atan2 (x, mpc_realref (op), a, GMP_RNDU);

            /* b = lower bound for atan (-x/(1+y)): for x negative, we need a
               lower bound on -x/(1+y), i.e., an upper bound on 1+y */
            mpfr_add_ui (a, mpc_imagref(op), 1, rnd2);
            /* if a is exactly zero, i.e., Im(op) = -1, then the error on a is 0,
               and we can simply ignore the terms involving Exp(a) in the error */
            if (mpfr_sgn (a) == 0)
            {
                MPC_ASSERT (mpfr_cmp_si (mpc_imagref(op), -1) == 0);
                /* check for intermediate underflow */
                expo = err; /* will leave err unchanged below */
            }
            else
                expo = mpfr_get_exp (a); /* expo = Exp(c) with the notations above */
            mpfr_atan2 (b, minus_op_re, a, GMP_RNDD);

            err = err < expo ? err : expo; /* err = min(Exp(a),Exp(c)) */
            mpfr_sub (x, x, b, GMP_RNDU);

            err = 5 + op_re_exp - err - mpfr_get_exp (x);
            /* error is bounded by [1 + 2^err] ulp(e) */
            err = err < 0 ? 1 : err + 1;

            mpfr_div_2ui (x, x, 1, GMP_RNDU);

            /* Note: using RND2=RNDD guarantees that if x is exactly representable
               on prec + ... bits, mpfr_can_round will return 0 */
            ok = mpfr_can_round (x, p - err, GMP_RNDU, GMP_RNDD,
                                 prec + (MPC_RND_RE (rnd) == GMP_RNDN));
        } while (ok == 0);

        /* Imaginary part
           Im(atan(x+I*y)) = 1/4 * [log(x^2+(1+y)^2) - log (x^2 +(1-y)^2)] */
        prec = mpfr_get_prec (mpc_imagref (rop)); /* result precision */

        /* a = o(1+y)    error(a) < 1 ulp(a)
           b = o(a^2)    error(b) < 5 ulp(b)
           c = o(x^2)    error(c) < 1 ulp(c)
           d = o(b+c)    error(d) < 7 ulp(d)
           e = o(log(d)) error(e) < [1 + 7*2^{2-Exp(e)}] ulp(e) = ke ulp(e)
           f = o(1-y)    error(f) < 1 ulp(f)
           g = o(f^2)    error(g) < 5 ulp(g)
           h = o(c+f)    error(h) < 7 ulp(h)
           i = o(log(h)) error(i) < [1 + 7*2^{2-Exp(i)}] ulp(i) = ki ulp(i)
           j = o(e-i)    error(j) < [1 + ke*2^{Exp(e)-Exp(j)}
                                       + ki*2^{Exp(i)-Exp(j)}] ulp(j)
                         error(j) < [1 + 2^{Exp(e)-Exp(j)} + 2^{Exp(i)-Exp(j)}
                                       + 7*2^{3-Exp(j)}] ulp(j)
                                  < [1 + 2^{max(Exp(e),Exp(i))-Exp(j)+1}
                                       + 7*2^{3-Exp(j)}] ulp(j)
           k = j/4       exact
        */
        err = 2;
        p = prec; /* working precision */

        do
        {
            p += mpc_ceil_log2 (p) + err;
            mpfr_set_prec (a, p);
            mpfr_set_prec (b, p);
            mpfr_set_prec (y, p);

            /* a = upper bound for log(x^2 + (1+y)^2) */
            ROUND_AWAY (mpfr_add_ui (a, mpc_imagref (op), 1, MPFR_RNDA), a);
            mpfr_sqr (a, a, GMP_RNDU);
            mpfr_sqr (y, mpc_realref (op), GMP_RNDU);
            mpfr_add (a, a, y, GMP_RNDU);
            mpfr_log (a, a, GMP_RNDU);

            /* b = lower bound for log(x^2 + (1-y)^2) */
            mpfr_ui_sub (b, 1, mpc_imagref (op), GMP_RNDZ); /* round to zero */
            mpfr_sqr (b, b, GMP_RNDZ);
            /* we could write mpfr_sqr (y, mpc_realref (op), GMP_RNDZ) but it is
               more efficient to reuse the value of y (x^2) above and subtract
               one ulp */
            mpfr_nextbelow (y);
            mpfr_add (b, b, y, GMP_RNDZ);
            mpfr_log (b, b, GMP_RNDZ);

            mpfr_sub (y, a, b, GMP_RNDU);

            if (mpfr_zero_p (y))
                /* FIXME: happens when x and y have very different magnitudes;
                   could be handled more efficiently                           */
                ok = 0;
            else
            {
                expo = MPC_MAX (mpfr_get_exp (a), mpfr_get_exp (b));
                expo = expo - mpfr_get_exp (y) + 1;
                err = 3 - mpfr_get_exp (y);
                /* error(j) <= [1 + 2^expo + 7*2^err] ulp(j) */
                if (expo <= err) /* error(j) <= [1 + 2^{err+1}] ulp(j) */
                    err = (err < 0) ? 1 : err + 2;
                else
                    err = (expo < 0) ? 1 : expo + 2;

                mpfr_div_2ui (y, y, 2, GMP_RNDN);
                MPC_ASSERT (!mpfr_zero_p (y));
                /* FIXME: underflow. Since the main term of the Taylor series
                   in y=0 is 1/(x^2+1) * y, this means that y is very small
                   and/or x very large; but then the mpfr_zero_p (y) above
                   should be true. This needs a proof, or better yet,
                   special code.                                              */

                ok = mpfr_can_round (y, p - err, GMP_RNDU, GMP_RNDD,
                                     prec + (MPC_RND_IM (rnd) == GMP_RNDN));
            }
        } while (ok == 0);

        inex = mpc_set_fr_fr (rop, x, y, rnd);

        mpfr_clears (a, b, x, y, (mpfr_ptr) 0);
        return inex;
    }
}
Exemple #13
0
 void bvisit(const ATan2 &x) {
     mpfr_class t(mpfr_get_prec(result_));
     apply(t.get_mpfr_t(), *(x.get_num()));
     apply(result_, *(x.get_den()));
     mpfr_atan2(result_, t.get_mpfr_t(), result_, rnd_);
 }
Exemple #14
0
void mexFunction( int nlhs, mxArray *plhs[],
                  int nrhs, const mxArray *prhs[] )
{
  double *prec,*eoutr,*eouti;
  int     mrows,ncols;
  char *input_buf;
  char *w1,*w2;
  int   buflen,status;
  mpfr_t xr,xi,yr,yi,zr,zi,temp,temp1,temp2,temp3,temp4;
  mp_exp_t expptr;
  
  /* Check for proper number of arguments. */
  if(nrhs!=5) {
    mexErrMsgTxt("5 inputs required.");
  } else if(nlhs>4) {
    mexErrMsgTxt("Too many output arguments");
  }
  
  /* The input must be a noncomplex scalar double.*/
  mrows = mxGetM(prhs[0]);
  ncols = mxGetN(prhs[0]);
  if( !mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
      !(mrows==1 && ncols==1) ) {
    mexErrMsgTxt("Input must be a noncomplex scalar double.");
  }
  
  /* Set precision and initialize mpfr variables */
  prec = mxGetPr(prhs[0]);
  mpfr_set_default_prec(*prec);
  mpfr_init(xr);  mpfr_init(xi);  
  mpfr_init(yr);  mpfr_init(yi);  
  mpfr_init(zr);  mpfr_init(zi);  
  mpfr_init(temp);  mpfr_init(temp1);
  mpfr_init(temp2);  mpfr_init(temp3);
  mpfr_init(temp4);
  
  /* Read the input strings into mpfr x real */
  buflen = (mxGetM(prhs[1]) * mxGetN(prhs[1])) + 1;
  input_buf=mxCalloc(buflen, sizeof(char));
  status = mxGetString(prhs[1], input_buf, buflen);
  mpfr_set_str(xr,input_buf,10,GMP_RNDN);
  /* Read the input strings into mpfr x imag */
  buflen = (mxGetM(prhs[2]) * mxGetN(prhs[2])) + 1;
  input_buf=mxCalloc(buflen, sizeof(char));
  status = mxGetString(prhs[2], input_buf, buflen);
  mpfr_set_str(xi,input_buf,10,GMP_RNDN);
  
  /* Read the input strings into mpfr y real */
  buflen = (mxGetM(prhs[3]) * mxGetN(prhs[3])) + 1;
  input_buf=mxCalloc(buflen, sizeof(char));
  status = mxGetString(prhs[3], input_buf, buflen);
  mpfr_set_str(yr,input_buf,10,GMP_RNDN);
  /* Read the input strings into mpfr y imag */
  buflen = (mxGetM(prhs[4]) * mxGetN(prhs[4])) + 1;
  input_buf=mxCalloc(buflen, sizeof(char));
  status = mxGetString(prhs[4], input_buf, buflen);
  mpfr_set_str(yi,input_buf,10,GMP_RNDN);
  
  /* Mathematical operation */
  /* ln(magnitude) */
  mpfr_mul(temp,xr,xr,GMP_RNDN);
  mpfr_mul(temp1,xi,xi,GMP_RNDN);
  mpfr_add(temp,temp,temp1,GMP_RNDN);
  mpfr_sqrt(temp,temp,GMP_RNDN);
  mpfr_log(temp,temp,GMP_RNDN);

  /* angle */
  mpfr_atan2(temp1,xi,xr,GMP_RNDN);

  /* real exp */
  mpfr_mul(temp3,temp,yr,GMP_RNDN);
  mpfr_mul(temp2,temp1,yi,GMP_RNDN);
  mpfr_sub(temp3,temp3,temp2,GMP_RNDN);
  mpfr_exp(temp3,temp3,GMP_RNDN);

  /* cos sin argument */
  mpfr_mul(temp2,temp1,yr,GMP_RNDN);
  mpfr_mul(temp4,temp,yi,GMP_RNDN);
  mpfr_add(temp2,temp2,temp4,GMP_RNDN);

  mpfr_cos(zr,temp2,GMP_RNDN);
  mpfr_mul(zr,zr,temp3,GMP_RNDN);
  mpfr_sin(zi,temp2,GMP_RNDN);
  mpfr_mul(zi,zi,temp3,GMP_RNDN);
  

  /* Retrieve results */
  mxFree(input_buf);
  input_buf=mpfr_get_str (NULL, &expptr, 10, 0, zr, GMP_RNDN);
  
  w1=malloc(strlen(input_buf)+20);
  w2=malloc(strlen(input_buf)+20);
  if (strncmp(input_buf, "-", 1)==0){
    strcpy(w2,&input_buf[1]);
    sprintf(w1,"-.%se%i",w2,expptr);
  } else {
    strcpy(w2,&input_buf[0]);
    sprintf(w1,"+.%se%i",w2,expptr);
  }
  plhs[0] = mxCreateString(w1);
/*   plhs[1] = mxCreateDoubleMatrix(mrows,ncols, mxREAL); */
/*   eoutr=mxGetPr(plhs[1]); */
/*   *eoutr=expptr; */

  mpfr_free_str(input_buf);
  input_buf=mpfr_get_str (NULL, &expptr, 10, 0, zi, GMP_RNDN);
  free(w1);
  free(w2);
  w1=malloc(strlen(input_buf)+20);
  w2=malloc(strlen(input_buf)+20);
  if (strncmp(input_buf, "-", 1)==0){
    strcpy(w2,&input_buf[1]);
    sprintf(w1,"-.%se%i",w2,expptr);
  } else {
    strcpy(w2,&input_buf[0]);
    sprintf(w1,"+.%se%i",w2,expptr);
  }
  plhs[1] = mxCreateString(w1);
/*   plhs[3] = mxCreateDoubleMatrix(mrows,ncols, mxREAL); */
/*   eouti=mxGetPr(plhs[3]); */
/*   *eouti=expptr; */
  

  mpfr_clear(xr);  mpfr_clear(xi);
  mpfr_clear(yr);  mpfr_clear(yi);
  mpfr_clear(zr);  mpfr_clear(zi);
  mpfr_clear(temp);  mpfr_clear(temp1);
  mpfr_clear(temp2);  mpfr_clear(temp3);
  mpfr_clear(temp4);
  mpfr_free_str(input_buf);
  free(w1);
  free(w2);
}
Exemple #15
0
CGAL::Gmpfr atan2(const CGAL::Gmpfr &y, const CGAL::Gmpfr &x)
{
    CGAL::Gmpfr result(0, std::max(gmp_result_precision(y), gmp_result_precision(x)));
    mpfr_atan2(result.fr(), y.fr(), x.fr(), gmp_rounding_mode(CGAL::Gmpfr::get_default_rndmode()));
    return result;
}