diff options
author | Stefan Krah <skrah@bytereef.org> | 2013-01-16 12:00:11 (GMT) |
---|---|---|
committer | Stefan Krah <skrah@bytereef.org> | 2013-01-16 12:00:11 (GMT) |
commit | 6d554b04286604c0ff935067314ff2da6588105a (patch) | |
tree | 5fef37f2205eff4cb85274f44f25b1a93040ccba /Modules | |
parent | 184f01544fd35e990f3de5325567a9efe3b24217 (diff) | |
parent | 59a4a93f43f2fa4f44b03ce0c1816eb2ae089fb9 (diff) | |
download | cpython-6d554b04286604c0ff935067314ff2da6588105a.zip cpython-6d554b04286604c0ff935067314ff2da6588105a.tar.gz cpython-6d554b04286604c0ff935067314ff2da6588105a.tar.bz2 |
Merge 3.3.
Diffstat (limited to 'Modules')
-rw-r--r-- | Modules/_decimal/_decimal.c | 120 | ||||
-rw-r--r-- | Modules/_decimal/tests/deccheck.py | 36 |
2 files changed, 69 insertions, 87 deletions
diff --git a/Modules/_decimal/_decimal.c b/Modules/_decimal/_decimal.c index 4dc9087..5e9fd67 100644 --- a/Modules/_decimal/_decimal.c +++ b/Modules/_decimal/_decimal.c @@ -202,6 +202,13 @@ static const char *dec_signal_string[MPD_NUM_FLAGS] = { "Underflow", }; +#ifdef EXTRA_FUNCTIONALITY + #define _PY_DEC_ROUND_GUARD MPD_ROUND_GUARD +#else + #define _PY_DEC_ROUND_GUARD (MPD_ROUND_GUARD-1) +#endif +static PyObject *round_map[_PY_DEC_ROUND_GUARD]; + static const char *invalid_rounding_err = "valid values for rounding are:\n\ [ROUND_CEILING, ROUND_FLOOR, ROUND_UP, ROUND_DOWN,\n\ @@ -249,13 +256,6 @@ type_error_int(const char *mesg) return -1; } -static PyObject * -type_error_ptr(const char *mesg) -{ - PyErr_SetString(PyExc_TypeError, mesg); - return NULL; -} - static int runtime_error_int(const char *mesg) { @@ -502,6 +502,27 @@ dec_addstatus(PyObject *context, uint32_t status) return 0; } +static int +getround(PyObject *v) +{ + int i; + + if (PyUnicode_Check(v)) { + for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) { + if (v == round_map[i]) { + return i; + } + } + for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) { + if (PyUnicode_Compare(v, round_map[i]) == 0) { + return i; + } + } + } + + return type_error_int(invalid_rounding_err); +} + /******************************************************************************/ /* SignalDict Object */ @@ -715,7 +736,6 @@ context_get##mem(PyObject *self, void *closure UNUSED) \ Dec_CONTEXT_GET_SSIZE(prec) Dec_CONTEXT_GET_SSIZE(emax) Dec_CONTEXT_GET_SSIZE(emin) -Dec_CONTEXT_GET_SSIZE(round) Dec_CONTEXT_GET_SSIZE(clamp) #ifdef EXTRA_FUNCTIONALITY @@ -724,6 +744,15 @@ Dec_CONTEXT_GET_ULONG(status) #endif static PyObject * +context_getround(PyObject *self, void *closure UNUSED) +{ + int i = mpd_getround(CTX(self)); + + Py_INCREF(round_map[i]); + return round_map[i]; +} + +static PyObject * context_getcapitals(PyObject *self, void *closure UNUSED) { return PyLong_FromLong(CtxCaps(self)); @@ -875,17 +904,16 @@ static int context_setround(PyObject *self, PyObject *value, void *closure UNUSED) { mpd_context_t *ctx; - mpd_ssize_t x; + int x; - x = PyLong_AsSsize_t(value); - if (x == -1 && PyErr_Occurred()) { + x = getround(value); + if (x == -1) { return -1; } - BOUNDS_CHECK(x, INT_MIN, INT_MAX); ctx = CTX(self); - if (!mpd_qsetround(ctx, (int)x)) { - return type_error_int(invalid_rounding_err); + if (!mpd_qsetround(ctx, x)) { + INTERNAL_ERROR_INT("context_setround"); /* GCOV_NOT_REACHED */ } return 0; @@ -1208,33 +1236,6 @@ context_dealloc(PyDecContextObject *self) } static int -getround(PyObject *v) -{ - const char *s; - long x; - int i; - - if (PyLong_Check(v)) { - x = PyLong_AsLong(v); - if (x == -1 && PyErr_Occurred()) { - return -1; - } - BOUNDS_CHECK(x, 0, INT_MAX); - return (int)x; - } - else if (PyUnicode_Check(v)) { - for (i = 0; i < MPD_ROUND_GUARD; i++) { - s = mpd_round_string[i]; - if (PyUnicode_CompareWithASCIIString(v, s) == 0) { - return i; - } - } - } - - return type_error_int("invalid rounding mode"); -} - -static int context_init(PyObject *self, PyObject *args, PyObject *kwds) { static char *kwlist[] = { @@ -1264,6 +1265,9 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds) if (prec != Py_None && context_setprec(self, prec, NULL) < 0) { return -1; } + if (rounding != Py_None && context_setround(self, rounding, NULL) < 0) { + return -1; + } if (emin != Py_None && context_setemin(self, emin, NULL) < 0) { return -1; } @@ -1277,16 +1281,6 @@ context_init(PyObject *self, PyObject *args, PyObject *kwds) return -1; } - if (rounding != Py_None) { - int x = getround(rounding); - if (x < 0) { - return -1; - } - if (!mpd_qsetround(CTX(self), x)) { - return type_error_int(invalid_rounding_err); - } - } - if (traps != Py_None) { if (PyList_Check(traps)) { ret = context_settraps_list(self, traps); @@ -3345,7 +3339,7 @@ PyDec_ToIntegralValue(PyObject *dec, PyObject *args, PyObject *kwds) return NULL; } if (!mpd_qsetround(&workctx, round)) { - return type_error_ptr(invalid_rounding_err); + INTERNAL_ERROR_PTR("PyDec_ToIntegralValue"); /* GCOV_NOT_REACHED */ } } @@ -3386,7 +3380,7 @@ PyDec_ToIntegralExact(PyObject *dec, PyObject *args, PyObject *kwds) return NULL; } if (!mpd_qsetround(&workctx, round)) { - return type_error_ptr(invalid_rounding_err); + INTERNAL_ERROR_PTR("PyDec_ToIntegralExact"); /* GCOV_NOT_REACHED */ } } @@ -4187,7 +4181,7 @@ dec_mpd_qquantize(PyObject *v, PyObject *args, PyObject *kwds) return NULL; } if (!mpd_qsetround(&workctx, round)) { - return type_error_ptr(invalid_rounding_err); + INTERNAL_ERROR_PTR("dec_mpd_qquantize"); /* GCOV_NOT_REACHED */ } } @@ -5419,17 +5413,6 @@ static struct int_constmap int_constants [] = { {"DECIMAL64", MPD_DECIMAL64}, {"DECIMAL128", MPD_DECIMAL128}, {"IEEE_CONTEXT_MAX_BITS", MPD_IEEE_CONTEXT_MAX_BITS}, -#endif - {"ROUND_CEILING", MPD_ROUND_CEILING}, - {"ROUND_FLOOR", MPD_ROUND_FLOOR}, - {"ROUND_UP", MPD_ROUND_UP}, - {"ROUND_DOWN", MPD_ROUND_DOWN}, - {"ROUND_HALF_UP", MPD_ROUND_HALF_UP}, - {"ROUND_HALF_DOWN", MPD_ROUND_HALF_DOWN}, - {"ROUND_HALF_EVEN", MPD_ROUND_HALF_EVEN}, - {"ROUND_05UP", MPD_ROUND_05UP}, -#ifdef EXTRA_FUNCTIONALITY - {"ROUND_TRUNC", MPD_ROUND_TRUNC}, /* int condition flags */ {"DecClamped", MPD_Clamped}, {"DecConversionSyntax", MPD_Conversion_syntax}, @@ -5680,6 +5663,13 @@ PyInit__decimal(void) int_cm->val)); } + /* Init string constants */ + for (i = 0; i < _PY_DEC_ROUND_GUARD; i++) { + ASSIGN_PTR(round_map[i], PyUnicode_InternFromString(mpd_round_string[i])); + Py_INCREF(round_map[i]); + CHECK_INT(PyModule_AddObject(m, mpd_round_string[i], round_map[i])); + } + /* Add specification version number */ CHECK_INT(PyModule_AddStringConstant(m, "__version__", " 1.70")); diff --git a/Modules/_decimal/tests/deccheck.py b/Modules/_decimal/tests/deccheck.py index 751ba57..a2853ad 100644 --- a/Modules/_decimal/tests/deccheck.py +++ b/Modules/_decimal/tests/deccheck.py @@ -158,17 +158,9 @@ CondMap = { C.FloatOperation: P.FloatOperation, } -RoundMap = { - C.ROUND_UP: P.ROUND_UP, - C.ROUND_DOWN: P.ROUND_DOWN, - C.ROUND_CEILING: P.ROUND_CEILING, - C.ROUND_FLOOR: P.ROUND_FLOOR, - C.ROUND_HALF_UP: P.ROUND_HALF_UP, - C.ROUND_HALF_DOWN: P.ROUND_HALF_DOWN, - C.ROUND_HALF_EVEN: P.ROUND_HALF_EVEN, - C.ROUND_05UP: P.ROUND_05UP -} -RoundModes = RoundMap.items() +RoundModes = [C.ROUND_UP, C.ROUND_DOWN, C.ROUND_CEILING, C.ROUND_FLOOR, + C.ROUND_HALF_UP, C.ROUND_HALF_DOWN, C.ROUND_HALF_EVEN, + C.ROUND_05UP] class Context(object): @@ -183,7 +175,7 @@ class Context(object): self.p.prec = self.c.prec self.p.Emin = self.c.Emin self.p.Emax = self.c.Emax - self.p.rounding = RoundMap[self.c.rounding] + self.p.rounding = self.c.rounding self.p.capitals = self.c.capitals self.settraps([sig for sig in self.c.traps if self.c.traps[sig]]) self.setstatus([sig for sig in self.c.flags if self.c.flags[sig]]) @@ -217,12 +209,12 @@ class Context(object): self.p.Emax = val def getround(self): - assert(self.c.rounding == RoundMap[self.p.rounding]) + assert(self.c.rounding == self.p.rounding) return self.c.rounding def setround(self, val): self.c.rounding = val - self.p.rounding = RoundMap[val] + self.p.rounding = val def getcapitals(self): assert(self.c.capitals == self.p.capitals) @@ -627,8 +619,12 @@ def convert(t, convstr=True): context.clear_status() - if not t.contextfunc and i == 0 or \ - convstr and isinstance(op, str): + if op in RoundModes: + t.cop.append(op) + t.pop.append(op) + + elif not t.contextfunc and i == 0 or \ + convstr and isinstance(op, str): try: c = C.Decimal(op) cex = None @@ -662,10 +658,6 @@ def convert(t, convstr=True): t.cop.append(op.c) t.pop.append(op.p) - elif op in RoundModes: - t.cop.append(op[0]) - t.pop.append(op[1]) - else: t.cop.append(op) t.pop.append(op) @@ -809,7 +801,7 @@ def test_method(method, testspecs, testfunc): log(" prec: %d emin: %d emax: %d", (context.prec, context.Emin, context.Emax)) restr_range = 9999 if context.Emax > 9999 else context.Emax+99 - for rounding in sorted(RoundMap): + for rounding in RoundModes: context.rounding = rounding context.capitals = random.randrange(2) if spec['clamp'] == 'rand': @@ -941,7 +933,7 @@ def test_round(method, prec, exprange, restricted_range, itr, stat): def test_from_float(method, prec, exprange, restricted_range, itr, stat): """Iterate the __float__ method through many test cases.""" - for rounding in sorted(RoundMap): + for rounding in RoundModes: context.rounding = rounding for i in range(1000): f = randfloat() |