[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

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