Index: Lib/decimal.py =================================================================== --- Lib/decimal.py (revision 61909) +++ Lib/decimal.py (working copy) @@ -1,3 +1,4 @@ +# XXX look for XXX and remove them # Copyright (c) 2004 Python Software Foundation. # All rights reserved. @@ -345,12 +346,12 @@ if sign == 0: if context.rounding == ROUND_CEILING: return Infsign[sign] - return _dec_from_triple(sign, '9'*context.prec, + return _dec_from_triple(sign, b'9'*context.prec, context.Emax-context.prec+1) if sign == 1: if context.rounding == ROUND_FLOOR: return Infsign[sign] - return _dec_from_triple(sign, '9'*context.prec, + return _dec_from_triple(sign, b'9'*context.prec, context.Emax-context.prec+1) @@ -539,16 +540,22 @@ self = object.__new__(cls) # From a string - # REs insist on real strings, so we can too. if isinstance(value, str): - m = _parser(value.strip()) + # all legal characters for a numeric string are ASCII + try: + bytes_value = bytes(value.strip(), 'ascii') + except UnicodeEncodeError: + return context._raise_error(ConversionSyntax, + "Invalid literal for Decimal: %r" % value) + + m = _parser(bytes_value) if m is None: if context is None: context = getcontext() return context._raise_error(ConversionSyntax, "Invalid literal for Decimal: %r" % value) - if m.group('sign') == "-": + if m.group('sign') == b"-": self._sign = 1 else: self._sign = 0 @@ -558,24 +565,25 @@ fracpart = m.group('frac') exp = int(m.group('exp') or '0') if fracpart is not None: - self._int = (intpart+fracpart).lstrip('0') or '0' + self._int = (intpart+fracpart).lstrip(b'0') or b'0' self._exp = exp - len(fracpart) else: - self._int = intpart.lstrip('0') or '0' + self._int = intpart.lstrip(b'0') or b'0' self._exp = exp self._is_special = False else: diag = m.group('diag') + assert diag is None or type(diag) is bytes #XXX remove this later if diag is not None: # NaN - self._int = diag.lstrip('0') + self._int = diag.lstrip(b'0') if m.group('signal'): self._exp = 'N' else: self._exp = 'n' else: # infinity - self._int = '0' + self._int = b'0' self._exp = 'F' self._is_special = True return self @@ -587,7 +595,7 @@ else: self._sign = 1 self._exp = 0 - self._int = str(abs(value)) + self._int = bytes(str(abs(value)), 'ascii') self._is_special = False return self @@ -602,7 +610,7 @@ # From an internal working value if isinstance(value, _WorkRep): self._sign = value.sign - self._int = str(value.int) + self._int = bytes(str(value.int), 'ascii') self._exp = int(value.exp) self._is_special = False return self @@ -621,7 +629,7 @@ self._sign = value[0] if value[2] == 'F': # infinity: value[1] is ignored - self._int = '0' + self._int = b'0' self._exp = value[2] self._is_special = True else: @@ -638,12 +646,12 @@ "0 through 9.") if value[2] in ('n', 'N'): # NaN: digits form the diagnostic - self._int = ''.join(map(str, digits)) + self._int = bytes(''.join(map(str, digits)), 'ascii') self._exp = value[2] self._is_special = True elif isinstance(value[2], int): # finite number: digits give the coefficient - self._int = ''.join(map(str, digits or [0])) + self._int = bytes(''.join(map(str, digits or [0])), 'ascii') self._exp = value[2] self._is_special = False else: @@ -756,7 +764,7 @@ NaNs and infinities are considered nonzero. """ - return self._is_special or self._int != '0' + return self._is_special or self._int != b'0' def _cmp(self, other): """Compare the two non-NaN decimal instances self and other. @@ -785,8 +793,8 @@ self_adjusted = self.adjusted() other_adjusted = other.adjusted() if self_adjusted == other_adjusted: - self_padded = self._int + '0'*(self._exp - other._exp) - other_padded = other._int + '0'*(other._exp - self._exp) + self_padded = self._int + b'0'*(self._exp - other._exp) + other_padded = other._int + b'0'*(other._exp - self._exp) return cmp(self_padded, other_padded) * (-1)**self._sign elif self_adjusted > other_adjusted: return (-1)**self._sign @@ -907,14 +915,15 @@ # zeros removed. return hash((self._sign, self._exp+len(self._int), - self._int.rstrip('0'))) + self._int.rstrip(b'0'))) def as_tuple(self): """Represents the number as a triple tuple. To show the internals exactly as they are. """ - return DecimalTuple(self._sign, tuple(map(int, self._int)), self._exp) + coeff = tuple(int(chr(i)) for i in self._int) + return DecimalTuple(self._sign, coeff, self._exp) def __repr__(self): """Represents the number as an instance of Decimal.""" @@ -932,9 +941,9 @@ if self._exp == 'F': return sign + 'Infinity' elif self._exp == 'n': - return sign + 'NaN' + self._int + return sign + 'NaN' + str(self._int, 'ascii') else: # self._exp == 'N' - return sign + 'sNaN' + self._int + return sign + 'sNaN' + str(self._int, 'ascii') # number of digits of self._int to left of decimal point leftdigits = self._exp + len(self._int) @@ -948,7 +957,7 @@ elif not eng: # usual scientific notation: 1 digit on left of the point dotplace = 1 - elif self._int == '0': + elif self._int == b'0': # engineering notation, zero dotplace = (leftdigits + 1) % 3 - 1 else: @@ -957,13 +966,13 @@ if dotplace <= 0: intpart = '0' - fracpart = '.' + '0'*(-dotplace) + self._int + fracpart = '.' + '0'*(-dotplace) + str(self._int, 'ascii') elif dotplace >= len(self._int): - intpart = self._int+'0'*(dotplace-len(self._int)) + intpart = str(self._int+b'0'*(dotplace-len(self._int)), 'ascii') fracpart = '' else: - intpart = self._int[:dotplace] - fracpart = '.' + self._int[dotplace:] + intpart = str(self._int[:dotplace], 'ascii') + fracpart = '.' + str(self._int[dotplace:], 'ascii') if leftdigits == dotplace: exp = '' else: @@ -1080,7 +1089,7 @@ sign = min(self._sign, other._sign) if negativezero: sign = 1 - ans = _dec_from_triple(sign, '0', exp) + ans = _dec_from_triple(sign, b'0', exp) ans = ans._fix(context) return ans if not self: @@ -1102,7 +1111,7 @@ if op1.sign != op2.sign: # Equal and opposite if op1.int == op2.int: - ans = _dec_from_triple(negativezero, '0', exp) + ans = _dec_from_triple(negativezero, b'0', exp) ans = ans._fix(context) return ans if op1.int < op2.int: @@ -1188,17 +1197,17 @@ # Special case for multiplying by zero if not self or not other: - ans = _dec_from_triple(resultsign, '0', resultexp) + ans = _dec_from_triple(resultsign, b'0', resultexp) # 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': + if self._int == b'1': ans = _dec_from_triple(resultsign, other._int, resultexp) ans = ans._fix(context) return ans - if other._int == '1': + if other._int == b'1': ans = _dec_from_triple(resultsign, self._int, resultexp) ans = ans._fix(context) return ans @@ -1206,7 +1215,7 @@ op1 = _WorkRep(self) op2 = _WorkRep(other) - ans = _dec_from_triple(resultsign, str(op1.int * op2.int), resultexp) + ans = _dec_from_triple(resultsign, bytes(str(op1.int * op2.int), 'ascii'), resultexp) ans = ans._fix(context) return ans @@ -1236,7 +1245,7 @@ if other._isinfinity(): context._raise_error(Clamped, 'Division by infinity') - return _dec_from_triple(sign, '0', context.Etiny()) + return _dec_from_triple(sign, b'0', context.Etiny()) # Special cases for zeroes if not other: @@ -1268,7 +1277,7 @@ coeff //= 10 exp += 1 - ans = _dec_from_triple(sign, str(coeff), exp) + ans = _dec_from_triple(sign, bytes(str(coeff), 'ascii'), exp) return ans._fix(context) def _divide(self, other, context): @@ -1285,7 +1294,7 @@ expdiff = self.adjusted() - other.adjusted() if not self or other._isinfinity() or expdiff <= -2: - return (_dec_from_triple(sign, '0', 0), + return (_dec_from_triple(sign, b'0', 0), self._rescale(ideal_exp, context.rounding)) if expdiff <= context.prec: op1 = _WorkRep(self) @@ -1296,8 +1305,8 @@ op2.int *= 10**(op2.exp - op1.exp) q, r = divmod(op1.int, op2.int) if q < 10**context.prec: - return (_dec_from_triple(sign, str(q), 0), - _dec_from_triple(self._sign, str(r), ideal_exp)) + return (_dec_from_triple(sign, bytes(str(q), 'ascii'), 0), + _dec_from_triple(self._sign, bytes(str(r), 'ascii'), ideal_exp)) # Here the quotient is too large to be representable ans = context._raise_error(DivisionImpossible, @@ -1423,7 +1432,7 @@ # self = 0 -> remainder = self, with ideal exponent ideal_exponent = min(self._exp, other._exp) if not self: - ans = _dec_from_triple(self._sign, '0', ideal_exponent) + ans = _dec_from_triple(self._sign, b'0', ideal_exponent) return ans._fix(context) # catch most cases of large or small quotient @@ -1460,7 +1469,7 @@ sign = 1-sign r = -r - ans = _dec_from_triple(sign, str(r), ideal_exponent) + ans = _dec_from_triple(sign, bytes(str(r), 'ascii'), ideal_exponent) return ans._fix(context) def __floordiv__(self, other, context=None): @@ -1514,7 +1523,7 @@ if self._exp >= 0: return s*int(self._int)*10**self._exp else: - return s*int(self._int[:self._exp] or '0') + return s*int(self._int[:self._exp] or b'0') __trunc__ = __int__ @@ -1540,7 +1549,7 @@ # precision-1 if _clamp=1. max_payload_len = context.prec - context._clamp if len(payload) > max_payload_len: - payload = payload[len(payload)-max_payload_len:].lstrip('0') + payload = payload[len(payload)-max_payload_len:].lstrip(b'0') return _dec_from_triple(self._sign, payload, self._exp, True) return Decimal(self) @@ -1571,7 +1580,7 @@ new_exp = min(max(self._exp, Etiny), exp_max) if new_exp != self._exp: context._raise_error(Clamped) - return _dec_from_triple(self._sign, '0', new_exp) + return _dec_from_triple(self._sign, b'0', new_exp) else: return Decimal(self) @@ -1593,13 +1602,13 @@ context._raise_error(Rounded) digits = len(self._int) + self._exp - exp_min if digits < 0: - self = _dec_from_triple(self._sign, '1', exp_min-1) + self = _dec_from_triple(self._sign, b'1', exp_min-1) digits = 0 this_function = getattr(self, self._pick_rounding_function[context.rounding]) changed = this_function(digits) - coeff = self._int[:digits] or '0' + coeff = self._int[:digits] or b'0' if changed == 1: - coeff = str(int(coeff)+1) + coeff = bytes(str(int(coeff)+1), 'ascii') ans = _dec_from_triple(self._sign, coeff, exp_min) if changed: @@ -1624,7 +1633,7 @@ # fold down if _clamp == 1 and self has too few digits if context._clamp == 1 and self._exp > Etop: context._raise_error(Clamped) - self_padded = self._int + '0'*(self._exp - Etop) + self_padded = self._int + b'0'*(self._exp - Etop) return _dec_from_triple(self._sign, self_padded, Etop) # here self was representable to begin with; return unchanged @@ -1658,7 +1667,7 @@ def _round_half_up(self, prec): """Rounds 5 up (away from 0)""" - if self._int[prec] in '56789': + if self._int[prec] in b'56789': return 1 elif _all_zeros(self._int, prec): return 0 @@ -1675,7 +1684,7 @@ def _round_half_even(self, prec): """Round 5 to even, rest to nearest.""" if _exact_half(self._int, prec) and \ - (prec == 0 or self._int[prec-1] in '02468'): + (prec == 0 or self._int[prec-1] in b'02468'): return -1 else: return self._round_half_up(prec) @@ -1702,7 +1711,7 @@ def _round_05up(self, prec): """Round down unless digit prec-1 is 0 or 5.""" - if prec and self._int[prec-1] not in '05': + if prec and self._int[prec-1] not in b'05': return self._round_down(prec) else: return -self._round_down(prec) @@ -1745,7 +1754,7 @@ product = Infsign[self._sign ^ other._sign] else: product = _dec_from_triple(self._sign ^ other._sign, - str(int(self._int) * int(other._int)), + bytes(str(int(self._int) * int(other._int)), 'ascii'), self._exp + other._exp) third = _convert_other(third, raiseit=True) @@ -1833,7 +1842,7 @@ base = pow(base, 10, modulo) base = pow(base, exponent.int, modulo) - return _dec_from_triple(sign, str(base), 0) + return _dec_from_triple(sign, bytes(str(base), 'ascii'), 0) def _power_exact(self, other, p): """Attempt to compute self**other exactly. @@ -1923,7 +1932,7 @@ zeros = min(exponent-ideal_exponent, p-1) else: zeros = 0 - return _dec_from_triple(0, '1' + '0'*zeros, exponent-zeros) + return _dec_from_triple(0, b'1' + b'0'*zeros, exponent-zeros) # case where y is negative: xc must be either a power # of 2 or a power of 5. @@ -1984,7 +1993,7 @@ if xc >= 10**p: return None xe = -e-xe - return _dec_from_triple(0, str(xc), xe) + return _dec_from_triple(0, bytes(str(xc), 'ascii'), xe) # now y is positive; find m and n such that y = m/n if ye >= 0: @@ -2046,7 +2055,7 @@ zeros = min(xe-ideal_exponent, p-len(str_xc)) else: zeros = 0 - return _dec_from_triple(0, str_xc+'0'*zeros, xe-zeros) + return _dec_from_triple(0, bytes(str_xc+'0'*zeros, 'ascii'), xe-zeros) def __pow__(self, other, modulo=None, context=None): """Return self ** other [ % modulo]. @@ -2112,7 +2121,7 @@ # 0**(+ve or Inf)= 0; 0**(-ve or -Inf) = Infinity if not self: if other._sign == 0: - return _dec_from_triple(result_sign, '0', 0) + return _dec_from_triple(result_sign, b'0', 0) else: return Infsign[result_sign] @@ -2121,7 +2130,7 @@ if other._sign == 0: return Infsign[result_sign] else: - return _dec_from_triple(result_sign, '0', 0) + return _dec_from_triple(result_sign, b'0', 0) # 1**other = 1, but the choice of exponent and the flags # depend on the exponent of self, and on whether other is a @@ -2148,7 +2157,7 @@ context._raise_error(Rounded) exp = 1-context.prec - return _dec_from_triple(result_sign, '1'+'0'*-exp, exp) + return _dec_from_triple(result_sign, b'1'+b'0'*-exp, exp) # compute adjusted exponent of self self_adj = self.adjusted() @@ -2157,7 +2166,7 @@ # self ** -infinity is infinity if self < 1, 0 if self > 1 if other._isinfinity(): if (other._sign == 0) == (self_adj < 0): - return _dec_from_triple(result_sign, '0', 0) + return _dec_from_triple(result_sign, b'0', 0) else: return Infsign[result_sign] @@ -2175,13 +2184,13 @@ # self > 1 and other +ve, or self < 1 and other -ve # possibility of overflow if bound >= len(str(context.Emax)): - ans = _dec_from_triple(result_sign, '1', context.Emax+1) + ans = _dec_from_triple(result_sign, b'1', context.Emax+1) else: # self > 1 and other -ve, or self < 1 and other +ve # possibility of underflow to 0 Etiny = context.Etiny() if bound >= len(str(-Etiny)): - ans = _dec_from_triple(result_sign, '1', Etiny-1) + ans = _dec_from_triple(result_sign, b'1', Etiny-1) # try for an exact result with precision +1 if ans is None: @@ -2208,7 +2217,7 @@ break extra += 3 - ans = _dec_from_triple(result_sign, str(coeff), exp) + ans = _dec_from_triple(result_sign, bytes(str(coeff), 'ascii'), exp) # the specification says that for non-integer other we need to # raise Inexact, even when the result is actually exact. In @@ -2220,7 +2229,7 @@ # pad with zeros up to length context.prec+1 if necessary if len(ans._int) <= context.prec: expdiff = context.prec+1 - len(ans._int) - ans = _dec_from_triple(ans._sign, ans._int+'0'*expdiff, + ans = _dec_from_triple(ans._sign, ans._int+b'0'*expdiff, ans._exp-expdiff) if ans.adjusted() < context.Emin: context._raise_error(Underflow) @@ -2253,11 +2262,11 @@ return dup if not dup: - return _dec_from_triple(dup._sign, '0', 0) + return _dec_from_triple(dup._sign, b'0', 0) exp_max = [context.Emax, context.Etop()][context._clamp] end = len(dup._int) exp = dup._exp - while dup._int[end-1] == '0' and exp < exp_max: + while dup._int[end-1] == ord('0') and exp < exp_max: exp += 1 end -= 1 return _dec_from_triple(dup._sign, dup._int[:end], exp) @@ -2301,7 +2310,7 @@ 'target exponent out of bounds in quantize') if not self: - ans = _dec_from_triple(self._sign, '0', exp._exp) + ans = _dec_from_triple(self._sign, b'0', exp._exp) return ans._fix(context) self_adjusted = self.adjusted() @@ -2361,24 +2370,24 @@ if self._is_special: return Decimal(self) if not self: - return _dec_from_triple(self._sign, '0', exp) + return _dec_from_triple(self._sign, b'0', exp) if self._exp >= exp: # pad answer with zeros if necessary return _dec_from_triple(self._sign, - self._int + '0'*(self._exp - exp), exp) + self._int + b'0'*(self._exp - exp), exp) # too many digits; round and lose data. If self.adjusted() < # exp-1, replace self by 10**(exp-1) before rounding digits = len(self._int) + self._exp - exp if digits < 0: - self = _dec_from_triple(self._sign, '1', exp-1) + self = _dec_from_triple(self._sign, b'1', exp-1) digits = 0 this_function = getattr(self, self._pick_rounding_function[rounding]) changed = this_function(digits) - coeff = self._int[:digits] or '0' + coeff = self._int[:digits] or b'0' if changed == 1: - coeff = str(int(coeff)+1) + coeff = bytes(str(int(coeff)+1), 'ascii') return _dec_from_triple(self._sign, coeff, exp) def _round(self, places, rounding): @@ -2422,7 +2431,7 @@ if self._exp >= 0: return Decimal(self) if not self: - return _dec_from_triple(self._sign, '0', 0) + return _dec_from_triple(self._sign, b'0', 0) if context is None: context = getcontext() if rounding is None: @@ -2464,7 +2473,7 @@ if not self: # exponent = self._exp // 2. sqrt(-0) = -0 - ans = _dec_from_triple(self._sign, '0', self._exp // 2) + ans = _dec_from_triple(self._sign, b'0', self._exp // 2) return ans._fix(context) if context is None: @@ -2541,7 +2550,7 @@ if n % 5 == 0: n += 1 - ans = _dec_from_triple(0, str(n), e) + ans = _dec_from_triple(0, bytes(str(n), 'ascii'), e) # round, and fit to current context context = context._shallow_copy() @@ -2634,13 +2643,13 @@ if self._exp >= 0: return True rest = self._int[self._exp:] - return rest == '0'*len(rest) + return rest == b'0'*len(rest) def _iseven(self): """Returns True if self is even. Assumes self is an integer.""" if not self or self._exp > 0: return True - return self._int[-1+self._exp] in '02468' + return self._int[-1+self._exp] in b'02468' def adjusted(self): """Return the adjusted exponent of self""" @@ -2800,16 +2809,16 @@ # larger exponent the result either overflows or underflows. if self._sign == 0 and adj > len(str((context.Emax+1)*3)): # overflow - ans = _dec_from_triple(0, '1', context.Emax+1) + ans = _dec_from_triple(0, b'1', context.Emax+1) elif self._sign == 1 and adj > len(str((-context.Etiny()+1)*3)): # underflow to 0 - ans = _dec_from_triple(0, '1', context.Etiny()-1) + ans = _dec_from_triple(0, b'1', context.Etiny()-1) elif self._sign == 0 and adj < -p: # p+1 digits; final round will raise correct flags - ans = _dec_from_triple(0, '1' + '0'*(p-1) + '1', -p) + ans = _dec_from_triple(0, b'1' + b'0'*(p-1) + b'1', -p) elif self._sign == 1 and adj < -p-1: # p+1 digits; final round will raise correct flags - ans = _dec_from_triple(0, '9'*(p+1), -p-1) + ans = _dec_from_triple(0, b'9'*(p+1), -p-1) # general case else: op = _WorkRep(self) @@ -2827,7 +2836,7 @@ break extra += 3 - ans = _dec_from_triple(0, str(coeff), exp) + ans = _dec_from_triple(0, bytes(str(coeff), 'ascii'), exp) # at this stage, ans should round correctly with *any* # rounding mode, not just with ROUND_HALF_EVEN @@ -2892,7 +2901,7 @@ def is_zero(self): """Return True if self is a zero; otherwise return False.""" - return not self._is_special and self._int == '0' + return not self._is_special and self._int == b'0' def _ln_exp_bound(self): """Compute a lower bound for the adjusted exponent of self.ln(). @@ -2961,7 +2970,7 @@ if coeff % (5*10**(len(str(abs(coeff)))-p-1)): break places += 3 - ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places) + ans = _dec_from_triple(int(coeff<0), bytes(str(abs(coeff)), 'ascii'), -places) context = context._shallow_copy() rounding = context._set_rounding(ROUND_HALF_EVEN) @@ -3024,7 +3033,7 @@ 'log10 of a negative value') # log10(10**n) = n - if self._int[0] == '1' and self._int[1:] == '0'*(len(self._int) - 1): + if self._int[0] == ord('1') and self._int[1:] == b'0'*(len(self._int) - 1): # answer may need rounding ans = Decimal(self._exp + len(self._int) - 1) else: @@ -3042,7 +3051,7 @@ if coeff % (5*10**(len(str(abs(coeff)))-p-1)): break places += 3 - ans = _dec_from_triple(int(coeff<0), str(abs(coeff)), -places) + ans = _dec_from_triple(int(coeff<0), bytes(str(abs(coeff)), 'ascii'), -places) context = context._shallow_copy() rounding = context._set_rounding(ROUND_HALF_EVEN) @@ -3089,19 +3098,19 @@ if self._sign != 0 or self._exp != 0: return False for dig in self._int: - if dig not in '01': + if dig not in b'01': return False return True def _fill_logical(self, context, opa, opb): dif = context.prec - len(opa) if dif > 0: - opa = '0'*dif + opa + opa = b'0'*dif + opa elif dif < 0: opa = opa[-context.prec:] dif = context.prec - len(opb) if dif > 0: - opb = '0'*dif + opb + opb = b'0'*dif + opb elif dif < 0: opb = opb[-context.prec:] return opa, opb @@ -3117,14 +3126,16 @@ (opa, opb) = self._fill_logical(context, self._int, other._int) # make the operation, and clean starting zeroes - result = "".join([str(int(a)&int(b)) for a,b in zip(opa,opb)]) - return _dec_from_triple(0, result.lstrip('0') or '0', 0) + result = bytes("".join([ + str(a-ord('0')&b-ord('0')) for a,b in zip(opa,opb) + ]), 'ascii') + return _dec_from_triple(0, result.lstrip(b'0') or b'0', 0) def logical_invert(self, context=None): """Invert all its digits.""" if context is None: context = getcontext() - return self.logical_xor(_dec_from_triple(0,'1'*context.prec,0), + return self.logical_xor(_dec_from_triple(0,b'1'*context.prec,0), context) def logical_or(self, other, context=None): @@ -3138,8 +3149,8 @@ (opa, opb) = self._fill_logical(context, self._int, other._int) # make the operation, and clean starting zeroes - result = "".join(str(int(a)|int(b)) for a,b in zip(opa,opb)) - return _dec_from_triple(0, result.lstrip('0') or '0', 0) + result = bytes("".join(str(a-ord('0')|b-ord('0')) for a,b in zip(opa,opb)), 'ascii') + return _dec_from_triple(0, result.lstrip(b'0') or b'0', 0) def logical_xor(self, other, context=None): """Applies an 'xor' operation between self and other's digits.""" @@ -3152,8 +3163,8 @@ (opa, opb) = self._fill_logical(context, self._int, other._int) # make the operation, and clean starting zeroes - result = "".join(str(int(a)^int(b)) for a,b in zip(opa,opb)) - return _dec_from_triple(0, result.lstrip('0') or '0', 0) + result = bytes("".join(str(a-ord('0')^b-ord('0')) for a,b in zip(opa,opb)), 'ascii') + return _dec_from_triple(0, result.lstrip(b'0') or b'0', 0) def max_mag(self, other, context=None): """Compares the values numerically with their sign ignored.""" @@ -3227,7 +3238,7 @@ if self._isinfinity() == -1: return negInf if self._isinfinity() == 1: - return _dec_from_triple(0, '9'*context.prec, context.Etop()) + return _dec_from_triple(0, b'9'*context.prec, context.Etop()) context = context.copy() context._set_rounding(ROUND_FLOOR) @@ -3235,7 +3246,7 @@ new_self = self._fix(context) if new_self != self: return new_self - return self.__sub__(_dec_from_triple(0, '1', context.Etiny()-1), + return self.__sub__(_dec_from_triple(0, b'1', context.Etiny()-1), context) def next_plus(self, context=None): @@ -3250,7 +3261,7 @@ if self._isinfinity() == 1: return Inf if self._isinfinity() == -1: - return _dec_from_triple(1, '9'*context.prec, context.Etop()) + return _dec_from_triple(1, b'9'*context.prec, context.Etop()) context = context.copy() context._set_rounding(ROUND_CEILING) @@ -3258,7 +3269,7 @@ new_self = self._fix(context) if new_self != self: return new_self - return self.__add__(_dec_from_triple(0, '1', context.Etiny()-1), + return self.__add__(_dec_from_triple(0, b'1', context.Etiny()-1), context) def next_toward(self, other, context=None): @@ -3375,12 +3386,12 @@ rotdig = self._int topad = context.prec - len(rotdig) if topad: - rotdig = '0'*topad + rotdig + rotdig = b'0'*topad + rotdig # let's rotate! rotated = rotdig[torot:] + rotdig[:torot] return _dec_from_triple(self._sign, - rotated.lstrip('0') or '0', self._exp) + rotated.lstrip(b'0') or b'0', self._exp) def scaleb (self, other, context=None): """Returns self operand after adding the second value to its exp.""" @@ -3429,17 +3440,17 @@ rotdig = self._int topad = context.prec - len(rotdig) if topad: - rotdig = '0'*topad + rotdig + rotdig = b'0'*topad + rotdig # let's shift! if torot < 0: rotated = rotdig[:torot] else: - rotated = rotdig + '0'*torot + rotated = rotdig + b'0'*torot rotated = rotated[-context.prec:] return _dec_from_triple(self._sign, - rotated.lstrip('0') or '0', self._exp) + rotated.lstrip(b'0') or b'0', self._exp) # Support for pickling, copy, and deepcopy def __reduce__(self): @@ -3523,13 +3534,13 @@ # figure out main part of numeric string... if dotplace <= 0: - num = '0.' + '0'*(-dotplace) + self._int + num = '0.' + '0'*(-dotplace) + str(self._int, 'ascii') elif dotplace >= len(self._int): # make sure we're not padding a '0' with extra zeros on the right - assert dotplace==len(self._int) or self._int != '0' - num = self._int + '0'*(dotplace-len(self._int)) + assert dotplace==len(self._int) or self._int != b'0' + num = str(self._int, 'ascii') + '0'*(dotplace-len(self._int)) else: - num = self._int[:dotplace] + '.' + self._int[dotplace:] + num = str(self._int[:dotplace], 'ascii') + '.' + str(self._int[dotplace:], 'ascii') # ...then the trailing exponent, or trailing '%' if leftdigits != dotplace or spec['type'] in 'eE': @@ -3552,6 +3563,8 @@ This function is for *internal use only*. """ + assert type(coefficient) is bytes + self = object.__new__(Decimal) self._sign = sign self._int = coefficient