static PyObject * mpmath_build_mpf(long sign, PympzObject *man, PyObject *exp, mpir_si bc) { PyObject *tup, *tsign, *tbc; if (!(tup = PyTuple_New(4))) { Py_DECREF((PyObject*)man); Py_DECREF(exp); return NULL; } if (!(tsign = PyIntOrLong_FromLong(sign))) { Py_DECREF((PyObject*)man); Py_DECREF(exp); Py_DECREF(tup); return NULL; } if (!(tbc = PyIntOrLong_FromSI(bc))) { Py_DECREF((PyObject*)man); Py_DECREF(exp); Py_DECREF(tup); Py_DECREF(tsign); return NULL; } PyTuple_SET_ITEM(tup, 0, tsign); PyTuple_SET_ITEM(tup, 1, (PyObject*)man); PyTuple_SET_ITEM(tup, 2, (exp)?exp:PyIntOrLong_FromLong(0)); PyTuple_SET_ITEM(tup, 3, tbc); return tup; }
static PyObject * GMPy_Real_RemQuo(PyObject *x, PyObject *y, CTXT_Object *context) { PyObject *result; MPFR_Object *value, *tempx, *tempy; long quobits = 0; CHECK_CONTEXT(context); value = GMPy_MPFR_New(0, context); tempx = GMPy_MPFR_From_Real(x, 1, context); tempy = GMPy_MPFR_From_Real(y, 1, context); result = PyTuple_New(2); if (!value || !tempx || !tempx || !result) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_XDECREF((PyObject*)value); Py_XDECREF(result); return NULL; } mpfr_clear_flags(); value->rc = mpfr_remquo(value->f, &quobits, tempx->f, tempy->f, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); _GMPy_MPFR_Cleanup(&value, context); PyTuple_SET_ITEM(result, 0, (PyObject*)value); PyTuple_SET_ITEM(result, 1, PyIntOrLong_FromLong(quobits)); return result; }
static PyObject * GMPy_Real_Lgamma(PyObject *x, CTXT_Object *context) { PyObject *result; MPFR_Object *value, *tempx; int signp = 0; CHECK_CONTEXT(context) tempx = GMPy_MPFR_From_Real(x, 1, context); value = GMPy_MPFR_New(0, context); result = PyTuple_New(2); if (!tempx || !value || !result) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)value); Py_XDECREF(result); return NULL; } mpfr_clear_flags(); value->rc = mpfr_lgamma(value->f, &signp, tempx->f, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); _GMPy_MPFR_Cleanup(&value, context); if (!value) { Py_DECREF(result); return NULL; } PyTuple_SET_ITEM(result, 0, (PyObject*)value); PyTuple_SET_ITEM(result, 1, PyIntOrLong_FromLong((long)signp)); return result; }
static PyObject * GMPy_MPZ_Function_Legendre(PyObject *self, PyObject *args) { MPZ_Object *tempx = NULL, *tempy = NULL; long res; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("legendre() requires 'mpz','mpz' arguments"); return NULL; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); return NULL; } if (mpz_sgn(tempy->z) <= 0 || mpz_even_p(tempy->z)) { VALUE_ERROR("y must be odd, prime, and >0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return NULL; } res = (long)(mpz_legendre(tempx->z, tempy->z)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return PyIntOrLong_FromLong(res); }
static PyObject * GMPy_XMPZ_Method_SubScript(XMPZ_Object* self, PyObject* item) { CTXT_Object *context = NULL; CHECK_CONTEXT(context); if (PyIndex_Check(item)) { Py_ssize_t i; i = PyIntOrLong_AsSsize_t(item); if (i == -1 && PyErr_Occurred()) { INDEX_ERROR("argument too large to be converted to an index"); return NULL; } if (i < 0) { i += mpz_sizeinbase(self->z, 2); } return PyIntOrLong_FromLong(mpz_tstbit(self->z, i)); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; MPZ_Object *result; #if PY_VERSION_HEX > 0x030200A4 if (PySlice_GetIndicesEx(item, #else if (PySlice_GetIndicesEx((PySliceObject*)item, #endif mpz_sizeinbase(self->z, 2), &start, &stop, &step, &slicelength) < 0) { return NULL; } if ((step < 0 && start < stop) || (step > 0 && start > stop)) { stop = start; } if (!(result = GMPy_MPZ_New(context))) { return NULL; } mpz_set_ui(result->z, 0); if (slicelength > 0) { for (cur = start, i = 0; i < slicelength; cur += step, i++) { if (mpz_tstbit(self->z, cur)) { mpz_setbit(result->z, i); } } } return (PyObject*)result; } else {
static PyObject * GMPy_Rational_Sign(PyObject *x, CTXT_Object *context) { long res; MPQ_Object *tempx; if (!(tempx = GMPy_MPQ_From_Rational(x, context))) { return NULL; } else { res = mpq_sgn(tempx->q); Py_DECREF((PyObject*)tempx); return PyIntOrLong_FromLong(res); } }
static PyObject * GMPy_Integer_Sign(PyObject *x, CTXT_Object *context) { long res; MPZ_Object *tempx; if (!(tempx = GMPy_MPZ_From_Integer(x, context))) { return NULL; } else { res = mpz_sgn(tempx->z); Py_DECREF((PyObject*)tempx); return PyIntOrLong_FromLong(res); } }
static PyObject * Pyxmpz_subscript(PyxmpzObject* self, PyObject* item) { if (PyIndex_Check(item)) { Py_ssize_t i; i = PyNumber_AsSsize_t(item, PyExc_IndexError); if (i == -1 && PyErr_Occurred()) return NULL; if (i < 0) i += mpz_sizeinbase(self->z, 2); return PyIntOrLong_FromLong(mpz_tstbit(self->z, i)); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength, cur, i; PyObject* result; #if PY_VERSION_HEX > 0x030200A4 if (PySlice_GetIndicesEx(item, #else if (PySlice_GetIndicesEx((PySliceObject*)item, #endif mpz_sizeinbase(self->z, 2), &start, &stop, &step, &slicelength) < 0) { return NULL; } if ((step < 0 && start < stop) || (step > 0 && start > stop)) stop = start; if (!(result = (PyObject*)Pympz_new())) return NULL; mpz_set_ui(Pympz_AS_MPZ(result), 0); if (slicelength > 0) { for (cur = start, i = 0; i < slicelength; cur += step, i++) { if (mpz_tstbit(self->z, cur)) { mpz_setbit(Pympz_AS_MPZ(result), i); } } } return result; } else {
static PyObject * GMPy_Real_Sign(PyObject *x, CTXT_Object *context) { long sign; MPFR_Object *tempx; PyObject *result; CHECK_CONTEXT(context); if (!(tempx = GMPy_MPFR_From_Real(x, 1, context))) { return NULL; } else { mpfr_clear_flags(); sign = mpfr_sgn(tempx->f); Py_DECREF((PyObject*)tempx); result = PyIntOrLong_FromLong(sign); GMPY_CHECK_ERANGE(result, context, "sign() of invalid value (NaN)"); return 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 * GMPy_MPZ_Function_Kronecker(PyObject *self, PyObject *args) { MPZ_Object *tempx = NULL, *tempy = NULL; long res; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("kronecker() requires 'mpz','mpz' arguments"); return NULL; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || !(tempy = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL))) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); return NULL; } res = (long)(mpz_kronecker(tempx->z, tempy->z)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return PyIntOrLong_FromLong(res); }
static PyObject * Pympz_mpmath_normalize(PyObject *self, PyObject *args) { long sign = 0; long bc = 0, prec = 0, shift, zbits, carry = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0, *rndstr = 0; MPZ_Object *man = 0, *upper = 0, *lower = 0; char rnd = 0; int err1, err2, err3; if (PyTuple_GET_SIZE(args) == 6) { /* Need better error-checking here. Under Python 3.0, overflow into C-long is possible. */ sign = GMPy_Integer_AsLongAndError(PyTuple_GET_ITEM(args, 0), &err1); man = (MPZ_Object *)PyTuple_GET_ITEM(args, 1); exp = PyTuple_GET_ITEM(args, 2); bc = GMPy_Integer_AsLongAndError(PyTuple_GET_ITEM(args, 3), &err2); prec = GMPy_Integer_AsLongAndError(PyTuple_GET_ITEM(args, 4), &err3); rndstr = PyTuple_GET_ITEM(args, 5); if (err1 || err2 || err3) { TYPE_ERROR("arguments long, MPZ_Object*, PyObject*, long, long, char needed"); return NULL; } } else { TYPE_ERROR("6 arguments required"); return NULL; } if (!MPZ_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 = GMPy_MPZ_New(NULL)) || !(lower = GMPy_MPZ_New(NULL))) { 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_FromLong(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_FromLong(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 * Pympz_mpmath_create(PyObject *self, PyObject *args) { long sign; long bc, shift, zbits, carry = 0, prec = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0; MPZ_Object *man = 0, *upper = 0, *lower = 0; int error; const char *rnd = "f"; if (PyTuple_GET_SIZE(args) < 2) { TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments"); return NULL; } switch (PyTuple_GET_SIZE(args)) { case 4: rnd = Py2or3String_AsString(PyTuple_GET_ITEM(args, 3)); case 3: prec = GMPy_Integer_AsLongAndError(PyTuple_GET_ITEM(args, 2), &error); if (error) return NULL; prec = ABS(prec); case 2: exp = PyTuple_GET_ITEM(args, 1); case 1: man = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL); if (!man) { TYPE_ERROR("mpmath_create() expects 'mpz','int'[,'int','str'] arguments"); return NULL; } } /* If the mantissa is 0, return the normalized representation. */ if (!mpz_sgn(man->z)) { return mpmath_build_mpf(0, man, 0, 0); } upper = GMPy_MPZ_New(NULL); lower = GMPy_MPZ_New(NULL); if (!upper || !lower) { Py_DECREF((PyObject*)man); Py_XDECREF((PyObject*)upper); Py_XDECREF((PyObject*)lower); return NULL; } /* Extract sign, make man positive, and set bit count */ sign = (mpz_sgn(man->z) == -1); mpz_abs(upper->z, man->z); bc = mpz_sizeinbase(upper->z, 2); if (!prec) prec = bc; shift = bc - prec; if (shift > 0) { switch (rnd[0]) { case 'f': if(sign) { mpz_cdiv_q_2exp(upper->z, upper->z, shift); } else { mpz_fdiv_q_2exp(upper->z, upper->z, shift); } break; case 'c': if(sign) { mpz_fdiv_q_2exp(upper->z, upper->z, shift); } else { mpz_cdiv_q_2exp(upper->z, upper->z, shift); } break; case 'd': mpz_fdiv_q_2exp(upper->z, upper->z, shift); break; case 'u': mpz_cdiv_q_2exp(upper->z, upper->z, shift); break; case 'n': default: mpz_tdiv_r_2exp(lower->z, upper->z, shift); mpz_tdiv_q_2exp(upper->z, upper->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_FromLong(shift))) { Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); return NULL; } if (!(newexp = PyNumber_Add(exp, tmp))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(tmp); return NULL; } Py_DECREF(tmp); bc = prec; } else { 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_FromLong(zbits))) { Py_DECREF((PyObject*)man); Py_DECREF((PyObject*)upper); Py_DECREF((PyObject*)lower); Py_DECREF(newexp); return NULL; } if (!(newexp2 = PyNumber_Add(newexp, tmp))) { Py_DECREF((PyObject*)man); 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); Py_DECREF((PyObject*)man); return mpmath_build_mpf(sign, upper, newexp2, bc); }