static Py_hash_t Pympq_hash(PympqObject *self) { #ifdef _PyHASH_MODULUS Py_hash_t hash = 0; mpz_t temp, temp1, mask; if (self->hash_cache != -1) return self->hash_cache; mpz_inoc(temp); mpz_inoc(temp1); mpz_inoc(mask); mpz_set_si(mask, 1); mpz_mul_2exp(mask, mask, _PyHASH_BITS); mpz_sub_ui(mask, mask, 1); if (!mpz_invert(temp, mpq_denref(self->q), mask)) { mpz_cloc(temp); mpz_cloc(temp1); mpz_cloc(mask); hash = _PyHASH_INF; if (mpz_sgn(mpq_numref(self->q))<0) hash = -hash; self->hash_cache = hash; return hash; } mpz_set(temp1, mask); mpz_sub_ui(temp1, temp1, 2); mpz_powm(temp, mpq_denref(self->q), temp1, mask); mpz_tdiv_r(temp1, mpq_numref(self->q), mask); mpz_mul(temp, temp, temp1); hash = (Py_hash_t)mpn_mod_1(temp->_mp_d, mpz_size(temp), _PyHASH_MODULUS); if (mpz_sgn(mpq_numref(self->q))<0) hash = -hash; if (hash==-1) hash = -2; mpz_cloc(temp); mpz_cloc(temp1); mpz_cloc(mask); self->hash_cache = hash; return hash; #else PyObject *temp; if (self->hash_cache != -1) return self->hash_cache; if (!(temp = Pympq_To_PyFloat(self))) { SYSTEM_ERROR("Could not convert 'mpq' to float."); return -1; } self->hash_cache = PyObject_Hash(temp); Py_DECREF(temp); return self->hash_cache; #endif }
static PyObject * GMPy_MPZ_Method_Round(PyObject *self, PyObject *args) { Py_ssize_t round_digits; MPZ_Object *result; mpz_t temp, rem; if (PyTuple_GET_SIZE(args) == 0) { Py_INCREF(self); return self; } 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 (round_digits >= 0) { Py_INCREF(self); return self; } round_digits = -round_digits; if ((result = GMPy_MPZ_New(NULL))) { if (round_digits >= mpz_sizeinbase(MPZ(self), 10)) { mpz_set_ui(result->z, 0); } else { mpz_inoc(temp); mpz_inoc(rem); mpz_ui_pow_ui(temp, 10, round_digits); mpz_fdiv_qr(result->z, rem, MPZ(self), temp); mpz_mul_2exp(rem, rem, 1); if (mpz_cmp(rem, temp) > 0) { mpz_add_ui(result->z, result->z, 1); } else if (mpz_cmp(rem, temp) == 0) { if (mpz_odd_p(result->z)) { mpz_add_ui(result->z, result->z, 1); } } mpz_mul(result->z, result->z, temp); mpz_cloc(rem); mpz_cloc(temp); } } return (PyObject*)result; }
static PyObject * GMPy_XMPZ_ISub_Slot(PyObject *self, PyObject *other) { if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if (!error) { if (temp >= 0) { mpz_sub_ui(MPZ(self), MPZ(self), temp); } else { mpz_add_ui(MPZ(self), MPZ(self), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_sub(MPZ(self), MPZ(self), tempz); mpz_cloc(tempz); } Py_INCREF(self); return self; } if (CHECK_MPZANY(other)) { mpz_sub(MPZ(self), MPZ(self), MPZ(other)); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; }
static PyObject * Pyxmpz_inplace_sub(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_sub(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si >= 0) { mpz_sub_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { mpz_add_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { mpz_sub(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_MPZ_IMul_Slot(PyObject *self, PyObject *other) { MPZ_Object *rz; if (!(rz = GMPy_MPZ_New(NULL))) return NULL; if (CHECK_MPZANY(other)) { mpz_mul(rz->z, MPZ(self), MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if (!error) { mpz_mul_si(rz->z, MPZ(self), temp); } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_mul(rz->z, MPZ(self), tempz); mpz_cloc(tempz); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_MPZ_IAdd_Slot(PyObject *self, PyObject *other) { MPZ_Object *result = NULL; if (CHECK_MPZANY(other)) { if ((result = GMPy_MPZ_New(NULL))) { mpz_add(result->z, MPZ(self), MPZ(other)); } return (PyObject*)result; } if (PyLong_CheckExact(other)) { if ((result = GMPy_MPZ_New(NULL))) { switch (Py_SIZE((PyLongObject*)other)) { case -1: mpz_sub_ui(result->z, MPZ(self), ((PyLongObject*)other)->ob_digit[0]); return (PyObject*)result; case 0: case 1: mpz_add_ui(result->z, MPZ(self), ((PyLongObject*)other)->ob_digit[0]); return (PyObject*)result; default: break; } } else { return NULL; } } if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if ((result = GMPy_MPZ_New(NULL))) { if (!error) { if (temp >= 0) { mpz_add_ui(result->z, MPZ(self), temp); } else { mpz_sub_ui(result->z, MPZ(self), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_add(result->z, MPZ(self), tempz); mpz_cloc(tempz); } } return (PyObject*)result; } Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_MPZ_IFloorDiv_Slot(PyObject *self, PyObject *other) { MPZ_Object *rz; if (!(rz = GMPy_MPZ_New(NULL))) return NULL; if (CHECK_MPZANY(other)) { if (mpz_sgn(MPZ(other)) == 0) { ZERO_ERROR("mpz division by zero"); return NULL; } mpz_fdiv_q(rz->z, MPZ(self), MPZ(other)); return (PyObject*)rz; } if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if (!error) { if (temp == 0) { ZERO_ERROR("mpz division by zero"); return NULL; } else if(temp > 0) { mpz_fdiv_q_ui(rz->z, MPZ(self), temp); } else { mpz_cdiv_q_ui(rz->z, MPZ(self), -temp); mpz_neg(rz->z, rz->z); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_fdiv_q(rz->z, MPZ(self), tempz); mpz_cloc(tempz); } return (PyObject*)rz; } Py_RETURN_NOTIMPLEMENTED; }
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 XMPZ_Object * GMPy_XMPZ_New(CTXT_Object *context) { XMPZ_Object *result; if (in_gmpyxmpzcache) { result = gmpyxmpzcache[--in_gmpyxmpzcache]; /* Py_INCREF does not set the debugging pointers, so need to use * _Py_NewReference instead. */ _Py_NewReference((PyObject*)result); } else { if (!(result = PyObject_New(XMPZ_Object, &XMPZ_Type))) return NULL; mpz_inoc(result->z); } return result; }
static PyObject * GMPy_XMPZ_IRem_Slot(PyObject *self, PyObject *other) { if (PyIntOrLong_Check(other)) { int error; long temp = GMPy_Integer_AsLongAndError(other, &error); if (!error) { if (temp > 0) { mpz_fdiv_r_ui(MPZ(self), MPZ(self), temp); } else if (temp == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } else { mpz_cdiv_r_ui(MPZ(self), MPZ(self), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_fdiv_r(MPZ(self), MPZ(self), tempz); mpz_cloc(tempz); } Py_INCREF(self); return self; } if (CHECK_MPZANY(other)) { if(mpz_sgn(MPZ(other)) == 0) { ZERO_ERROR("xmpz modulo by zero"); return NULL; } mpz_fdiv_r(MPZ(self), MPZ(self), MPZ(other)); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; }
static PyObject * Pyxmpz_inplace_floordiv(PyObject *a, PyObject *b) { mpz_t tempz; mpir_si temp_si; int overflow; if (PyIntOrLong_Check(b)) { temp_si = PyLong_AsSIAndOverflow(b, &overflow); if (overflow) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, b); mpz_fdiv_q(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), tempz); mpz_cloc(tempz); } else if(temp_si == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } else if(temp_si > 0) { mpz_fdiv_q_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), temp_si); } else { mpz_cdiv_q_ui(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), -temp_si); mpz_neg(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a)); } Py_INCREF(a); return a; } if (CHECK_MPZANY(b)) { if (mpz_sgn(Pyxmpz_AS_MPZ(b)) == 0) { ZERO_ERROR("xmpz division by zero"); return NULL; } mpz_fdiv_q(Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(a), Pyxmpz_AS_MPZ(b)); Py_INCREF(a); return a; } Py_RETURN_NOTIMPLEMENTED; }
static PyxmpzObject * Pyxmpz_new(void) { PyxmpzObject *self; TRACE("Entering Pyxmpz_new\n"); if (in_pyxmpzcache) { TRACE("Pyxmpz_new is reusing an old object\n"); self = pyxmpzcache[--in_pyxmpzcache]; /* Py_INCREF does not set the debugging pointers, so need to use * _Py_NewReference instead. */ _Py_NewReference((PyObject*)self); } else { TRACE("Pyxmpz_new is creating a new object\n"); if (!(self = PyObject_New(PyxmpzObject, &Pyxmpz_Type))) return NULL; mpz_inoc(self->z); } return self; }
static PyObject * Pyxmpz_inplace_ior(PyObject *self, PyObject *other) { mpz_t tempz; if(CHECK_MPZANY(other)) { mpz_ior(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(other)); Py_INCREF(self); return self; } if(PyIntOrLong_Check(other)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_ior(Pyxmpz_AS_MPZ(self), Pyxmpz_AS_MPZ(self), tempz); mpz_cloc(tempz); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_XMPZ_IXor_Slot(PyObject *self, PyObject *other) { mpz_t tempz; if(CHECK_MPZANY(other)) { mpz_xor(MPZ(self), MPZ(self), MPZ(other)); Py_INCREF(self); return self; } if(PyIntOrLong_Check(other)) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, other); mpz_xor(MPZ(self), MPZ(self), tempz); mpz_cloc(tempz); Py_INCREF(self); return self; } Py_RETURN_NOTIMPLEMENTED; }
static MPZ_Object * GMPy_MPZ_New(CTXT_Object *context) { MPZ_Object *result; if (in_gmpympzcache) { result = gmpympzcache[--in_gmpympzcache]; /* Py_INCREF does not set the debugging pointers, so need to use * _Py_NewReference instead. */ _Py_NewReference((PyObject*)result); } else { if (!(result = PyObject_New(MPZ_Object, &MPZ_Type))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } mpz_inoc(result->z); } result->hash_cache = -1; return result; }
static PyObject * GMPy_Integer_Pow(PyObject *b, PyObject *e, PyObject *m, CTXT_Object *context) { MPZ_Object *result = NULL, *tempb = NULL, *tempe = NULL, *tempm = NULL; int has_mod; /* Try to parse the modulus value first. */ if (m == Py_None) { has_mod = 0; } else { has_mod = 1; if (!IS_INTEGER(m)) { Py_RETURN_NOTIMPLEMENTED; } else { if (!(tempm = GMPy_MPZ_From_Integer(m, context))) { goto err; } } } result = GMPy_MPZ_New(context); tempb = GMPy_MPZ_From_Integer(b, context); tempe = GMPy_MPZ_From_Integer(e, context); if (!tempb || !tempe || !result) { goto err; } if (!has_mod) { /* When no modulo is present, the exponent must fit in unsigned long. */ unsigned long el; if (mpz_sgn(tempe->z) < 0) { VALUE_ERROR("pow() exponent cannot be negative"); goto err; } if (!mpz_fits_ulong_p(tempe->z)) { VALUE_ERROR("pow() outrageous exponent"); goto err; } el = mpz_get_ui(tempe->z); mpz_pow_ui(result->z, tempb->z, el); } else { /* Modulo is present. */ int sign; mpz_t mm, base, exp; sign = mpz_sgn(tempm->z); if (sign == 0) { VALUE_ERROR("pow() 3rd argument cannot be 0"); goto err; } mpz_inoc(mm); mpz_abs(mm, tempm->z); /* A negative exponent is allowed if inverse exists. */ if (mpz_sgn(tempe->z) < 0) { mpz_inoc(base); mpz_inoc(exp); if (!mpz_invert(base, tempb->z, mm)) { VALUE_ERROR("pow() base not invertible"); mpz_cloc(base); mpz_cloc(exp); mpz_cloc(mm); goto err; } else { mpz_abs(exp, tempe->z); } mpz_powm(result->z, base, exp, mm); mpz_cloc(base); mpz_cloc(exp); } else { mpz_powm(result->z, tempb->z, tempe->z, mm); } mpz_cloc(mm); /* Python uses a rather peculiar convention for negative modulos * If the modulo is negative, result should be in the interval * m < r <= 0 . */ if ((sign < 0) && (mpz_sgn(MPZ(result)) > 0)) { mpz_add(result->z, result->z, tempm->z); } } Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempm); return (PyObject*)result; err: Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempm); Py_DECREF((PyObject*)result); return NULL; }
static PyObject * GMPy_Complex_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context) { MPC_Object *tempb = NULL, *tempe = NULL, *result= NULL; MPFR_Object *tempf = NULL; MPZ_Object *tempz = NULL; if (mod != Py_None) { TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers"); return NULL; } CHECK_CONTEXT(context); result = GMPy_MPC_New(0, 0, context); tempb = GMPy_MPC_From_Complex(base, 1, 1, context); if (!result || !tempb) { goto err; } mpfr_clear_flags(); if (PyIntOrLong_Check(exp)) { int error; long temp_exp = GMPy_Integer_AsLongAndError(exp, &error); if (!error) { result->rc = mpc_pow_si(result->c, tempb->c, temp_exp, GET_MPC_ROUND(context)); } else { mpz_t tempzz; mpz_inoc(tempzz); mpz_set_PyIntOrLong(tempzz, exp); result->rc = mpc_pow_z(result->c, tempb->c, tempzz, GET_MPC_ROUND(context)); mpz_cloc(tempzz); } } else if (IS_INTEGER(exp)) { if (!(tempz = GMPy_MPZ_From_Integer(exp, context))) { goto err; } result->rc = mpc_pow_z(result->c, tempb->c, tempz->z, GET_MPC_ROUND(context)); } else if (IS_REAL(exp)) { if (!(tempf = GMPy_MPFR_From_Real(exp, 1, context))) { goto err; } result->rc = mpc_pow_fr(result->c, tempb->c, tempf->f, GET_MPC_ROUND(context)); } else { if (!(tempe = GMPy_MPC_From_Complex(exp, 1, 1, context))) { goto err; } result->rc = mpc_pow(result->c, tempb->c, tempe->c, GET_MPC_ROUND(context)); } GMPY_MPC_CLEANUP(result, context, "pow()"); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempf); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); return (PyObject*)result; err: Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempf); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); return NULL; }
static PyObject * GMPy_Real_Pow(PyObject *base, PyObject *exp, PyObject *mod, CTXT_Object *context) { MPFR_Object *tempb = NULL, *tempe = NULL, *result = NULL; MPZ_Object *tempz = NULL; MPC_Object *mpc_result = NULL; if (mod != Py_None) { TYPE_ERROR("pow() 3rd argument not allowed unless all arguments are integers"); return NULL; } CHECK_CONTEXT(context); result = GMPy_MPFR_New(0, context); tempb = GMPy_MPFR_From_Real(base, 1, context); if (!result || !tempb) { goto err; } mpfr_clear_flags(); if (PyIntOrLong_Check(exp)) { int error; long temp_exp = GMPy_Integer_AsLongAndError(exp, &error); if (!error) { result->rc = mpfr_pow_si(result->f, tempb->f, temp_exp, GET_MPFR_ROUND(context)); } else { mpz_t tempzz; mpz_inoc(tempzz); mpz_set_PyIntOrLong(tempzz, exp); result->rc = mpfr_pow_z(result->f, tempb->f, tempzz, GET_MPFR_ROUND(context)); mpz_cloc(tempzz); } } else if (IS_INTEGER(exp)) { if (!(tempz = GMPy_MPZ_From_Integer(exp, context))) { goto err; } result->rc = mpfr_pow_z(result->f, tempb->f, tempz->z, GET_MPFR_ROUND(context)); } else { if (!(tempe = GMPy_MPFR_From_Real(exp, 1, context))) { goto err; } result->rc = mpfr_pow(result->f, tempb->f, tempe->f, GET_MPFR_ROUND(context)); } /* If the result is NaN, check if a complex result works. */ if (result && mpfr_nanflag_p() && context->ctx.allow_complex) { mpc_result = (MPC_Object*)GMPy_Complex_Pow(base, exp, Py_None, context); if (!mpc_result || MPC_IS_NAN_P(mpc_result)) { Py_XDECREF((PyObject*)mpc_result); context->ctx.invalid = 1; GMPY_INVALID("pow() invalid operation"); goto err; } /* return a valid complex result */ Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempb); Py_XDECREF((PyObject*)result); return (PyObject*)mpc_result; } GMPY_MPFR_CLEANUP(result, context, "pow()"); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); return (PyObject*)result; err: Py_XDECREF((PyObject*)result); Py_XDECREF((PyObject*)tempz); Py_XDECREF((PyObject*)tempe); Py_XDECREF((PyObject*)tempb); return NULL; }
static PyObject * GMPy_MPZ_unpack(PyObject *self, PyObject *args) { mp_bitcnt_t nbits, total_bits, guard_bit, extra_bits, temp_bits; Py_ssize_t index = 0, lst_count, i, lst_ptr = 0; PyObject *result; mpz_t temp; mp_limb_t extra = 0; MPZ_Object *item, *tempx = NULL; CTXT_Object *context = NULL; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == -1 && PyErr_Occurred()) { return NULL; } if (!(tempx = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), context))) { TYPE_ERROR("unpack() requires 'int','int' arguments"); return NULL; } if (mpz_sgn(tempx->z) < 0) { VALUE_ERROR("unpack() requires x >= 0"); return NULL; } if (mpz_sgn(tempx->z) == 0) { total_bits = 0; } else { total_bits = mpz_sizeinbase(tempx->z, 2); } lst_count = total_bits / nbits; if ((total_bits % nbits) || !lst_count) { lst_count += 1; } if (!(result = PyList_New(lst_count))) { Py_DECREF((PyObject*)tempx); return NULL; } if (mpz_sgn(tempx->z) == 0) { if (!(item = GMPy_MPZ_New(context))) { Py_DECREF((PyObject*)tempx); Py_DECREF(result); return NULL; } mpz_set_ui(item->z, 0); PyList_SET_ITEM(result, 0, (PyObject*)item); Py_DECREF((PyObject*)tempx); return result; } mpz_inoc(temp); guard_bit = nbits + (2 * mp_bits_per_limb); extra_bits = 0; index = 0; while (lst_ptr < lst_count) { i = 0; temp_bits = 0; mpz_set_ui(temp, 0); mpz_setbit(temp, guard_bit); while (temp_bits + extra_bits < nbits) { temp->_mp_d[i++] = mpz_getlimbn(tempx->z, index++); temp_bits += mp_bits_per_limb; } mpz_clrbit(temp, guard_bit); mpz_mul_2exp(temp, temp, extra_bits); if (mpz_sgn(temp) == 0 && extra != 0) { mpz_set_ui(temp, 1); temp->_mp_d[0] = extra; } else { mpn_add_1(temp->_mp_d, temp->_mp_d, mpz_size(temp), extra); } temp_bits += extra_bits; while ((lst_ptr < lst_count) && (temp_bits >= nbits)) { if(!(item = GMPy_MPZ_New(context))) { mpz_cloc(temp); Py_DECREF((PyObject*)tempx); Py_DECREF(result); return NULL; } mpz_tdiv_r_2exp(item->z, temp, nbits); PyList_SET_ITEM(result, lst_ptr++, (PyObject*)item); mpz_tdiv_q_2exp(temp, temp, nbits); temp_bits -= nbits; } extra = mpz_getlimbn(temp, 0); extra_bits = temp_bits; } Py_DECREF((PyObject*)tempx); mpz_cloc(temp); return result; }
static PyObject * GMPy_Real_Sub(PyObject *x, PyObject *y, CTXT_Object *context) { MPFR_Object *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPFR_New(0, context))) return NULL; /* This only processes mpfr if the exponent is still in-bounds. Need * to handle the rare case at the end. */ if (MPFR_Check(x) && MPFR_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_sub(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); goto done; } if (MPFR_Check(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (!error) { mpfr_clear_flags(); result->rc = mpfr_sub_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context)); goto done; } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpfr_clear_flags(); result->rc = mpfr_sub_z(result->f, MPFR(x), tempz, GET_MPFR_ROUND(context)); mpz_cloc(tempz); goto done; } } if (CHECK_MPZANY(y)) { mpfr_clear_flags(); result->rc = mpfr_sub_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context)); 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_sub_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempy); goto done; } if (PyFloat_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_sub_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context)); goto done; } } if (MPFR_Check(y)) { if (PyIntOrLong_Check(x)) { int error; long temp = GMPy_Integer_AsLongAndError(x, &error); if (!error) { mpfr_clear_flags(); result->rc = mpfr_sub_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context)); mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context)); goto done; } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpfr_clear_flags(); result->rc = mpfr_sub_z(result->f, MPFR(y), tempz, GET_MPFR_ROUND(context)); mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context)); mpz_cloc(tempz); goto done; } } if (CHECK_MPZANY(x)) { mpfr_clear_flags(); result->rc = mpfr_sub_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context)); mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context)); goto done; } if (IS_RATIONAL(x)) { MPQ_Object *tempx; if (!(tempx = GMPy_MPQ_From_Number(x, context))) { Py_DECREF((PyObject*)result); return NULL; } mpfr_clear_flags(); result->rc = mpfr_sub_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context)); mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); goto done; } if (PyFloat_Check(x)) { mpfr_clear_flags(); result->rc = mpfr_sub_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context)); mpfr_neg(result->f, result->f, GET_MPFR_ROUND(context)); goto done; } } 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_sub(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); goto done; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; done: GMPY_MPFR_CLEANUP(result, context, "subtraction"); return (PyObject*)result; }
static PyObject * GMPy_Real_Add(PyObject *x, PyObject *y, CTXT_Object *context) { MPFR_Object *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPFR_New(0, context))) return NULL; if (MPFR_Check(x) && MPFR_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_add(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); goto done; } if (MPFR_Check(x)) { if (PyIntOrLong_Check(y)) { mpz_t tempz; long temp; int error; temp = GMPy_Integer_AsLongAndError(y, &error); if (error) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpfr_clear_flags(); result->rc = mpfr_add_z(result->f, MPFR(x), tempz, GET_MPFR_ROUND(context)); mpz_cloc(tempz); goto done; } else { mpfr_clear_flags(); result->rc = mpfr_add_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context)); goto done; } } if (CHECK_MPZANY(y)) { mpfr_clear_flags(); result->rc = mpfr_add_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context)); 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_add_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempy); goto done; } if (PyFloat_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_add_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context)); goto done; } } if (MPFR_Check(y)) { if (PyIntOrLong_Check(x)) { mpz_t tempz; long temp; int error; temp = GMPy_Integer_AsLongAndError(x, &error); if (error) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpfr_clear_flags(); result->rc = mpfr_add_z(result->f, MPFR(y), tempz, GET_MPFR_ROUND(context)); mpz_cloc(tempz); goto done; } else { mpfr_clear_flags(); result->rc = mpfr_add_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context)); goto done; } } if (CHECK_MPZANY(x)) { mpfr_clear_flags(); result->rc = mpfr_add_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context)); goto done; } if (IS_RATIONAL(x)) { MPQ_Object *tempx; if (!(tempx = GMPy_MPQ_From_Number(x, context))) { Py_DECREF((PyObject*)result); return NULL; } mpfr_clear_flags(); result->rc = mpfr_add_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); goto done; } if (PyFloat_Check(x)) { mpfr_clear_flags(); result->rc = mpfr_add_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context)); goto done; } } 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_add(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); goto done; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; done: GMPY_MPFR_CLEANUP(result, context, "addition"); return (PyObject*)result; }
static PyObject * GMPy_Integer_DivMod(PyObject *x, PyObject *y, CTXT_Object *context) { PyObject *result; MPZ_Object *tempx, *tempy, *rem, *quo; mpz_t tempz; long temp; int error; result = PyTuple_New(2); rem = GMPy_MPZ_New(context); quo = GMPy_MPZ_New(context); if (!result || !rem || !quo) { Py_XDECREF((PyObject*)rem); Py_XDECREF((PyObject*)quo); Py_XDECREF(result); return NULL; } if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { temp = GMPy_Integer_AsLongAndError(y, &error); if (error) { mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpz_fdiv_qr(quo->z, rem->z, MPZ(x), tempz); mpz_cloc(tempz); } else if (temp > 0) { mpz_fdiv_qr_ui(quo->z, rem->z, MPZ(x), temp); } else if (temp == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rem); Py_DECREF((PyObject*)quo); Py_DECREF(result); return NULL; } else { mpz_cdiv_qr_ui(quo->z, rem->z, MPZ(x), -temp); mpz_neg(quo->z, quo->z); } PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rem); Py_DECREF((PyObject*)quo); Py_DECREF(result); return NULL; } mpz_fdiv_qr(quo->z, rem->z, MPZ(x), MPZ(y)); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } } if (CHECK_MPZANY(y) && PyIntOrLong_Check(x)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)rem); Py_DECREF((PyObject*)quo); Py_DECREF(result); return NULL; } mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpz_fdiv_qr(quo->z, rem->z, tempz, MPZ(y)); mpz_cloc(tempz); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return (PyObject*)result; } if (IS_INTEGER(x) && IS_INTEGER(y)) { tempx = GMPy_MPZ_From_Integer(x, context); tempy = GMPy_MPZ_From_Integer(y, context); if (!tempx || !tempy) { SYSTEM_ERROR("could not convert Integer to mpz"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)rem); Py_DECREF((PyObject*)quo); Py_DECREF(result); return NULL; } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("division or modulo by zero"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)rem); Py_DECREF((PyObject*)quo); Py_DECREF(result); return NULL; } mpz_fdiv_qr(quo->z, rem->z, tempx->z, tempy->z); 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; }
static PyObject * GMPy_MPZ_pack(PyObject *self, PyObject *args) { mp_bitcnt_t nbits, total_bits, tempx_bits; Py_ssize_t index, lst_count, i, temp_bits, limb_count; PyObject *lst; mpz_t temp; MPZ_Object *result, *tempx = 0; CTXT_Object *context = NULL; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } nbits = mp_bitcnt_t_From_Integer(PyTuple_GET_ITEM(args, 1)); if (nbits == -1 && PyErr_Occurred()) { return NULL; } if (!PyList_Check(PyTuple_GET_ITEM(args, 0))) { TYPE_ERROR("pack() requires 'list','int' arguments"); return NULL; } if (!(result = GMPy_MPZ_New(context))) return NULL; lst = PyTuple_GET_ITEM(args, 0); lst_count = PyList_GET_SIZE(lst); total_bits = nbits * lst_count; if ((total_bits / lst_count) != nbits) { VALUE_ERROR("result too large to store in an 'mpz'"); return NULL; } mpz_set_ui(result->z, 0); mpz_setbit(result->z, total_bits + (mp_bits_per_limb * 2)); mpz_inoc(temp); mpz_set_ui(temp, 0); limb_count = 0; tempx_bits = 0; for (index = 0; index < lst_count; index++) { if (!(tempx = GMPy_MPZ_From_Integer(PyList_GetItem(lst, index), context)) || (mpz_sgn(tempx->z) < 0) || (mpz_sizeinbase(tempx->z,2) > (size_t)nbits)) { TYPE_ERROR("pack() requires list elements be positive integers < 2^n bits"); mpz_cloc(temp); Py_XDECREF((PyObject*)tempx); Py_DECREF((PyObject*)result); return NULL; } mpz_mul_2exp(tempx->z, tempx->z, tempx_bits); mpz_add(temp, temp, tempx->z); tempx_bits += nbits; i = 0; temp_bits = mpz_sizeinbase(temp, 2) * mpz_sgn(temp); while (tempx_bits >= mp_bits_per_limb) { if (temp_bits > 0) { result->z->_mp_d[limb_count] = mpz_getlimbn(temp, i); } i += 1; tempx_bits -= mp_bits_per_limb; limb_count += 1; temp_bits -= mp_bits_per_limb; } if (temp_bits > 0) { mpz_tdiv_q_2exp(temp, temp, mp_bits_per_limb * i); } else { mpz_set_ui(temp, 0); } Py_DECREF((PyObject*)tempx); } result->z->_mp_d[limb_count] = mpz_getlimbn(temp, 0); mpz_clrbit(result->z, total_bits + (mp_bits_per_limb * 2)); mpz_cloc(temp); return (PyObject*)result; }
static PyObject * GMPY_mpz_lucasv_mod(PyObject *self, PyObject *args) { /* Adaptation of algorithm found in http://joye.site88.net/papers/JQ96lucas.pdf * calculate v[k] (modulo n) of Lucas V sequence for p,q. * Note: p^2-4q=0 is not tested, not a proper Lucas sequence!! */ PympzObject *result = 0, *p, *q, *k, *n; size_t s = 0, j = 0; mpz_t vl, vh, ql, qh, tmp; if (PyTuple_Size(args) != 4) { TYPE_ERROR("lucasv_mod() requires 4 integer arguments"); return NULL; } /* Take advantage of the cache of mpz_t objects maintained by GMPY2 to * avoid memory allocations. */ mpz_inoc(vl); mpz_inoc(vh); mpz_inoc(ql); mpz_inoc(qh); mpz_inoc(tmp); p = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); q = Pympz_From_Integer(PyTuple_GET_ITEM(args, 1)); k = Pympz_From_Integer(PyTuple_GET_ITEM(args, 2)); n = Pympz_From_Integer(PyTuple_GET_ITEM(args, 3)); if (!p || !q || !k || !n) { TYPE_ERROR("lucasv_mod() requires 4 integer arguments"); goto cleanup; } /* Check if p*p - 4*q == 0. */ mpz_mul(tmp, p->z, p->z); mpz_mul_ui(qh, q->z, 4); mpz_sub(tmp, tmp, qh); if (mpz_sgn(tmp) == 0) { VALUE_ERROR("invalid values for p,q in lucasv_mod()"); goto cleanup; } /* Check if k < 0. */ if (mpz_sgn(k->z) < 0) { VALUE_ERROR("invalid value for k in lucasv_mod()"); goto cleanup; } /* Check if n > 0. */ if (mpz_sgn(n->z) <= 0) { VALUE_ERROR("invalid value for n in lucasv_mod()"); goto cleanup; } mpz_set_si(vl, 2); mpz_set(vh, p->z); mpz_set_si(ql, 1); mpz_set_si(qh, 1); mpz_set_si(tmp,0); s = mpz_scan1(k->z, 0); for (j = mpz_sizeinbase(k->z,2)-1; j >= s+1; j--) { /* ql = ql*qh (mod n) */ mpz_mul(ql, ql, qh); mpz_mod(ql, ql, n->z); if (mpz_tstbit(k->z,j) == 1) { /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql (mod n) */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* vh = vh*vh - 2*qh (mod n) */ mpz_mul(vh, vh, vh); mpz_mul_si(tmp, qh, 2); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); } else { /* qh = ql */ mpz_set(qh, ql); /* vh = vh*vl - p*ql (mod n) */ mpz_mul(vh, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vh, vh, tmp); mpz_mod(vh, vh, n->z); /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); } } /* ql = ql*qh */ mpz_mul(ql, ql, qh); /* qh = ql*q */ mpz_mul(qh, ql, q->z); /* vl = vh*vl - p*ql */ mpz_mul(vl, vh, vl); mpz_mul(tmp, ql, p->z); mpz_sub(vl, vl, tmp); /* ql = ql*qh */ mpz_mul(ql, ql, qh); for (j = 1; j <= s; j++) { /* vl = vl*vl - 2*ql (mod n) */ mpz_mul(vl, vl, vl); mpz_mul_si(tmp, ql, 2); mpz_sub(vl, vl, tmp); mpz_mod(vl, vl, n->z); /* ql = ql*ql (mod n) */ mpz_mul(ql, ql, ql); mpz_mod(ql, ql, n->z); } if (!(result = (PympzObject*)Pympz_new())) goto cleanup; /* vl contains our return value */ mpz_mod(result->z, vl, n->z); cleanup: mpz_cloc(vl); mpz_cloc(vh); mpz_cloc(ql); mpz_cloc(qh); mpz_cloc(tmp); Py_XDECREF((PyObject*)p); Py_XDECREF((PyObject*)q); Py_XDECREF((PyObject*)k); Py_XDECREF((PyObject*)n); return (PyObject*)result; }
static PyObject * GMPy_Integer_DivMod(PyObject *x, PyObject *y, CTXT_Object *context) { PyObject *result = NULL; MPZ_Object *tempx = NULL, *tempy = NULL, *rem = NULL, *quo = NULL; if (!(result = PyTuple_New(2)) || !(rem = GMPy_MPZ_New(context)) || !(quo = GMPy_MPZ_New(context))) { /* LCOV_EXCL_START */ goto error; /* LCOV_EXCL_STOP */ } if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (error) { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpz_fdiv_qr(quo->z, rem->z, MPZ(x), tempz); mpz_cloc(tempz); } else if (temp > 0) { mpz_fdiv_qr_ui(quo->z, rem->z, MPZ(x), temp); } else if (temp == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } else { mpz_cdiv_qr_ui(quo->z, rem->z, MPZ(x), -temp); mpz_neg(quo->z, quo->z); } PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } mpz_fdiv_qr(quo->z, rem->z, MPZ(x), MPZ(y)); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return result; } } if (CHECK_MPZANY(y) && PyIntOrLong_Check(x)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpz_fdiv_qr(quo->z, rem->z, tempz, MPZ(y)); mpz_cloc(tempz); PyTuple_SET_ITEM(result, 0, (PyObject*)quo); PyTuple_SET_ITEM(result, 1, (PyObject*)rem); return (PyObject*)result; } } if (IS_INTEGER(x) && IS_INTEGER(y)) { if (!(tempx = GMPy_MPZ_From_Integer(x, context)) || !(tempy = GMPy_MPZ_From_Integer(y, context))) { /* LCOV_EXCL_START */ goto error; /* LCOV_EXCL_STOP */ } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("division or modulo by zero"); goto error; } mpz_fdiv_qr(quo->z, rem->z, tempx->z, tempy->z); 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_Integer_DivMod()."); /* LCOV_EXCL_STOP */ error: Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_XDECREF((PyObject*)rem); Py_XDECREF((PyObject*)quo); Py_XDECREF(result); return NULL; }
static PyObject * GMPy_MPZ_Function_Divm(PyObject *self, PyObject *args) { MPZ_Object *result = NULL, *num = NULL, *den = NULL, *mod = NULL; mpz_t numz, denz, modz, gcdz; int ok = 0; if (PyTuple_GET_SIZE(args) != 3) { TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments"); return NULL; } if (!(result = GMPy_MPZ_New(NULL))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } if (!(num = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 0), NULL)) || !(den = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 1), NULL)) || !(mod = GMPy_MPZ_From_Integer(PyTuple_GET_ITEM(args, 2), NULL))) { TYPE_ERROR("divm() requires 'mpz','mpz','mpz' arguments"); Py_XDECREF((PyObject*)num); Py_XDECREF((PyObject*)den); Py_XDECREF((PyObject*)mod); Py_DECREF((PyObject*)result); return NULL; } /* Make copies so we don't destroy the input. */ mpz_inoc(numz); mpz_inoc(denz); mpz_inoc(modz); mpz_set(numz, num->z); mpz_set(denz, den->z); mpz_set(modz, mod->z); Py_DECREF((PyObject*)num); Py_DECREF((PyObject*)den); Py_DECREF((PyObject*)mod); if (mpz_invert(result->z, denz, modz)) { /* inverse exists */ ok = 1; } else { /* last-ditch attempt: do num, den AND mod have a gcd>1 ? */ mpz_inoc(gcdz); mpz_gcd(gcdz, numz, denz); mpz_gcd(gcdz, gcdz, modz); mpz_divexact(numz, numz, gcdz); mpz_divexact(denz, denz, gcdz); mpz_divexact(modz, modz, gcdz); mpz_cloc(gcdz); ok = mpz_invert(result->z, denz, modz); } if (ok) { mpz_mul(result->z, result->z, numz); mpz_mod(result->z, result->z, modz); mpz_cloc(numz); mpz_cloc(denz); mpz_cloc(modz); return (PyObject*)result; } else { ZERO_ERROR("not invertible"); mpz_cloc(numz); mpz_cloc(denz); mpz_cloc(modz); Py_DECREF((PyObject*)result); return NULL; } }
static PyObject * GMPy_Integer_Mod(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result; CHECK_CONTEXT(context); if (!(result = GMPy_MPZ_New(context))) return NULL; if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (!error) { if (temp > 0) { mpz_fdiv_r_ui(result->z, MPZ(x), temp); } else if (temp == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } else { mpz_cdiv_r_ui(result->z, MPZ(x), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpz_fdiv_r(result->z, MPZ(x), tempz); mpz_cloc(tempz); } return (PyObject*)result; } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_r(result->z, MPZ(x), MPZ(y)); return (PyObject*)result; } } if (CHECK_MPZANY(y)) { if (mpz_sgn(MPZ(y)) == 0) { ZERO_ERROR("division or modulo by zero"); Py_DECREF((PyObject*)result); return NULL; } if (PyIntOrLong_Check(x)) { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpz_fdiv_r(result->z, tempz, MPZ(y)); mpz_cloc(tempz); return (PyObject*)result; } } if (IS_INTEGER(x) && IS_INTEGER(y)) { MPZ_Object *tempx, *tempy; tempx = GMPy_MPZ_From_Integer(x, context); tempy = GMPy_MPZ_From_Integer(y, context); if (!tempx || !tempy) { SYSTEM_ERROR("could not convert Integer to mpz"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } if (mpz_sgn(tempy->z) == 0) { ZERO_ERROR("division or modulo by zero"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpz_fdiv_r(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_Real_Mul(PyObject *x, PyObject *y, CTXT_Object *context) { MPFR_Object *result = NULL; CHECK_CONTEXT(context); if (!(result = GMPy_MPFR_New(0, context))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } if (MPFR_Check(x) && MPFR_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_mul(result->f, MPFR(x), MPFR(y), GET_MPFR_ROUND(context)); goto done; } if (MPFR_Check(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (!error) { mpfr_clear_flags(); result->rc = mpfr_mul_si(result->f, MPFR(x), temp, GET_MPFR_ROUND(context)); goto done; } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpfr_clear_flags(); result->rc = mpfr_mul_z(result->f, MPFR(x), tempz, GET_MPFR_ROUND(context)); mpz_cloc(tempz); goto done; } } if (CHECK_MPZANY(y)) { mpfr_clear_flags(); result->rc = mpfr_mul_z(result->f, MPFR(x), MPZ(y), GET_MPFR_ROUND(context)); goto done; } if (IS_RATIONAL(y)) { MPQ_Object *tempy = NULL; if (!(tempy = GMPy_MPQ_From_Number(y, context))) { /* LCOV_EXCL_START */ Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ } mpfr_clear_flags(); result->rc = mpfr_mul_q(result->f, MPFR(x), tempy->q, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempy); goto done; } if (PyFloat_Check(y)) { mpfr_clear_flags(); result->rc = mpfr_mul_d(result->f, MPFR(x), PyFloat_AS_DOUBLE(y), GET_MPFR_ROUND(context)); goto done; } } if (MPFR_Check(y)) { if (PyIntOrLong_Check(x)) { int error; long temp = GMPy_Integer_AsLongAndError(x, &error); if (!error) { mpfr_clear_flags(); result->rc = mpfr_mul_si(result->f, MPFR(y), temp, GET_MPFR_ROUND(context)); goto done; } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpfr_clear_flags(); result->rc = mpfr_mul_z(result->f, MPFR(y), tempz, GET_MPFR_ROUND(context)); mpz_cloc(tempz); goto done; } } if (CHECK_MPZANY(x)) { mpfr_clear_flags(); result->rc = mpfr_mul_z(result->f, MPFR(y), MPZ(x), GET_MPFR_ROUND(context)); goto done; } if (IS_RATIONAL(x)) { MPQ_Object *tempx = NULL; if (!(tempx = GMPy_MPQ_From_Number(x, context))) { /* LCOV_EXCL_START */ Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ } mpfr_clear_flags(); result->rc = mpfr_mul_q(result->f, MPFR(y), tempx->q, GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); goto done; } if (PyFloat_Check(x)) { mpfr_clear_flags(); result->rc = mpfr_mul_d(result->f, MPFR(y), PyFloat_AS_DOUBLE(x), GET_MPFR_ROUND(context)); goto done; } } if (IS_REAL(x) && IS_REAL(y)) { MPFR_Object *tempx = NULL, *tempy = NULL; if (!(tempx = GMPy_MPFR_From_Real(x, 1, context)) || !(tempy = GMPy_MPFR_From_Real(y, 1, context))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ } mpfr_clear_flags(); result->rc = mpfr_mul(result->f, MPFR(tempx), MPFR(tempy), GET_MPFR_ROUND(context)); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); goto done; } /* LCOV_EXCL_START */ Py_DECREF((PyObject*)result); SYSTEM_ERROR("Internal error in GMPy_Real_Mul()."); return NULL; /* LCOV_EXCL_STOP */ done: _GMPy_MPFR_Cleanup(&result, context); return (PyObject*)result; }
static PyObject * GMPy_Integer_Add(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result; if (!(result = GMPy_MPZ_New(context))) return NULL; if (CHECK_MPZANY(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (!error) { if (temp >= 0) { mpz_add_ui(result->z, MPZ(x), temp); } else { mpz_sub_ui(result->z, MPZ(x), -temp); } } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpz_add(result->z, MPZ(x), tempz); mpz_cloc(tempz); } return (PyObject*)result; } if (CHECK_MPZANY(y)) { mpz_add(result->z, MPZ(x), MPZ(y)); return (PyObject*)result; } } if (CHECK_MPZANY(y)) { if (PyIntOrLong_Check(x)) { int error; long temp = GMPy_Integer_AsLongAndError(x, &error); if (!error) { if (temp >= 0) { mpz_add_ui(result->z, MPZ(y), temp); } else { mpz_sub_ui(result->z, MPZ(y), -temp); } return (PyObject*)result; } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpz_add(result->z, MPZ(y), tempz); mpz_cloc(tempz); return (PyObject*)result; } } } if (IS_INTEGER(x) && IS_INTEGER(y)) { MPZ_Object *tempx, *tempy; tempx = GMPy_MPZ_From_Integer(x, context); tempy = GMPy_MPZ_From_Integer(y, context); if (!tempx || !tempy) { Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; } mpz_add(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } Py_DECREF((PyObject*)result); Py_RETURN_NOTIMPLEMENTED; }
static PyObject * GMPy_Integer_Mul(PyObject *x, PyObject *y, CTXT_Object *context) { MPZ_Object *result = NULL; if (!(result = GMPy_MPZ_New(context))) { /* LCOV_EXCL_START */ return NULL; /* LCOV_EXCL_STOP */ } if (MPZ_Check(x)) { if (PyIntOrLong_Check(y)) { int error; long temp = GMPy_Integer_AsLongAndError(y, &error); if (!error) { mpz_mul_si(result->z, MPZ(x), temp); } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, y); mpz_mul(result->z, MPZ(x), tempz); mpz_cloc(tempz); } return (PyObject*)result; } if (MPZ_Check(y)) { mpz_mul(result->z, MPZ(x), MPZ(y)); return (PyObject*)result; } } if (MPZ_Check(y)) { if (PyIntOrLong_Check(x)) { int error; long temp = GMPy_Integer_AsLongAndError(x, &error); if (!error) { mpz_mul_si(result->z, MPZ(y), temp); } else { mpz_t tempz; mpz_inoc(tempz); mpz_set_PyIntOrLong(tempz, x); mpz_mul(result->z, MPZ(y), tempz); mpz_cloc(tempz); } return (PyObject*)result; } } if (IS_INTEGER(x) && IS_INTEGER(y)) { MPZ_Object *tempx = NULL, *tempy = NULL; if (!(tempx = GMPy_MPZ_From_Integer(x, context)) || !(tempy = GMPy_MPZ_From_Integer(y, context))) { /* LCOV_EXCL_START */ Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ } mpz_mul(result->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); return (PyObject*)result; } /* LCOV_EXCL_START */ SYSTEM_ERROR("Internal error in GMPy_Integer_Mul()."); Py_DECREF((PyObject*)result); return NULL; /* LCOV_EXCL_STOP */ }