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));
}
Example #3
0
static MPC_Object *
GMPy_MPC_New(mpfr_prec_t rprec, mpfr_prec_t iprec, CTXT_Object *context)
{
    MPC_Object *self;

    CHECK_CONTEXT(context);

    if (rprec == 0 || rprec == 1)
        rprec = GET_REAL_PREC(context) + rprec * GET_GUARD_BITS(context);
    if (iprec == 0 || iprec == 1)
        iprec = GET_IMAG_PREC(context) + iprec * GET_GUARD_BITS(context);

    if (rprec < MPFR_PREC_MIN || rprec > MPFR_PREC_MAX ||
        iprec < MPFR_PREC_MIN || iprec > MPFR_PREC_MAX) {
        VALUE_ERROR("invalid value for precision");
        return NULL;
    }
    if (in_gmpympccache) {
        self = gmpympccache[--in_gmpympccache];
        /* Py_INCREF does not set the debugging pointers, so need to use
           _Py_NewReference instead. */
        _Py_NewReference((PyObject*)self);
        if (rprec == iprec) {
            mpc_set_prec(self->c, rprec);
        }
        else {
            mpc_clear(self->c);
            mpc_init3(self->c, rprec, iprec);
        }
    }
    else {
        if (!(self = PyObject_New(MPC_Object, &MPC_Type))) {
            /* LCOV_EXCL_START */
            return NULL;
            /* LCOV_EXCL_STOP */
        }
        mpc_init3(self->c, rprec, iprec);
    }
    self->hash_cache = -1;
    self->rc = 0;
    return self;
}
Example #4
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 #5
0
int
mpc_pow_ui (mpc_ptr z, mpc_srcptr x, unsigned long y, mpc_rnd_t rnd)
{
  mpc_t yy;
  int inex;

  mpc_init3 (yy, sizeof (unsigned long) * CHAR_BIT, MPFR_PREC_MIN);
  mpc_set_ui (yy, y, MPC_RNDNN);   /* exact */
  inex = mpc_pow (z, x, yy, rnd);
  mpc_clear (yy);
  return inex;
}
Example #6
0
static void
compare_mpc_pow (mpfr_prec_t pmax, int iter, unsigned long nbits)
   /* copied from tpow_ui.c and replaced unsigned by signed */
{
  mpfr_prec_t p;
  mpc_t x, y, z, t;
  long n;
  int i, inex_pow, inex_pow_si;
  mpc_rnd_t rnd;

  mpc_init3 (y, sizeof (unsigned long) * CHAR_BIT, MPFR_PREC_MIN);
  for (p = MPFR_PREC_MIN; p <= pmax; p++)
    for (i = 0; i < iter; i++)
      {
        mpc_init2 (x, p);
        mpc_init2 (z, p);
        mpc_init2 (t, p);
        mpc_urandom (x, rands);
        n = (signed long) gmp_urandomb_ui (rands, nbits);
        mpc_set_si (y, n, MPC_RNDNN);
        for (rnd = 0; rnd < 16; rnd ++)
          {
            inex_pow = mpc_pow (z, x, y, rnd);
            inex_pow_si = mpc_pow_si (t, x, n, rnd);
            if (mpc_cmp (z, t) != 0)
              {
                printf ("mpc_pow and mpc_pow_si differ for x=");
                mpc_out_str (stdout, 10, 0, x, MPC_RNDNN);
                printf (" n=%li\n", n);
                printf ("mpc_pow gives ");
                mpc_out_str (stdout, 10, 0, z, MPC_RNDNN);
                printf ("\nmpc_pow_si gives ");
                mpc_out_str (stdout, 10, 0, t, MPC_RNDNN);
                printf ("\n");
                exit (1);
              }
            if (inex_pow != inex_pow_si)
              {
                printf ("mpc_pow and mpc_pow_si give different flags for x=");
                mpc_out_str (stdout, 10, 0, x, MPC_RNDNN);
                printf (" n=%li\n", n);
                printf ("mpc_pow gives %d\n", inex_pow);
                printf ("mpc_pow_si gives %d\n", inex_pow_si);
                exit (1);
              }
          }
        mpc_clear (x);
        mpc_clear (z);
        mpc_clear (t);
      }
  mpc_clear (y);
}
Example #7
0
int
mpc_pow_d (mpc_ptr z, mpc_srcptr x, double y, mpc_rnd_t rnd)
{
  mpc_t yy;
  int inex;
  
  MPC_ASSERT(FLT_RADIX == 2);
  mpc_init3 (yy, DBL_MANT_DIG, MPFR_PREC_MIN);
  mpc_set_d (yy, y, MPC_RNDNN);   /* exact */
  inex = mpc_pow (z, x, yy, rnd);
  mpc_clear (yy);
  return inex;
}
Example #8
0
static int
mpc_div_imag (mpc_ptr rop, mpc_srcptr z, mpc_srcptr w, mpc_rnd_t rnd)
/* Assumes z finite and w finite and non-zero, with real part
   of w a signed zero.                                        */
{
   int inex_re, inex_im;
   int overlap = (rop == z) || (rop == w);
   int imag_z = mpfr_zero_p (mpc_realref (z));
   mpfr_t wloc;
   mpc_t tmprop;
   mpc_ptr dest = (overlap) ? tmprop : rop;
   /* save signs of operands in case there are overlaps */
   int zrs = MPFR_SIGNBIT (mpc_realref (z));
   int zis = MPFR_SIGNBIT (mpc_imagref (z));
   int wrs = MPFR_SIGNBIT (mpc_realref (w));
   int wis = MPFR_SIGNBIT (mpc_imagref (w));

   if (overlap)
      mpc_init3 (tmprop, MPC_PREC_RE (rop), MPC_PREC_IM (rop));

   wloc[0] = mpc_imagref(w)[0]; /* copies mpfr struct IM(w) into wloc */
   inex_re = mpfr_div (mpc_realref(dest), mpc_imagref(z), wloc, MPC_RND_RE(rnd));
   mpfr_neg (wloc, wloc, MPFR_RNDN);
   /* changes the sign only in wloc, not in w; no need to correct later */
   inex_im = mpfr_div (mpc_imagref(dest), mpc_realref(z), wloc, MPC_RND_IM(rnd));

   if (overlap) {
      /* Note: we could use mpc_swap here, but this might cause problems
         if rop and tmprop have been allocated using different methods, since
         it will swap the significands of rop and tmprop. See
         http://lists.gforge.inria.fr/pipermail/mpc-discuss/2009-August/000504.html */
      mpc_set (rop, tmprop, MPC_RNDNN); /* exact */
      mpc_clear (tmprop);
   }

   /* correct signs of zeroes if necessary, which does not affect the
      inexact flags                                                    */
   if (mpfr_zero_p (mpc_realref (rop)))
      mpfr_setsign (mpc_realref (rop), mpc_realref (rop), (zrs != wrs && zis != wis),
         MPFR_RNDN); /* exact */
   if (imag_z)
      mpfr_setsign (mpc_imagref (rop), mpc_imagref (rop), (zis != wrs && zrs == wis),
         MPFR_RNDN);

   return MPC_INEX(inex_re, inex_im);
}
Example #9
0
static void
bug20091120 (void)
{
  mpc_t x, y;

  mpc_init2 (x, 53);
  mpc_init3 (y, 17, 42);
  mpc_set_ui_ui (x, 1, 1, MPC_RNDNN);
  mpc_asinh (y, x, MPC_RNDNN);
  if (mpfr_get_prec (mpc_realref(y)) != 17 ||
      mpfr_get_prec (mpc_imagref(y)) != 42)
    {
      printf ("Error, mpc_asinh changed the precisions!!!\n");
      exit (1);
    }
  mpc_clear (x);
  mpc_clear (y);
}
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 #11
0
File: mpc.c Project: rforge/mpc
SEXP R_mpc_add(SEXP e1, SEXP e2) {
	mpc_t *z1 = (mpc_t *)R_ExternalPtrAddr(e1);
	mpc_t *z = (mpc_t *)malloc(sizeof(mpc_t));
	if (z == NULL) {
		Rf_error("Could not allocate memory for MPC type.");
	}

	if (Rf_inherits(e2, "mpc")) {
		mpc_t *z2 = (mpc_t *)R_ExternalPtrAddr(e2);
		mpfr_prec_t real_prec, imag_prec;
		Rmpc_get_max_prec(&real_prec, &imag_prec, *z1, *z2);
		mpc_init3(*z, real_prec, imag_prec);
		mpc_add(*z, *z1, *z2, Rmpc_get_rounding());
	} else if (Rf_isInteger(e2)) {
		mpc_init2(*z, mpc_get_prec(*z1));
		mpc_add_ui(*z, *z1, INTEGER(e2)[0], Rmpc_get_rounding());
	} else if (Rf_isNumeric(e2)) {
		mpfr_t x;
		mpfr_init2(x, 53);
                // We use GMP_RNDN rather than MPFR_RNDN for compatibility
                // with mpfr 2.4.x and earlier as well as more modern versions.
		mpfr_set_d(x, REAL(e2)[0], GMP_RNDN);
		/* Max of mpc precision z2 and 53 from e2. */
		Rprintf("Precision: %d\n", mpc_get_prec(*z1));
		mpc_init2(*z, max(mpc_get_prec(*z1), 53));
		mpc_add_fr(*z, *z1, x, Rmpc_get_rounding());
	} else {
		/* TODO(mstokely): Add support for mpfr types here. */
		free(z);
		Rf_error("Invalid second operand for mpc addition.");
	}
	SEXP retVal = PROTECT(R_MakeExternalPtr((void *)z,
		Rf_install("mpc ptr"), R_NilValue));
	Rf_setAttrib(retVal, R_ClassSymbol, Rf_mkString("mpc"));
	R_RegisterCFinalizerEx(retVal, mpcFinalizer, TRUE);
	UNPROTECT(1);
	return retVal;
}
Example #12
0
static PympcObject *
Pympc_new(mpfr_prec_t rprec, mpfr_prec_t iprec)
{
    PympcObject *self;

    TRACE("Entering Pympc_new\n");

    if (rprec == 0)
        rprec = context->now.mpc_rprec;
    if (iprec == 0)
        iprec = context->now.mpc_iprec;
    if (rprec < MPFR_PREC_MIN || rprec > MPFR_PREC_MAX ||
        iprec < MPFR_PREC_MIN || iprec > MPFR_PREC_MAX) {
        VALUE_ERROR("invalid value for precision");
        return NULL;
    }
    if (!(self = PyObject_New(PympcObject, &Pympc_Type)))
        return NULL;
    mpc_init3(self->c, rprec, iprec);
    self->hash_cache = -1;
    self->rc = 0;
    self->round_mode = 0;
    return self;
}
Example #13
0
mpcomplex mpcomplex::neg() const{
    mpc_t negativeValue;
    mpc_init3( negativeValue , mpc_prec, default_rnd );
    mpc_neg(negativeValue, mpc_val , default_rnd );
    return mpcomplex( negativeValue );
}
Example #14
0
mpcomplex mpcomplex::sqrt() const{
    mpc_t sqrtValue;
    mpc_init3(sqrtValue , mpc_prec, default_rnd );
    mpc_sqrt(sqrtValue, mpc_val , default_rnd );
    return mpcomplex( sqrtValue );
}
Example #15
0
mpcomplex operator/(const mpcomplex& a, const long int& b) {
    mpc_t value;
    mpc_init3( value , a.mpc_prec, a.mpc_prec );
    mpc_div_ui(value, a.mpc_val, b, a.default_rnd);
    return mpcomplex(value);
}
Example #16
0
mpcomplex operator*(const mpcomplex& a, const mpcomplex& b) {
    mpc_t value;
    mpc_init3( value , a.mpc_prec, a.mpc_prec );
    mpc_mul(value, a.mpc_val, b.mpc_val, a.default_rnd);
    return mpcomplex(value);
}
Example #17
0
mpcomplex operator*(const long int& a, const mpcomplex& b) {
    mpc_t value;
    mpc_init3( value , b.mpc_prec, b.mpc_prec );
    mpc_mul_ui(value, b.mpc_val, a, b.default_rnd);
    return mpcomplex(value);
}
Example #18
0
mpcomplex operator/(const long int& a, const mpcomplex& b) {
    mpc_t value;
    mpc_init3( value , b.mpc_prec, b.mpc_prec );
    mpc_ui_div(value, a, b.mpc_val, b.mpc_rnd);
    return mpcomplex(value);
}
static int
mpc_sin_cos_nonfinite (mpc_ptr rop_sin, mpc_ptr rop_cos, mpc_srcptr op,
   mpc_rnd_t rnd_sin, mpc_rnd_t rnd_cos)
   /* assumes that op (that is, its real or imaginary part) is not finite */
{
   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) {
      if (mpfr_nan_p (MPC_RE (op_loc)) || mpfr_nan_p (MPC_IM (op_loc))) {
         mpc_set (rop_sin, op_loc, rnd_sin);
         if (mpfr_nan_p (MPC_IM (op_loc))) {
            /* sin(x +i*NaN) = NaN +i*NaN, except for x=0 */
            /* sin(-0 +i*NaN) = -0 +i*NaN */
            /* sin(+0 +i*NaN) = +0 +i*NaN */
            if (!mpfr_zero_p (MPC_RE (op_loc)))
               mpfr_set_nan (MPC_RE (rop_sin));
         }
         else /* op = NaN + i*y */
            if (!mpfr_inf_p (MPC_IM (op_loc)) && !mpfr_zero_p (MPC_IM (op_loc)))
            /* sin(NaN -i*Inf) = NaN -i*Inf */
            /* sin(NaN -i*0) = NaN -i*0 */
            /* sin(NaN +i*0) = NaN +i*0 */
            /* sin(NaN +i*Inf) = NaN +i*Inf */
            /* sin(NaN +i*y) = NaN +i*NaN, when 0<|y|<Inf */
            mpfr_set_nan (MPC_IM (rop_sin));
      }
      else if (mpfr_inf_p (MPC_RE (op_loc))) {
         mpfr_set_nan (MPC_RE (rop_sin));

         if (!mpfr_inf_p (MPC_IM (op_loc)) && !mpfr_zero_p (MPC_IM (op_loc)))
            /* sin(+/-Inf +i*y) = NaN +i*NaN, when 0<|y|<Inf */
            mpfr_set_nan (MPC_IM (rop_sin));
         else
            /* sin(+/-Inf -i*Inf) = NaN -i*Inf */
            /* sin(+/-Inf +i*Inf) = NaN +i*Inf */
            /* sin(+/-Inf -i*0) = NaN -i*0 */
            /* sin(+/-Inf +i*0) = NaN +i*0 */
            mpfr_set (MPC_IM (rop_sin), MPC_IM (op_loc), MPC_RND_IM (rnd_sin));
      }
      else if (mpfr_zero_p (MPC_RE (op_loc))) {
         /* sin(-0 -i*Inf) = -0 -i*Inf */
         /* sin(+0 -i*Inf) = +0 -i*Inf */
         /* sin(-0 +i*Inf) = -0 +i*Inf */
         /* sin(+0 +i*Inf) = +0 +i*Inf */
         mpc_set (rop_sin, op_loc, rnd_sin);
      }
      else {
         /* sin(x -i*Inf) = +Inf*(sin(x) -i*cos(x)) */
         /* sin(x +i*Inf) = +Inf*(sin(x) +i*cos(x)) */
         mpfr_t s, c;
         mpfr_init2 (s, 2);
         mpfr_init2 (c, 2);
         mpfr_sin_cos (s, c, MPC_RE (op_loc), GMP_RNDZ);
         mpfr_set_inf (MPC_RE (rop_sin), MPFR_SIGN (s));
         mpfr_set_inf (MPC_IM (rop_sin), MPFR_SIGN (c)*MPFR_SIGN (MPC_IM (op_loc)));
         mpfr_clear (s);
         mpfr_clear (c);
      }
   }

   if (rop_cos != NULL) {
      if (mpfr_nan_p (MPC_RE (op_loc))) {
         /* cos(NaN + i * NaN) = NaN + i * NaN */
         /* cos(NaN - i * Inf) = +Inf + i * NaN */
         /* cos(NaN + i * Inf) = +Inf + i * NaN */
         /* cos(NaN - i * 0) = NaN - i * 0 */
         /* cos(NaN + i * 0) = NaN + i * 0 */
         /* cos(NaN + i * y) = NaN + i * NaN, when y != 0 */
         if (mpfr_inf_p (MPC_IM (op_loc)))
            mpfr_set_inf (MPC_RE (rop_cos), +1);
         else
            mpfr_set_nan (MPC_RE (rop_cos));

         if (mpfr_zero_p (MPC_IM (op_loc)))
            mpfr_set (MPC_IM (rop_cos), MPC_IM (op_loc), MPC_RND_IM (rnd_cos));
         else
            mpfr_set_nan (MPC_IM (rop_cos));
      }
      else if (mpfr_nan_p (MPC_IM (op_loc))) {
          /* cos(-Inf + i * NaN) = NaN + i * NaN */
          /* cos(+Inf + i * NaN) = NaN + i * NaN */
          /* cos(-0 + i * NaN) = NaN - i * 0 */
          /* cos(+0 + i * NaN) = NaN + i * 0 */
          /* cos(x + i * NaN) = NaN + i * NaN, when x != 0 */
         if (mpfr_zero_p (MPC_RE (op_loc)))
            mpfr_set (MPC_IM (rop_cos), MPC_RE (op_loc), MPC_RND_IM (rnd_cos));
         else
            mpfr_set_nan (MPC_IM (rop_cos));

         mpfr_set_nan (MPC_RE (rop_cos));
      }
      else if (mpfr_inf_p (MPC_RE (op_loc))) {
         /* cos(-Inf -i*Inf) = cos(+Inf +i*Inf) = -Inf +i*NaN */
         /* cos(-Inf +i*Inf) = cos(+Inf -i*Inf) = +Inf +i*NaN */
         /* cos(-Inf -i*0) = cos(+Inf +i*0) = NaN -i*0 */
         /* cos(-Inf +i*0) = cos(+Inf -i*0) = NaN +i*0 */
         /* cos(-Inf +i*y) = cos(+Inf +i*y) = NaN +i*NaN, when y != 0 */

         const int same_sign =
            mpfr_signbit (MPC_RE (op_loc)) == mpfr_signbit (MPC_IM (op_loc));

         if (mpfr_inf_p (MPC_IM (op_loc)))
            mpfr_set_inf (MPC_RE (rop_cos), (same_sign ? -1 : +1));
         else
            mpfr_set_nan (MPC_RE (rop_cos));

         if (mpfr_zero_p (MPC_IM (op_loc)))
            mpfr_setsign (MPC_IM (rop_cos), MPC_IM (op_loc), same_sign,
                          MPC_RND_IM(rnd_cos));
         else
            mpfr_set_nan (MPC_IM (rop_cos));
      }
      else if (mpfr_zero_p (MPC_RE (op_loc))) {
         /* cos(-0 -i*Inf) = cos(+0 +i*Inf) = +Inf -i*0 */
         /* cos(-0 +i*Inf) = cos(+0 -i*Inf) = +Inf +i*0 */
         const int same_sign =
            mpfr_signbit (MPC_RE (op_loc)) == mpfr_signbit (MPC_IM (op_loc));

         mpfr_setsign (MPC_IM (rop_cos), MPC_RE (op_loc), same_sign,
                       MPC_RND_IM (rnd_cos));
         mpfr_set_inf (MPC_RE (rop_cos), +1);
      }
      else {
         /* cos(x -i*Inf) = +Inf*cos(x) +i*Inf*sin(x), when x != 0 */
         /* cos(x +i*Inf) = +Inf*cos(x) -i*Inf*sin(x), when x != 0 */
         mpfr_t s, c;
         mpfr_init2 (c, 2);
         mpfr_init2 (s, 2);
         mpfr_sin_cos (s, c, MPC_RE (op_loc), GMP_RNDN);
         mpfr_set_inf (MPC_RE (rop_cos), mpfr_sgn (c));
         mpfr_set_inf (MPC_IM (rop_cos),
            (mpfr_sgn (MPC_IM (op_loc)) == mpfr_sgn (s) ? -1 : +1));
         mpfr_clear (s);
         mpfr_clear (c);
      }
   }

   if (overlap)
      mpc_clear (op_loc);

   return MPC_INEX12 (MPC_INEX (0,0), MPC_INEX (0,0));
      /* everything is exact */
}
Example #20
0
void mpcomplex::init() {
    mpc_init3( mpc_val , mpc_prec, mpc_prec );
}
Example #21
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);
}