summaryrefslogtreecommitdiff
path: root/Lib/decimal.py
diff options
context:
space:
mode:
authorChristian Heimes <christian@cheimes.de>2007-12-17 20:04:13 +0000
committerChristian Heimes <christian@cheimes.de>2007-12-17 20:04:13 +0000
commit9eff22194e1ff303ac804089911e673b05a2f24e (patch)
tree2ab8f7a92726cb0c1ba3725905c59eff2a4b6459 /Lib/decimal.py
parentc5c28b4a491177299c6035f366942c60646f7e90 (diff)
downloadcpython-9eff22194e1ff303ac804089911e673b05a2f24e.tar.gz
Merged revisions 59512-59540 via svnmerge from
svn+ssh://pythondev@svn.python.org/python/trunk ........ r59513 | raymond.hettinger | 2007-12-15 01:07:25 +0100 (Sat, 15 Dec 2007) | 6 lines Optimize PyList_AsTuple(). Improve cache performance by doing the pointer copy and object increment in one pass. For small lists, save the overhead of the call to memcpy() -- this comes up in calls like f(*listcomp). ........ r59519 | christian.heimes | 2007-12-15 06:38:35 +0100 (Sat, 15 Dec 2007) | 2 lines Fixed #1624: Remove output comparison for test_pep277 I had to modify Brett's patch slightly. ........ r59520 | georg.brandl | 2007-12-15 10:34:59 +0100 (Sat, 15 Dec 2007) | 2 lines Add note about future import needed for with statement. ........ r59522 | georg.brandl | 2007-12-15 10:36:37 +0100 (Sat, 15 Dec 2007) | 2 lines Argh, wrong version. ........ r59524 | georg.brandl | 2007-12-16 12:06:09 +0100 (Sun, 16 Dec 2007) | 2 lines Dummy commit to investigate #1617. ........ r59525 | georg.brandl | 2007-12-16 12:21:48 +0100 (Sun, 16 Dec 2007) | 2 lines Revert dummy commit now that the build slave is building. ........ r59527 | georg.brandl | 2007-12-16 16:47:46 +0100 (Sun, 16 Dec 2007) | 2 lines Remove orphaned footnote reference. ........ r59528 | georg.brandl | 2007-12-16 16:53:49 +0100 (Sun, 16 Dec 2007) | 2 lines Remove gratuitous unicode character. ........ r59529 | georg.brandl | 2007-12-16 16:59:19 +0100 (Sun, 16 Dec 2007) | 2 lines Remove another unnecessary Unicode character. ........ r59530 | georg.brandl | 2007-12-16 17:00:36 +0100 (Sun, 16 Dec 2007) | 2 lines Remove curious space-like characters. ........ r59532 | georg.brandl | 2007-12-16 20:36:51 +0100 (Sun, 16 Dec 2007) | 2 lines Adapt conf.py to new option names. ........ r59533 | christian.heimes | 2007-12-16 22:39:43 +0100 (Sun, 16 Dec 2007) | 1 line Fixed #1638: %zd configure test fails on Linux ........ r59536 | georg.brandl | 2007-12-17 00:11:16 +0100 (Mon, 17 Dec 2007) | 2 lines Simplify. ........ r59537 | georg.brandl | 2007-12-17 00:13:29 +0100 (Mon, 17 Dec 2007) | 2 lines Use PEP 8. ........ r59539 | georg.brandl | 2007-12-17 00:15:07 +0100 (Mon, 17 Dec 2007) | 2 lines Don't use quotes for non-string code. ........ r59540 | facundo.batista | 2007-12-17 15:18:42 +0100 (Mon, 17 Dec 2007) | 4 lines Removed the private _rounding_decision: it was not needed, and the code is now simpler. Thanks Mark Dickinson. ........
Diffstat (limited to 'Lib/decimal.py')
-rw-r--r--Lib/decimal.py132
1 files changed, 38 insertions, 94 deletions
diff --git a/Lib/decimal.py b/Lib/decimal.py
index ba335bba46..b25f6e6191 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -147,10 +147,6 @@ ROUND_UP = 'ROUND_UP'
ROUND_HALF_DOWN = 'ROUND_HALF_DOWN'
ROUND_05UP = 'ROUND_05UP'
-# Rounding decision (not part of the public API)
-NEVER_ROUND = 'NEVER_ROUND' # Round in division (non-divmod), sqrt ONLY
-ALWAYS_ROUND = 'ALWAYS_ROUND' # Every operation rounds at end.
-
# Errors
class DecimalException(ArithmeticError):
@@ -932,9 +928,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
if context is None:
context = getcontext()
- if context._rounding_decision == ALWAYS_ROUND:
- return ans._fix(context)
- return ans
+ return ans._fix(context)
def __pos__(self, context=None):
"""Returns a copy, unless it is a sNaN.
@@ -954,26 +948,23 @@ class Decimal(_numbers.Real, _numbers.Inexact):
if context is None:
context = getcontext()
- if context._rounding_decision == ALWAYS_ROUND:
- return ans._fix(context)
- return ans
+ return ans._fix(context)
- def __abs__(self, round=1, context=None):
+ def __abs__(self, round=True, context=None):
"""Returns the absolute value of self.
- If the second argument is 0, do not round.
+ If the keyword argument 'round' is false, do not round. The
+ expression self.__abs__(round=False) is equivalent to
+ self.copy_abs().
"""
+ if not round:
+ return self.copy_abs()
+
if self._is_special:
ans = self._check_nans(context=context)
if ans:
return ans
- if not round:
- if context is None:
- context = getcontext()
- context = context._shallow_copy()
- context._set_rounding_decision(NEVER_ROUND)
-
if self._sign:
ans = self.__neg__(context=context)
else:
@@ -1006,8 +997,6 @@ class Decimal(_numbers.Real, _numbers.Inexact):
if other._isinfinity():
return Decimal(other) # Can't both be infinity here
- shouldround = context._rounding_decision == ALWAYS_ROUND
-
exp = min(self._exp, other._exp)
negativezero = 0
if context.rounding == ROUND_FLOOR and self._sign != other._sign:
@@ -1019,33 +1008,29 @@ class Decimal(_numbers.Real, _numbers.Inexact):
if negativezero:
sign = 1
ans = _dec_from_triple(sign, '0', exp)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
if not self:
exp = max(exp, other._exp - context.prec-1)
ans = other._rescale(exp, context.rounding)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
if not other:
exp = max(exp, self._exp - context.prec-1)
ans = self._rescale(exp, context.rounding)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
op1 = _WorkRep(self)
op2 = _WorkRep(other)
- op1, op2 = _normalize(op1, op2, shouldround, context.prec)
+ op1, op2 = _normalize(op1, op2, context.prec)
result = _WorkRep()
if op1.sign != op2.sign:
# Equal and opposite
if op1.int == op2.int:
ans = _dec_from_triple(negativezero, '0', exp)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
if op1.int < op2.int:
op1, op2 = op2, op1
@@ -1070,8 +1055,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
result.exp = op1.exp
ans = Decimal(result)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
__radd__ = __add__
@@ -1128,34 +1112,29 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return Infsign[resultsign]
resultexp = self._exp + other._exp
- shouldround = context._rounding_decision == ALWAYS_ROUND
# Special case for multiplying by zero
if not self or not other:
ans = _dec_from_triple(resultsign, '0', resultexp)
- if shouldround:
- # Fixing in case the exponent is out of bounds
- ans = ans._fix(context)
+ # Fixing in case the exponent is out of bounds
+ ans = ans._fix(context)
return ans
# Special case for multiplying by power of 10
if self._int == '1':
ans = _dec_from_triple(resultsign, other._int, resultexp)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
if other._int == '1':
ans = _dec_from_triple(resultsign, self._int, resultexp)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
op1 = _WorkRep(self)
op2 = _WorkRep(other)
ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp)
- if shouldround:
- ans = ans._fix(context)
+ ans = ans._fix(context)
return ans
__rmul__ = __mul__
@@ -1292,8 +1271,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
context._raise_error(InvalidOperation, 'x % 0'))
quotient, remainder = self._divide(other, context)
- if context._rounding_decision == ALWAYS_ROUND:
- remainder = remainder._fix(context)
+ remainder = remainder._fix(context)
return quotient, remainder
def __rdivmod__(self, other, context=None):
@@ -1327,8 +1305,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
return context._raise_error(DivisionUndefined, '0 % 0')
remainder = self._divide(other, context)[1]
- if context._rounding_decision == ALWAYS_ROUND:
- remainder = remainder._fix(context)
+ remainder = remainder._fix(context)
return remainder
def __rmod__(self, other, context=None):
@@ -2498,9 +2475,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
else:
ans = self
- if context._rounding_decision == ALWAYS_ROUND:
- return ans._fix(context)
- return ans
+ return ans._fix(context)
def min(self, other, context=None):
"""Returns the smaller value.
@@ -2534,9 +2509,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
else:
ans = other
- if context._rounding_decision == ALWAYS_ROUND:
- return ans._fix(context)
- return ans
+ return ans._fix(context)
def _isinteger(self):
"""Returns whether self is an integer"""
@@ -3107,9 +3080,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
else:
ans = self
- if context._rounding_decision == ALWAYS_ROUND:
- return ans._fix(context)
- return ans
+ return ans._fix(context)
def min_mag(self, other, context=None):
"""Compares the values numerically with their sign ignored."""
@@ -3139,9 +3110,7 @@ class Decimal(_numbers.Real, _numbers.Inexact):
else:
ans = other
- if context._rounding_decision == ALWAYS_ROUND:
- return ans._fix(context)
- return ans
+ return ans._fix(context)
def next_minus(self, context=None):
"""Returns the largest representable number smaller than itself."""
@@ -3434,7 +3403,6 @@ class Context(object):
Contains:
prec - precision (for use in rounding, division, square roots..)
rounding - rounding type (how you round)
- _rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
traps - If traps[exception] = 1, then the exception is
raised when it is caused. Otherwise, a value is
substituted in.
@@ -3450,7 +3418,6 @@ class Context(object):
def __init__(self, prec=None, rounding=None,
traps=None, flags=None,
- _rounding_decision=None,
Emin=None, Emax=None,
capitals=None, _clamp=0,
_ignored_flags=None):
@@ -3488,16 +3455,16 @@ class Context(object):
def _shallow_copy(self):
"""Returns a shallow copy from self."""
- nc = Context(self.prec, self.rounding, self.traps, self.flags,
- self._rounding_decision, self.Emin, self.Emax,
- self.capitals, self._clamp, self._ignored_flags)
+ nc = Context(self.prec, self.rounding, self.traps,
+ self.flags, self.Emin, self.Emax,
+ self.capitals, self._clamp, self._ignored_flags)
return nc
def copy(self):
"""Returns a deep copy from self."""
nc = Context(self.prec, self.rounding, self.traps.copy(),
- self.flags.copy(), self._rounding_decision, self.Emin,
- self.Emax, self.capitals, self._clamp, self._ignored_flags)
+ self.flags.copy(), self.Emin, self.Emax,
+ self.capitals, self._clamp, self._ignored_flags)
return nc
__copy__ = copy
@@ -3554,27 +3521,6 @@ class Context(object):
"""Returns maximum exponent (= Emax - prec + 1)"""
return int(self.Emax - self.prec + 1)
- def _set_rounding_decision(self, type):
- """Sets the rounding decision.
-
- Sets the rounding decision, and returns the current (previous)
- rounding decision. Often used like:
-
- context = context._shallow_copy()
- # That so you don't change the calling context
- # if an error occurs in the middle (say DivisionImpossible is raised).
-
- rounding = context._set_rounding_decision(NEVER_ROUND)
- instance = instance / Decimal(2)
- context._set_rounding_decision(rounding)
-
- This will make it not round for that operation.
- """
-
- rounding = self._rounding_decision
- self._rounding_decision = type
- return rounding
-
def _set_rounding(self, type):
"""Sets the rounding type.
@@ -4762,7 +4708,7 @@ class _WorkRep(object):
-def _normalize(op1, op2, shouldround = 0, prec = 0):
+def _normalize(op1, op2, prec = 0):
"""Normalizes op1, op2 to have the same exp and length of coefficient.
Done during addition.
@@ -4779,13 +4725,12 @@ def _normalize(op1, op2, shouldround = 0, prec = 0):
# as adding any positive quantity smaller than 10**exp; similarly
# for subtraction. So if other is smaller than 10**exp we replace
# it with 10**exp. This avoids tmp.exp - other.exp getting too large.
- if shouldround:
- tmp_len = len(str(tmp.int))
- other_len = len(str(other.int))
- exp = tmp.exp + min(-1, tmp_len - prec - 2)
- if other_len + other.exp - 1 < exp:
- other.int = 1
- other.exp = exp
+ tmp_len = len(str(tmp.int))
+ other_len = len(str(other.int))
+ exp = tmp.exp + min(-1, tmp_len - prec - 2)
+ if other_len + other.exp - 1 < exp:
+ other.int = 1
+ other.exp = exp
tmp.int *= 10 ** (tmp.exp - other.exp)
tmp.exp = other.exp
@@ -5153,7 +5098,6 @@ DefaultContext = Context(
prec=28, rounding=ROUND_HALF_EVEN,
traps=[DivisionByZero, Overflow, InvalidOperation],
flags=[],
- _rounding_decision=ALWAYS_ROUND,
Emax=999999999,
Emin=-999999999,
capitals=1