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 } }
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 * Pygmpy_mpq(PyObject *self, PyObject *args, PyObject *keywds) { PympqObject *result = 0, *temp; PyObject *n = 0, *m = 0; int base = 10; Py_ssize_t argc; static char *kwlist[] = {"s", "base", NULL }; argc = PyTuple_Size(args); if (argc > 2) { TYPE_ERROR("mpq() requires 0, 1 or 2 arguments"); return NULL; } if (argc == 0) { if ((result = (PympqObject*)Pympq_new())) { mpq_set_ui(result->q, 0, 0); } return (PyObject*)result; } n = PyTuple_GetItem(args, 0); if (PyStrOrUnicode_Check(n)) { /* keyword base is legal */ if (PyArg_ParseTupleAndKeywords(args, keywds, "O|i", kwlist, &n, &base)) { if ((base!=0) && ((base<2)||(base>62))) { VALUE_ERROR("base for mpq() must be 0 or in the " "interval 2 ... 62"); } else { result = Pympq_From_PyStr(n, base); } } return (PyObject*)result; } if (isDecimal(n)) { return (PyObject*)Pympq_From_Decimal(n); } if (argc == 2) m = PyTuple_GetItem(args, 1); #ifdef WITHMPFR if (!isReal(n) || (m && !isReal(m))) { #else if (!(isRational(n) || PyFloat_Check(n)) || (m && !(isRational(m) || PyFloat_Check(m)))) { #endif TYPE_ERROR("mpq() requires numeric or string argument"); return NULL; } /* should now have one or two numeric values */ result = Pympq_From_Number(n); if (!result && !PyErr_Occurred()) { TYPE_ERROR("mpq() requires numeric or string argument"); return NULL; } if (m) { temp = Pympq_From_Number(m); if (!temp && !PyErr_Occurred()) { TYPE_ERROR("mpq() requires numeric or string argument"); Py_DECREF((PyObject*)result); return NULL; } if (mpq_sgn(temp->q) == 0) { ZERO_ERROR("zero denominator in 'mpq'"); Py_DECREF((PyObject*)result); Py_DECREF((PyObject*)temp); return NULL; } mpq_div(result->q, result->q, temp->q); Py_DECREF((PyObject*)temp); } return (PyObject*)result; } /* Functions that operate strictly on mpq. */ /* produce digits for an mpq in requested base, default 10 */ PyDoc_STRVAR(doc_qdigitsm, "x.digits([base=10]) -> string\n\n" "Return a Python string representing x in the given base (2 to 62,\n" "default is 10). A leading '-' is present if x<0, but no leading '+'\n" "is present if x>=0.\n"); static PyObject * Pympq_digits(PyObject *self, PyObject *args) { int base = 10; PyObject *result; SELF_MPQ_ONE_ARG("|i", &base); result = Pympq_To_PyStr((PympqObject*)self, base, 0); Py_DECREF(self); return result; }