Removed the private _rounding_decision: it was not needed, and the code

is now simpler.  Thanks Mark Dickinson.
This commit is contained in:
Facundo Batista 2007-12-17 14:18:42 +00:00
parent d41b8dc58c
commit e64acfad3d
1 changed files with 38 additions and 94 deletions

View File

@ -146,10 +146,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):
@ -911,9 +907,7 @@ class Decimal(object):
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.
@ -933,26 +927,23 @@ class Decimal(object):
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:
@ -985,8 +976,6 @@ class Decimal(object):
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:
@ -998,33 +987,29 @@ class Decimal(object):
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
@ -1049,8 +1034,7 @@ class Decimal(object):
result.exp = op1.exp
ans = Decimal(result)
if shouldround:
ans = ans._fix(context)
ans = ans._fix(context)
return ans
__radd__ = __add__
@ -1107,34 +1091,29 @@ class Decimal(object):
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__
@ -1274,8 +1253,7 @@ class Decimal(object):
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):
@ -1309,8 +1287,7 @@ class Decimal(object):
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):
@ -2487,9 +2464,7 @@ class Decimal(object):
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.
@ -2523,9 +2498,7 @@ class Decimal(object):
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"""
@ -3096,9 +3069,7 @@ class Decimal(object):
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."""
@ -3128,9 +3099,7 @@ class Decimal(object):
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."""
@ -3423,7 +3392,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.
@ -3439,7 +3407,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):
@ -3479,16 +3446,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
@ -3545,27 +3512,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.
@ -4753,7 +4699,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.
@ -4770,13 +4716,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
@ -5144,7 +5089,6 @@ DefaultContext = Context(
prec=28, rounding=ROUND_HALF_EVEN,
traps=[DivisionByZero, Overflow, InvalidOperation],
flags=[],
_rounding_decision=ALWAYS_ROUND,
Emax=999999999,
Emin=-999999999,
capitals=1