static void check_special_pow_si () { mpfr_t a, b; mp_exp_t emin; mpfr_init (a); mpfr_init (b); mpfr_set_str (a, "2E100000000", 10, GMP_RNDN); mpfr_set_si (b, -10, GMP_RNDN); test_pow (b, a, b, GMP_RNDN); if (!MPFR_IS_ZERO(b)) { printf("Pow(2E10000000, -10) failed\n"); mpfr_dump (a); mpfr_dump (b); exit(1); } emin = mpfr_get_emin (); mpfr_set_emin (-10); mpfr_set_si (a, -2, GMP_RNDN); mpfr_pow_si (b, a, -10000, GMP_RNDN); if (!MPFR_IS_ZERO (b)) { printf ("Pow_so (1, -10000) doesn't underflow if emin=-10.\n"); mpfr_dump (a); mpfr_dump (b); exit (1); } mpfr_set_emin (emin); mpfr_clear (a); mpfr_clear (b); }
static void pow_si_long_min (void) { mpfr_t x, y, z; int inex; mpfr_inits2 (sizeof(long) * CHAR_BIT + 32, x, y, z, (void *) 0); mpfr_set_si_2exp (x, 3, -1, GMP_RNDN); /* 1.5 */ inex = mpfr_set_si (y, LONG_MIN, GMP_RNDN); MPFR_ASSERTN (inex == 0); mpfr_nextbelow (y); mpfr_pow (y, x, y, GMP_RNDD); inex = mpfr_set_si (z, LONG_MIN, GMP_RNDN); MPFR_ASSERTN (inex == 0); mpfr_nextabove (z); mpfr_pow (z, x, z, GMP_RNDU); mpfr_pow_si (x, x, LONG_MIN, GMP_RNDN); /* 1.5^LONG_MIN */ if (mpfr_cmp (x, y) < 0 || mpfr_cmp (x, z) > 0) { printf ("Error in pow_si_long_min\n"); exit (1); } mpfr_clears (x, y, z, (void *) 0); }
static int pm2 (mpfr_ptr y, mpfr_srcptr x, mpfr_rnd_t rnd_mode) { return mpfr_pow_si (y, x, -2, rnd_mode); }
static void special () { mpfr_t x, y, z, t; mpfr_init2 (x, 53); mpfr_init2 (y, 53); mpfr_init2 (z, 53); mpfr_init2 (t, 2); mpfr_set_ui (x, 2, GMP_RNDN); mpfr_pow_si (x, x, -2, GMP_RNDN); if (mpfr_cmp_ui_2exp (x, 1, -2)) { printf ("Error in pow_si(x,x,-2) for x=2\n"); exit (1); } mpfr_set_ui (x, 2, GMP_RNDN); mpfr_set_si (y, -2, GMP_RNDN); test_pow (x, x, y, GMP_RNDN); if (mpfr_cmp_ui_2exp (x, 1, -2)) { printf ("Error in pow(x,x,y) for x=2, y=-2\n"); exit (1); } mpfr_set_prec (x, 2); mpfr_set_str_binary (x, "1.0e-1"); mpfr_set_prec (y, 53); mpfr_set_str_binary (y, "0.11010110011100101010110011001010100111000001000101110E-1"); mpfr_set_prec (z, 2); test_pow (z, x, y, GMP_RNDZ); mpfr_set_str_binary (x, "1.0e-1"); if (mpfr_cmp (x, z)) { printf ("Error in mpfr_pow (1)\n"); exit (1); } mpfr_set_prec (x, 64); mpfr_set_prec (y, 64); mpfr_set_prec (z, 64); mpfr_set_prec (t, 64); mpfr_set_str_binary (x, "0.111011000111100000111010000101010100110011010000011"); mpfr_set_str_binary (y, "0.111110010100110000011101100011010111000010000100101"); mpfr_set_str_binary (t, "0.1110110011110110001000110100100001001111010011111000010000011001"); test_pow (z, x, y, GMP_RNDN); if (mpfr_cmp (z, t)) { printf ("Error in mpfr_pow for prec=64, rnd=GMP_RNDN\n"); exit (1); } mpfr_set_prec (x, 53); mpfr_set_prec (y, 53); mpfr_set_prec (z, 53); mpfr_set_str (x, "5.68824667828621954868e-01", 10, GMP_RNDN); mpfr_set_str (y, "9.03327850535952658895e-01", 10, GMP_RNDN); test_pow (z, x, y, GMP_RNDZ); if (mpfr_cmp_str1 (z, "0.60071044650456473235")) { printf ("Error in mpfr_pow for prec=53, rnd=GMP_RNDZ\n"); exit (1); } mpfr_set_prec (t, 2); mpfr_set_prec (x, 30); mpfr_set_prec (y, 30); mpfr_set_prec (z, 30); mpfr_set_str (x, "1.00000000001010111110001111011e1", 2, GMP_RNDN); mpfr_set_str (t, "-0.5", 10, GMP_RNDN); test_pow (z, x, t, GMP_RNDN); mpfr_set_str (y, "1.01101001111010101110000101111e-1", 2, GMP_RNDN); if (mpfr_cmp (z, y)) { printf ("Error in mpfr_pow for prec=30, rnd=GMP_RNDN\n"); exit (1); } mpfr_set_prec (x, 21); mpfr_set_prec (y, 21); mpfr_set_prec (z, 21); mpfr_set_str (x, "1.11111100100001100101", 2, GMP_RNDN); test_pow (z, x, t, GMP_RNDZ); mpfr_set_str (y, "1.01101011010001100000e-1", 2, GMP_RNDN); if (mpfr_cmp (z, y)) { printf ("Error in mpfr_pow for prec=21, rnd=GMP_RNDZ\n"); printf ("Expected "); mpfr_out_str (stdout, 2, 0, y, GMP_RNDN); printf ("\nGot "); mpfr_out_str (stdout, 2, 0, z, GMP_RNDN); printf ("\n"); exit (1); } /* From http://www.terra.es/personal9/ismaeljc/hall.htm */ mpfr_set_prec (x, 113); mpfr_set_prec (y, 2); mpfr_set_prec (z, 169); mpfr_set_str1 (x, "6078673043126084065007902175846955"); mpfr_set_ui_2exp (y, 3, -1, GMP_RNDN); test_pow (z, x, y, GMP_RNDZ); if (mpfr_cmp_str1 (z, "473928882491000966028828671876527456070714790264144")) { printf ("Error in mpfr_pow for 6078673043126084065007902175846955"); printf ("^(3/2), GMP_RNDZ\nExpected "); printf ("4.73928882491000966028828671876527456070714790264144e50"); printf ("\nGot "); mpfr_out_str (stdout, 10, 0, z, GMP_RNDN); printf ("\n"); exit (1); } test_pow (z, x, y, GMP_RNDU); if (mpfr_cmp_str1 (z, "473928882491000966028828671876527456070714790264145")) { printf ("Error in mpfr_pow for 6078673043126084065007902175846955"); printf ("^(3/2), GMP_RNDU\nExpected "); printf ("4.73928882491000966028828671876527456070714790264145e50"); printf ("\nGot "); mpfr_out_str (stdout, 10, 0, z, GMP_RNDN); printf ("\n"); exit (1); } mpfr_set_inf (x, 1); mpfr_set_prec (y, 2); mpfr_set_str_binary (y, "1E10"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_inf (x, -1); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_prec (y, 10); mpfr_set_str_binary (y, "1.000000001E9"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_NEG(z)); mpfr_set_str_binary (y, "1.000000001E8"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_inf (x, -1); mpfr_set_prec (y, 2 * mp_bits_per_limb); mpfr_set_ui (y, 1, GMP_RNDN); mpfr_mul_2exp (y, y, mp_bits_per_limb - 1, GMP_RNDN); /* y = 2^(mp_bits_per_limb - 1) */ test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_nextabove (y); test_pow (z, x, y, GMP_RNDN); /* y = 2^(mp_bits_per_limb - 1) + epsilon */ MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_nextbelow (y); mpfr_div_2exp (y, y, 1, GMP_RNDN); mpfr_nextabove (y); test_pow (z, x, y, GMP_RNDN); /* y = 2^(mp_bits_per_limb - 2) + epsilon */ MPFR_ASSERTN(mpfr_inf_p (z) && MPFR_IS_POS(z)); mpfr_set_si (x, -1, GMP_RNDN); mpfr_set_prec (y, 2); mpfr_set_str_binary (y, "1E10"); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (z, 1) == 0); /* Check (-0)^(17.0001) */ mpfr_set_prec (x, 6); mpfr_set_prec (y, 640); MPFR_SET_ZERO (x); MPFR_SET_NEG (x); mpfr_set_ui (y, 17, GMP_RNDN); mpfr_nextabove (y); test_pow (z, x, y, GMP_RNDN); MPFR_ASSERTN (MPFR_IS_ZERO (z) && MPFR_IS_POS (z)); mpfr_clear (x); mpfr_clear (y); mpfr_clear (z); mpfr_clear (t); }
MpfrFloat MpfrFloat::pow(const MpfrFloat& value, long exponent) { MpfrFloat retval(MpfrFloat::kNoInitialization); mpfr_pow_si(retval.mData->mFloat, value.mData->mFloat, exponent, GMP_RNDN); return retval; }
static void check_pow_si (void) { mpfr_t x; mpfr_init (x); mpfr_set_nan (x); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_nan_p (x)); mpfr_set_inf (x, 1); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); mpfr_set_inf (x, -1); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_NEG(x)); mpfr_set_inf (x, -1); mpfr_pow_si (x, x, -2, GMP_RNDN); MPFR_ASSERTN(mpfr_cmp_ui (x, 0) == 0 && MPFR_IS_POS(x)); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); mpfr_pow_si (x, x, -1, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) < 0); mpfr_set_ui (x, 0, GMP_RNDN); mpfr_neg (x, x, GMP_RNDN); mpfr_pow_si (x, x, -2, GMP_RNDN); MPFR_ASSERTN(mpfr_inf_p (x) && mpfr_sgn (x) > 0); mpfr_set_si (x, 2, GMP_RNDN); mpfr_pow_si (x, x, LONG_MAX, GMP_RNDN); /* 2^LONG_MAX */ if (LONG_MAX > mpfr_get_emax () - 1) /* LONG_MAX + 1 > emax */ { MPFR_ASSERTN (mpfr_inf_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 1, LONG_MAX)); } mpfr_set_si (x, 2, GMP_RNDN); mpfr_pow_si (x, x, LONG_MIN, GMP_RNDN); /* 2^LONG_MIN */ if (LONG_MIN + 1 < mpfr_get_emin ()) { MPFR_ASSERTN (mpfr_zero_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 1, LONG_MIN)); } mpfr_set_si (x, 2, GMP_RNDN); mpfr_pow_si (x, x, LONG_MIN + 1, GMP_RNDN); /* 2^(LONG_MIN+1) */ if (mpfr_nan_p (x)) { printf ("Error in pow_si(2, LONG_MIN+1): got NaN\n"); exit (1); } if (LONG_MIN + 2 < mpfr_get_emin ()) { MPFR_ASSERTN (mpfr_zero_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 1, LONG_MIN + 1)); } mpfr_set_si_2exp (x, 1, -1, GMP_RNDN); /* 0.5 */ mpfr_pow_si (x, x, LONG_MIN, GMP_RNDN); /* 2^(-LONG_MIN) */ if (LONG_MIN < 1 - mpfr_get_emax ()) /* 1 - LONG_MIN > emax */ { MPFR_ASSERTN (mpfr_inf_p (x)); } else { MPFR_ASSERTN (mpfr_cmp_si_2exp (x, 2, - (LONG_MIN + 1))); } mpfr_clear (x); }
static PyObject * GMPy_Real_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context) { MPFR_Object *tempb = NULL, *tempe = NULL, *result = NULL; MPZ_Object *tempz = NULL; MPC_Object *mpc_result = NULL; if (mod != Py_None) { TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers"); return NULL; } CHECK_CONTEXT(context); result = GMPy_MPFR_New(0, context); tempb = GMPy_MPFR_From_Real(base, 1, context); if (!result || !tempb) { goto err; } mpfr_clear_flags(); if (PyIntOrLong_Check(exp)) { int error; long temp_exp = GMPy_Integer_AsLongAndError(exp, &error); if (!error) { result->rc = mpfr_pow_si(result->f, tempb->f, temp_exp, GET_MPFR_ROUND(context)); } else { mpz_t tempzz; mpz_inoc(tempzz); mpz_set_PyIntOrLong(tempzz, exp); result->rc = mpfr_pow_z(result->f, tempb->f, tempzz, GET_MPFR_ROUND(context)); mpz_cloc(tempzz); } } else if (IS_INTEGER(exp)) { if (!(tempz = GMPy_MPZ_From_Integer(exp, context))) { goto err; } result->rc = mpfr_pow_z(result->f, tempb->f, tempz->z, GET_MPFR_ROUND(context)); } else { if (!(tempe = GMPy_MPFR_From_Real(exp, 1, context))) { goto err; } result->rc = mpfr_pow(result->f, tempb->f, tempe->f, GET_MPFR_ROUND(context)); } /* If the result is NaN, check if a complex result works. */ if (result && mpfr_nanflag_p() && context->ctx.allow_complex) { mpc_result = (MPC_Object*)GMPy_Complex_Pow(base, exp, Py_None, context); if (!mpc_result || MPC_IS_NAN_P(mpc_result)) { Py_XDECREF((PyObject*)mpc_result); context->ctx.invalid = 1; GMPY_INVALID("pow() invalid operation"); goto err; } /* return a valid complex result */ Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)result); return (PyObject*)mpc_result; } GMPY_MPFR_CLEANUP(result, context, "pow()"); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); return (PyObject*)result; err: Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); return NULL; }
void power(ElementType &result, const ElementType& a, int n) const { mpfr_pow_si(&result, &a, n, GMP_RNDN); }
/* Compare the result (z1,inex1) of mpfr_pow with all flags cleared with those of mpfr_pow with all flags set and of the other power functions. Arguments x and y are the input values; sx and sy are their string representations (sx may be null); rnd contains the rounding mode; s is a string containing the function that called test_others. */ static void test_others (const void *sx, const char *sy, mpfr_rnd_t rnd, mpfr_srcptr x, mpfr_srcptr y, mpfr_srcptr z1, int inex1, unsigned int flags, const char *s) { mpfr_t z2; int inex2; int spx = sx != NULL; if (!spx) sx = x; mpfr_init2 (z2, mpfr_get_prec (z1)); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow (z2, x, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow, flags set"); /* If y is an integer that fits in an unsigned long and is not -0, we can test mpfr_pow_ui. */ if (MPFR_IS_POS (y) && mpfr_integer_p (y) && mpfr_fits_ulong_p (y, MPFR_RNDN)) { unsigned long yy = mpfr_get_ui (y, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_pow_ui (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_pow_ui, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow_ui (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow_ui, flags set"); /* If x is an integer that fits in an unsigned long and is not -0, we can also test mpfr_ui_pow_ui. */ if (MPFR_IS_POS (x) && mpfr_integer_p (x) && mpfr_fits_ulong_p (x, MPFR_RNDN)) { unsigned long xx = mpfr_get_ui (x, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_ui_pow_ui (z2, xx, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_ui_pow_ui, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_ui_pow_ui (z2, xx, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_ui_pow_ui, flags set"); } } /* If y is an integer but not -0 and not huge, we can test mpfr_pow_z, and possibly mpfr_pow_si (and possibly mpfr_ui_div). */ if (MPFR_IS_ZERO (y) ? MPFR_IS_POS (y) : (mpfr_integer_p (y) && MPFR_GET_EXP (y) < 256)) { mpz_t yyy; /* If y fits in a long, we can test mpfr_pow_si. */ if (mpfr_fits_slong_p (y, MPFR_RNDN)) { long yy = mpfr_get_si (y, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_pow_si (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_pow_si, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow_si (z2, x, yy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow_si, flags set"); /* If y = -1, we can test mpfr_ui_div. */ if (yy == -1) { mpfr_clear_flags (); inex2 = mpfr_ui_div (z2, 1, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_ui_div, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_ui_div (z2, 1, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_ui_div, flags set"); } /* If y = 2, we can test mpfr_sqr. */ if (yy == 2) { mpfr_clear_flags (); inex2 = mpfr_sqr (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_sqr, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_sqr (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_sqr, flags set"); } } /* Test mpfr_pow_z. */ mpz_init (yyy); mpfr_get_z (yyy, y, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_pow_z (z2, x, yyy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_pow_z, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_pow_z (z2, x, yyy, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_pow_z, flags set"); mpz_clear (yyy); } /* If y = 0.5, we can test mpfr_sqrt, except if x is -0 or -Inf (because the rule for mpfr_pow on these special values is different). */ if (MPFR_IS_PURE_FP (y) && mpfr_cmp_str1 (y, "0.5") == 0 && ! ((MPFR_IS_ZERO (x) || MPFR_IS_INF (x)) && MPFR_IS_NEG (x))) { mpfr_clear_flags (); inex2 = mpfr_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_sqrt, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_sqrt, flags set"); } #if MPFR_VERSION >= MPFR_VERSION_NUM(2,4,0) /* If y = -0.5, we can test mpfr_rec_sqrt, except if x = -Inf (because the rule for mpfr_pow on -Inf is different). */ if (MPFR_IS_PURE_FP (y) && mpfr_cmp_str1 (y, "-0.5") == 0 && ! (MPFR_IS_INF (x) && MPFR_IS_NEG (x))) { mpfr_clear_flags (); inex2 = mpfr_rec_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_rec_sqrt, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_rec_sqrt (z2, x, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_rec_sqrt, flags set"); } #endif /* If x is an integer that fits in an unsigned long and is not -0, we can test mpfr_ui_pow. */ if (MPFR_IS_POS (x) && mpfr_integer_p (x) && mpfr_fits_ulong_p (x, MPFR_RNDN)) { unsigned long xx = mpfr_get_ui (x, MPFR_RNDN); mpfr_clear_flags (); inex2 = mpfr_ui_pow (z2, xx, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_ui_pow, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_ui_pow (z2, xx, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_ui_pow, flags set"); /* If x = 2, we can test mpfr_exp2. */ if (xx == 2) { mpfr_clear_flags (); inex2 = mpfr_exp2 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_exp2, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_exp2 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_exp2, flags set"); } /* If x = 10, we can test mpfr_exp10. */ if (xx == 10) { mpfr_clear_flags (); inex2 = mpfr_exp10 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, flags, s, "mpfr_exp10, flags cleared"); __gmpfr_flags = MPFR_FLAGS_ALL; inex2 = mpfr_exp10 (z2, y, rnd); cmpres (spx, sx, sy, rnd, z1, inex1, z2, inex2, MPFR_FLAGS_ALL, s, "mpfr_exp10, flags set"); } } mpfr_clear (z2); }
/* The computation of z = pow(x,y) is done by z = exp(y * log(x)) = x^y */ int mpfr_pow (mpfr_ptr z, mpfr_srcptr x, mpfr_srcptr y, mp_rnd_t rnd_mode) { int inexact = 0; if (MPFR_IS_NAN(x) || MPFR_IS_NAN(y)) { MPFR_SET_NAN(z); MPFR_RET_NAN; } if (MPFR_IS_INF(y)) { mpfr_t one; int cmp; if (MPFR_SIGN(y) > 0) { if (MPFR_IS_INF(x)) { MPFR_CLEAR_FLAGS(z); if (MPFR_SIGN(x) > 0) MPFR_SET_INF(z); else MPFR_SET_ZERO(z); MPFR_SET_POS(z); MPFR_RET(0); } MPFR_CLEAR_FLAGS(z); if (MPFR_IS_ZERO(x)) { MPFR_SET_ZERO(z); MPFR_SET_POS(z); MPFR_RET(0); } mpfr_init2(one, BITS_PER_MP_LIMB); mpfr_set_ui(one, 1, GMP_RNDN); cmp = mpfr_cmp_abs(x, one); mpfr_clear(one); if (cmp > 0) { MPFR_SET_INF(z); MPFR_SET_POS(z); MPFR_RET(0); } else if (cmp < 0) { MPFR_SET_ZERO(z); MPFR_SET_POS(z); MPFR_RET(0); } else { MPFR_SET_NAN(z); MPFR_RET_NAN; } } else { if (MPFR_IS_INF(x)) { MPFR_CLEAR_FLAGS(z); if (MPFR_SIGN(x) > 0) MPFR_SET_ZERO(z); else MPFR_SET_INF(z); MPFR_SET_POS(z); MPFR_RET(0); } if (MPFR_IS_ZERO(x)) { MPFR_SET_INF(z); MPFR_SET_POS(z); MPFR_RET(0); } mpfr_init2(one, BITS_PER_MP_LIMB); mpfr_set_ui(one, 1, GMP_RNDN); cmp = mpfr_cmp_abs(x, one); mpfr_clear(one); MPFR_CLEAR_FLAGS(z); if (cmp > 0) { MPFR_SET_ZERO(z); MPFR_SET_POS(z); MPFR_RET(0); } else if (cmp < 0) { MPFR_SET_INF(z); MPFR_SET_POS(z); MPFR_RET(0); } else { MPFR_SET_NAN(z); MPFR_RET_NAN; } } } if (MPFR_IS_ZERO(y)) { return mpfr_set_ui (z, 1, GMP_RNDN); } if (mpfr_isinteger (y)) { mpz_t zi; long int zii; int exptol; mpz_init(zi); exptol = mpfr_get_z_exp (zi, y); if (exptol>0) mpz_mul_2exp(zi, zi, exptol); else mpz_tdiv_q_2exp(zi, zi, (unsigned long int) (-exptol)); zii=mpz_get_ui(zi); mpz_clear(zi); return mpfr_pow_si (z, x, zii, rnd_mode); } if (MPFR_IS_INF(x)) { if (MPFR_SIGN(x) > 0) { MPFR_CLEAR_FLAGS(z); if (MPFR_SIGN(y) > 0) MPFR_SET_INF(z); else MPFR_SET_ZERO(z); MPFR_SET_POS(z); MPFR_RET(0); } else { MPFR_SET_NAN(z); MPFR_RET_NAN; } } if (MPFR_IS_ZERO(x)) { MPFR_CLEAR_FLAGS(z); MPFR_SET_ZERO(z); MPFR_SET_SAME_SIGN(z, x); MPFR_RET(0); } if (MPFR_SIGN(x) < 0) { MPFR_SET_NAN(z); MPFR_RET_NAN; } MPFR_CLEAR_FLAGS(z); /* General case */ { /* Declaration of the intermediary variable */ mpfr_t t, te, ti; int loop = 0, ok; /* Declaration of the size variable */ mp_prec_t Nx = MPFR_PREC(x); /* Precision of input variable */ mp_prec_t Ny = MPFR_PREC(y); /* Precision of input variable */ mp_prec_t Nt; /* Precision of the intermediary variable */ long int err; /* Precision of error */ /* compute the precision of intermediary variable */ Nt=MAX(Nx,Ny); /* the optimal number of bits : see algorithms.ps */ Nt=Nt+5+_mpfr_ceil_log2(Nt); /* initialise of intermediary variable */ mpfr_init(t); mpfr_init(ti); mpfr_init(te); do { loop ++; /* reactualisation of the precision */ mpfr_set_prec (t, Nt); mpfr_set_prec (ti, Nt); mpfr_set_prec (te, Nt); /* compute exp(y*ln(x)) */ mpfr_log (ti, x, GMP_RNDU); /* ln(n) */ mpfr_mul (te, y, ti, GMP_RNDU); /* y*ln(n) */ mpfr_exp (t, te, GMP_RNDN); /* exp(x*ln(n))*/ /* estimation of the error -- see pow function in algorithms.ps*/ err = Nt - (MPFR_EXP(te) + 3); /* actualisation of the precision */ Nt += 10; ok = mpfr_can_round (t, err, GMP_RNDN, rnd_mode, Ny); /* check exact power */ if (ok == 0 && loop == 1) ok = mpfr_pow_is_exact (x, y); } while (err < 0 || ok == 0); inexact = mpfr_set (z, t, rnd_mode); mpfr_clear (t); mpfr_clear (ti); mpfr_clear (te); } return inexact; }
SeedValue seed_mpfr_pow (SeedContext ctx, SeedObject function, SeedObject this_object, gsize argument_count, const SeedValue args[], SeedException * exception) { mpfr_rnd_t rnd; mpfr_ptr rop, op1, op2; gint ret; glong iop; gulong uiop1, uiop2; seed_mpfr_t argt1, argt2; /* only want 1 double argument. alternatively, could accept 2, add those, and set from the result*/ CHECK_ARG_COUNT("mpfr.pow", 3); rop = seed_object_get_private(this_object); rnd = seed_value_to_mpfr_rnd_t(ctx, args[2], exception); argt1 = seed_mpfr_arg_type(ctx, args[0], exception); argt2 = seed_mpfr_arg_type(ctx, args[1], exception); if ( (argt1 & argt2) == SEED_MPFR_MPFR ) { /* both mpfr_t */ op1 = seed_object_get_private(args[0]); op2 = seed_object_get_private(args[1]); ret = mpfr_pow(rop, op1, op2, rnd); } else if ( (argt1 | argt2) == (SEED_MPFR_MPFR | SEED_MPFR_DOUBLE) ) { /* a double and an mpfr_t. Figure out the order */ /* FIXME: is this switching ui and si bad? si_pow doesn't exist, and it's all from double anyway */ if ( argt1 == SEED_MPFR_MPFR ) { op1 = seed_object_get_private(args[0]); iop = seed_value_to_long(ctx, args[1], exception); ret = mpfr_pow_si(rop, op1, iop, rnd); } else { uiop1 = seed_value_to_ulong(ctx, args[0], exception); op2 = seed_object_get_private(args[1]); ret = mpfr_ui_pow(rop, uiop1, op2, rnd); } } else if ( (argt1 & argt2) == SEED_MPFR_DOUBLE ) { /* pretend both ui */ uiop1 = seed_value_to_ulong(ctx, args[0], exception); uiop2 = seed_value_to_ulong(ctx, args[1], exception); ret = mpfr_ui_pow_ui(rop, uiop1, uiop2, rnd); } else { TYPE_EXCEPTION("mpfr.pow", "int or unsigned int and mpfr_t"); } return seed_value_from_int(ctx, ret, exception); }