Kaydet (Commit) dab988dd authored tarafından Raymond Hettinger's avatar Raymond Hettinger

SF patch #1043218

Simplify internal calls and logic for _fix() and _fixexponents().
(Contributed by Facundo Batista.)
üst 7a8ce5af
...@@ -459,7 +459,7 @@ class Decimal(object): ...@@ -459,7 +459,7 @@ class Decimal(object):
# (-1)**_sign * _int * 10**_exp # (-1)**_sign * _int * 10**_exp
# Special values are signified by _is_special == True # Special values are signified by _is_special == True
# We're immutable, so use _new__ not __init__ # We're immutable, so use __new__ not __init__
def __new__(cls, value="0", context=None): def __new__(cls, value="0", context=None):
"""Create a decimal point instance. """Create a decimal point instance.
...@@ -851,7 +851,7 @@ class Decimal(object): ...@@ -851,7 +851,7 @@ class Decimal(object):
if context is None: if context is None:
context = getcontext() context = getcontext()
if context._rounding_decision == ALWAYS_ROUND: if context._rounding_decision == ALWAYS_ROUND:
return Decimal((sign, self._int, self._exp))._fix(context=context) return Decimal((sign, self._int, self._exp))._fix(context)
return Decimal( (sign, self._int, self._exp)) return Decimal( (sign, self._int, self._exp))
def __pos__(self, context=None): def __pos__(self, context=None):
...@@ -873,7 +873,7 @@ class Decimal(object): ...@@ -873,7 +873,7 @@ class Decimal(object):
context = getcontext() context = getcontext()
if context._rounding_decision == ALWAYS_ROUND: if context._rounding_decision == ALWAYS_ROUND:
ans = self._fix(context=context) ans = self._fix(context)
else: else:
ans = Decimal(self) ans = Decimal(self)
ans._sign = sign ans._sign = sign
...@@ -943,14 +943,14 @@ class Decimal(object): ...@@ -943,14 +943,14 @@ class Decimal(object):
exp = other._exp - context.prec-1 exp = other._exp - context.prec-1
ans = other._rescale(exp, watchexp=0, context=context) ans = other._rescale(exp, watchexp=0, context=context)
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
if not other: if not other:
if exp < self._exp - context.prec-1: if exp < self._exp - context.prec-1:
exp = self._exp - context.prec-1 exp = self._exp - context.prec-1
ans = self._rescale(exp, watchexp=0, context=context) ans = self._rescale(exp, watchexp=0, context=context)
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
op1 = _WorkRep(self) op1 = _WorkRep(self)
...@@ -991,7 +991,7 @@ class Decimal(object): ...@@ -991,7 +991,7 @@ class Decimal(object):
result.exp = op1.exp result.exp = op1.exp
ans = Decimal(result) ans = Decimal(result)
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
__radd__ = __add__ __radd__ = __add__
...@@ -1052,7 +1052,7 @@ class Decimal(object): ...@@ -1052,7 +1052,7 @@ class Decimal(object):
if context is None: if context is None:
context = getcontext() context = getcontext()
if round and context._rounding_decision == ALWAYS_ROUND: if round and context._rounding_decision == ALWAYS_ROUND:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
def __mul__(self, other, context=None): def __mul__(self, other, context=None):
...@@ -1090,19 +1090,19 @@ class Decimal(object): ...@@ -1090,19 +1090,19 @@ class Decimal(object):
ans = Decimal((resultsign, (0,), resultexp)) ans = Decimal((resultsign, (0,), resultexp))
if shouldround: if shouldround:
#Fixing in case the exponent is out of bounds #Fixing in case the exponent is out of bounds
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
# 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 = Decimal((resultsign, other._int, resultexp)) ans = Decimal((resultsign, other._int, resultexp))
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
if other._int == (1,): if other._int == (1,):
ans = Decimal((resultsign, self._int, resultexp)) ans = Decimal((resultsign, self._int, resultexp))
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
op1 = _WorkRep(self) op1 = _WorkRep(self)
...@@ -1110,7 +1110,7 @@ class Decimal(object): ...@@ -1110,7 +1110,7 @@ class Decimal(object):
ans = Decimal( (resultsign, map(int, str(op1.int * op2.int)), resultexp)) ans = Decimal( (resultsign, map(int, str(op1.int * op2.int)), resultexp))
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
__rmul__ = __mul__ __rmul__ = __mul__
...@@ -1209,7 +1209,7 @@ class Decimal(object): ...@@ -1209,7 +1209,7 @@ class Decimal(object):
exp = min(self._exp, other._exp) exp = min(self._exp, other._exp)
ans2 = self._rescale(exp, context=context, watchexp=0) ans2 = self._rescale(exp, context=context, watchexp=0)
if shouldround: if shouldround:
ans2 = ans2._fix(context=context) ans2 = ans2._fix(context)
return (Decimal( (sign, (0,), 0) ), return (Decimal( (sign, (0,), 0) ),
ans2) ans2)
...@@ -1246,7 +1246,7 @@ class Decimal(object): ...@@ -1246,7 +1246,7 @@ class Decimal(object):
watchexp=0) watchexp=0)
context._regard_flags(*frozen) context._regard_flags(*frozen)
if shouldround: if shouldround:
otherside = otherside._fix(context=context) otherside = otherside._fix(context)
return (Decimal(res), otherside) return (Decimal(res), otherside)
if op1.int == 0 and adjust >= 0 and not divmod: if op1.int == 0 and adjust >= 0 and not divmod:
...@@ -1286,7 +1286,7 @@ class Decimal(object): ...@@ -1286,7 +1286,7 @@ class Decimal(object):
ans = Decimal(res) ans = Decimal(res)
if shouldround: if shouldround:
ans = ans._fix(context=context) ans = ans._fix(context)
return ans return ans
def __rdiv__(self, other, context=None): def __rdiv__(self, other, context=None):
...@@ -1371,7 +1371,7 @@ class Decimal(object): ...@@ -1371,7 +1371,7 @@ class Decimal(object):
r._sign, comparison._sign = s1, s2 r._sign, comparison._sign = s1, s2
#Get flags now #Get flags now
self.__divmod__(other, context=context) self.__divmod__(other, context=context)
return r._fix(context=context) return r._fix(context)
r._sign, comparison._sign = s1, s2 r._sign, comparison._sign = s1, s2
rounding = context._set_rounding_decision(NEVER_ROUND) rounding = context._set_rounding_decision(NEVER_ROUND)
...@@ -1402,7 +1402,7 @@ class Decimal(object): ...@@ -1402,7 +1402,7 @@ class Decimal(object):
else: else:
r._sign, comparison._sign = s1, s2 r._sign, comparison._sign = s1, s2
return r._fix(context=context) return r._fix(context)
def __floordiv__(self, other, context=None): def __floordiv__(self, other, context=None):
"""self // other""" """self // other"""
...@@ -1441,44 +1441,31 @@ class Decimal(object): ...@@ -1441,44 +1441,31 @@ class Decimal(object):
""" """
return long(self.__int__()) return long(self.__int__())
def _fix(self, prec=None, rounding=None, folddown=None, context=None): def _fix(self, context):
"""Round if it is necessary to keep self within prec precision. """Round if it is necessary to keep self within prec precision.
Rounds and fixes the exponent. Does not raise on a sNaN. Rounds and fixes the exponent. Does not raise on a sNaN.
Arguments: Arguments:
self - Decimal instance self - Decimal instance
prec - precision to which to round. By default, the context decides.
rounding - Rounding method. By default, the context decides.
folddown - Fold down high elements, by default context._clamp
context - context used. context - context used.
""" """
if self._is_special: if self._is_special:
return self return self
if context is None: if context is None:
context = getcontext() context = getcontext()
if prec is None: prec = context.prec
prec = context.prec ans = self._fixexponents(prec, context)
ans = Decimal(self)
ans = ans._fixexponents(prec, rounding, folddown=folddown,
context=context)
if len(ans._int) > prec: if len(ans._int) > prec:
ans = ans._round(prec, rounding, context=context) ans = ans._round(prec, context=context)
ans = ans._fixexponents(prec, rounding, folddown=folddown, ans = ans._fixexponents(prec, context)
context=context)
return ans return ans
def _fixexponents(self, prec=None, rounding=None, folddown=None, def _fixexponents(self, prec, context):
context=None): """Fix the exponents and return a copy with the exponent in bounds.
"""Fix the exponents and return a copy with the exponent in bounds.""" Only call if known to not be a special value.
if self._is_special: """
return self folddown = context._clamp
if context is None:
context = getcontext()
if prec is None:
prec = context.prec
if folddown is None:
folddown = context._clamp
Emin = context.Emin Emin = context.Emin
ans = Decimal(self) ans = Decimal(self)
ans_adjusted = ans.adjusted() ans_adjusted = ans.adjusted()
...@@ -1756,7 +1743,7 @@ class Decimal(object): ...@@ -1756,7 +1743,7 @@ class Decimal(object):
context.prec = firstprec context.prec = firstprec
if shouldround: if shouldround:
return val._fix(context=context) return val._fix(context)
return val return val
def __rpow__(self, other, context=None): def __rpow__(self, other, context=None):
...@@ -1772,7 +1759,7 @@ class Decimal(object): ...@@ -1772,7 +1759,7 @@ class Decimal(object):
if ans: if ans:
return ans return ans
dup = self._fix(context=context) dup = self._fix(context)
if dup._isinfinity(): if dup._isinfinity():
return dup return dup
...@@ -1786,7 +1773,7 @@ class Decimal(object): ...@@ -1786,7 +1773,7 @@ class Decimal(object):
return Decimal( (dup._sign, dup._int[:end], exp) ) return Decimal( (dup._sign, dup._int[:end], exp) )
def quantize(self, exp, rounding = None, context=None, watchexp = 1): def quantize(self, exp, rounding=None, context=None, watchexp=1):
"""Quantize self so its exponent is the same as that of exp. """Quantize self so its exponent is the same as that of exp.
Similar to self._rescale(exp._exp) but with error checking. Similar to self._rescale(exp._exp) but with error checking.
...@@ -1817,7 +1804,7 @@ class Decimal(object): ...@@ -1817,7 +1804,7 @@ class Decimal(object):
return self._isinfinity() and other._isinfinity() and True return self._isinfinity() and other._isinfinity() and True
return self._exp == other._exp return self._exp == other._exp
def _rescale(self, exp, rounding = None, context=None, watchexp = 1): def _rescale(self, exp, rounding=None, context=None, watchexp=1):
"""Rescales so that the exponent is exp. """Rescales so that the exponent is exp.
exp = exp to scale to (an integer) exp = exp to scale to (an integer)
...@@ -1848,13 +1835,13 @@ class Decimal(object): ...@@ -1848,13 +1835,13 @@ class Decimal(object):
return ans return ans
diff = self._exp - exp diff = self._exp - exp
digits = len(self._int)+diff digits = len(self._int) + diff
if watchexp and digits > context.prec: if watchexp and digits > context.prec:
return context._raise_error(InvalidOperation, 'Rescale > prec') return context._raise_error(InvalidOperation, 'Rescale > prec')
tmp = Decimal(self) tmp = Decimal(self)
tmp._int = (0,)+tmp._int tmp._int = (0,) + tmp._int
digits += 1 digits += 1
prevexact = context.flags[Inexact] prevexact = context.flags[Inexact]
...@@ -1875,7 +1862,7 @@ class Decimal(object): ...@@ -1875,7 +1862,7 @@ class Decimal(object):
return context._raise_error(InvalidOperation, 'rescale(a, INF)') return context._raise_error(InvalidOperation, 'rescale(a, INF)')
return tmp return tmp
def to_integral(self, rounding = None, context=None): def to_integral(self, rounding=None, context=None):
"""Rounds to the nearest integer, without raising inexact, rounded.""" """Rounds to the nearest integer, without raising inexact, rounded."""
if self._is_special: if self._is_special:
ans = self._check_nans(context=context) ans = self._check_nans(context=context)
...@@ -1991,7 +1978,7 @@ class Decimal(object): ...@@ -1991,7 +1978,7 @@ class Decimal(object):
context.prec = firstprec context.prec = firstprec
context.rounding = rounding context.rounding = rounding
ans = ans._fix(context=context) ans = ans._fix(context)
rounding = context._set_rounding_decision(NEVER_ROUND) rounding = context._set_rounding_decision(NEVER_ROUND)
if not ans.__mul__(ans, context=context) == self: if not ans.__mul__(ans, context=context) == self:
...@@ -2011,7 +1998,7 @@ class Decimal(object): ...@@ -2011,7 +1998,7 @@ class Decimal(object):
context._regard_flags(flags) context._regard_flags(flags)
context.Emax, context.Emin = Emax, Emin context.Emax, context.Emin = Emax, Emin
return ans._fix(context=context) return ans._fix(context)
def max(self, other, context=None): def max(self, other, context=None):
"""Returns the larger value. """Returns the larger value.
...@@ -2057,7 +2044,7 @@ class Decimal(object): ...@@ -2057,7 +2044,7 @@ class Decimal(object):
if context is None: if context is None:
context = getcontext() context = getcontext()
context._rounding_decision == ALWAYS_ROUND context._rounding_decision == ALWAYS_ROUND
return ans._fix(context=context) return ans._fix(context)
def min(self, other, context=None): def min(self, other, context=None):
"""Returns the smaller value. """Returns the smaller value.
...@@ -2103,7 +2090,7 @@ class Decimal(object): ...@@ -2103,7 +2090,7 @@ class Decimal(object):
if context is None: if context is None:
context = getcontext() context = getcontext()
context._rounding_decision == ALWAYS_ROUND context._rounding_decision == ALWAYS_ROUND
return ans._fix(context=context) return ans._fix(context)
def _isinteger(self): def _isinteger(self):
"""Returns whether self is an integer""" """Returns whether self is an integer"""
...@@ -2316,7 +2303,7 @@ class Context(object): ...@@ -2316,7 +2303,7 @@ class Context(object):
def create_decimal(self, num='0'): def create_decimal(self, num='0'):
"""Creates a new Decimal instance but using self as context.""" """Creates a new Decimal instance but using self as context."""
d = Decimal(num, context=self) d = Decimal(num, context=self)
return d._fix(context=self) return d._fix(self)
#Methods #Methods
def abs(self, a): def abs(self, a):
...@@ -2348,7 +2335,7 @@ class Context(object): ...@@ -2348,7 +2335,7 @@ class Context(object):
return a.__add__(b, context=self) return a.__add__(b, context=self)
def _apply(self, a): def _apply(self, a):
return str(a._fix(context=self)) return str(a._fix(self))
def compare(self, a, b): def compare(self, a, b):
"""Compares values numerically. """Compares values numerically.
......
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