static PyObject * GMPy_Rational_Abs(PyObject *x, CTXT_Object *context) { MPQ_Object *result = NULL; if (MPQ_Check(x)) { if (mpz_sgn(mpq_numref(MPQ(x))) >= 0) { Py_INCREF(x); return x; } else { if ((result = GMPy_MPQ_New(context))) { mpq_set(result->q, MPQ(x)); mpz_abs(mpq_numref(result->q), mpq_numref(result->q)); } return (PyObject*)result; } } /* This is safe because result is not an incremented reference to an * existing value. MPQ is already handled so GMPy_MPQ_From_Rational() * can't return an incremented reference to an existing value (which it * would do if passed an MPQ). */ if ((result = GMPy_MPQ_From_Rational(x, context))) { mpz_abs(mpq_numref(result->q), mpq_numref(result->q)); } return (PyObject*)result; }
static PyObject * GMPy_Rational_Add(PyObject *x, PyObject *y, CTXT_Object *context) { MPQ_Object *result; if (!(result = GMPy_MPQ_New(context))) return NULL; if (MPQ_Check(x) && MPQ_Check(y)) { mpq_add(result->q, MPQ(x), MPQ(y)); return (PyObject*)result; } if (IS_RATIONAL(x) && IS_RATIONAL(y)) { MPQ_Object *tempx, *tempy; tempx = GMPy_MPQ_From_Number(x, context); tempy = GMPy_MPQ_From_Number(y, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpq_add(result->q, tempx->q, tempy->q); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_Rational_FloorDiv(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result; MPQ_Object *tempq; CHECK_CONTEXT(context); result = GMPy_MPZ_New(context); tempq = GMPy_MPQ_New(context); if (!result || !tempq) { Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)tempq); return NULL; } if (MPQ_Check(x) && MPQ_Check(y)) { if (mpq_sgn(MPQ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } mpq_div(tempq->q, MPQ(x), MPQ(y)); mpz_fdiv_q(result->z, mpq_numref(tempq->q), mpq_denref(tempq->q)); Py_DECREF((PyObject*)tempq); return (PyObject*)result; } if (IS_RATIONAL(x) && IS_RATIONAL(y)) { MPQ_Object *tempx, *tempy; tempx = GMPy_MPQ_From_Number(x, context); tempy = GMPy_MPQ_From_Number(y, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); goto error; } if (mpq_sgn(tempy->q) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); goto error; } mpq_div(tempq->q, tempx->q, tempy->q); mpz_fdiv_q(result->z, mpq_numref(tempq->q), mpq_denref(tempq->q)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)tempq); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; error: Py_DECREF((PyObject*)result); Py_DECREF((PyObject*)tempq); return NULL; }
static PyObject * GMPy_Rational_DivMod(PyObject *x, PyObject *y, CTXT_Object *context) { MPQ_Object *tempx, *tempy, *rem; MPZ_Object *quo; PyObject *result; CHECK_CONTEXT(context); result = PyTuple_New(2); rem = GMPy_MPQ_New(context); quo = GMPy_MPZ_New(context); if (!result || !rem || !quo) { Py_XDECREF(result); Py_XDECREF((PyObject*)rem); Py_XDECREF((PyObject*)quo); return NULL; } if (IS_RATIONAL(x) && IS_RATIONAL(y)) { tempx = GMPy_MPQ_From_Number(x, context); tempy = GMPy_MPQ_From_Number(y, context); if (!tempx || !tempy) { SYSTEM_ERROR("could not convert Rational to mpq"); goto error; } if (mpq_sgn(tempy->q) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } mpq_div(rem->q, tempx->q, tempy->q); mpz_fdiv_q(quo->z, mpq_numref(rem->q), mpq_denref(rem->q)); /* Need to calculate x - quo * y. */ mpq_set_z(rem->q, quo->z); mpq_mul(rem->q, rem->q, tempy->q); mpq_sub(rem->q, tempx->q, rem->q); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; error: Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)rem); Py_DECREF((PyObject*)quo); Py_DECREF(result); return NULL; }
static PyObject * GMPy_Rational_DivMod(PyObject *x, PyObject *y, CTXT_Object *context) { MPQ_Object *tempx = NULL, *tempy = NULL, *rem = NULL; MPZ_Object *quo = NULL; PyObject *result = NULL; if (!(result = PyTuple_New(2)) || !(rem = GMPy_MPQ_New(context)) || !(quo = GMPy_MPZ_New(context))) { /* LCOV_EXCL_START */ goto error; /* LCOV_EXCL_STOP */ } if (IS_RATIONAL(x) && IS_RATIONAL(y)) { if (!(tempx = GMPy_MPQ_From_Number(x, context)) || !(tempy = GMPy_MPQ_From_Number(y, context))) { /* LCOV_EXCL_START */ goto error; /* LCOV_EXCL_STOP */ } if (mpq_sgn(tempy->q) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } mpq_div(rem->q, tempx->q, tempy->q); mpz_fdiv_q(quo->z, mpq_numref(rem->q), mpq_denref(rem->q)); /* Need to calculate x - quo * y. */ mpq_set_z(rem->q, quo->z); mpq_mul(rem->q, rem->q, tempy->q); mpq_sub(rem->q, tempx->q, rem->q); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } /* LCOV_EXCL_START */ SYSTEM_ERROR("Internal error in GMPy_Rational_DivMod()."); error: Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_XDECREF((PyObject*)rem); Py_XDECREF((PyObject*)quo); Py_XDECREF(result); return NULL; /* LCOV_EXCL_STOP */ }
static PyObject * _GMPy_MPQ_Minus(PyObject *x, CTXT_Object *context) { MPQ_Object *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPQ_New(context))) { return NULL; } mpq_neg(result->q, MPQ(x)); return (PyObject*)result; }
static PyObject * GMPy_Rational_Mod(PyObject *x, PyObject *y, CTXT_Object *context) { mpz_t tempz; MPQ_Object *tempx, *tempy, *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPQ_New(context))) return NULL; if (IS_RATIONAL(x) && IS_RATIONAL(y)) { tempx = GMPy_MPQ_From_Number(x, context); tempy = GMPy_MPQ_From_Number(y, context); if (!tempx || !tempy) { SYSTEM_ERROR("could not convert Rational to mpq"); goto error; } if (mpq_sgn(tempy->q) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } mpz_inoc(tempz); mpq_div(result->q, tempx->q, tempy->q); mpz_fdiv_q(tempz, mpq_numref(result->q), mpq_denref(result->q)); /* Need to calculate x - tempz * y. */ mpq_set_z(result->q, tempz); mpq_mul(result->q, result->q, tempy->q); mpq_sub(result->q, tempx->q, result->q); mpz_cloc(tempz); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; error: Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; }
static PyObject * GMPy_Rational_Mul(PyObject *x, PyObject *y, CTXT_Object *context) { MPQ_Object *result = NULL; if (!(result = GMPy_MPQ_New(context))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } if (MPQ_Check(x) && MPQ_Check(y)) { mpq_mul(result->q, MPQ(x), MPQ(y)); return (PyObject*)result; } if (IS_RATIONAL(x) && IS_RATIONAL(y)) { MPQ_Object *tempx = NULL, *tempy = NULL; if (!(tempx = GMPy_MPQ_From_Number(x, context)) || !(tempy = GMPy_MPQ_From_Number(y, context))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ } mpq_mul(result->q, tempx->q, tempy->q); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } /* LCOV_EXCL_START */ SYSTEM_ERROR("Internal error in GMPy_Rational_Mul()."); Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ }
static PyObject * GMPy_MPQ_Factory(PyObject *self, PyObject *args, PyObject *keywds) { MPQ_Object *result, *temp; PyObject *n, *m; int base = 10; Py_ssize_t argc, keywdc = 0; static char *kwlist[] = {"s", "base", NULL }; CTXT_Object *context = NULL; if (self && CTXT_Check(self)) { context = (CTXT_Object*)self; } else { CHECK_CONTEXT(context); } argc = PyTuple_Size(args); if (keywds) { keywdc = PyDict_Size(keywds); } if (argc + keywdc > 2) { TYPE_ERROR("mpq() takes at most 2 arguments"); return NULL; } if (argc + keywdc == 0) { if ((result = GMPy_MPQ_New(context))) { mpq_set_ui(result->q, 0, 1); } return (PyObject*)result; } if (argc == 0) { TYPE_ERROR("mpq() requires at least one non-keyword argument"); return NULL; } n = PyTuple_GetItem(args, 0); /* Handle the case where the first argument is a string. */ if (PyStrOrUnicode_Check(n)) { /* keyword base is legal */ if (keywdc || argc > 1) { if (!(PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base))) { return NULL; } } if ((base != 0) && ((base < 2) || (base > 62))) { VALUE_ERROR("base for mpq() must be 0 or in the interval [2, 62]"); return NULL; } return (PyObject*)GMPy_MPQ_From_PyStr(n, base, context); } /* Handle 1 argument. It must be non-complex number. */ if (argc == 1) { if (IS_REAL(n)) { return (PyObject*)GMPy_MPQ_From_Number(n, context); } } /* Handle 2 arguments. Both arguments must be integer or rational. */ if (argc == 2) { m = PyTuple_GetItem(args, 1); if (IS_RATIONAL(n) && IS_RATIONAL(m)) { result = GMPy_MPQ_From_Rational(n, context); temp = GMPy_MPQ_From_Rational(m, context); if (!result || !temp) { Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)temp); return NULL; } if (mpq_sgn(temp->q) == 0) { ZERO_ERROR("zero denominator in mpq()"); Py_DECREF((PyObject*)result); Py_DECREF((PyObject*)temp); return NULL; } mpq_div(result->q, result->q, temp->q); Py_DECREF((PyObject*)temp); return (PyObject*)result; } } TYPE_ERROR("mpq() requires numeric or string argument"); return NULL; }
static PyObject * GMPy_Rational_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context) { MPQ_Object *tempbq = NULL, *resultq = NULL; MPZ_Object *tempez = NULL; int bsign; long tempexp; if (mod != Py_None) { TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers"); return NULL; } /* Only support mpq**int. Everything else gets converted to mpf. */ if (IS_RATIONAL(base) && IS_INTEGER(exp)) { resultq = GMPy_MPQ_New(context); tempbq = GMPy_MPQ_From_Rational(base, context); tempez = GMPy_MPZ_From_Integer(exp, context); if (!resultq || !tempbq || !tempez) { Py_XDECREF((PyObject*)resultq); Py_XDECREF((PyObject*)tempbq); Py_XDECREF((PyObject*)tempez); return NULL; } if (!mpz_fits_slong_p(tempez->z)) { VALUE_ERROR("mpq.pow() outrageous exponent"); Py_DECREF((PyObject*)resultq); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } tempexp = mpz_get_si(tempez->z); if (tempexp == 0) { mpq_set_si(resultq->q, 1, 1); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return (PyObject*)resultq; } bsign = mpq_sgn(tempbq->q); if (tempexp < 0) { if (bsign == 0) { ZERO_ERROR("pow() 0 base to negative exponent"); Py_DECREF((PyObject*)resultq); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } if (bsign < 0) { mpz_neg(mpq_numref(resultq->q), mpq_denref(tempbq->q)); } else { mpz_set(mpq_numref(resultq->q), mpq_denref(tempbq->q)); } mpz_abs(mpq_denref(resultq->q), mpq_numref(tempbq->q)); tempexp = -tempexp; } else { mpq_set(resultq->q, tempbq->q); } if (tempexp > 1) { mpz_pow_ui(mpq_numref(resultq->q), mpq_numref(resultq->q), tempexp); mpz_pow_ui(mpq_denref(resultq->q), mpq_denref(resultq->q), tempexp); } Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return (PyObject*)resultq; } else { return GMPy_Real_Pow(base, exp, Py_None, context); } }
static PyObject * GMPy_Real_DivMod_2(PyObject *x, PyObject *y, CTXT_Object *context) { MPFR_Object *tempx = NULL, *tempy = NULL, *quo = NULL, *rem = NULL; PyObject *result = NULL; CHECK_CONTEXT(context); if (!(result = PyTuple_New(2)) || !(rem = GMPy_MPFR_New(0, context)) || !(quo = GMPy_MPFR_New(0, context))) { /* LCOV_EXCL_START */ goto error; /* LCOV_EXCL_STOP */ } if (IS_REAL(x) && IS_REAL(y)) { if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) || !(tempy = GMPy_MPFR_From_Real(y, 1, context))) { /* LCOV_EXCL_START */ goto error; /* LCOV_EXCL_STOP */ } if (mpfr_zero_p(tempy->f)) { context->ctx.divzero = 1; if (context->ctx.traps & TRAP_DIVZERO) { GMPY_DIVZERO("divmod() division by zero"); goto error; } } if (mpfr_nan_p(tempx->f) || mpfr_nan_p(tempy->f) || mpfr_inf_p(tempx->f)) { context->ctx.invalid = 1; if (context->ctx.traps & TRAP_INVALID) { GMPY_INVALID("divmod() invalid operation"); goto error; } else { mpfr_set_nan(quo->f); mpfr_set_nan(rem->f); } } else if (mpfr_inf_p(tempy->f)) { context->ctx.invalid = 1; if (context->ctx.traps & TRAP_INVALID) { GMPY_INVALID("divmod() invalid operation"); goto error; } if (mpfr_zero_p(tempx->f)) { mpfr_set_zero(quo->f, mpfr_sgn(tempy->f)); mpfr_set_zero(rem->f, mpfr_sgn(tempy->f)); } else if ((mpfr_signbit(tempx->f)) != (mpfr_signbit(tempy->f))) { mpfr_set_si(quo->f, -1, MPFR_RNDN); mpfr_set_inf(rem->f, mpfr_sgn(tempy->f)); } else { mpfr_set_si(quo->f, 0, MPFR_RNDN); rem->rc = mpfr_set(rem->f, tempx->f, MPFR_RNDN); } } else { MPQ_Object *mpqx = NULL, *mpqy = NULL, *temp_rem = NULL; MPZ_Object *temp_quo = NULL; if (!(mpqx = GMPy_MPQ_From_MPFR(tempx, context)) || !(mpqy = GMPy_MPQ_From_MPFR(tempy, context))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)mpqx); Py_XDECREF((PyObject*)mpqy); goto error; /* LCOV_EXCL_STOP */ } if (!(temp_rem = GMPy_MPQ_New(context)) || !(temp_quo = GMPy_MPZ_New(context))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)temp_rem); Py_XDECREF((PyObject*)temp_quo); Py_XDECREF((PyObject*)mpqx); Py_XDECREF((PyObject*)mpqy); goto error; /* LCOV_EXCL_STOP */ } Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); mpq_div(temp_rem->q, mpqx->q, mpqy->q); mpz_fdiv_q(temp_quo->z, mpq_numref(temp_rem->q), mpq_denref(temp_rem->q)); /* Need to calculate x - quo * y. */ mpq_set_z(temp_rem->q, temp_quo->z); mpq_mul(temp_rem->q, temp_rem->q, mpqy->q); mpq_sub(temp_rem->q, mpqx->q, temp_rem->q); Py_DECREF((PyObject*)mpqx); Py_DECREF((PyObject*)mpqy); quo->rc = mpfr_set_z(quo->f, temp_quo->z, MPFR_RNDD); rem->rc = mpfr_set_q(rem->f, temp_rem->q, MPFR_RNDN); Py_DECREF((PyObject*)temp_rem); Py_DECREF((PyObject*)temp_quo); GMPY_MPFR_CHECK_RANGE(quo, context); GMPY_MPFR_CHECK_RANGE(rem, context); GMPY_MPFR_SUBNORMALIZE(quo, context); GMPY_MPFR_SUBNORMALIZE(rem, context); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } } /* LCOV_EXCL_START */ SYSTEM_ERROR("Internal error in GMPy_Real_DivMod_2()."); error: Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_XDECREF((PyObject*)rem); Py_XDECREF((PyObject*)quo); Py_XDECREF(result); return NULL; /* LCOV_EXCL_STOP */ }