static PyObject * Pympany_binary(PyObject *self, PyObject *other) { if (self && Pympz_Check(self)) return Pympz2binary((PympzObject*)self); else if(self && Pyxmpz_Check(self)) return Pyxmpz2binary((PyxmpzObject*)self); else if(self && Pympq_Check(self)) return Pympq2binary((PympqObject*)self); #ifdef WITHMPFR else if(self && Pympfr_Check(self)) return Pympfr2binary((PympfrObject*)self); #endif else if(Pympz_Check(other)) return Pympz2binary((PympzObject*)other); else if(Pyxmpz_Check(other)) return Pyxmpz2binary((PyxmpzObject*)other); else if(Pympq_Check(other)) return Pympq2binary((PympqObject*)other); #ifdef WITHMPFR else if(Pympfr_Check(other)) return Pympfr2binary((PympfrObject*)other); #endif TYPE_ERROR("binary() requires a gmpy2 object as argument"); return NULL; }
static PyObject * Pympany_copy(PyObject *self, PyObject *other) { if (self && Pympz_Check(self)) return (PyObject*)Pympz2Pympz(self); else if (self && Pyxmpz_Check(self)) return (PyObject*)Pyxmpz2Pyxmpz(self); else if (self && Pympq_Check(self)) return (PyObject*)Pympq2Pympq(self); #ifdef WITHMPFR else if (self && Pympfr_Check(self)) return (PyObject*)Pympfr2Pympfr(self, 0); #endif else if (Pympz_Check(other)) return (PyObject*)Pympz2Pympz(other); else if (Pyxmpz_Check(other)) return (PyObject*)Pyxmpz2Pyxmpz(other); else if (Pympq_Check(other)) return (PyObject*)Pympq2Pympq(other); #ifdef WITHMPFR else if (Pympfr_Check(other)) return (PyObject*)Pympfr2Pympfr(other, 0); #endif TYPE_ERROR("_copy() requires a gmpy2 object as argument"); return NULL; }
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 * Pympz_mpmath_normalize(PyObject *self, PyObject *args) { long sign = 0; mpir_si bc = 0, prec = 0, shift, zbits, carry = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0; PympzObject *man = 0, *upper = 0, *lower = 0; char rnd = 0; if (PyTuple_GET_SIZE(args) == 6) { /* Need better error-checking here. Under Python 3.0, overflow into C-long is possible. */ sign = clong_From_Integer(PyTuple_GET_ITEM(args, 0)); man = (PympzObject *)PyTuple_GET_ITEM(args, 1); exp = PyTuple_GET_ITEM(args, 2); bc = SI_From_Integer(PyTuple_GET_ITEM(args, 3)); prec = SI_From_Integer(PyTuple_GET_ITEM(args, 4)); rndstr = PyTuple_GET_ITEM(args, 5); if (PyErr_Occurred()) { TYPE_ERROR("arguments long, PympzObject*, PyObject*, long, long, char needed"); return NULL; } } else { TYPE_ERROR("6 arguments required"); return NULL; } if (!Pympz_Check(man)) { TYPE_ERROR("argument is not an mpz"); return NULL; } /* If rndstr really is a string, extract the first character. */ if (Py2or3String_Check(rndstr)) { rnd = Py2or3String_AsString(rndstr)[0]; } else { VALUE_ERROR("invalid rounding mode specified"); return NULL; } /* If the mantissa is 0, return the normalized representation. */ if (!mpz_sgn(man->z)) { Py_INCREF((PyObject*)man); return mpmath_build_mpf(0, man, 0, 0); } /* if bc <= prec and the number is odd return it */ if ((bc <= prec) && mpz_odd_p(man->z)) { Py_INCREF((PyObject*)man); Py_INCREF((PyObject*)exp); return mpmath_build_mpf(sign, man, exp, bc); } if (!(upper = (PympzObject*)Pympz_new()) || !(lower = (PympzObject*)Pympz_new())) { Py_XDECREF((PyObject*)upper); Py_XDECREF((PyObject*)lower); } shift = bc - prec; if (shift>0) { switch (rnd) { case 'f': if(sign) { mpz_cdiv_q_2exp(upper->z, man->z, shift); } else { mpz_fdiv_q_2exp(upper->z, man->z, shift); } break; case 'c': if(sign) { mpz_fdiv_q_2exp(upper->z, man->z, shift); } else { mpz_cdiv_q_2exp(upper->z, man->z, shift); } break; case 'd': mpz_fdiv_q_2exp(upper->z, man->z, shift); break; case 'u': mpz_cdiv_q_2exp(upper->z, man->z, shift); break; case 'n': default: mpz_tdiv_r_2exp(lower->z, man->z, shift); mpz_tdiv_q_2exp(upper->z, man->z, shift); if (mpz_sgn(lower->z)) { /* lower is not 0 so it must have at least 1 bit set */ if (mpz_sizeinbase(lower->z, 2) == shift) { /* lower is >= 1/2 */ if (mpz_scan1(lower->z, 0) == shift-1) { /* lower is exactly 1/2 */ if (mpz_odd_p(upper->z)) carry = 1; } else { carry = 1; } } } if (carry) mpz_add_ui(upper->z, upper->z, 1); } if (!(tmp = PyIntOrLong_FromSI(shift))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); return NULL; } if (!(newexp = PyNumber_Add(exp, tmp))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); return NULL; } Py_DECREF(tmp); bc = prec; } else { mpz_set(upper->z, man->z); newexp = exp; Py_INCREF(newexp); } /* Strip trailing 0 bits. */ if ((zbits = mpz_scan1(upper->z, 0))) mpz_tdiv_q_2exp(upper->z, upper->z, zbits); if (!(tmp = PyIntOrLong_FromSI(zbits))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(newexp); return NULL; } if (!(newexp2 = PyNumber_Add(newexp, tmp))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); Py_DECREF(newexp); return NULL; } Py_DECREF(newexp); Py_DECREF(tmp); bc -= zbits; /* Check if one less than a power of 2 was rounded up. */ if (!mpz_cmp_ui(upper->z, 1)) bc = 1; Py_DECREF((PyObject*)lower); return mpmath_build_mpf(sign, upper, newexp2, bc); }
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; } }