[Python-checkins] r58138 - in python/branches/decimal-branch/Lib: decimal.py test/decimaltestdata/extra.decTest

facundo.batista python-checkins at python.org
Thu Sep 13 16:53:40 CEST 2007


Author: facundo.batista
Date: Thu Sep 13 16:53:39 2007
New Revision: 58138

Modified:
   python/branches/decimal-branch/Lib/decimal.py
   python/branches/decimal-branch/Lib/test/decimaltestdata/extra.decTest
Log:

Now raises TypeError instead returning NotImplemented when the function
is not __xxx__. Changed _convert_other() to be able to return a better
message and at the same time be more concise.


Modified: python/branches/decimal-branch/Lib/decimal.py
==============================================================================
--- python/branches/decimal-branch/Lib/decimal.py	(original)
+++ python/branches/decimal-branch/Lib/decimal.py	Thu Sep 13 16:53:39 2007
@@ -752,9 +752,7 @@
         NaN => one is NaN
         Like __cmp__, but returns Decimal instances.
         """
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
+        other = _convert_other(other, raiseit=True)
 
         # Compare(NaN, NaN) = NaN
         if (self._is_special or other and other._is_special):
@@ -1359,9 +1357,7 @@
         if context is None:
             context = getcontext()
 
-        other = _convert_other(other)
-        if other is NotImplemented:
-            raise TypeError("Unable to convert %s to Decimal" % other)
+        other = _convert_other(other, raiseit=True)
 
         ans = self._check_nans(other, context)
         if ans:
@@ -1638,42 +1634,25 @@
         and a single final rounding is performed.
         """
 
+        other = _convert_other(other, raiseit=True)
+        third = _convert_other(third, raiseit=True)
+
         if context is None:
             context = getcontext()
 
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
+        # do self*other in fresh context with no traps and no rounding
+        mul_context = Context(traps=[], flags=[],
+                              _rounding_decision=NEVER_ROUND)
+        product = self.__mul__(other, mul_context)
 
-        third = _convert_other(third)
-        if third is NotImplemented:
-            return third
-
-        # deal correctly with NaNs:
-        self_is_nan = self._isnan()
-        other_is_nan = other._isnan()
-        third_is_nan = third._isnan()
-        if self_is_nan or other_is_nan or third_is_nan:
-            if self_is_nan == 2:
-                return context._raise_error(InvalidOperation, 'sNaN',
-                                        1, self)
-            if other_is_nan == 2:
-                return context._raise_error(InvalidOperation, 'sNaN',
-                                        1, other)
-            if third_is_nan == 2:
-                return context._raise_error(InvalidOperation, 'sNaN',
-                                        1, third)
-            if self_is_nan:
-                return self
-            if other_is_nan:
-                return other
-            return third
+        if mul_context.flags[InvalidOperation]:
+            # reraise in current context
+            return context._raise_error(InvalidOperation,
+                                        'invalid multiplication in fma',
+                                        1, product)
 
-        context = context._shallow_copy()
-        rounding_decision = context._set_rounding_decision(NEVER_ROUND)
-        product = self.__mul__(other, context)
-        context._set_rounding_decision(rounding_decision)
-        return product.__add__(third, context)
+        ans = product.__add__(third, context)
+        return ans
 
     def _power_modulo(self, other, modulo, context=None):
         """Three argument version of __pow__"""
@@ -1681,17 +1660,8 @@
         # if can't convert other and modulo to Decimal, raise
         # TypeError; there's no point returning NotImplemented (no
         # equivalent of __rpow__ for three argument pow)
-        other = _convert_other(other)
-        if other is NotImplemented:
-            raise TypeError("The second argument to pow should be " +
-                            "an integer or an instance of Decimal.  Got " +
-                            str(other))
-
-        modulo = _convert_other(modulo)
-        if modulo is NotImplemented:
-            raise TypeError("The third argument to pow should be " +
-                            "an integer or an instance of Decimal.  Got " +
-                            str(modulo))
+        other = _convert_other(other, raiseit=True)
+        modulo = _convert_other(modulo, raiseit=True)
 
         if context is None:
             context = getcontext()
@@ -2447,9 +2417,7 @@
         Like max(self, other) except if one is not a number, returns
         NaN (and signals if one is sNaN).  Also rounds.
         """
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
+        other = _convert_other(other, raiseit=True)
 
         if self._is_special or other._is_special:
             # If one operand is a quiet NaN and the other is number, then the
@@ -2492,9 +2460,7 @@
         Like min(self, other) except if one is not a number, returns
         NaN (and signals if one is sNaN).  Also rounds.
         """
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
+        other = _convert_other(other, raiseit=True)
 
         if self._is_special or other._is_special:
             # If one operand is a quiet NaN and the other is number, then the
@@ -3112,9 +3078,7 @@
 
     def max_mag(self, other, context=None):
         """Compares the values numerically with their sign ignored."""
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
+        other = _convert_other(other, raiseit=True)
 
         if self._is_special or other._is_special:
             # If one operand is a quiet NaN and the other is number, then the
@@ -3145,9 +3109,7 @@
 
     def min_mag(self, other, context=None):
         """Compares the values numerically with their sign ignored."""
-        other = _convert_other(other)
-        if other is NotImplemented:
-            return other
+        other = _convert_other(other, raiseit=True)
 
         if self._is_special or other._is_special:
             # If one operand is a quiet NaN and the other is number, then the
@@ -3229,11 +3191,7 @@
         numerically equal, then the result is a copy of self with the
         sign set to be the same as the sign of other.
         """
-        other = _convert_other(other)
-        if other is NotImplemented:
-            raise TypeError("The second argument to next_toward should be " +
-                            "an integer or an instance of Decimal.  Got " +
-                            str(other))
+        other = _convert_other(other, raiseit=True)
 
         if context is None:
             context = getcontext()
@@ -5154,7 +5112,7 @@
 
 ##### Helper Functions ####################################################
 
-def _convert_other(other):
+def _convert_other(other, raiseit=False):
     """Convert other to Decimal.
 
     Verifies that it's ok to use in an implicit construction.
@@ -5163,6 +5121,8 @@
         return other
     if isinstance(other, (int, long)):
         return Decimal(other)
+    if raiseit:
+        raise TypeError("Unable to convert %s to Decimal" % other)
     return NotImplemented
 
 _infinity_map = {

Modified: python/branches/decimal-branch/Lib/test/decimaltestdata/extra.decTest
==============================================================================
--- python/branches/decimal-branch/Lib/test/decimaltestdata/extra.decTest	(original)
+++ python/branches/decimal-branch/Lib/test/decimaltestdata/extra.decTest	Thu Sep 13 16:53:39 2007
@@ -147,6 +147,13 @@
 extr1201 scaleb 5678 0 -> 5.68E+3 Inexact Rounded
 extr1202 scaleb -9105 -1 -> -910 Inexact Rounded
 
+-- Invalid operation from 0 * infinity in fma
+-- takes precedence over a third-argument sNaN
+extr1300 fma 0 Inf sNaN123 -> NaN Invalid_operation
+extr1301 fma Inf 0 sNaN456 -> NaN Invalid_operation
+extr1302 fma 0E123 -Inf sNaN789 -> NaN Invalid_operation
+extr1302 fma -Inf 0E-456 sNaN148 -> NaN Invalid_operation
+
 ------------------------------------------------------------------------
 -- The following tests (pwmx0 through pwmx440) are for the            --
 -- three-argument version of power:                                   --


More information about the Python-checkins mailing list