SeedValue seed_mpfr_div (SeedContext ctx, SeedObject function, SeedObject this_object, gsize argument_count, const SeedValue args[], SeedException * exception) { mpfr_rnd_t rnd; mpfr_ptr rop, op1, op2; gdouble dop1, dop2; gint ret; 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.div", 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_div(rop, op1, op2, rnd); } else if ( (argt1 | argt2) == (SEED_MPFR_MPFR | SEED_MPFR_DOUBLE) ) { /* a double and an mpfr_t. Figure out the order */ if ( argt1 == SEED_MPFR_MPFR ) { op1 = seed_object_get_private(args[0]); dop2 = seed_value_to_double(ctx, args[1], exception); mpfr_div_d(rop, op1, dop2, rnd); } else { dop1 = seed_value_to_double(ctx, args[0], exception); op2 = seed_object_get_private(args[1]); mpfr_d_div(rop, dop1, op2, rnd); } } else if ( (argt1 & argt2) == SEED_MPFR_DOUBLE ) { /* 2 doubles. hopefully doesn't happen */ dop1 = seed_value_to_double(ctx, args[0], exception); dop2 = seed_value_to_double(ctx, args[1], exception); ret = mpfr_set_d(rop, dop1 / dop2, rnd); } else { TYPE_EXCEPTION("mpfr.div", "double or mpfr_t"); } return seed_value_from_int(ctx, ret, exception); }
int main (void) { mpfr_t x, y, z; double d; int inexact; tests_start_mpfr (); /* check with enough precision */ mpfr_init2 (x, IEEE_DBL_MANT_DIG); mpfr_init2 (y, IEEE_DBL_MANT_DIG); mpfr_init2 (z, IEEE_DBL_MANT_DIG); mpfr_set_str (y, "4096", 10, MPFR_RNDN); d = 0.125; mpfr_clear_flags (); inexact = mpfr_d_div (x, d, y, MPFR_RNDN); if (inexact != 0) { printf ("Inexact flag error in mpfr_d_div\n"); exit (1); } mpfr_set_str (z, " 0.000030517578125", 10, MPFR_RNDN); if (mpfr_cmp (z, x)) { printf ("Error in mpfr_d_div ("); mpfr_out_str (stdout, 10, 0, y, MPFR_RNDN); printf (" + %.20g)\nexpected ", d); mpfr_out_str (stdout, 10, 0, z, MPFR_RNDN); printf ("\ngot "); mpfr_out_str (stdout, 10, 0, x, MPFR_RNDN); printf ("\n"); exit (1); } mpfr_clears (x, y, z, (mpfr_ptr) 0); check_nans (); test_generic (2, 1000, 100); tests_end_mpfr (); return 0; }
static PyObject * GMPy_Real_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context) { MPFR_Object *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPFR_New(0, context))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } if (MPFR_Check(x)) { if (MPFR_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_div(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } if (PyIntOrLong_Check(y)) { int error; long tempi = GMPy_Integer_AsLongAndError(y, &error); if (!error) { mpfr_clear_flags(); result->rc = mpfr_div_si(result->f, MPFR(x), tempi, GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } else { mpz_set_PyIntOrLong(global.tempz, y); mpfr_clear_flags(); result->rc = mpfr_div_z(result->f, MPFR(x), global.tempz, GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } } if (CHECK_MPZANY(y)) { mpfr_clear_flags(); result->rc = mpfr_div_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } if (IS_RATIONAL(y)) { MPQ_Object *tempy; if (!(tempy = GMPy_MPQ_From_Number(y, context))) { Py_DECREF((PyObject*)result); return NULL; } mpfr_clear_flags(); result->rc = mpfr_div_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); Py_DECREF((PyObject*)tempy); goto done; } if (PyFloat_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_div_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } } if (MPFR_Check(y)) { if (PyIntOrLong_Check(x)) { int error; long tempi = GMPy_Integer_AsLongAndError(x, &error); if (!error) { mpfr_clear_flags(); result->rc = mpfr_si_div(result->f, tempi, MPFR(y), GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } } /* Since mpfr_z_div does not exist, this combination is handled at the * end by converting x to an mpfr. Ditto for rational.*/ if (PyFloat_Check(x)) { mpfr_clear_flags(); result->rc = mpfr_d_div(result->f, PyFloat_AS_DOUBLE(x), MPFR(y), GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); goto done; } } /* Handle the remaining cases. * Note: verify that MPZ if converted at full precision! */ if (IS_REAL(x) && IS_REAL(y)) { MPFR_Object *tempx, *tempy; tempx = GMPy_MPFR_From_Real(x, 1, context); tempy = GMPy_MPFR_From_Real(y, 1, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpfr_clear_flags(); result->rc = mpfr_div(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context)); result->rc = mpfr_floor(result->f, result->f); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); goto done; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; done: _GMPy_MPFR_Cleanup(&result, context); return (PyObject*)result; }
static void check_nans (void) { mpfr_t x, y; int inexact; mpfr_init2 (x, 123); mpfr_init2 (y, 123); /* 1.0 / nan is nan */ mpfr_set_nan (x); mpfr_clear_flags (); inexact = mpfr_d_div (y, 1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_NAN); MPFR_ASSERTN (mpfr_nan_p (y)); /* 1.0 / +inf == +0 */ mpfr_set_inf (x, 1); mpfr_clear_flags (); inexact = mpfr_d_div (y, 1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_zero_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); /* 1.0 / -inf == -0 */ mpfr_set_inf (x, -1); mpfr_clear_flags (); inexact = mpfr_d_div (y, 1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_zero_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); #if !defined(MPFR_ERRDIVZERO) /* 1.0 / 0 == +inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, 1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); /* -1.0 / 0 == -inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, -1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); /* 1.0 / -0 == -inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, 1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); /* -1.0 / -0 == +inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, -1.0, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == MPFR_FLAGS_DIVBY0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); /* +inf / 0 == +inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, DBL_POS_INF, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); /* -inf / 0 == -inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, DBL_NEG_INF, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); /* +inf / -0 == -inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, DBL_POS_INF, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_NEG (y)); /* -inf / -0 == +inf */ mpfr_set_ui (x, 0, MPFR_RNDN); mpfr_neg (x, x, MPFR_RNDN); mpfr_clear_flags (); inexact = mpfr_d_div (y, DBL_NEG_INF, x, MPFR_RNDN); MPFR_ASSERTN (inexact == 0); MPFR_ASSERTN (__gmpfr_flags == 0); MPFR_ASSERTN (mpfr_inf_p (y)); MPFR_ASSERTN (MPFR_IS_POS (y)); #endif mpfr_clear (x); mpfr_clear (y); }