return (PyObject *) pylong;
}
- Py_XSETREF(exponent, long_methods->nb_power(tmp, exponent, Py_None));
+/* Convert a Decimal to its exact integer ratio representation. */
+static PyObject *
+dec_as_integer_ratio(PyObject *self, PyObject *args UNUSED)
+{
+ PyObject *numerator = NULL;
+ PyObject *denominator = NULL;
+ PyObject *exponent = NULL;
+ PyObject *result = NULL;
+ PyObject *tmp;
+ mpd_ssize_t exp;
+ PyObject *context;
+ uint32_t status = 0;
+ PyNumberMethods *long_methods = PyLong_Type.tp_as_number;
+
+ if (mpd_isspecial(MPD(self))) {
+ if (mpd_isnan(MPD(self))) {
+ PyErr_SetString(PyExc_ValueError,
+ "cannot convert NaN to integer ratio");
+ }
+ else {
+ PyErr_SetString(PyExc_OverflowError,
+ "cannot convert Infinity to integer ratio");
+ }
+ return NULL;
+ }
+
+ CURRENT_CONTEXT(context);
+
+ tmp = dec_alloc();
+ if (tmp == NULL) {
+ return NULL;
+ }
+
+ if (!mpd_qcopy(MPD(tmp), MPD(self), &status)) {
+ Py_DECREF(tmp);
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ exp = mpd_iszero(MPD(tmp)) ? 0 : MPD(tmp)->exp;
+ MPD(tmp)->exp = 0;
+
+ /* context and rounding are unused here: the conversion is exact */
+ numerator = dec_as_long(tmp, context, MPD_ROUND_FLOOR);
+ Py_DECREF(tmp);
+ if (numerator == NULL) {
+ goto error;
+ }
+
+ exponent = PyLong_FromSsize_t(exp < 0 ? -exp : exp);
+ if (exponent == NULL) {
+ goto error;
+ }
+
+ tmp = PyLong_FromLong(10);
+ if (tmp == NULL) {
+ goto error;
+ }
+
- Py_XSETREF(numerator, long_methods->nb_multiply(numerator, exponent));
++ Py_SETREF(exponent, long_methods->nb_power(tmp, exponent, Py_None));
+ Py_DECREF(tmp);
+ if (exponent == NULL) {
+ goto error;
+ }
+
+ if (exp >= 0) {
- Py_XSETREF(numerator, long_methods->nb_floor_divide(numerator, tmp));
- Py_XSETREF(denominator, long_methods->nb_floor_divide(denominator, tmp));
++ Py_SETREF(numerator, long_methods->nb_multiply(numerator, exponent));
+ if (numerator == NULL) {
+ goto error;
+ }
+ denominator = PyLong_FromLong(1);
+ if (denominator == NULL) {
+ goto error;
+ }
+ }
+ else {
+ denominator = exponent;
+ exponent = NULL;
+ tmp = _PyLong_GCD(numerator, denominator);
+ if (tmp == NULL) {
+ goto error;
+ }
++ Py_SETREF(numerator, long_methods->nb_floor_divide(numerator, tmp));
++ Py_SETREF(denominator, long_methods->nb_floor_divide(denominator, tmp));
+ Py_DECREF(tmp);
+ if (numerator == NULL || denominator == NULL) {
+ goto error;
+ }
+ }
+
+ result = PyTuple_Pack(2, numerator, denominator);
+
+
+error:
+ Py_XDECREF(exponent);
+ Py_XDECREF(denominator);
+ Py_XDECREF(numerator);
+ return result;
+}
+
static PyObject *
PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds)
{
to be truncated by PyLong_FromDouble(). */
numerator = PyLong_FromDouble(float_part);
- if (numerator == NULL) goto error;
+ if (numerator == NULL)
+ goto error;
+ denominator = PyLong_FromLong(1);
+ if (denominator == NULL)
+ goto error;
+ py_exponent = PyLong_FromLong(Py_ABS(exponent));
+ if (py_exponent == NULL)
+ goto error;
/* fold in 2**exponent */
- denominator = PyLong_FromLong(1);
- py_exponent = PyLong_FromLong(labs((long)exponent));
- if (py_exponent == NULL) goto error;
- INPLACE_UPDATE(py_exponent,
- long_methods->nb_lshift(denominator, py_exponent));
- if (py_exponent == NULL) goto error;
if (exponent > 0) {
- Py_XSETREF(numerator,
- INPLACE_UPDATE(numerator,
- long_methods->nb_multiply(numerator, py_exponent));
- if (numerator == NULL) goto error;
++ Py_SETREF(numerator,
+ long_methods->nb_lshift(numerator, py_exponent));
+ if (numerator == NULL)
+ goto error;
}
else {
- Py_XSETREF(denominator,
- Py_DECREF(denominator);
- denominator = py_exponent;
- py_exponent = NULL;
++ Py_SETREF(denominator,
+ long_methods->nb_lshift(denominator, py_exponent));
+ if (denominator == NULL)
+ goto error;
}
result_pair = PyTuple_Pack(2, numerator, denominator);