Commit de9b9207 authored by Facundo Batista's avatar Facundo Batista

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

is now simpler.  Thanks Mark Dickinson.
parent e52d535a
...@@ -146,10 +146,6 @@ ROUND_UP = 'ROUND_UP' ...@@ -146,10 +146,6 @@ ROUND_UP = 'ROUND_UP'
ROUND_HALF_DOWN = 'ROUND_HALF_DOWN' ROUND_HALF_DOWN = 'ROUND_HALF_DOWN'
ROUND_05UP = 'ROUND_05UP' 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 # Errors
class DecimalException(ArithmeticError): class DecimalException(ArithmeticError):
...@@ -911,9 +907,7 @@ class Decimal(object): ...@@ -911,9 +907,7 @@ class Decimal(object):
if context is None: if context is None:
context = getcontext() context = getcontext()
if context._rounding_decision == ALWAYS_ROUND:
return ans._fix(context) return ans._fix(context)
return ans
def __pos__(self, context=None): def __pos__(self, context=None):
"""Returns a copy, unless it is a sNaN. """Returns a copy, unless it is a sNaN.
...@@ -933,26 +927,23 @@ class Decimal(object): ...@@ -933,26 +927,23 @@ class Decimal(object):
if context is None: if context is None:
context = getcontext() context = getcontext()
if context._rounding_decision == ALWAYS_ROUND:
return ans._fix(context) return ans._fix(context)
return ans
def __abs__(self, round=1, context=None): def __abs__(self, round=True, context=None):
"""Returns the absolute value of self. """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: if self._is_special:
ans = self._check_nans(context=context) ans = self._check_nans(context=context)
if ans: if ans:
return 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: if self._sign:
ans = self.__neg__(context=context) ans = self.__neg__(context=context)
else: else:
...@@ -985,8 +976,6 @@ class Decimal(object): ...@@ -985,8 +976,6 @@ class Decimal(object):
if other._isinfinity(): if other._isinfinity():
return Decimal(other) # Can't both be infinity here return Decimal(other) # Can't both be infinity here
shouldround = context._rounding_decision == ALWAYS_ROUND
exp = min(self._exp, other._exp) exp = min(self._exp, other._exp)
negativezero = 0 negativezero = 0
if context.rounding == ROUND_FLOOR and self._sign != other._sign: if context.rounding == ROUND_FLOOR and self._sign != other._sign:
...@@ -998,32 +987,28 @@ class Decimal(object): ...@@ -998,32 +987,28 @@ class Decimal(object):
if negativezero: if negativezero:
sign = 1 sign = 1
ans = _dec_from_triple(sign, '0', exp) ans = _dec_from_triple(sign, '0', exp)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
if not self: if not self:
exp = max(exp, other._exp - context.prec-1) exp = max(exp, other._exp - context.prec-1)
ans = other._rescale(exp, context.rounding) ans = other._rescale(exp, context.rounding)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
if not other: if not other:
exp = max(exp, self._exp - context.prec-1) exp = max(exp, self._exp - context.prec-1)
ans = self._rescale(exp, context.rounding) ans = self._rescale(exp, context.rounding)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
op1 = _WorkRep(self) op1 = _WorkRep(self)
op2 = _WorkRep(other) op2 = _WorkRep(other)
op1, op2 = _normalize(op1, op2, shouldround, context.prec) op1, op2 = _normalize(op1, op2, context.prec)
result = _WorkRep() result = _WorkRep()
if op1.sign != op2.sign: if op1.sign != op2.sign:
# Equal and opposite # Equal and opposite
if op1.int == op2.int: if op1.int == op2.int:
ans = _dec_from_triple(negativezero, '0', exp) ans = _dec_from_triple(negativezero, '0', exp)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
if op1.int < op2.int: if op1.int < op2.int:
...@@ -1049,7 +1034,6 @@ class Decimal(object): ...@@ -1049,7 +1034,6 @@ class Decimal(object):
result.exp = op1.exp result.exp = op1.exp
ans = Decimal(result) ans = Decimal(result)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
...@@ -1107,12 +1091,10 @@ class Decimal(object): ...@@ -1107,12 +1091,10 @@ class Decimal(object):
return Infsign[resultsign] return Infsign[resultsign]
resultexp = self._exp + other._exp resultexp = self._exp + other._exp
shouldround = context._rounding_decision == ALWAYS_ROUND
# Special case for multiplying by zero # Special case for multiplying by zero
if not self or not other: if not self or not other:
ans = _dec_from_triple(resultsign, '0', resultexp) ans = _dec_from_triple(resultsign, '0', resultexp)
if shouldround:
# Fixing in case the exponent is out of bounds # Fixing in case the exponent is out of bounds
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
...@@ -1120,12 +1102,10 @@ class Decimal(object): ...@@ -1120,12 +1102,10 @@ class Decimal(object):
# Special case for multiplying by power of 10 # Special case for multiplying by power of 10
if self._int == '1': if self._int == '1':
ans = _dec_from_triple(resultsign, other._int, resultexp) ans = _dec_from_triple(resultsign, other._int, resultexp)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
if other._int == '1': if other._int == '1':
ans = _dec_from_triple(resultsign, self._int, resultexp) ans = _dec_from_triple(resultsign, self._int, resultexp)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
...@@ -1133,7 +1113,6 @@ class Decimal(object): ...@@ -1133,7 +1113,6 @@ class Decimal(object):
op2 = _WorkRep(other) op2 = _WorkRep(other)
ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp) ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp)
if shouldround:
ans = ans._fix(context) ans = ans._fix(context)
return ans return ans
...@@ -1274,7 +1253,6 @@ class Decimal(object): ...@@ -1274,7 +1253,6 @@ class Decimal(object):
context._raise_error(InvalidOperation, 'x % 0')) context._raise_error(InvalidOperation, 'x % 0'))
quotient, remainder = self._divide(other, context) quotient, remainder = self._divide(other, context)
if context._rounding_decision == ALWAYS_ROUND:
remainder = remainder._fix(context) remainder = remainder._fix(context)
return quotient, remainder return quotient, remainder
...@@ -1309,7 +1287,6 @@ class Decimal(object): ...@@ -1309,7 +1287,6 @@ class Decimal(object):
return context._raise_error(DivisionUndefined, '0 % 0') return context._raise_error(DivisionUndefined, '0 % 0')
remainder = self._divide(other, context)[1] remainder = self._divide(other, context)[1]
if context._rounding_decision == ALWAYS_ROUND:
remainder = remainder._fix(context) remainder = remainder._fix(context)
return remainder return remainder
...@@ -2487,9 +2464,7 @@ class Decimal(object): ...@@ -2487,9 +2464,7 @@ class Decimal(object):
else: else:
ans = self ans = self
if context._rounding_decision == ALWAYS_ROUND:
return ans._fix(context) return ans._fix(context)
return ans
def min(self, other, context=None): def min(self, other, context=None):
"""Returns the smaller value. """Returns the smaller value.
...@@ -2523,9 +2498,7 @@ class Decimal(object): ...@@ -2523,9 +2498,7 @@ class Decimal(object):
else: else:
ans = other ans = other
if context._rounding_decision == ALWAYS_ROUND:
return ans._fix(context) return ans._fix(context)
return ans
def _isinteger(self): def _isinteger(self):
"""Returns whether self is an integer""" """Returns whether self is an integer"""
...@@ -3096,9 +3069,7 @@ class Decimal(object): ...@@ -3096,9 +3069,7 @@ class Decimal(object):
else: else:
ans = self ans = self
if context._rounding_decision == ALWAYS_ROUND:
return ans._fix(context) return ans._fix(context)
return ans
def min_mag(self, other, context=None): def min_mag(self, other, context=None):
"""Compares the values numerically with their sign ignored.""" """Compares the values numerically with their sign ignored."""
...@@ -3128,9 +3099,7 @@ class Decimal(object): ...@@ -3128,9 +3099,7 @@ class Decimal(object):
else: else:
ans = other ans = other
if context._rounding_decision == ALWAYS_ROUND:
return ans._fix(context) return ans._fix(context)
return ans
def next_minus(self, context=None): def next_minus(self, context=None):
"""Returns the largest representable number smaller than itself.""" """Returns the largest representable number smaller than itself."""
...@@ -3423,7 +3392,6 @@ class Context(object): ...@@ -3423,7 +3392,6 @@ class Context(object):
Contains: Contains:
prec - precision (for use in rounding, division, square roots..) prec - precision (for use in rounding, division, square roots..)
rounding - rounding type (how you round) rounding - rounding type (how you round)
_rounding_decision - ALWAYS_ROUND, NEVER_ROUND -- do you round?
traps - If traps[exception] = 1, then the exception is traps - If traps[exception] = 1, then the exception is
raised when it is caused. Otherwise, a value is raised when it is caused. Otherwise, a value is
substituted in. substituted in.
...@@ -3439,7 +3407,6 @@ class Context(object): ...@@ -3439,7 +3407,6 @@ class Context(object):
def __init__(self, prec=None, rounding=None, def __init__(self, prec=None, rounding=None,
traps=None, flags=None, traps=None, flags=None,
_rounding_decision=None,
Emin=None, Emax=None, Emin=None, Emax=None,
capitals=None, _clamp=0, capitals=None, _clamp=0,
_ignored_flags=None): _ignored_flags=None):
...@@ -3479,16 +3446,16 @@ class Context(object): ...@@ -3479,16 +3446,16 @@ class Context(object):
def _shallow_copy(self): def _shallow_copy(self):
"""Returns a shallow copy from self.""" """Returns a shallow copy from self."""
nc = Context(self.prec, self.rounding, self.traps, self.flags, nc = Context(self.prec, self.rounding, self.traps,
self._rounding_decision, self.Emin, self.Emax, self.flags, self.Emin, self.Emax,
self.capitals, self._clamp, self._ignored_flags) self.capitals, self._clamp, self._ignored_flags)
return nc return nc
def copy(self): def copy(self):
"""Returns a deep copy from self.""" """Returns a deep copy from self."""
nc = Context(self.prec, self.rounding, self.traps.copy(), nc = Context(self.prec, self.rounding, self.traps.copy(),
self.flags.copy(), self._rounding_decision, self.Emin, self.flags.copy(), self.Emin, self.Emax,
self.Emax, self.capitals, self._clamp, self._ignored_flags) self.capitals, self._clamp, self._ignored_flags)
return nc return nc
__copy__ = copy __copy__ = copy
...@@ -3545,27 +3512,6 @@ class Context(object): ...@@ -3545,27 +3512,6 @@ class Context(object):
"""Returns maximum exponent (= Emax - prec + 1)""" """Returns maximum exponent (= Emax - prec + 1)"""
return int(self.Emax - self.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): def _set_rounding(self, type):
"""Sets the rounding type. """Sets the rounding type.
...@@ -4753,7 +4699,7 @@ class _WorkRep(object): ...@@ -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. """Normalizes op1, op2 to have the same exp and length of coefficient.
Done during addition. Done during addition.
...@@ -4770,7 +4716,6 @@ def _normalize(op1, op2, shouldround = 0, prec = 0): ...@@ -4770,7 +4716,6 @@ def _normalize(op1, op2, shouldround = 0, prec = 0):
# as adding any positive quantity smaller than 10**exp; similarly # as adding any positive quantity smaller than 10**exp; similarly
# for subtraction. So if other is smaller than 10**exp we replace # 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. # it with 10**exp. This avoids tmp.exp - other.exp getting too large.
if shouldround:
tmp_len = len(str(tmp.int)) tmp_len = len(str(tmp.int))
other_len = len(str(other.int)) other_len = len(str(other.int))
exp = tmp.exp + min(-1, tmp_len - prec - 2) exp = tmp.exp + min(-1, tmp_len - prec - 2)
...@@ -5144,7 +5089,6 @@ DefaultContext = Context( ...@@ -5144,7 +5089,6 @@ DefaultContext = Context(
prec=28, rounding=ROUND_HALF_EVEN, prec=28, rounding=ROUND_HALF_EVEN,
traps=[DivisionByZero, Overflow, InvalidOperation], traps=[DivisionByZero, Overflow, InvalidOperation],
flags=[], flags=[],
_rounding_decision=ALWAYS_ROUND,
Emax=999999999, Emax=999999999,
Emin=-999999999, Emin=-999999999,
capitals=1 capitals=1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment