diff options
Diffstat (limited to 'Modules/_decimal')
-rw-r--r-- | Modules/_decimal/_decimal.c | 101 | ||||
-rw-r--r-- | Modules/_decimal/docstrings.h | 9 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/basearith.c | 1 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/io.c | 1 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/memory.c | 7 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpalloc.h (renamed from Modules/_decimal/libmpdec/memory.h) | 4 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpdecimal.c | 2 | ||||
-rw-r--r-- | Modules/_decimal/libmpdec/mpdecimal.h | 4 | ||||
-rw-r--r-- | Modules/_decimal/tests/deccheck.py | 6 |
9 files changed, 123 insertions, 12 deletions
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index e15941a..3ba8e35 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -36,7 +36,6 @@ #include <stdlib.h> #include "docstrings.h" -#include "memory.h" #if !defined(MPD_VERSION_HEX) || MPD_VERSION_HEX < 0x02040100 @@ -3394,6 +3393,105 @@ dec_as_long(PyObject *dec, PyObject *context, int round) return (PyObject *) pylong; } +/* 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; + + 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_SETREF(exponent, _py_long_power(tmp, exponent, Py_None)); + Py_DECREF(tmp); + if (exponent == NULL) { + goto error; + } + + if (exp >= 0) { + Py_SETREF(numerator, _py_long_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, _py_long_floor_divide(numerator, tmp)); + Py_SETREF(denominator, _py_long_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) { @@ -4702,6 +4800,7 @@ static PyMethodDef dec_methods [] = /* Miscellaneous */ { "from_float", dec_from_float, METH_O|METH_CLASS, doc_from_float }, { "as_tuple", PyDec_AsTuple, METH_NOARGS, doc_as_tuple }, + { "as_integer_ratio", dec_as_integer_ratio, METH_NOARGS, doc_as_integer_ratio }, /* Special methods */ { "__copy__", dec_copy, METH_NOARGS, NULL }, diff --git a/Modules/_decimal/docstrings.h b/Modules/_decimal/docstrings.h index 71029a9..f7fd6e7 100644 --- a/Modules/_decimal/docstrings.h +++ b/Modules/_decimal/docstrings.h @@ -70,6 +70,15 @@ PyDoc_STRVAR(doc_as_tuple, Return a tuple representation of the number.\n\ \n"); +PyDoc_STRVAR(doc_as_integer_ratio, +"as_integer_ratio($self, /)\n--\n\n\ +Decimal.as_integer_ratio() -> (int, int)\n\ +\n\ +Return a pair of integers, whose ratio is exactly equal to the original\n\ +Decimal and with a positive denominator. The ratio is in lowest terms.\n\ +Raise OverflowError on infinities and a ValueError on NaNs.\n\ +\n"); + PyDoc_STRVAR(doc_canonical, "canonical($self, /)\n--\n\n\ Return the canonical encoding of the argument. Currently, the encoding\n\ diff --git a/Modules/_decimal/libmpdec/basearith.c b/Modules/_decimal/libmpdec/basearith.c index 35de6b8..dfe1523 100644 --- a/Modules/_decimal/libmpdec/basearith.c +++ b/Modules/_decimal/libmpdec/basearith.c @@ -32,7 +32,6 @@ #include <string.h> #include <assert.h> #include "constants.h" -#include "memory.h" #include "typearith.h" #include "basearith.h" diff --git a/Modules/_decimal/libmpdec/io.c b/Modules/_decimal/libmpdec/io.c index a45a429..3aadfb0 100644 --- a/Modules/_decimal/libmpdec/io.c +++ b/Modules/_decimal/libmpdec/io.c @@ -37,7 +37,6 @@ #include <locale.h> #include "bits.h" #include "constants.h" -#include "memory.h" #include "typearith.h" #include "io.h" diff --git a/Modules/_decimal/libmpdec/memory.c b/Modules/_decimal/libmpdec/memory.c index 0f41fe5..a854e09 100644 --- a/Modules/_decimal/libmpdec/memory.c +++ b/Modules/_decimal/libmpdec/memory.c @@ -30,7 +30,12 @@ #include <stdio.h> #include <stdlib.h> #include "typearith.h" -#include "memory.h" +#include "mpalloc.h" + + +#if defined(_MSC_VER) + #pragma warning(disable : 4232) +#endif /* Guaranteed minimum allocation for a coefficient. May be changed once diff --git a/Modules/_decimal/libmpdec/memory.h b/Modules/_decimal/libmpdec/mpalloc.h index 9c98d1a..efd7119 100644 --- a/Modules/_decimal/libmpdec/memory.h +++ b/Modules/_decimal/libmpdec/mpalloc.h @@ -26,8 +26,8 @@ */ -#ifndef MEMORY_H -#define MEMORY_H +#ifndef MPALLOC_H +#define MPALLOC_H #include "mpdecimal.h" diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c index 593f9f5..328ab92 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.c +++ b/Modules/_decimal/libmpdec/mpdecimal.c @@ -36,7 +36,7 @@ #include "bits.h" #include "convolute.h" #include "crt.h" -#include "memory.h" +#include "mpalloc.h" #include "typearith.h" #include "umodarith.h" diff --git a/Modules/_decimal/libmpdec/mpdecimal.h b/Modules/_decimal/libmpdec/mpdecimal.h index 5ca7413..56e4887 100644 --- a/Modules/_decimal/libmpdec/mpdecimal.h +++ b/Modules/_decimal/libmpdec/mpdecimal.h @@ -108,9 +108,9 @@ MPD_PRAGMA(MPD_HIDE_SYMBOLS_START) #define MPD_MAJOR_VERSION 2 #define MPD_MINOR_VERSION 4 -#define MPD_MICRO_VERSION 1 +#define MPD_MICRO_VERSION 2 -#define MPD_VERSION "2.4.1" +#define MPD_VERSION "2.4.2" #define MPD_VERSION_HEX ((MPD_MAJOR_VERSION << 24) | \ (MPD_MINOR_VERSION << 16) | \ diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py index ab7d5bd..f907531 100644 --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -50,8 +50,8 @@ Functions = { '__abs__', '__bool__', '__ceil__', '__complex__', '__copy__', '__floor__', '__float__', '__hash__', '__int__', '__neg__', '__pos__', '__reduce__', '__repr__', '__str__', '__trunc__', - 'adjusted', 'as_tuple', 'canonical', 'conjugate', 'copy_abs', - 'copy_negate', 'is_canonical', 'is_finite', 'is_infinite', + 'adjusted', 'as_integer_ratio', 'as_tuple', 'canonical', 'conjugate', + 'copy_abs', 'copy_negate', 'is_canonical', 'is_finite', 'is_infinite', 'is_nan', 'is_qnan', 'is_signed', 'is_snan', 'is_zero', 'radix' ), # Unary with optional context: @@ -128,7 +128,7 @@ ContextFunctions = { # Functions that require a restricted exponent range for reasonable runtimes. UnaryRestricted = [ '__ceil__', '__floor__', '__int__', '__trunc__', - 'to_integral', 'to_integral_value' + 'as_integer_ratio', 'to_integral', 'to_integral_value' ] BinaryRestricted = ['__round__'] |