[Python-checkins] r69458 - in sandbox/trunk/decimal/decimal_in_c: deccoeff.c decimal.py test_decimal.py
mark.dickinson
python-checkins at python.org
Mon Feb 9 11:46:21 CET 2009
Author: mark.dickinson
Date: Mon Feb 9 11:46:20 2009
New Revision: 69458
Log:
Remove uses of cmp() from decimal.py.
Replace use of Py_CmpToRich in deccoeff.c, rename tp_compare to tp_reserved.
Register Decimal as a kind of number; don't subclass from numbers.Real.
Update tests to match those in py3k branch.
Modified:
sandbox/trunk/decimal/decimal_in_c/deccoeff.c
sandbox/trunk/decimal/decimal_in_c/decimal.py
sandbox/trunk/decimal/decimal_in_c/test_decimal.py
Modified: sandbox/trunk/decimal/decimal_in_c/deccoeff.c
==============================================================================
--- sandbox/trunk/decimal/decimal_in_c/deccoeff.c (original)
+++ sandbox/trunk/decimal/decimal_in_c/deccoeff.c Mon Feb 9 11:46:20 2009
@@ -2121,21 +2121,55 @@
{
deccoeff *a, *b;
PyObject *z = NULL;
- if (!compatible_with_deccoeff(v)) {
- Py_INCREF(Py_NotImplemented);
+ int three_way_result;
+ bool rich_result;
+
+ /* convert both arguments to deccoeffs */
+ if (!compatible_with_deccoeff(v) || !compatible_with_deccoeff(w)) {
z = Py_NotImplemented;
+ Py_INCREF(z);
+ return z;
}
- else if ((a = convert_to_deccoeff(v)) != NULL) {
- if (!compatible_with_deccoeff(w)) {
- Py_INCREF(Py_NotImplemented);
- z = Py_NotImplemented;
- }
- else if ((b = convert_to_deccoeff(w)) != NULL) {
- z = Py_CmpToRich(op, _deccoeff_compare(a, b));
- Py_DECREF(b);
- }
+ a = convert_to_deccoeff(v);
+ if (a == NULL)
+ return NULL;
+ b = convert_to_deccoeff(w);
+ if (b == NULL) {
Py_DECREF(a);
+ return NULL;
+ }
+
+ /* do three-way comparison */
+ three_way_result = _deccoeff_compare(a, b);
+ Py_DECREF(a);
+ Py_DECREF(b);
+
+ /* convert three-way comparison result to rich comparison */
+ switch(op) {
+ case Py_EQ:
+ rich_result = three_way_result == 0;
+ break;
+ case Py_NE:
+ rich_result = three_way_result != 0;
+ break;
+ case Py_LT:
+ rich_result = three_way_result < 0;
+ break;
+ case Py_LE:
+ rich_result = three_way_result <= 0;
+ break;
+ case Py_GT:
+ rich_result = three_way_result > 0;
+ break;
+ case Py_GE:
+ rich_result = three_way_result >= 0;
+ break;
+ default:
+ PyErr_BadArgument();
+ return NULL;
}
+ z = rich_result ? Py_True : Py_False;
+ Py_INCREF(z);
return z;
}
@@ -2369,7 +2403,7 @@
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
- 0, /* tp_compare */
+ 0, /* tp_reserved */
(reprfunc)deccoeff_repr, /* tp_repr */
&deccoeff_as_number, /* tp_as_number */
0, /* tp_as_sequence */
Modified: sandbox/trunk/decimal/decimal_in_c/decimal.py
==============================================================================
--- sandbox/trunk/decimal/decimal_in_c/decimal.py (original)
+++ sandbox/trunk/decimal/decimal_in_c/decimal.py Mon Feb 9 11:46:20 2009
@@ -134,9 +134,9 @@
from deccoeff import Deccoeff, _Decimal
-import numbers as _numbers
import copy as _copy
import math as _math
+import numbers as _numbers
try:
from collections import namedtuple as _namedtuple
@@ -545,7 +545,11 @@
##### Decimal class #######################################################
-class Decimal(_Decimal, _numbers.Real):
+# Do not subclass Decimal from numbers.Real and do not register it as such
+# (because Decimals are not interoperable with floats). See the notes in
+# numbers.py for more detail.
+
+class Decimal(_Decimal):
"""Floating point class for decimal arithmetic."""
# Generally, the value of the Decimal instance is given by
@@ -772,7 +776,7 @@
else:
return -1
- # check for zeros; note that cmp(0, -0) should return 0
+ # check for zeros; note that _cmp(0, -0) should return 0
if not self:
if not other:
return 0
@@ -781,33 +785,42 @@
if not other:
return (-1)**self._sign
- # If different signs, neg one is less
- if other._sign < self._sign:
- return -1
- if self._sign < other._sign:
- return 1
+ # if signs differ, the argument with negative sign is smaller
+ if self._sign != other._sign:
+ if self._sign:
+ return -1
+ else:
+ return 1
# signs are the same; if both arguments are negative,
# swap them and treat as positive.
if self._sign == 1:
self, other = other, self
+ # compare adjusted exponents
self_adjusted = self.adjusted()
other_adjusted = other.adjusted()
-
if self_adjusted != other_adjusted:
- return [1, -1][self_adjusted < other_adjusted]
+ if self_adjusted < other_adjusted:
+ return -1
+ else:
+ return 1
+ # adjusted exponents are the same; compare coefficients
lendiff = self._int.digit_length() - other._int.digit_length()
- if lendiff == 0:
- return cmp(self._int, other._int)
- elif lendiff > 0:
- # self is longer than other
- return (cmp(self._int[lendiff:], other._int) or
- cmp(self._int[:lendiff], deccoeff_zero))
- else: #lendiff < 0
- return (cmp(self._int, other._int[-lendiff:]) or
- cmp(deccoeff_zero, other._int[:-lendiff]))
+ if lendiff >= 0:
+ self_split = self._int[lendiff:], self._int[:lendiff]
+ other_split = other._int, deccoeff_zero
+ else:
+ self_split = self._int, deccoeff_zero
+ other_split = other._int[-lendiff:], other._int[:-lendiff]
+
+ if self_split != other_split:
+ if self_split < other_split:
+ return -1
+ else:
+ return 1
+ return 0
# Note: The Decimal standard doesn't cover rich comparisons for
# Decimals. In particular, the specification is silent on the
@@ -3602,6 +3615,12 @@
assert not special
return Decimal._finite(sign, coefficient, exponent)
+# Register Decimal as a kind of Number (an abstract base class).
+# However, do not register it as Real (because Decimals are not
+# interoperable with floats).
+_numbers.Number.register(Decimal)
+
+
##### Context class #######################################################
Modified: sandbox/trunk/decimal/decimal_in_c/test_decimal.py
==============================================================================
--- sandbox/trunk/decimal/decimal_in_c/test_decimal.py (original)
+++ sandbox/trunk/decimal/decimal_in_c/test_decimal.py Mon Feb 9 11:46:20 2009
@@ -30,6 +30,7 @@
import pickle, copy
import unittest
from decimal import *
+import numbers
from test.support import (TestSkipped, run_unittest, run_doctest,
is_resource_enabled)
import random
@@ -1012,17 +1013,11 @@
self.failUnless(da != dc)
self.failUnless(da <= db)
self.failUnless(da >= db)
- self.assertEqual(cmp(dc,da), 1)
- self.assertEqual(cmp(da,dc), -1)
- self.assertEqual(cmp(da,db), 0)
#a Decimal and an int
self.failUnless(dc > 23)
self.failUnless(23 < dc)
self.assertEqual(dc, 45)
- self.assertEqual(cmp(dc,23), 1)
- self.assertEqual(cmp(23,dc), -1)
- self.assertEqual(cmp(dc,45), 0)
#a Decimal and uncomparable
self.assertNotEqual(da, 'ugly')
@@ -1394,6 +1389,12 @@
class DecimalPythonAPItests(unittest.TestCase):
+ def test_abc(self):
+ self.assert_(issubclass(Decimal, numbers.Number))
+ self.assert_(not issubclass(Decimal, numbers.Real))
+ self.assert_(isinstance(Decimal(0), numbers.Number))
+ self.assert_(not isinstance(Decimal(0), numbers.Real))
+
def test_pickle(self):
d = Decimal('-3.141590000')
p = pickle.dumps(d)
More information about the Python-checkins
mailing list