static PyObject * Pygmpy_t_divmod(PyObject *self, PyObject *args) { PyObject *x, *y, *result; PympzObject *q, *r, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); CREATE_TWO_MPZ_TUPLE(q, r, result); if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("t_divmod() division by 0"); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_tdiv_qr(q->z, r->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("t_divmod() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("t_divmod() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); Py_DECREF((PyObject*)r); Py_DECREF(result); return NULL; } mpz_tdiv_qr(q->z, r->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } PyTuple_SET_ITEM(result, 0, (PyObject*)q); PyTuple_SET_ITEM(result, 1, (PyObject*)r); return result; }
static PyObject * Pyxmpz_inplace_pow(PyObject *in_b, PyObject *in_e, PyObject *in_m) { PympzObject *e = 0; mpir_ui el; if (!Pyxmpz_Check(in_b)) { PyErr_SetString(PyExc_TypeError, "base must be an Integer"); return NULL; } if (in_m != Py_None) { SYSTEM_ERROR("modulo not expected"); return NULL; } e = Pympz_From_Integer(in_e); if (!e) { TYPE_ERROR("expected an integer exponent"); return NULL; } if (mpz_sgn(e->z) < 0) { VALUE_ERROR("xmpz.pow with negative power"); Py_DECREF((PyObject*)e); return NULL; } if (!mpz_fits_ui_p(e->z)) { VALUE_ERROR("xmpz.pow outrageous exponent"); Py_DECREF((PyObject*)e); return NULL; } el = mpz_get_ui(e->z); mpz_pow_ui(Pyxmpz_AS_MPZ(in_b), Pyxmpz_AS_MPZ(in_b), el); Py_DECREF((PyObject*)e); Py_INCREF((PyObject*)in_b); return (PyObject*)in_b; }
static PyObject * Pygmpy_c_div(PyObject *self, PyObject *args) { PyObject *x, *y; PympzObject *q, *tempx, *tempy; if (PyTuple_GET_SIZE(args) != 2) { TYPE_ERROR("c_div() requires 'mpz','mpz' arguments"); return NULL; } x = PyTuple_GET_ITEM(args, 0); y = PyTuple_GET_ITEM(args, 1); if (!(q = Pympz_new())) return NULL; if (CHECK_MPZANY(x) && CHECK_MPZANY(y)) { if (mpz_sgn(Pympz_AS_MPZ(y)) == 0) { ZERO_ERROR("c_div() division by 0"); Py_DECREF((PyObject*)q); return NULL; } mpz_cdiv_q(q->z, Pympz_AS_MPZ(x), Pympz_AS_MPZ(y)); } else { tempx = Pympz_From_Integer(x); tempy = Pympz_From_Integer(y); if (!tempx || !tempy) { TYPE_ERROR("c_div() requires 'mpz','mpz' arguments"); Py_XDECREF((PyObject*)tempx); Py_XDECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } if (mpz_sgn(Pympz_AS_MPZ(tempy)) == 0) { ZERO_ERROR("c_div() division by 0"); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); Py_DECREF((PyObject*)q); return NULL; } mpz_cdiv_q(q->z, tempx->z, tempy->z); Py_DECREF((PyObject*)tempx); Py_DECREF((PyObject*)tempy); } return (PyObject*)q; }
static PyObject * Pympz_mpmath_create(PyObject *self, PyObject *args) { long sign; mpir_si bc, shift, zbits, carry = 0, prec = 0; PyObject *exp = 0, *newexp = 0, *newexp2 = 0, *tmp = 0; PympzObject *man = 0, *upper = 0, *lower = 0; 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 = SI_From_Integer(PyTuple_GET_ITEM(args, 2)); if (prec == -1 && PyErr_Occurred()) return NULL; prec = ABS(prec); case 2: exp = PyTuple_GET_ITEM(args, 1); case 1: man = Pympz_From_Integer(PyTuple_GET_ITEM(args, 0)); 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 = (PympzObject*)Pympz_new(); lower = (PympzObject*)Pympz_new(); 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_FromSI(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_FromSI(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); }
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 * Pympq_pow(PyObject *base, PyObject *exp, PyObject *m) { PympqObject *rq, *tempbq; PympzObject *tempez; #ifdef WITHMPFR PympfrObject *rf, *tempbf, *tempef; #endif int esign, bsign; mpir_si tempexp; if ((PyObject*)m != Py_None) { TYPE_ERROR("mpq.pow() no modulo allowed"); return NULL; } /* Only support mpq**int. Everything else gets converted to mpf. */ if (isRational(base) && isInteger(exp)) { tempbq = Pympq_From_Rational(base); tempez = Pympz_From_Integer(exp); if (!tempbq || !tempez) { 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*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } if (!(rq = (PympqObject*)Pympq_new())) { Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } esign = mpz_sgn(tempez->z); if (esign == 0) { mpq_set_si(rq->q, 1, 1); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return (PyObject*)rq; } bsign = mpq_sgn(tempbq->q); if (esign < 0) { if (bsign == 0) { ZERO_ERROR("mpq.pow() 0 base to negative exponent"); Py_DECREF((PyObject*)rq); Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return NULL; } if (bsign < 0) { mpz_neg(mpq_numref(rq->q), mpq_denref(tempbq->q)); } else { mpz_set(mpq_numref(rq->q), mpq_denref(tempbq->q)); } mpz_abs(mpq_denref(rq->q), mpq_numref(tempbq->q)); tempexp = -mpz_get_si(tempez->z); } else { mpq_set(rq->q, tempbq->q); tempexp = mpz_get_si(tempez->z); } if (tempexp>1) { mpz_pow_ui(mpq_numref(rq->q), mpq_numref(rq->q), tempexp); mpz_pow_ui(mpq_denref(rq->q), mpq_denref(rq->q), tempexp); } Py_DECREF((PyObject*)tempbq); Py_DECREF((PyObject*)tempez); return (PyObject*)rq; } else { #ifdef WITHMPFR tempbf = Pympfr_From_Real(base, 0); tempef = Pympfr_From_Real(exp, 0); rf = (PympfrObject*)Pympfr_new(0); if (!tempbf || !tempef || !rf) { TYPE_ERROR("mpq.pow() unsupported operands"); Py_XDECREF((PyObject*)tempbf); Py_XDECREF((PyObject*)tempef); Py_XDECREF((PyObject*)rf); return NULL; } rf->rc = mpfr_pow(rf->f, tempbf->f, tempef->f, context->ctx.mpfr_round); Py_DECREF((PyObject*)tempbf); Py_DECREF((PyObject*)tempef); return (PyObject*)rf; #else TYPE_ERROR("mpq.pow() unsupported operands"); return NULL; #endif } }