[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

AltStyle によって変換されたページ (->オリジナル) /