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;
}
示例#2
0
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;
}
示例#4
0
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);
}
示例#5
0
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;
}
示例#6
0
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
    }
}