[Python-checkins] python/nondist/sandbox/decimal Decimal.py, 1.12,
1.13 test_Decimal.py, 1.5, 1.6
eprice at users.sourceforge.net
eprice at users.sourceforge.net
Fri Feb 6 11:31:35 EST 2004
Update of /cvsroot/python/python/nondist/sandbox/decimal
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv12521
Modified Files:
Decimal.py test_Decimal.py
Log Message:
Updated to pass newer test cases. Most notably, NaNs with diagnostic info work.
Index: Decimal.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/decimal/Decimal.py,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** Decimal.py 12 Aug 2003 23:04:23 -0000 1.12
--- Decimal.py 6 Feb 2004 16:31:32 -0000 1.13
***************
*** 248,252 ****
def handle(self, context, *args):
if args:
! return (NaN,NaN)
return NaN
--- 248,253 ----
def handle(self, context, *args):
if args:
! if args[0] == 1: #sNaN, must drop 's' but keep diagnostics
! return Decimal( (args[1]._sign, args[1]._int, 'n') )
return NaN
***************
*** 374,377 ****
--- 375,382 ----
ExceptionList = filter(filterfunct, globals().values())
+ #To fix reloading, force it to create a new context
+ #Old contexts have different exceptions in their dicts, making problems.
+ if hasattr(threading.currentThread(), '__decimal_context__'):
+ del threading.currentThread().__decimal_context__
def setcontext(context):
***************
*** 423,433 ****
return
if isnan(value):
! sig = isnan(value) - 1
! self._exp = sig and 'N' or 'n'
! self._sign = 0
! self._int = (0,) #snan or nan
return
self._convertString(value, context)
- # Only a string if it works here
return
--- 428,444 ----
return
if isnan(value):
! sig, sign, diag = isnan(value)
! if len(diag) > context.prec: #Diagnostic info too long
! self._sign, self._int, self._exp = \
! context.raise_error(ConversionSyntax)
! return
! if sig == 1:
! self._exp = 'n' #qNaN
! else: #sig == 2
! self._exp = 'N' #sNaN
! self._sign = sign
! self._int = tuple(map(int, tuple(diag))) #Diagnostic info
return
self._convertString(value, context)
return
***************
*** 441,452 ****
raise ValueError, 'Invalid arguments'
if value[0] not in [0,1]:
! raise ValueError, 'Invalid sign'
# FIXME: Add more input validation checks here
self._sign = value[0]
self._int = tuple(value[1])
if value[2] in ('F','n','N'):
! self._exp = value[2]
else:
! self._exp = long(value[2])
return
--- 452,464 ----
raise ValueError, 'Invalid arguments'
if value[0] not in [0,1]:
! raise ValueError, 'Invalid sign'
!
# FIXME: Add more input validation checks here
self._sign = value[0]
self._int = tuple(value[1])
if value[2] in ('F','n','N'):
! self._exp = value[2]
else:
! self._exp = long(value[2])
return
***************
*** 468,472 ****
if isinstance(value, float):
! #self._convertString(_floatToString(value), context)
#
# This would give a more strictly accurate representation,
--- 480,485 ----
if isinstance(value, float):
! # Another possibility would be:
! # self._convertString(_floatToString(value), context)
#
# This would give a more strictly accurate representation,
***************
*** 521,531 ****
if self._isnan() == 2:
! return context.raise_error(InvalidOperation, 'sNaN')
if other is not None and other._isnan() == 2:
! return context.raise_error(InvalidOperation, 'sNaN')
if self._isnan():
! return NaN
if other is not None and other._isnan():
! return NaN
return 0
--- 534,546 ----
if self._isnan() == 2:
! return context.raise_error(InvalidOperation, 'sNaN',
! 1, self)
if other is not None and other._isnan() == 2:
! return context.raise_error(InvalidOperation, 'sNaN',
! 1, other)
if self._isnan():
! return self
if other is not None and other._isnan():
! return other
return 0
***************
*** 540,544 ****
self._sign, self._int, self._exp = _string2exact(value)
except ValueError:
! self._sign, self._int, self._exp = context.raise_error(ConversionSyntax)
return
--- 555,560 ----
self._sign, self._int, self._exp = _string2exact(value)
except ValueError:
! self._sign, self._int, self._exp = \
! context.raise_error(ConversionSyntax)
return
***************
*** 660,671 ****
"""
if self._isnan():
if self._isnan() == 2:
! return 'sNaN'
! return 'NaN'
if self._isinfinity():
! sign = self._isinfinity()
! if sign > 0:
! return 'Infinity'
! return '-Infinity'
if context is None:
--- 676,690 ----
"""
if self._isnan():
+ minus = '-'*self._sign
+ if self._int == (0,):
+ info = ''
+ else:
+ info = ''.join(map(str, self._int))
if self._isnan() == 2:
! return minus + 'sNaN' + info
! return minus + 'NaN' + info
if self._isinfinity():
! minus = '-'*self._sign
! return minus + 'Infinity'
if context is None:
***************
*** 675,678 ****
--- 694,717 ----
numdigits = len(self._int)
leftdigits = self._exp + numdigits
+ if eng and not self: #self = 0eX wants 0[.0[0]]eY, not [[0]0]0eY
+ if self._exp < 0 and self._exp >= -6: #short, no need for e/E
+ s = '-'*self._sign + '0.' + '0'*(abs(self._exp))
+ return s
+ #exp is closest mult. of 3 >= self._exp
+ exp = ((self._exp - 1)// 3 + 1) * 3
+ if exp != self._exp:
+ s = '0.'+'0'*(exp - self._exp)
+ else:
+ s = '0'
+ if exp != 0:
+ if context.capitals:
+ s += 'E'
+ else:
+ s += 'e'
+ if exp > 0:
+ s += '+' #0.0e+3, not 0.0e3
+ s += str(exp)
+ s = '-'*self._sign + s
+ return s
if eng:
dotplace = (leftdigits-1)%3+1
***************
*** 900,904 ****
if context is None:
context = getcontext()
! # -Decimal(0) = Decimal(0), which we don't want
# (-0 - 0 = -0 + (-0) = -0, but -0 + 0 = 0.)
# so we change the sign directly.
--- 939,946 ----
if context is None:
context = getcontext()
! ans = self._check_nans(other, context=context)
! if ans:
! return ans
! # -Decimal(0) = Decimal(0), which we don't want since
# (-0 - 0 = -0 + (-0) = -0, but -0 + 0 = 0.)
# so we change the sign directly.
***************
*** 1076,1079 ****
--- 1118,1123 ----
context.raise_error(Clamped, 'Division by infinity')
return Decimal((sign, (0,), context.Etiny()))
+ if self._isinfinity():
+ return Infsign[sign]
#These two have different precision.
if not self:
***************
*** 1089,1105 ****
if not other:
return context.raise_error(DivisionByZero, 'x / 0', sign)
- if self._isinfinity():
- return Infsign[sign]
if divmod:
if other._isinfinity():
return (Decimal((sign, (0,), 0)), Decimal(self))
- if not self:
- otherside = Decimal(self)
- otherside._exp = min(self._exp, other._exp)
- return (Decimal((sign, (0,), 0)), otherside)
-
- if not other:
- return context.raise_error(DivisionByZero, 'divmod(x,0)',
- sign, 1)
if self._isinfinity():
if divmod == 1:
--- 1133,1139 ----
***************
*** 1111,1114 ****
--- 1145,1156 ----
return (Infsign[sign],
context.raise_error(InvalidOperation, 'INF % x'))
+ if not self:
+ otherside = Decimal(self)
+ otherside._exp = min(self._exp, other._exp)
+ return (Decimal((sign, (0,), 0)), otherside)
+
+ if not other:
+ return context.raise_error(DivisionByZero, 'divmod(x,0)',
+ sign, 1)
#OK, so neither = 0, INF
***************
*** 1121,1125 ****
if divmod == 1 or divmod == 3:
! ans2 = Decimal(self)
if shouldround:
ans2 = ans2.fix(context=context)
--- 1163,1168 ----
if divmod == 1 or divmod == 3:
! exp = min(self._exp, other._exp)
! ans2 = self.rescale(exp, context=context, watchexp=0)
if shouldround:
ans2 = ans2.fix(context=context)
***************
*** 1160,1165 ****
watchexp=0)
context.regard_flags(*frozen)
- if not otherside:
- otherside._exp = 0
if shouldround:
otherside = otherside.fix(context=context)
--- 1203,1206 ----
***************
*** 1199,1204 ****
context.regard_flags(*frozen)
- if not otherside:
- otherside._exp = 0
return (Decimal(res), otherside)
--- 1240,1243 ----
***************
*** 1332,1336 ****
"""Converts self to a long, truncating if necessary."""
if self._isnan():
-
context = getcontext()
return context.raise_error(InvalidContext)
--- 1371,1374 ----
***************
*** 1755,1763 ****
if context is None:
context = getcontext()
! if exp._isinfinity() or self._isinfinity():
! return context.raise_error(InvalidOperation, 'quantize with an INF')
ans = self._check_nans(exp, context)
if ans:
return ans
return self.rescale(exp._exp, rounding, context, watchexp)
--- 1793,1806 ----
if context is None:
context = getcontext()
!
ans = self._check_nans(exp, context)
if ans:
return ans
+
+ if exp._isinfinity() or self._isinfinity():
+ if exp._isinfinity() and self._isinfinity():
+ return self #if both are inf, it is OK
+ return context.raise_error(InvalidOperation,
+ 'quantize with one INF')
return self.rescale(exp._exp, rounding, context, watchexp)
***************
*** 2491,2495 ****
DEFAULT_TRAPS = BASIC_DEFAULT_TRAPS
DEFAULT_FLAGS= BASIC_DEFAULT_FLAGS
! DEFAULT_ROUNDING_DECISION = EXTENDED_DEFAULT_ROUNDING_DECISION
elif DEFAULT_CONTEXT == EXTENDED_DEFAULT_CONTEXT:
--- 2534,2538 ----
DEFAULT_TRAPS = BASIC_DEFAULT_TRAPS
DEFAULT_FLAGS= BASIC_DEFAULT_FLAGS
! DEFAULT_ROUNDING_DECISION = BASIC_DEFAULT_ROUNDING_DECISION
elif DEFAULT_CONTEXT == EXTENDED_DEFAULT_CONTEXT:
***************
*** 2524,2537 ****
"""Determines whether a string or float is NaN
! 1 => NaN
! 2 => sNaN
"""
if isinstance(num, float):
num = str(num)
num = num.lower()
! if num == 'nan':
! return 1
! if num == 'snan':
! return 2
return 0
--- 2567,2594 ----
"""Determines whether a string or float is NaN
! (1, sign, diagnostic info as string) => NaN
! (2, sign, diagnostic info as string) => sNaN
! 0 => not a NaN
"""
if isinstance(num, float):
num = str(num)
num = num.lower()
!
! #get the sign, get rid of trailing [+-]
! sign = 0
! if num[0] == '+':
! num = num[1:]
! elif num[0] == '-': #elif avoids '+-nan'
! num = num[1:]
! sign = 1
!
! if num.startswith('nan'):
! if len(num) > 3 and not num[3:].isdigit(): #diagnostic info
! return 0
! return (1, sign, num[3:].lstrip('0'))
! if num.startswith('snan'):
! if len(num) > 4 and not num[4:].isdigit():
! return 0
! return (2, sign, num[4:].lstrip('0'))
return 0
Index: test_Decimal.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/decimal/test_Decimal.py,v
retrieving revision 1.5
retrieving revision 1.6
diff -C2 -d -r1.5 -r1.6
*** test_Decimal.py 12 Nov 2003 20:38:41 -0000 1.5
--- test_Decimal.py 6 Feb 2004 16:31:32 -0000 1.6
***************
*** 12,15 ****
--- 12,19 ----
skip_expected = not os.path.isdir(dir)
+ # Make sure it actually raises errors when not expected and caught in flags
+ # Slower, since it runs some things several times.
+ EXTENDEDERRORTEST = False
+
#Map the test cases' error names to the actual errors
***************
*** 158,161 ****
--- 162,178 ----
v = FixQuotes(val)
if fname in ('tosci', 'toeng'):
+ if EXTENDEDERRORTEST:
+ for error in theirexceptions:
+ self.context.trap_enablers[error] = 1
+ try:
+ funct(self.context.new(v))
+ except error:
+ pass
+ except ExceptionList, e:
+ self.fail("Raised %s in %s when %s disabled" % \
+ (e, s, error))
+ else:
+ self.fail("Did not raise %s in %s" % (error, s))
+ self.context.trap_enablers[error] = 0
v = self.context.new(v)
#elif fname == 'rescale' and i == 1:
***************
*** 169,173 ****
ans = FixQuotes(ans)
!
try:
result = str(funct(*vals))
--- 186,203 ----
ans = FixQuotes(ans)
!
! if EXTENDEDERRORTEST and fname not in ('tosci', 'toeng'):
! for error in theirexceptions:
! self.context.trap_enablers[error] = 1
! try:
! funct(*vals)
! except error:
! pass
! except ExceptionList, e:
! self.fail("Raised %s in %s when %s disabled" % \
! (e, s, error))
! else:
! self.fail("Did not raise %s in %s" % (error, s))
! self.context.trap_enablers[error] = 0
try:
result = str(funct(*vals))
***************
*** 184,189 ****
theirexceptions.sort()
! self.assertEqual(result, ans, 'Incorrect answer for ' + s + ' -- got ' + result)
! self.assertEqual(myexceptions, theirexceptions, 'Incorrect flags set in ' + s + ' -- got '
+ str(myexceptions))
--- 214,221 ----
theirexceptions.sort()
! self.assertEqual(result, ans,
! 'Incorrect answer for ' + s + ' -- got ' + result)
! self.assertEqual(myexceptions, theirexceptions,
! 'Incorrect flags set in ' + s + ' -- got ' \
+ str(myexceptions))
***************
*** 268,277 ****
self.eval_file(dir + 'inexact' + '.decTest')
! #def test_integer(self):
! # """Tests the Decimal class on Cowlishaw's integer tests.
! #
! # See www2.hursley.ibm.com/decimal/decTest.zip to download the suite.
! # """
! # self.eval_file(dir + 'integer' + '.decTest')
def test_max(self):
--- 300,309 ----
self.eval_file(dir + 'inexact' + '.decTest')
! def test_integer(self):
! """Tests the Decimal class on Cowlishaw's integer tests.
!
! See www2.hursley.ibm.com/decimal/decTest.zip to download the suite.
! """
! self.eval_file(dir + 'integer' + '.decTest')
def test_max(self):
More information about the Python-checkins
mailing list