static PyObject * Pympq_sizeof(PyObject *self, PyObject *other) { return PyIntOrLong_FromSize_t(sizeof(PympqObject) + \ (mpq_numref(Pympq_AS_MPQ(self))->_mp_alloc * sizeof(mp_limb_t)) + \ (mpq_denref(Pympq_AS_MPQ(self))->_mp_alloc * sizeof(mp_limb_t))); }
static PyObject * Pympq_trunc(PyObject *self, PyObject *other) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) { mpz_tdiv_q(result->z, mpq_numref(Pympq_AS_MPQ(self)), mpq_denref(Pympq_AS_MPQ(self))); } return (PyObject*)result; }
static PyObject * Pympq_mul(PyObject *self, PyObject *args) { PympqObject *result; PyObject *other; PARSE_TWO_MPQ(other, "mul() requires 'mpq','mpq' arguments"); if ((result = (PympqObject*)Pympq_new())) mpq_mul(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; }
static PyObject * Pympany_printf(PyObject *self, PyObject *args) { PyObject *result = 0, *x = 0; char *buffer = 0, *fmtcode = 0; int buflen; void *generic; if (!PyArg_ParseTuple(args, "sO", &fmtcode, &x)) return NULL; if (CHECK_MPZANY(x) || Pympq_Check(x)) { if (CHECK_MPZANY(x)) generic = Pympz_AS_MPZ(x); else generic = Pympq_AS_MPQ(x); buflen = gmp_asprintf(&buffer, fmtcode, generic); result = Py_BuildValue("s", buffer); PyMem_Free(buffer); return result; } #ifdef WITHMPFR else if(Pympfr_Check(x)) { generic = Pympfr_AS_MPFR(x); buflen = mpfr_asprintf(&buffer, fmtcode, generic); result = Py_BuildValue("s", buffer); PyMem_Free(buffer); return result; } #endif else { TYPE_ERROR("printf() requires a gmpy2 object as argument"); return NULL; } }
static PyObject * Pympq_getdenom(PympqObject *self, void *closure) { PympzObject *result; if ((result = (PympzObject*)Pympz_new())) mpz_set(result->z, mpq_denref(Pympq_AS_MPQ(self))); return (PyObject*)result; }
static PyObject * Pympq_square(PyObject *self, PyObject *other) { PympqObject *tempx, *result; if (!(result = (PympqObject*)Pympq_new())) return NULL; if (self && (Pympq_Check(self))) { mpq_mul(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(self)); } else if (Pympq_Check(other)) { mpq_mul(result->q, Pympq_AS_MPQ(other), Pympq_AS_MPQ(other)); } else { if (!(tempx = Pympq_From_Rational(other))) { TYPE_ERROR("square() requires 'mpq' argument"); Py_DECREF((PyObject*)result); return NULL; } else { mpq_mul(result->q, Pympq_AS_MPQ(tempx), Pympq_AS_MPQ(tempx)); Py_DECREF((PyObject*)tempx); } } return (PyObject*)result; }
static int isOne(PyObject* obj) { int overflow = 0; long temp; if (!obj) return 1; if (Pympq_Check(obj)) { return (0==mpz_cmp_ui(mpq_denref(Pympq_AS_MPQ(obj)),1)) && (0==mpz_cmp_ui(mpq_numref(Pympq_AS_MPQ(obj)),1)); } else if (Pympz_Check(obj)) { return 0==mpz_cmp_ui(Pympz_AS_MPZ(obj),1); } else if (Pyxmpz_Check(obj)) { return 0==mpz_cmp_ui(Pyxmpz_AS_MPZ(obj),1); #ifdef PY2 } else if (PyInt_Check(obj)) { return PyInt_AS_LONG(obj)==1; #endif } #ifdef WITHMPFR else if (Pympfr_Check(obj)) { return mpfr_get_d(Pympfr_AS_MPFR(obj), context->ctx.mpfr_round)==1.0; } #endif else if (PyFloat_Check(obj)) { return PyFloat_AS_DOUBLE(obj)==1.0; } else if (PyLong_Check(obj)) { temp = PyLong_AsLongAndOverflow(obj, &overflow); if (!overflow && temp == 1) return 1; else return 0; } return 0; }
static PyObject * Pympq_div(PyObject *self, PyObject *args) { PympqObject *result; PyObject *other; PARSE_TWO_MPQ(other, "div() requires 'mpq','mpq' arguments"); if ((result = (PympqObject*)Pympq_new())) { if (mpq_sgn(Pympq_AS_MPQ(other)) == 0) { ZERO_ERROR("'mpq' division by zero"); Py_DECREF((PyObject*)result); result = 0; } else { mpq_div(result->q, Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); } } Py_DECREF(self); Py_DECREF(other); return (PyObject*)result; }
static PyObject * Pympq_denom(PyObject *self, PyObject *args) { PympzObject *result; if (!(result = (PympzObject*)Pympz_new())) return NULL; SELF_MPQ_NO_ARG; assert(Pympq_Check(self)); mpz_set(result->z, mpq_denref(Pympq_AS_MPQ(self))); Py_DECREF(self); return (PyObject*)result; }
static PyObject * Pympq_sign(PyObject *self, PyObject *other) { long res; PympqObject* tempx; if (Pympq_Check(other)) { res = mpq_sgn(Pympq_AS_MPQ(other)); } else { if (!(tempx = Pympq_From_Number(other))) { TYPE_ERROR("sign() requires 'mpq' argument"); return NULL; } else { res = mpq_sgn(tempx->q); Py_DECREF((PyObject*)tempx); } } return PyIntOrLong_FromLong(res); }
static PyObject * Pympq_round(PyObject *self, PyObject *args) { Py_ssize_t round_digits = 0; PympqObject *resultq; PympzObject *resultz; mpz_t temp, rem; /* If args is NULL or the size of args is 0, we just return an mpz. */ if (!args || PyTuple_GET_SIZE(args) == 0) { if (!(resultz = (PympzObject*)Pympz_new())) return NULL; mpz_inoc(rem); mpz_fdiv_qr(resultz->z, rem, mpq_numref(Pympq_AS_MPQ(self)), mpq_denref(Pympq_AS_MPQ(self))); mpz_mul_2exp(rem, rem, 1); if (mpz_cmp(rem, mpq_denref(Pympq_AS_MPQ(self))) > 0) { mpz_add_ui(resultz->z, resultz->z, 1); } else if (mpz_cmp(rem, mpq_denref(Pympq_AS_MPQ(self))) == 0) { if (mpz_odd_p(resultz->z)) { mpz_add_ui(resultz->z, resultz->z, 1); } } mpz_cloc(rem); return (PyObject*)resultz; } if (PyTuple_GET_SIZE(args) > 1) { TYPE_ERROR("Too many arguments for __round__()."); return NULL; } if (PyTuple_GET_SIZE(args) == 1) { round_digits = ssize_t_From_Integer(PyTuple_GET_ITEM(args, 0)); if (round_digits == -1 && PyErr_Occurred()) { TYPE_ERROR("__round__() requires 'int' argument"); return NULL; } } if (!(resultq = (PympqObject*)Pympq_new())) return NULL; mpz_inoc(temp); mpz_ui_pow_ui(temp, 10, round_digits > 0 ? round_digits : -round_digits); mpq_set(resultq->q, Pympq_AS_MPQ(self)); if (round_digits > 0) { mpz_mul(mpq_numref(resultq->q), mpq_numref(resultq->q), temp); mpq_canonicalize(resultq->q); if (!(resultz = (PympzObject*)Pympq_round((PyObject*)resultq, NULL))) { mpz_cloc(temp); return NULL; } mpz_set(mpq_numref(resultq->q), resultz->z); Py_DECREF((PyObject*)resultz); mpz_set(mpq_denref(resultq->q), temp); mpz_cloc(temp); mpq_canonicalize(resultq->q); } else { mpz_mul(mpq_denref(resultq->q), mpq_denref(resultq->q), temp); mpq_canonicalize(resultq->q); if (!(resultz = (PympzObject*)Pympq_round((PyObject*)resultq, NULL))) { mpz_cloc(temp); return NULL; } mpq_set_ui(resultq->q, 0, 1); mpz_mul(mpq_numref(resultq->q), resultz->z, temp); Py_DECREF((PyObject*)resultz); mpz_cloc(temp); mpq_canonicalize(resultq->q); } return (PyObject*)resultq; }
static PyObject * Pympq_qdiv(PyObject *self, PyObject *args) { PyObject *other = 0; PyObject *s = 0; int wasone; if ( self && Pympq_Check(self)) { if (!PyArg_ParseTuple(args, "|O", &other)) return NULL; } else { if (!PyArg_ParseTuple(args, "O|O", &self, &other)) return NULL; } wasone = isOne(other); /* optimize if self must be returned unchanged */ if (Pympq_Check(self) && wasone) { /* optimize if self is mpq and result must==self */ if (mpz_cmp_ui(mpq_denref(Pympq_AS_MPQ(self)), 1) != 0) { Py_INCREF(self); return self; } else { /* denominator is 1, optimize returning an mpz */ s = Pympz_new(); mpz_set(Pympz_AS_MPZ(s), mpq_numref(Pympq_AS_MPQ(self))); return s; } } else if (Pympz_Check(self) && wasone) { /* optimize if self is mpz and result must==self */ Py_INCREF(self); return self; } /* normal, non-optimized case: must make new object as result */ self = (PyObject*)Pympq_From_Rational(self); if (!self) { if (!PyErr_Occurred()) TYPE_ERROR("first argument cannot be converted to 'mpq'"); return NULL; } if (wasone) { /* self was mpf, float, int, long... */ s = self; } else { /* other explicitly present and !=1... must compute */ other = (PyObject*)Pympq_From_Rational(other); if (!other) { Py_DECREF(self); if (!PyErr_Occurred()) TYPE_ERROR("second argument cannot be converted to 'mpq'"); return NULL; } if (mpq_sgn(Pympq_AS_MPQ(other))==0) { PyObject* result = 0; ZERO_ERROR("division or modulo by zero in qdiv"); Py_DECREF(self); Py_DECREF(other); return result; } s = Pympq_new(); mpq_div(Pympq_AS_MPQ(s), Pympq_AS_MPQ(self), Pympq_AS_MPQ(other)); Py_DECREF(self); Py_DECREF(other); } if (mpz_cmp_ui(mpq_denref(Pympq_AS_MPQ(s)), 1) != 0) { return s; } else { /* denominator is 1, return an mpz */ PyObject* ss = Pympz_new(); if (ss) mpz_set(Pympz_AS_MPZ(ss), mpq_numref(Pympq_AS_MPQ(s))); Py_DECREF(s); return ss; } }