diff options
Diffstat (limited to 'Lib/test/test_long.py')
-rw-r--r-- | Lib/test/test_long.py | 1278 |
1 files changed, 766 insertions, 512 deletions
diff --git a/Lib/test/test_long.py b/Lib/test/test_long.py index f0847e7ab43..3ebc1f7fed0 100644 --- a/Lib/test/test_long.py +++ b/Lib/test/test_long.py @@ -1,10 +1,11 @@ import unittest +from test import support + import sys import random import math - -from test import test_int, test_support +import array # Used for lazy formatting of failure messages class Frm(object): @@ -16,7 +17,7 @@ class Frm(object): return self.format % self.args # SHIFT should match the value in longintrepr.h for best testing. -SHIFT = sys.long_info.bits_per_digit +SHIFT = sys.int_info.bits_per_digit BASE = 2 ** SHIFT MASK = BASE - 1 KARATSUBA_CUTOFF = 70 # from longobject.c @@ -26,62 +27,54 @@ KARATSUBA_CUTOFF = 70 # from longobject.c MAXDIGITS = 15 # build some special values -special = map(long, [0, 1, 2, BASE, BASE >> 1]) -special.append(0x5555555555555555L) -special.append(0xaaaaaaaaaaaaaaaaL) +special = [0, 1, 2, BASE, BASE >> 1, 0x5555555555555555, 0xaaaaaaaaaaaaaaaa] # some solid strings of one bits -p2 = 4L # 0 and 1 already added +p2 = 4 # 0 and 1 already added for i in range(2*SHIFT): special.append(p2 - 1) p2 = p2 << 1 del p2 # add complements & negations -special = special + map(lambda x: ~x, special) + \ - map(lambda x: -x, special) - -L = [ - ('0', 0), - ('1', 1), - ('9', 9), - ('10', 10), - ('99', 99), - ('100', 100), - ('314', 314), - (' 314', 314), - ('314 ', 314), - (' \t\t 314 \t\t ', 314), - (repr(sys.maxint), sys.maxint), - (' 1x', ValueError), - (' 1 ', 1), - (' 1\02 ', ValueError), - ('', ValueError), - (' ', ValueError), - (' \t\t ', ValueError) -] -if test_support.have_unicode: - L += [ - (unicode('0'), 0), - (unicode('1'), 1), - (unicode('9'), 9), - (unicode('10'), 10), - (unicode('99'), 99), - (unicode('100'), 100), - (unicode('314'), 314), - (unicode(' 314'), 314), - (unicode('\u0663\u0661\u0664 ','raw-unicode-escape'), 314), - (unicode(' \t\t 314 \t\t '), 314), - (unicode(' 1x'), ValueError), - (unicode(' 1 '), 1), - (unicode(' 1\02 '), ValueError), - (unicode(''), ValueError), - (unicode(' '), ValueError), - (unicode(' \t\t '), ValueError), - (unichr(0x200), ValueError), -] - -class LongTest(test_int.IntLongCommonTests, unittest.TestCase): - - ntype = long +special += [~x for x in special] + [-x for x in special] + +DBL_MAX = sys.float_info.max +DBL_MAX_EXP = sys.float_info.max_exp +DBL_MIN_EXP = sys.float_info.min_exp +DBL_MANT_DIG = sys.float_info.mant_dig +DBL_MIN_OVERFLOW = 2**DBL_MAX_EXP - 2**(DBL_MAX_EXP - DBL_MANT_DIG - 1) + +# pure Python version of correctly-rounded true division +def truediv(a, b): + """Correctly-rounded true division for integers.""" + negative = a^b < 0 + a, b = abs(a), abs(b) + + # exceptions: division by zero, overflow + if not b: + raise ZeroDivisionError("division by zero") + if a >= DBL_MIN_OVERFLOW * b: + raise OverflowError("int/int too large to represent as a float") + + # find integer d satisfying 2**(d - 1) <= a/b < 2**d + d = a.bit_length() - b.bit_length() + if d >= 0 and a >= 2**d * b or d < 0 and a * 2**-d >= b: + d += 1 + + # compute 2**-exp * a / b for suitable exp + exp = max(d, DBL_MIN_EXP) - DBL_MANT_DIG + a, b = a << max(-exp, 0), b << max(exp, 0) + q, r = divmod(a, b) + + # round-half-to-even: fractional part is r/b, which is > 0.5 iff + # 2*r > b, and == 0.5 iff 2*r == b. + if 2*r > b or 2*r == b and q % 2 == 1: + q += 1 + + result = math.ldexp(q, exp) + return -result if negative else result + + +class LongTest(unittest.TestCase): # Get quasi-random long consisting of ndigits digits (in base BASE). # quasi == the most-significant digit will not be 0, and the number @@ -93,7 +86,7 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): self.assertTrue(ndigits > 0) nbits_hi = ndigits * SHIFT nbits_lo = nbits_hi - SHIFT + 1 - answer = 0L + answer = 0 nbits = 0 r = int(random.random() * (SHIFT * 2)) | 1 # force 1 bits to start while nbits < nbits_lo: @@ -114,8 +107,8 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): # BASE). The sign bit is also random. def getran2(ndigits): - answer = 0L - for i in xrange(ndigits): + answer = 0 + for i in range(ndigits): answer = (answer << SHIFT) | random.randint(0, MASK) if random.random() < 0.5: answer = -answer @@ -136,46 +129,47 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): self.assertTrue(y < r <= 0, Frm("bad mod from divmod on %r and %r", x, y)) def test_division(self): - digits = range(1, MAXDIGITS+1) + range(KARATSUBA_CUTOFF, - KARATSUBA_CUTOFF + 14) + digits = list(range(1, MAXDIGITS+1)) + list(range(KARATSUBA_CUTOFF, + KARATSUBA_CUTOFF + 14)) digits.append(KARATSUBA_CUTOFF * 3) for lenx in digits: x = self.getran(lenx) for leny in digits: - y = self.getran(leny) or 1L + y = self.getran(leny) or 1 self.check_division(x, y) # specific numbers chosen to exercise corner cases of the # current long division implementation # 30-bit cases involving a quotient digit estimate of BASE+1 - self.check_division(1231948412290879395966702881L, - 1147341367131428698L) - self.check_division(815427756481275430342312021515587883L, - 707270836069027745L) - self.check_division(627976073697012820849443363563599041L, - 643588798496057020L) - self.check_division(1115141373653752303710932756325578065L, - 1038556335171453937726882627L) + self.check_division(1231948412290879395966702881, + 1147341367131428698) + self.check_division(815427756481275430342312021515587883, + 707270836069027745) + self.check_division(627976073697012820849443363563599041, + 643588798496057020) + self.check_division(1115141373653752303710932756325578065, + 1038556335171453937726882627) # 30-bit cases that require the post-subtraction correction step - self.check_division(922498905405436751940989320930368494L, - 949985870686786135626943396L) - self.check_division(768235853328091167204009652174031844L, - 1091555541180371554426545266L) + self.check_division(922498905405436751940989320930368494, + 949985870686786135626943396) + self.check_division(768235853328091167204009652174031844, + 1091555541180371554426545266) # 15-bit cases involving a quotient digit estimate of BASE+1 - self.check_division(20172188947443L, 615611397L) - self.check_division(1020908530270155025L, 950795710L) - self.check_division(128589565723112408L, 736393718L) - self.check_division(609919780285761575L, 18613274546784L) + self.check_division(20172188947443, 615611397) + self.check_division(1020908530270155025, 950795710) + self.check_division(128589565723112408, 736393718) + self.check_division(609919780285761575, 18613274546784) # 15-bit cases that require the post-subtraction correction step - self.check_division(710031681576388032L, 26769404391308L) - self.check_division(1933622614268221L, 30212853348836L) + self.check_division(710031681576388032, 26769404391308) + self.check_division(1933622614268221, 30212853348836) def test_karatsuba(self): - digits = range(1, 5) + range(KARATSUBA_CUTOFF, KARATSUBA_CUTOFF + 10) + digits = list(range(1, 5)) + list(range(KARATSUBA_CUTOFF, + KARATSUBA_CUTOFF + 10)) digits.extend([KARATSUBA_CUTOFF * 10, KARATSUBA_CUTOFF * 100]) bits = [digit * SHIFT for digit in digits] @@ -183,15 +177,15 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): # Test products of long strings of 1 bits -- (2**x-1)*(2**y-1) == # 2**(x+y) - 2**x - 2**y + 1, so the proper result is easy to check. for abits in bits: - a = (1L << abits) - 1 + a = (1 << abits) - 1 for bbits in bits: if bbits < abits: continue - b = (1L << bbits) - 1 + b = (1 << bbits) - 1 x = a * b - y = ((1L << (abits + bbits)) - - (1L << abits) - - (1L << bbits) + + y = ((1 << (abits + bbits)) - + (1 << abits) - + (1 << bbits) + 1) self.assertEqual(x, y, Frm("bad result for a*b: a=%r, b=%r, x=%r, y=%r", a, b, x, y)) @@ -213,8 +207,8 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): eq(x ^ ~x, -1, Frm("x ^ ~x != -1 for x=%r", x)) eq(-x, 1 + ~x, Frm("not -x == 1 + ~x for x=%r", x)) eq(-x, ~(x-1), Frm("not -x == ~(x-1) forx =%r", x)) - for n in xrange(2*SHIFT): - p2 = 2L ** n + for n in range(2*SHIFT): + p2 = 2 ** n eq(x << n >> n, x, Frm("x << n >> n != x for x=%r, n=%r", (x, n))) eq(x // p2, x >> n, @@ -257,7 +251,7 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): def test_bitop_identities(self): for x in special: self.check_bitop_identities_1(x) - digits = xrange(1, MAXDIGITS+1) + digits = range(1, MAXDIGITS+1) for lenx in digits: x = self.getran(lenx) self.check_bitop_identities_1(x) @@ -267,9 +261,6 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): self.check_bitop_identities_3(x, y, self.getran((lenx + leny)//2)) def slow_format(self, x, base): - if (x, base) == (0, 8): - # this is an oddball! - return "0L" digits = [] sign = 0 if x < 0: @@ -280,8 +271,8 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): digits.reverse() digits = digits or [0] return '-'[:sign] + \ - {8: '0', 10: '', 16: '0x'}[base] + \ - "".join(map(lambda i: "0123456789abcdef"[i], digits)) + "L" + {2: '0b', 8: '0o', 10: '', 16: '0x'}[base] + \ + "".join("0123456789abcdef"[i] for i in digits) def check_format_1(self, x): for base, mapper in (8, oct), (10, repr), (16, hex): @@ -290,11 +281,11 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): msg = Frm("%s returned %r but expected %r for %r", mapper.__name__, got, expected, x) self.assertEqual(got, expected, msg) - self.assertEqual(long(got, 0), x, Frm('long("%s", 0) != %r', got, x)) + self.assertEqual(int(got, 0), x, Frm('int("%s", 0) != %r', got, x)) # str() has to be checked a little differently since there's no # trailing "L" got = str(x) - expected = self.slow_format(x, 10)[:-1] + expected = self.slow_format(x, 10) msg = Frm("%s returned %r but expected %r for %r", mapper.__name__, got, expected, x) self.assertEqual(got, expected, msg) @@ -302,47 +293,18 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): def test_format(self): for x in special: self.check_format_1(x) - for i in xrange(10): - for lenx in xrange(1, MAXDIGITS+1): + for i in range(10): + for lenx in range(1, MAXDIGITS+1): x = self.getran(lenx) self.check_format_1(x) def test_long(self): - self.assertEqual(long(314), 314L) - self.assertEqual(long(3.14), 3L) - self.assertEqual(long(314L), 314L) - # Check that long() of basic types actually returns a long - self.assertEqual(type(long(314)), long) - self.assertEqual(type(long(3.14)), long) - self.assertEqual(type(long(314L)), long) - # Check that conversion from float truncates towards zero - self.assertEqual(long(-3.14), -3L) - self.assertEqual(long(3.9), 3L) - self.assertEqual(long(-3.9), -3L) - self.assertEqual(long(3.5), 3L) - self.assertEqual(long(-3.5), -3L) - self.assertEqual(long("-3"), -3L) - self.assertEqual(long("0b10", 2), 2L) - self.assertEqual(long("0o10", 8), 8L) - self.assertEqual(long("0x10", 16), 16L) - if test_support.have_unicode: - self.assertEqual(long(unicode("-3")), -3L) - # Different base: - self.assertEqual(long("10",16), 16L) - if test_support.have_unicode: - self.assertEqual(long(unicode("10"),16), 16L) - # Check conversions from string (same test set as for int(), and then some) + # Check conversions from string LL = [ - ('1' + '0'*20, 10L**20), - ('1' + '0'*100, 10L**100) + ('1' + '0'*20, 10**20), + ('1' + '0'*100, 10**100) ] - L2 = L[:] - if test_support.have_unicode: - L2 += [ - (unicode('1') + unicode('0')*20, 10L**20), - (unicode('1') + unicode('0')*100, 10L**100), - ] - for s, v in L2 + LL: + for s, v in LL: for sign in "", "+", "-": for prefix in "", " ", "\t", " \t\t ": ss = prefix + sign + s @@ -350,377 +312,95 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): if sign == "-" and v is not ValueError: vv = -v try: - self.assertEqual(long(ss), long(vv)) - except v: + self.assertEqual(int(ss), vv) + except ValueError: pass - self.assertRaises(ValueError, long, '123\0') - self.assertRaises(ValueError, long, '53', 40) - self.assertRaises(TypeError, long, 1, 12) + # trailing L should no longer be accepted... + self.assertRaises(ValueError, int, '123L') + self.assertRaises(ValueError, int, '123l') + self.assertRaises(ValueError, int, '0L') + self.assertRaises(ValueError, int, '-37L') + self.assertRaises(ValueError, int, '0x32L', 16) + self.assertRaises(ValueError, int, '1L', 21) + # ... but it's just a normal digit if base >= 22 + self.assertEqual(int('1L', 22), 43) # tests with base 0 - self.assertEqual(long(' 0123 ', 0), 83) - self.assertEqual(long(' 0123 ', 0), 83) - self.assertEqual(long('000', 0), 0) - self.assertEqual(long('0o123', 0), 83) - self.assertEqual(long('0x123', 0), 291) - self.assertEqual(long('0b100', 0), 4) - self.assertEqual(long(' 0O123 ', 0), 83) - self.assertEqual(long(' 0X123 ', 0), 291) - self.assertEqual(long(' 0B100 ', 0), 4) - self.assertEqual(long('0', 0), 0) - self.assertEqual(long('+0', 0), 0) - self.assertEqual(long('-0', 0), 0) - self.assertEqual(long('00', 0), 0) - self.assertRaises(ValueError, long, '08', 0) - self.assertRaises(ValueError, long, '-012395', 0) - - # SF patch #1638879: embedded NULs were not detected with - # explicit base - self.assertRaises(ValueError, long, '123\0', 10) - self.assertRaises(ValueError, long, '123\x00 245', 20) - - self.assertEqual(long('100000000000000000000000000000000', 2), - 4294967296) - self.assertEqual(long('102002022201221111211', 3), 4294967296) - self.assertEqual(long('10000000000000000', 4), 4294967296) - self.assertEqual(long('32244002423141', 5), 4294967296) - self.assertEqual(long('1550104015504', 6), 4294967296) - self.assertEqual(long('211301422354', 7), 4294967296) - self.assertEqual(long('40000000000', 8), 4294967296) - self.assertEqual(long('12068657454', 9), 4294967296) - self.assertEqual(long('4294967296', 10), 4294967296) - self.assertEqual(long('1904440554', 11), 4294967296) - self.assertEqual(long('9ba461594', 12), 4294967296) - self.assertEqual(long('535a79889', 13), 4294967296) - self.assertEqual(long('2ca5b7464', 14), 4294967296) - self.assertEqual(long('1a20dcd81', 15), 4294967296) - self.assertEqual(long('100000000', 16), 4294967296) - self.assertEqual(long('a7ffda91', 17), 4294967296) - self.assertEqual(long('704he7g4', 18), 4294967296) - self.assertEqual(long('4f5aff66', 19), 4294967296) - self.assertEqual(long('3723ai4g', 20), 4294967296) - self.assertEqual(long('281d55i4', 21), 4294967296) - self.assertEqual(long('1fj8b184', 22), 4294967296) - self.assertEqual(long('1606k7ic', 23), 4294967296) - self.assertEqual(long('mb994ag', 24), 4294967296) - self.assertEqual(long('hek2mgl', 25), 4294967296) - self.assertEqual(long('dnchbnm', 26), 4294967296) - self.assertEqual(long('b28jpdm', 27), 4294967296) - self.assertEqual(long('8pfgih4', 28), 4294967296) - self.assertEqual(long('76beigg', 29), 4294967296) - self.assertEqual(long('5qmcpqg', 30), 4294967296) - self.assertEqual(long('4q0jto4', 31), 4294967296) - self.assertEqual(long('4000000', 32), 4294967296) - self.assertEqual(long('3aokq94', 33), 4294967296) - self.assertEqual(long('2qhxjli', 34), 4294967296) - self.assertEqual(long('2br45qb', 35), 4294967296) - self.assertEqual(long('1z141z4', 36), 4294967296) - - self.assertEqual(long('100000000000000000000000000000001', 2), - 4294967297) - self.assertEqual(long('102002022201221111212', 3), 4294967297) - self.assertEqual(long('10000000000000001', 4), 4294967297) - self.assertEqual(long('32244002423142', 5), 4294967297) - self.assertEqual(long('1550104015505', 6), 4294967297) - self.assertEqual(long('211301422355', 7), 4294967297) - self.assertEqual(long('40000000001', 8), 4294967297) - self.assertEqual(long('12068657455', 9), 4294967297) - self.assertEqual(long('4294967297', 10), 4294967297) - self.assertEqual(long('1904440555', 11), 4294967297) - self.assertEqual(long('9ba461595', 12), 4294967297) - self.assertEqual(long('535a7988a', 13), 4294967297) - self.assertEqual(long('2ca5b7465', 14), 4294967297) - self.assertEqual(long('1a20dcd82', 15), 4294967297) - self.assertEqual(long('100000001', 16), 4294967297) - self.assertEqual(long('a7ffda92', 17), 4294967297) - self.assertEqual(long('704he7g5', 18), 4294967297) - self.assertEqual(long('4f5aff67', 19), 4294967297) - self.assertEqual(long('3723ai4h', 20), 4294967297) - self.assertEqual(long('281d55i5', 21), 4294967297) - self.assertEqual(long('1fj8b185', 22), 4294967297) - self.assertEqual(long('1606k7id', 23), 4294967297) - self.assertEqual(long('mb994ah', 24), 4294967297) - self.assertEqual(long('hek2mgm', 25), 4294967297) - self.assertEqual(long('dnchbnn', 26), 4294967297) - self.assertEqual(long('b28jpdn', 27), 4294967297) - self.assertEqual(long('8pfgih5', 28), 4294967297) - self.assertEqual(long('76beigh', 29), 4294967297) - self.assertEqual(long('5qmcpqh', 30), 4294967297) - self.assertEqual(long('4q0jto5', 31), 4294967297) - self.assertEqual(long('4000001', 32), 4294967297) - self.assertEqual(long('3aokq95', 33), 4294967297) - self.assertEqual(long('2qhxjlj', 34), 4294967297) - self.assertEqual(long('2br45qc', 35), 4294967297) - self.assertEqual(long('1z141z5', 36), 4294967297) + self.assertEqual(int('000', 0), 0) + self.assertEqual(int('0o123', 0), 83) + self.assertEqual(int('0x123', 0), 291) + self.assertEqual(int('0b100', 0), 4) + self.assertEqual(int(' 0O123 ', 0), 83) + self.assertEqual(int(' 0X123 ', 0), 291) + self.assertEqual(int(' 0B100 ', 0), 4) + self.assertEqual(int('0', 0), 0) + self.assertEqual(int('+0', 0), 0) + self.assertEqual(int('-0', 0), 0) + self.assertEqual(int('00', 0), 0) + self.assertRaises(ValueError, int, '08', 0) + self.assertRaises(ValueError, int, '-012395', 0) + + # invalid bases + invalid_bases = [-909, + 2**31-1, 2**31, -2**31, -2**31-1, + 2**63-1, 2**63, -2**63, -2**63-1, + 2**100, -2**100, + ] + for base in invalid_bases: + self.assertRaises(ValueError, int, '42', base) def test_conversion(self): - # Test __long__() - class ClassicMissingMethods: - pass - self.assertRaises(AttributeError, long, ClassicMissingMethods()) - - class MissingMethods(object): - pass - self.assertRaises(TypeError, long, MissingMethods()) - - class Foo0: - def __long__(self): - return 42L - class Foo1(object): - def __long__(self): - return 42L - - class Foo2(long): - def __long__(self): - return 42L - - class Foo3(long): - def __long__(self): - return self - - class Foo4(long): + class JustLong: + # test that __long__ no longer used in 3.x def __long__(self): return 42 + self.assertRaises(TypeError, int, JustLong()) - class Foo5(long): + class LongTrunc: + # __long__ should be ignored in 3.x def __long__(self): - return 42. - - self.assertEqual(long(Foo0()), 42L) - self.assertEqual(long(Foo1()), 42L) - self.assertEqual(long(Foo2()), 42L) - self.assertEqual(long(Foo3()), 0) - self.assertEqual(long(Foo4()), 42) - self.assertRaises(TypeError, long, Foo5()) - - class Classic: - pass - for base in (object, Classic): - class LongOverridesTrunc(base): - def __long__(self): - return 42 - def __trunc__(self): - return -12 - self.assertEqual(long(LongOverridesTrunc()), 42) - - class JustTrunc(base): - def __trunc__(self): - return 42 - self.assertEqual(long(JustTrunc()), 42) - - for trunc_result_base in (object, Classic): - class Integral(trunc_result_base): - def __int__(self): - return 42 - - class TruncReturnsNonLong(base): - def __trunc__(self): - return Integral() - self.assertEqual(long(TruncReturnsNonLong()), 42) - - class NonIntegral(trunc_result_base): - def __trunc__(self): - # Check that we avoid infinite recursion. - return NonIntegral() - - class TruncReturnsNonIntegral(base): - def __trunc__(self): - return NonIntegral() - try: - long(TruncReturnsNonIntegral()) - except TypeError as e: - self.assertEqual(str(e), - "__trunc__ returned non-Integral" - " (type NonIntegral)") - else: - self.fail("Failed to raise TypeError with %s" % - ((base, trunc_result_base),)) - - def test_misc(self): - - # check the extremes in int<->long conversion - hugepos = sys.maxint - hugeneg = -hugepos - 1 - hugepos_aslong = long(hugepos) - hugeneg_aslong = long(hugeneg) - self.assertEqual(hugepos, hugepos_aslong, "long(sys.maxint) != sys.maxint") - self.assertEqual(hugeneg, hugeneg_aslong, - "long(-sys.maxint-1) != -sys.maxint-1") - - # long -> int should not fail for hugepos_aslong or hugeneg_aslong - x = int(hugepos_aslong) - try: - self.assertEqual(x, hugepos, - "converting sys.maxint to long and back to int fails") - except OverflowError: - self.fail("int(long(sys.maxint)) overflowed!") - if not isinstance(x, int): - self.fail("int(long(sys.maxint)) should have returned int") - x = int(hugeneg_aslong) - try: - self.assertEqual(x, hugeneg, - "converting -sys.maxint-1 to long and back to int fails") - except OverflowError: - self.fail("int(long(-sys.maxint-1)) overflowed!") - if not isinstance(x, int): - self.fail("int(long(-sys.maxint-1)) should have returned int") - # but long -> int should overflow for hugepos+1 and hugeneg-1 - x = hugepos_aslong + 1 - try: - y = int(x) - except OverflowError: - self.fail("int(long(sys.maxint) + 1) mustn't overflow") - self.assertIsInstance(y, long, - "int(long(sys.maxint) + 1) should have returned long") - - x = hugeneg_aslong - 1 - try: - y = int(x) - except OverflowError: - self.fail("int(long(-sys.maxint-1) - 1) mustn't overflow") - self.assertIsInstance(y, long, - "int(long(-sys.maxint-1) - 1) should have returned long") - - class long2(long): - pass - x = long2(1L<<100) - y = int(x) - self.assertTrue(type(y) is long, - "overflowing int conversion must return long not long subtype") - - # long -> Py_ssize_t conversion - class X(object): - def __getslice__(self, i, j): - return i, j - - with test_support.check_py3k_warnings(): - self.assertEqual(X()[-5L:7L], (-5, 7)) - # use the clamping effect to test the smallest and largest longs - # that fit a Py_ssize_t - slicemin, slicemax = X()[-2L**100:2L**100] - self.assertEqual(X()[slicemin:slicemax], (slicemin, slicemax)) - - def test_issue9869(self): - # Issue 9869: Interpreter crash when initializing an instance - # of a long subclass from an object whose __long__ method returns - # a plain int. - class BadLong(object): - def __long__(self): - return 1000000 - - class MyLong(long): - pass - - x = MyLong(BadLong()) - self.assertIsInstance(x, long) - self.assertEqual(x, 1000000) - - -# ----------------------------------- tests of auto int->long conversion - - def test_auto_overflow(self): - special = [0, 1, 2, 3, sys.maxint-1, sys.maxint, sys.maxint+1] - sqrt = int(math.sqrt(sys.maxint)) - special.extend([sqrt-1, sqrt, sqrt+1]) - special.extend([-i for i in special]) - - def checkit(*args): - # Heavy use of nested scopes here! - self.assertEqual(got, expected, - Frm("for %r expected %r got %r", args, expected, got)) + return 42 + def __trunc__(self): + return 1729 + self.assertEqual(int(LongTrunc()), 1729) - for x in special: - longx = long(x) - - expected = -longx - got = -x - checkit('-', x) - - for y in special: - longy = long(y) - - expected = longx + longy - got = x + y - checkit(x, '+', y) - - expected = longx - longy - got = x - y - checkit(x, '-', y) - - expected = longx * longy - got = x * y - checkit(x, '*', y) - - if y: - with test_support.check_py3k_warnings(): - expected = longx / longy - got = x / y - checkit(x, '/', y) - - expected = longx // longy - got = x // y - checkit(x, '//', y) - - expected = divmod(longx, longy) - got = divmod(longx, longy) - checkit(x, 'divmod', y) - - if abs(y) < 5 and not (x == 0 and y < 0): - expected = longx ** longy - got = x ** y - checkit(x, '**', y) - - for z in special: - if z != 0 : - if y >= 0: - expected = pow(longx, longy, long(z)) - got = pow(x, y, z) - checkit('pow', x, y, '%', z) - else: - self.assertRaises(TypeError, pow,longx, longy, long(z)) - - @unittest.skipUnless(float.__getformat__("double").startswith("IEEE"), - "test requires IEEE 754 doubles") + @support.requires_IEEE_754 def test_float_conversion(self): - import sys - DBL_MAX = sys.float_info.max - DBL_MAX_EXP = sys.float_info.max_exp - DBL_MANT_DIG = sys.float_info.mant_dig - - exact_values = [0L, 1L, 2L, - long(2**53-3), - long(2**53-2), - long(2**53-1), - long(2**53), - long(2**53+2), - long(2**54-4), - long(2**54-2), - long(2**54), - long(2**54+4)] + + exact_values = [0, 1, 2, + 2**53-3, + 2**53-2, + 2**53-1, + 2**53, + 2**53+2, + 2**54-4, + 2**54-2, + 2**54, + 2**54+4] for x in exact_values: - self.assertEqual(long(float(x)), x) - self.assertEqual(long(float(-x)), -x) + self.assertEqual(float(x), x) + self.assertEqual(float(-x), -x) # test round-half-even for x, y in [(1, 0), (2, 2), (3, 4), (4, 4), (5, 4), (6, 6), (7, 8)]: - for p in xrange(15): - self.assertEqual(long(float(2L**p*(2**53+x))), 2L**p*(2**53+y)) + for p in range(15): + self.assertEqual(int(float(2**p*(2**53+x))), 2**p*(2**53+y)) for x, y in [(0, 0), (1, 0), (2, 0), (3, 4), (4, 4), (5, 4), (6, 8), (7, 8), (8, 8), (9, 8), (10, 8), (11, 12), (12, 12), (13, 12), (14, 16), (15, 16)]: - for p in xrange(15): - self.assertEqual(long(float(2L**p*(2**54+x))), 2L**p*(2**54+y)) + for p in range(15): + self.assertEqual(int(float(2**p*(2**54+x))), 2**p*(2**54+y)) # behaviour near extremes of floating-point range - long_dbl_max = long(DBL_MAX) + int_dbl_max = int(DBL_MAX) top_power = 2**DBL_MAX_EXP - halfway = (long_dbl_max + top_power)//2 - self.assertEqual(float(long_dbl_max), DBL_MAX) - self.assertEqual(float(long_dbl_max+1), DBL_MAX) + halfway = (int_dbl_max + top_power)//2 + self.assertEqual(float(int_dbl_max), DBL_MAX) + self.assertEqual(float(int_dbl_max+1), DBL_MAX) self.assertEqual(float(halfway-1), DBL_MAX) self.assertRaises(OverflowError, float, halfway) self.assertEqual(float(1-halfway), -DBL_MAX) @@ -732,21 +412,21 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): self.assertRaises(OverflowError, float, 2*top_power) self.assertRaises(OverflowError, float, top_power*top_power) - for p in xrange(100): - x = long(2**p * (2**53 + 1) + 1) - y = long(2**p * (2**53+ 2)) - self.assertEqual(long(float(x)), y) + for p in range(100): + x = 2**p * (2**53 + 1) + 1 + y = 2**p * (2**53 + 2) + self.assertEqual(int(float(x)), y) - x = long(2**p * (2**53 + 1)) - y = long(2**p * 2**53) - self.assertEqual(long(float(x)), y) + x = 2**p * (2**53 + 1) + y = 2**p * 2**53 + self.assertEqual(int(float(x)), y) def test_float_overflow(self): for x in -2.0, -1.0, 0.0, 1.0, 2.0: - self.assertEqual(float(long(x)), x) + self.assertEqual(float(int(x)), x) shuge = '12345' * 120 - huge = 1L << 30000 + huge = 1 << 30000 mhuge = -huge namespace = {'huge': huge, 'mhuge': mhuge, 'shuge': shuge, 'math': math} for test in ["float(huge)", "float(mhuge)", @@ -761,19 +441,21 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): "1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.", "math.sin(huge)", "math.sin(mhuge)", "math.sqrt(huge)", "math.sqrt(mhuge)", # should do better - "math.floor(huge)", "math.floor(mhuge)"]: + # math.floor() of an int returns an int now + ##"math.floor(huge)", "math.floor(mhuge)", + ]: self.assertRaises(OverflowError, eval, test, namespace) - # XXX Perhaps float(shuge) can raise OverflowError on some box? - # The comparison should not. - self.assertNotEqual(float(shuge), int(shuge), - "float(shuge) should not equal int(shuge)") + # XXX Perhaps float(shuge) can raise OverflowError on some box? + # The comparison should not. + self.assertNotEqual(float(shuge), int(shuge), + "float(shuge) should not equal int(shuge)") def test_logs(self): LOG10E = math.log10(math.e) - for exp in range(10) + [100, 1000, 10000]: + for exp in list(range(10)) + [100, 1000, 10000]: value = 10 ** exp log10 = math.log10(value) self.assertAlmostEqual(log10, exp) @@ -784,7 +466,7 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): log = math.log(value) self.assertAlmostEqual(log, expected) - for bad in -(1L << 10000), -2L, 0L: + for bad in -(1 << 10000), -2, 0: self.assertRaises(ValueError, math.log, bad) self.assertRaises(ValueError, math.log10, bad) @@ -798,7 +480,7 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): # represents all Python ints, longs and floats exactly). class Rat: def __init__(self, value): - if isinstance(value, (int, long)): + if isinstance(value, int): self.n = value self.d = 1 elif isinstance(value, float): @@ -837,29 +519,42 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): else: raise TypeError("can't deal with %r" % value) - def __cmp__(self, other): + def _cmp__(self, other): if not isinstance(other, Rat): other = Rat(other) - return cmp(self.n * other.d, self.d * other.n) + x, y = self.n * other.d, self.d * other.n + return (x > y) - (x < y) + def __eq__(self, other): + return self._cmp__(other) == 0 + def __ne__(self, other): + return self._cmp__(other) != 0 + def __ge__(self, other): + return self._cmp__(other) >= 0 + def __gt__(self, other): + return self._cmp__(other) > 0 + def __le__(self, other): + return self._cmp__(other) <= 0 + def __lt__(self, other): + return self._cmp__(other) < 0 cases = [0, 0.001, 0.99, 1.0, 1.5, 1e20, 1e200] # 2**48 is an important boundary in the internals. 2**53 is an # important boundary for IEEE double precision. for t in 2.0**48, 2.0**50, 2.0**53: cases.extend([t - 1.0, t - 0.3, t, t + 0.3, t + 1.0, - long(t-1), long(t), long(t+1)]) - cases.extend([0, 1, 2, sys.maxint, float(sys.maxint)]) - # 1L<<20000 should exceed all double formats. long(1e200) is to + int(t-1), int(t), int(t+1)]) + cases.extend([0, 1, 2, sys.maxsize, float(sys.maxsize)]) + # 1 << 20000 should exceed all double formats. int(1e200) is to # check that we get equality with 1e200 above. - t = long(1e200) - cases.extend([0L, 1L, 2L, 1L << 20000, t-1, t, t+1]) + t = int(1e200) + cases.extend([0, 1, 2, 1 << 20000, t-1, t, t+1]) cases.extend([-x for x in cases]) for x in cases: Rx = Rat(x) for y in cases: Ry = Rat(y) - Rcmp = cmp(Rx, Ry) - xycmp = cmp(x, y) + Rcmp = (Rx > Ry) - (Rx < Ry) + xycmp = (x > y) - (x < y) eq(Rcmp, xycmp, Frm("%r %r %d %d", x, y, Rcmp, xycmp)) eq(x == y, Rcmp == 0, Frm("%r == %r %d", x, y, Rcmp)) eq(x != y, Rcmp != 0, Frm("%r != %r %d", x, y, Rcmp)) @@ -868,15 +563,254 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): eq(x > y, Rcmp > 0, Frm("%r > %r %d", x, y, Rcmp)) eq(x >= y, Rcmp >= 0, Frm("%r >= %r %d", x, y, Rcmp)) + def test__format__(self): + self.assertEqual(format(123456789, 'd'), '123456789') + self.assertEqual(format(123456789, 'd'), '123456789') + + # sign and aligning are interdependent + self.assertEqual(format(1, "-"), '1') + self.assertEqual(format(-1, "-"), '-1') + self.assertEqual(format(1, "-3"), ' 1') + self.assertEqual(format(-1, "-3"), ' -1') + self.assertEqual(format(1, "+3"), ' +1') + self.assertEqual(format(-1, "+3"), ' -1') + self.assertEqual(format(1, " 3"), ' 1') + self.assertEqual(format(-1, " 3"), ' -1') + self.assertEqual(format(1, " "), ' 1') + self.assertEqual(format(-1, " "), '-1') + + # hex + self.assertEqual(format(3, "x"), "3") + self.assertEqual(format(3, "X"), "3") + self.assertEqual(format(1234, "x"), "4d2") + self.assertEqual(format(-1234, "x"), "-4d2") + self.assertEqual(format(1234, "8x"), " 4d2") + self.assertEqual(format(-1234, "8x"), " -4d2") + self.assertEqual(format(1234, "x"), "4d2") + self.assertEqual(format(-1234, "x"), "-4d2") + self.assertEqual(format(-3, "x"), "-3") + self.assertEqual(format(-3, "X"), "-3") + self.assertEqual(format(int('be', 16), "x"), "be") + self.assertEqual(format(int('be', 16), "X"), "BE") + self.assertEqual(format(-int('be', 16), "x"), "-be") + self.assertEqual(format(-int('be', 16), "X"), "-BE") + + # octal + self.assertEqual(format(3, "b"), "11") + self.assertEqual(format(-3, "b"), "-11") + self.assertEqual(format(1234, "b"), "10011010010") + self.assertEqual(format(-1234, "b"), "-10011010010") + self.assertEqual(format(1234, "-b"), "10011010010") + self.assertEqual(format(-1234, "-b"), "-10011010010") + self.assertEqual(format(1234, " b"), " 10011010010") + self.assertEqual(format(-1234, " b"), "-10011010010") + self.assertEqual(format(1234, "+b"), "+10011010010") + self.assertEqual(format(-1234, "+b"), "-10011010010") + + # make sure these are errors + self.assertRaises(ValueError, format, 3, "1.3") # precision disallowed + self.assertRaises(ValueError, format, 3, "+c") # sign not allowed + # with 'c' + + # ensure that only int and float type specifiers work + for format_spec in ([chr(x) for x in range(ord('a'), ord('z')+1)] + + [chr(x) for x in range(ord('A'), ord('Z')+1)]): + if not format_spec in 'bcdoxXeEfFgGn%': + self.assertRaises(ValueError, format, 0, format_spec) + self.assertRaises(ValueError, format, 1, format_spec) + self.assertRaises(ValueError, format, -1, format_spec) + self.assertRaises(ValueError, format, 2**100, format_spec) + self.assertRaises(ValueError, format, -(2**100), format_spec) + + # ensure that float type specifiers work; format converts + # the int to a float + for format_spec in 'eEfFgG%': + for value in [0, 1, -1, 100, -100, 1234567890, -1234567890]: + self.assertEqual(format(value, format_spec), + format(float(value), format_spec)) + def test_nan_inf(self): - self.assertRaises(OverflowError, long, float('inf')) - self.assertRaises(OverflowError, long, float('-inf')) - self.assertRaises(ValueError, long, float('nan')) + self.assertRaises(OverflowError, int, float('inf')) + self.assertRaises(OverflowError, int, float('-inf')) + self.assertRaises(ValueError, int, float('nan')) + + def test_true_division(self): + huge = 1 << 40000 + mhuge = -huge + self.assertEqual(huge / huge, 1.0) + self.assertEqual(mhuge / mhuge, 1.0) + self.assertEqual(huge / mhuge, -1.0) + self.assertEqual(mhuge / huge, -1.0) + self.assertEqual(1 / huge, 0.0) + self.assertEqual(1 / huge, 0.0) + self.assertEqual(1 / mhuge, 0.0) + self.assertEqual(1 / mhuge, 0.0) + self.assertEqual((666 * huge + (huge >> 1)) / huge, 666.5) + self.assertEqual((666 * mhuge + (mhuge >> 1)) / mhuge, 666.5) + self.assertEqual((666 * huge + (huge >> 1)) / mhuge, -666.5) + self.assertEqual((666 * mhuge + (mhuge >> 1)) / huge, -666.5) + self.assertEqual(huge / (huge << 1), 0.5) + self.assertEqual((1000000 * huge) / huge, 1000000) + + namespace = {'huge': huge, 'mhuge': mhuge} + + for overflow in ["float(huge)", "float(mhuge)", + "huge / 1", "huge / 2", "huge / -1", "huge / -2", + "mhuge / 100", "mhuge / 200"]: + self.assertRaises(OverflowError, eval, overflow, namespace) + + for underflow in ["1 / huge", "2 / huge", "-1 / huge", "-2 / huge", + "100 / mhuge", "200 / mhuge"]: + result = eval(underflow, namespace) + self.assertEqual(result, 0.0, + "expected underflow to 0 from %r" % underflow) + + for zero in ["huge / 0", "mhuge / 0"]: + self.assertRaises(ZeroDivisionError, eval, zero, namespace) + + def check_truediv(self, a, b, skip_small=True): + """Verify that the result of a/b is correctly rounded, by + comparing it with a pure Python implementation of correctly + rounded division. b should be nonzero.""" + + # skip check for small a and b: in this case, the current + # implementation converts the arguments to float directly and + # then applies a float division. This can give doubly-rounded + # results on x87-using machines (particularly 32-bit Linux). + if skip_small and max(abs(a), abs(b)) < 2**DBL_MANT_DIG: + return + + try: + # use repr so that we can distinguish between -0.0 and 0.0 + expected = repr(truediv(a, b)) + except OverflowError: + expected = 'overflow' + except ZeroDivisionError: + expected = 'zerodivision' + + try: + got = repr(a / b) + except OverflowError: + got = 'overflow' + except ZeroDivisionError: + got = 'zerodivision' + + self.assertEqual(expected, got, "Incorrectly rounded division {}/{}: " + "expected {}, got {}".format(a, b, expected, got)) + + @support.requires_IEEE_754 + def test_correctly_rounded_true_division(self): + # more stringent tests than those above, checking that the + # result of true division of ints is always correctly rounded. + # This test should probably be considered CPython-specific. + + # Exercise all the code paths not involving Gb-sized ints. + # ... divisions involving zero + self.check_truediv(123, 0) + self.check_truediv(-456, 0) + self.check_truediv(0, 3) + self.check_truediv(0, -3) + self.check_truediv(0, 0) + # ... overflow or underflow by large margin + self.check_truediv(671 * 12345 * 2**DBL_MAX_EXP, 12345) + self.check_truediv(12345, 345678 * 2**(DBL_MANT_DIG - DBL_MIN_EXP)) + # ... a much larger or smaller than b + self.check_truediv(12345*2**100, 98765) + self.check_truediv(12345*2**30, 98765*7**81) + # ... a / b near a boundary: one of 1, 2**DBL_MANT_DIG, 2**DBL_MIN_EXP, + # 2**DBL_MAX_EXP, 2**(DBL_MIN_EXP-DBL_MANT_DIG) + bases = (0, DBL_MANT_DIG, DBL_MIN_EXP, + DBL_MAX_EXP, DBL_MIN_EXP - DBL_MANT_DIG) + for base in bases: + for exp in range(base - 15, base + 15): + self.check_truediv(75312*2**max(exp, 0), 69187*2**max(-exp, 0)) + self.check_truediv(69187*2**max(exp, 0), 75312*2**max(-exp, 0)) + + # overflow corner case + for m in [1, 2, 7, 17, 12345, 7**100, + -1, -2, -5, -23, -67891, -41**50]: + for n in range(-10, 10): + self.check_truediv(m*DBL_MIN_OVERFLOW + n, m) + self.check_truediv(m*DBL_MIN_OVERFLOW + n, -m) + + # check detection of inexactness in shifting stage + for n in range(250): + # (2**DBL_MANT_DIG+1)/(2**DBL_MANT_DIG) lies halfway + # between two representable floats, and would usually be + # rounded down under round-half-to-even. The tiniest of + # additions to the numerator should cause it to be rounded + # up instead. + self.check_truediv((2**DBL_MANT_DIG + 1)*12345*2**200 + 2**n, + 2**DBL_MANT_DIG*12345) + + # 1/2731 is one of the smallest division cases that's subject + # to double rounding on IEEE 754 machines working internally with + # 64-bit precision. On such machines, the next check would fail, + # were it not explicitly skipped in check_truediv. + self.check_truediv(1, 2731) + + # a particularly bad case for the old algorithm: gives an + # error of close to 3.5 ulps. + self.check_truediv(295147931372582273023, 295147932265116303360) + for i in range(1000): + self.check_truediv(10**(i+1), 10**i) + self.check_truediv(10**i, 10**(i+1)) + + # test round-half-to-even behaviour, normal result + for m in [1, 2, 4, 7, 8, 16, 17, 32, 12345, 7**100, + -1, -2, -5, -23, -67891, -41**50]: + for n in range(-10, 10): + self.check_truediv(2**DBL_MANT_DIG*m + n, m) + + # test round-half-to-even, subnormal result + for n in range(-20, 20): + self.check_truediv(n, 2**1076) + + # largeish random divisions: a/b where |a| <= |b| <= + # 2*|a|; |ans| is between 0.5 and 1.0, so error should + # always be bounded by 2**-54 with equality possible only + # if the least significant bit of q=ans*2**53 is zero. + for M in [10**10, 10**100, 10**1000]: + for i in range(1000): + a = random.randrange(1, M) + b = random.randrange(a, 2*a+1) + self.check_truediv(a, b) + self.check_truediv(-a, b) + self.check_truediv(a, -b) + self.check_truediv(-a, -b) + + # and some (genuinely) random tests + for _ in range(10000): + a_bits = random.randrange(1000) + b_bits = random.randrange(1, 1000) + x = random.randrange(2**a_bits) + y = random.randrange(1, 2**b_bits) + self.check_truediv(x, y) + self.check_truediv(x, -y) + self.check_truediv(-x, y) + self.check_truediv(-x, -y) + + def test_small_ints(self): + for i in range(-5, 257): + self.assertTrue(i is i + 0) + self.assertTrue(i is i * 1) + self.assertTrue(i is i - 0) + self.assertTrue(i is i // 1) + self.assertTrue(i is i & -1) + self.assertTrue(i is i | 0) + self.assertTrue(i is i ^ 0) + self.assertTrue(i is ~~i) + self.assertTrue(i is i**1) + self.assertTrue(i is int(str(i))) + self.assertTrue(i is i<<2>>2, str(i)) + # corner cases + i = 1 << 70 + self.assertTrue(i - i is 0) + self.assertTrue(0 * i is 0) def test_bit_length(self): tiny = 1e-10 - for x in xrange(-65000, 65000): - x = long(x) + for x in range(-65000, 65000): k = x.bit_length() # Check equivalence with Python version self.assertEqual(k, len(bin(x).lstrip('-0b'))) @@ -894,13 +828,13 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): self.assertEqual(k, 1 + math.floor( math.log(abs(x))/math.log(2) + tiny)) - self.assertEqual((0L).bit_length(), 0) - self.assertEqual((1L).bit_length(), 1) - self.assertEqual((-1L).bit_length(), 1) - self.assertEqual((2L).bit_length(), 2) - self.assertEqual((-2L).bit_length(), 2) + self.assertEqual((0).bit_length(), 0) + self.assertEqual((1).bit_length(), 1) + self.assertEqual((-1).bit_length(), 1) + self.assertEqual((2).bit_length(), 2) + self.assertEqual((-2).bit_length(), 2) for i in [2, 3, 15, 16, 17, 31, 32, 33, 63, 64, 234]: - a = 2L**i + a = 2**i self.assertEqual((a-1).bit_length(), i) self.assertEqual((1-a).bit_length(), i) self.assertEqual((a).bit_length(), i+1) @@ -908,9 +842,329 @@ class LongTest(test_int.IntLongCommonTests, unittest.TestCase): self.assertEqual((a+1).bit_length(), i+1) self.assertEqual((-a-1).bit_length(), i+1) + def test_round(self): + # check round-half-even algorithm. For round to nearest ten; + # rounding map is invariant under adding multiples of 20 + test_dict = {0:0, 1:0, 2:0, 3:0, 4:0, 5:0, + 6:10, 7:10, 8:10, 9:10, 10:10, 11:10, 12:10, 13:10, 14:10, + 15:20, 16:20, 17:20, 18:20, 19:20} + for offset in range(-520, 520, 20): + for k, v in test_dict.items(): + got = round(k+offset, -1) + expected = v+offset + self.assertEqual(got, expected) + self.assertTrue(type(got) is int) + + # larger second argument + self.assertEqual(round(-150, -2), -200) + self.assertEqual(round(-149, -2), -100) + self.assertEqual(round(-51, -2), -100) + self.assertEqual(round(-50, -2), 0) + self.assertEqual(round(-49, -2), 0) + self.assertEqual(round(-1, -2), 0) + self.assertEqual(round(0, -2), 0) + self.assertEqual(round(1, -2), 0) + self.assertEqual(round(49, -2), 0) + self.assertEqual(round(50, -2), 0) + self.assertEqual(round(51, -2), 100) + self.assertEqual(round(149, -2), 100) + self.assertEqual(round(150, -2), 200) + self.assertEqual(round(250, -2), 200) + self.assertEqual(round(251, -2), 300) + self.assertEqual(round(172500, -3), 172000) + self.assertEqual(round(173500, -3), 174000) + self.assertEqual(round(31415926535, -1), 31415926540) + self.assertEqual(round(31415926535, -2), 31415926500) + self.assertEqual(round(31415926535, -3), 31415927000) + self.assertEqual(round(31415926535, -4), 31415930000) + self.assertEqual(round(31415926535, -5), 31415900000) + self.assertEqual(round(31415926535, -6), 31416000000) + self.assertEqual(round(31415926535, -7), 31420000000) + self.assertEqual(round(31415926535, -8), 31400000000) + self.assertEqual(round(31415926535, -9), 31000000000) + self.assertEqual(round(31415926535, -10), 30000000000) + self.assertEqual(round(31415926535, -11), 0) + self.assertEqual(round(31415926535, -12), 0) + self.assertEqual(round(31415926535, -999), 0) + + # should get correct results even for huge inputs + for k in range(10, 100): + got = round(10**k + 324678, -3) + expect = 10**k + 325000 + self.assertEqual(got, expect) + self.assertTrue(type(got) is int) + + # nonnegative second argument: round(x, n) should just return x + for n in range(5): + for i in range(100): + x = random.randrange(-10000, 10000) + got = round(x, n) + self.assertEqual(got, x) + self.assertTrue(type(got) is int) + for huge_n in 2**31-1, 2**31, 2**63-1, 2**63, 2**100, 10**100: + self.assertEqual(round(8979323, huge_n), 8979323) + + # omitted second argument + for i in range(100): + x = random.randrange(-10000, 10000) + got = round(x) + self.assertEqual(got, x) + self.assertTrue(type(got) is int) + + # bad second argument + bad_exponents = ('brian', 2.0, 0j, None) + for e in bad_exponents: + self.assertRaises(TypeError, round, 3, e) + + def test_to_bytes(self): + def check(tests, byteorder, signed=False): + for test, expected in tests.items(): + try: + self.assertEqual( + test.to_bytes(len(expected), byteorder, signed=signed), + expected) + except Exception as err: + raise AssertionError( + "failed to convert {0} with byteorder={1} and signed={2}" + .format(test, byteorder, signed)) from err + + # Convert integers to signed big-endian byte arrays. + tests1 = { + 0: b'\x00', + 1: b'\x01', + -1: b'\xff', + -127: b'\x81', + -128: b'\x80', + -129: b'\xff\x7f', + 127: b'\x7f', + 129: b'\x00\x81', + -255: b'\xff\x01', + -256: b'\xff\x00', + 255: b'\x00\xff', + 256: b'\x01\x00', + 32767: b'\x7f\xff', + -32768: b'\xff\x80\x00', + 65535: b'\x00\xff\xff', + -65536: b'\xff\x00\x00', + -8388608: b'\x80\x00\x00' + } + check(tests1, 'big', signed=True) + + # Convert integers to signed little-endian byte arrays. + tests2 = { + 0: b'\x00', + 1: b'\x01', + -1: b'\xff', + -127: b'\x81', + -128: b'\x80', + -129: b'\x7f\xff', + 127: b'\x7f', + 129: b'\x81\x00', + -255: b'\x01\xff', + -256: b'\x00\xff', + 255: b'\xff\x00', + 256: b'\x00\x01', + 32767: b'\xff\x7f', + -32768: b'\x00\x80', + 65535: b'\xff\xff\x00', + -65536: b'\x00\x00\xff', + -8388608: b'\x00\x00\x80' + } + check(tests2, 'little', signed=True) + + # Convert integers to unsigned big-endian byte arrays. + tests3 = { + 0: b'\x00', + 1: b'\x01', + 127: b'\x7f', + 128: b'\x80', + 255: b'\xff', + 256: b'\x01\x00', + 32767: b'\x7f\xff', + 32768: b'\x80\x00', + 65535: b'\xff\xff', + 65536: b'\x01\x00\x00' + } + check(tests3, 'big', signed=False) + + # Convert integers to unsigned little-endian byte arrays. + tests4 = { + 0: b'\x00', + 1: b'\x01', + 127: b'\x7f', + 128: b'\x80', + 255: b'\xff', + 256: b'\x00\x01', + 32767: b'\xff\x7f', + 32768: b'\x00\x80', + 65535: b'\xff\xff', + 65536: b'\x00\x00\x01' + } + check(tests4, 'little', signed=False) + + self.assertRaises(OverflowError, (256).to_bytes, 1, 'big', signed=False) + self.assertRaises(OverflowError, (256).to_bytes, 1, 'big', signed=True) + self.assertRaises(OverflowError, (256).to_bytes, 1, 'little', signed=False) + self.assertRaises(OverflowError, (256).to_bytes, 1, 'little', signed=True) + self.assertRaises(OverflowError, (-1).to_bytes, 2, 'big', signed=False), + self.assertRaises(OverflowError, (-1).to_bytes, 2, 'little', signed=False) + self.assertEqual((0).to_bytes(0, 'big'), b'') + self.assertEqual((1).to_bytes(5, 'big'), b'\x00\x00\x00\x00\x01') + self.assertEqual((0).to_bytes(5, 'big'), b'\x00\x00\x00\x00\x00') + self.assertEqual((-1).to_bytes(5, 'big', signed=True), + b'\xff\xff\xff\xff\xff') + self.assertRaises(OverflowError, (1).to_bytes, 0, 'big') + + def test_from_bytes(self): + def check(tests, byteorder, signed=False): + for test, expected in tests.items(): + try: + self.assertEqual( + int.from_bytes(test, byteorder, signed=signed), + expected) + except Exception as err: + raise AssertionError( + "failed to convert {0} with byteorder={1!r} and signed={2}" + .format(test, byteorder, signed)) from err + + # Convert signed big-endian byte arrays to integers. + tests1 = { + b'': 0, + b'\x00': 0, + b'\x00\x00': 0, + b'\x01': 1, + b'\x00\x01': 1, + b'\xff': -1, + b'\xff\xff': -1, + b'\x81': -127, + b'\x80': -128, + b'\xff\x7f': -129, + b'\x7f': 127, + b'\x00\x81': 129, + b'\xff\x01': -255, + b'\xff\x00': -256, + b'\x00\xff': 255, + b'\x01\x00': 256, + b'\x7f\xff': 32767, + b'\x80\x00': -32768, + b'\x00\xff\xff': 65535, + b'\xff\x00\x00': -65536, + b'\x80\x00\x00': -8388608 + } + check(tests1, 'big', signed=True) + + # Convert signed little-endian byte arrays to integers. + tests2 = { + b'': 0, + b'\x00': 0, + b'\x00\x00': 0, + b'\x01': 1, + b'\x00\x01': 256, + b'\xff': -1, + b'\xff\xff': -1, + b'\x81': -127, + b'\x80': -128, + b'\x7f\xff': -129, + b'\x7f': 127, + b'\x81\x00': 129, + b'\x01\xff': -255, + b'\x00\xff': -256, + b'\xff\x00': 255, + b'\x00\x01': 256, + b'\xff\x7f': 32767, + b'\x00\x80': -32768, + b'\xff\xff\x00': 65535, + b'\x00\x00\xff': -65536, + b'\x00\x00\x80': -8388608 + } + check(tests2, 'little', signed=True) + + # Convert unsigned big-endian byte arrays to integers. + tests3 = { + b'': 0, + b'\x00': 0, + b'\x01': 1, + b'\x7f': 127, + b'\x80': 128, + b'\xff': 255, + b'\x01\x00': 256, + b'\x7f\xff': 32767, + b'\x80\x00': 32768, + b'\xff\xff': 65535, + b'\x01\x00\x00': 65536, + } + check(tests3, 'big', signed=False) + + # Convert integers to unsigned little-endian byte arrays. + tests4 = { + b'': 0, + b'\x00': 0, + b'\x01': 1, + b'\x7f': 127, + b'\x80': 128, + b'\xff': 255, + b'\x00\x01': 256, + b'\xff\x7f': 32767, + b'\x00\x80': 32768, + b'\xff\xff': 65535, + b'\x00\x00\x01': 65536, + } + check(tests4, 'little', signed=False) + + class myint(int): + pass + + self.assertTrue(type(myint.from_bytes(b'\x00', 'big')) is myint) + self.assertEqual(myint.from_bytes(b'\x01', 'big'), 1) + self.assertTrue( + type(myint.from_bytes(b'\x00', 'big', signed=False)) is myint) + self.assertEqual(myint.from_bytes(b'\x01', 'big', signed=False), 1) + self.assertTrue(type(myint.from_bytes(b'\x00', 'little')) is myint) + self.assertEqual(myint.from_bytes(b'\x01', 'little'), 1) + self.assertTrue(type(myint.from_bytes( + b'\x00', 'little', signed=False)) is myint) + self.assertEqual(myint.from_bytes(b'\x01', 'little', signed=False), 1) + self.assertEqual( + int.from_bytes([255, 0, 0], 'big', signed=True), -65536) + self.assertEqual( + int.from_bytes((255, 0, 0), 'big', signed=True), -65536) + self.assertEqual(int.from_bytes( + bytearray(b'\xff\x00\x00'), 'big', signed=True), -65536) + self.assertEqual(int.from_bytes( + bytearray(b'\xff\x00\x00'), 'big', signed=True), -65536) + self.assertEqual(int.from_bytes( + array.array('B', b'\xff\x00\x00'), 'big', signed=True), -65536) + self.assertEqual(int.from_bytes( + memoryview(b'\xff\x00\x00'), 'big', signed=True), -65536) + self.assertRaises(ValueError, int.from_bytes, [256], 'big') + self.assertRaises(ValueError, int.from_bytes, [0], 'big\x00') + self.assertRaises(ValueError, int.from_bytes, [0], 'little\x00') + self.assertRaises(TypeError, int.from_bytes, "", 'big') + self.assertRaises(TypeError, int.from_bytes, "\x00", 'big') + self.assertRaises(TypeError, int.from_bytes, 0, 'big') + self.assertRaises(TypeError, int.from_bytes, 0, 'big', True) + self.assertRaises(TypeError, myint.from_bytes, "", 'big') + self.assertRaises(TypeError, myint.from_bytes, "\x00", 'big') + self.assertRaises(TypeError, myint.from_bytes, 0, 'big') + self.assertRaises(TypeError, int.from_bytes, 0, 'big', True) + + def test_access_to_nonexistent_digit_0(self): + # http://bugs.python.org/issue14630: A bug in _PyLong_Copy meant that + # ob_digit[0] was being incorrectly accessed for instances of a + # subclass of int, with value 0. + class Integer(int): + def __new__(cls, value=0): + self = int.__new__(cls, value) + self.foo = 'foo' + return self + + integers = [Integer(0) for i in range(1000)] + for n in map(int, integers): + self.assertEqual(n, 0) + def test_main(): - test_support.run_unittest(LongTest) + support.run_unittest(LongTest) if __name__ == "__main__": test_main() |