PageRenderTime 152ms CodeModel.GetById 31ms app.highlight 107ms RepoModel.GetById 1ms app.codeStats 1ms

/Lib/test/test_long.py

http://unladen-swallow.googlecode.com/
Python | 759 lines | 738 code | 9 blank | 12 comment | 19 complexity | 93fe95a83e1b3361b078198e392c0774 MD5 | raw file
  1import unittest
  2from test import test_support
  3import sys
  4
  5import random
  6
  7# Used for lazy formatting of failure messages
  8class Frm(object):
  9    def __init__(self, format, *args):
 10        self.format = format
 11        self.args = args
 12
 13    def __str__(self):
 14        return self.format % self.args
 15
 16# SHIFT should match the value in longintrepr.h for best testing.
 17SHIFT = 15
 18BASE = 2 ** SHIFT
 19MASK = BASE - 1
 20KARATSUBA_CUTOFF = 70   # from longobject.c
 21
 22# Max number of base BASE digits to use in test cases.  Doubling
 23# this will more than double the runtime.
 24MAXDIGITS = 15
 25
 26# build some special values
 27special = map(long, [0, 1, 2, BASE, BASE >> 1])
 28special.append(0x5555555555555555L)
 29special.append(0xaaaaaaaaaaaaaaaaL)
 30#  some solid strings of one bits
 31p2 = 4L  # 0 and 1 already added
 32for i in range(2*SHIFT):
 33    special.append(p2 - 1)
 34    p2 = p2 << 1
 35del p2
 36# add complements & negations
 37special = special + map(lambda x: ~x, special) + \
 38                    map(lambda x: -x, special)
 39
 40L = [
 41        ('0', 0),
 42        ('1', 1),
 43        ('9', 9),
 44        ('10', 10),
 45        ('99', 99),
 46        ('100', 100),
 47        ('314', 314),
 48        (' 314', 314),
 49        ('314 ', 314),
 50        ('  \t\t  314  \t\t  ', 314),
 51        (repr(sys.maxint), sys.maxint),
 52        ('  1x', ValueError),
 53        ('  1  ', 1),
 54        ('  1\02  ', ValueError),
 55        ('', ValueError),
 56        (' ', ValueError),
 57        ('  \t\t  ', ValueError)
 58]
 59if test_support.have_unicode:
 60    L += [
 61        (unicode('0'), 0),
 62        (unicode('1'), 1),
 63        (unicode('9'), 9),
 64        (unicode('10'), 10),
 65        (unicode('99'), 99),
 66        (unicode('100'), 100),
 67        (unicode('314'), 314),
 68        (unicode(' 314'), 314),
 69        (unicode('\u0663\u0661\u0664 ','raw-unicode-escape'), 314),
 70        (unicode('  \t\t  314  \t\t  '), 314),
 71        (unicode('  1x'), ValueError),
 72        (unicode('  1  '), 1),
 73        (unicode('  1\02  '), ValueError),
 74        (unicode(''), ValueError),
 75        (unicode(' '), ValueError),
 76        (unicode('  \t\t  '), ValueError),
 77        (unichr(0x200), ValueError),
 78]
 79
 80
 81class LongTest(unittest.TestCase):
 82
 83    # Get quasi-random long consisting of ndigits digits (in base BASE).
 84    # quasi == the most-significant digit will not be 0, and the number
 85    # is constructed to contain long strings of 0 and 1 bits.  These are
 86    # more likely than random bits to provoke digit-boundary errors.
 87    # The sign of the number is also random.
 88
 89    def getran(self, ndigits):
 90        self.assert_(ndigits > 0)
 91        nbits_hi = ndigits * SHIFT
 92        nbits_lo = nbits_hi - SHIFT + 1
 93        answer = 0L
 94        nbits = 0
 95        r = int(random.random() * (SHIFT * 2)) | 1  # force 1 bits to start
 96        while nbits < nbits_lo:
 97            bits = (r >> 1) + 1
 98            bits = min(bits, nbits_hi - nbits)
 99            self.assert_(1 <= bits <= SHIFT)
100            nbits = nbits + bits
101            answer = answer << bits
102            if r & 1:
103                answer = answer | ((1 << bits) - 1)
104            r = int(random.random() * (SHIFT * 2))
105        self.assert_(nbits_lo <= nbits <= nbits_hi)
106        if random.random() < 0.5:
107            answer = -answer
108        return answer
109
110    # Get random long consisting of ndigits random digits (relative to base
111    # BASE).  The sign bit is also random.
112
113    def getran2(ndigits):
114        answer = 0L
115        for i in xrange(ndigits):
116            answer = (answer << SHIFT) | random.randint(0, MASK)
117        if random.random() < 0.5:
118            answer = -answer
119        return answer
120
121    def check_division(self, x, y):
122        eq = self.assertEqual
123        q, r = divmod(x, y)
124        q2, r2 = x//y, x%y
125        pab, pba = x*y, y*x
126        eq(pab, pba, Frm("multiplication does not commute for %r and %r", x, y))
127        eq(q, q2, Frm("divmod returns different quotient than / for %r and %r", x, y))
128        eq(r, r2, Frm("divmod returns different mod than %% for %r and %r", x, y))
129        eq(x, q*y + r, Frm("x != q*y + r after divmod on x=%r, y=%r", x, y))
130        if y > 0:
131            self.assert_(0 <= r < y, Frm("bad mod from divmod on %r and %r", x, y))
132        else:
133            self.assert_(y < r <= 0, Frm("bad mod from divmod on %r and %r", x, y))
134
135    def test_division(self):
136        digits = range(1, MAXDIGITS+1) + range(KARATSUBA_CUTOFF,
137                                               KARATSUBA_CUTOFF + 14)
138        digits.append(KARATSUBA_CUTOFF * 3)
139        for lenx in digits:
140            x = self.getran(lenx)
141            for leny in digits:
142                y = self.getran(leny) or 1L
143                self.check_division(x, y)
144
145    def test_karatsuba(self):
146        digits = range(1, 5) + range(KARATSUBA_CUTOFF, KARATSUBA_CUTOFF + 10)
147        digits.extend([KARATSUBA_CUTOFF * 10, KARATSUBA_CUTOFF * 100])
148
149        bits = [digit * SHIFT for digit in digits]
150
151        # Test products of long strings of 1 bits -- (2**x-1)*(2**y-1) ==
152        # 2**(x+y) - 2**x - 2**y + 1, so the proper result is easy to check.
153        for abits in bits:
154            a = (1L << abits) - 1
155            for bbits in bits:
156                if bbits < abits:
157                    continue
158                b = (1L << bbits) - 1
159                x = a * b
160                y = ((1L << (abits + bbits)) -
161                     (1L << abits) -
162                     (1L << bbits) +
163                     1)
164                self.assertEqual(x, y,
165                    Frm("bad result for a*b: a=%r, b=%r, x=%r, y=%r", a, b, x, y))
166
167    def check_bitop_identities_1(self, x):
168        eq = self.assertEqual
169        eq(x & 0, 0, Frm("x & 0 != 0 for x=%r", x))
170        eq(x | 0, x, Frm("x | 0 != x for x=%r", x))
171        eq(x ^ 0, x, Frm("x ^ 0 != x for x=%r", x))
172        eq(x & -1, x, Frm("x & -1 != x for x=%r", x))
173        eq(x | -1, -1, Frm("x | -1 != -1 for x=%r", x))
174        eq(x ^ -1, ~x, Frm("x ^ -1 != ~x for x=%r", x))
175        eq(x, ~~x, Frm("x != ~~x for x=%r", x))
176        eq(x & x, x, Frm("x & x != x for x=%r", x))
177        eq(x | x, x, Frm("x | x != x for x=%r", x))
178        eq(x ^ x, 0, Frm("x ^ x != 0 for x=%r", x))
179        eq(x & ~x, 0, Frm("x & ~x != 0 for x=%r", x))
180        eq(x | ~x, -1, Frm("x | ~x != -1 for x=%r", x))
181        eq(x ^ ~x, -1, Frm("x ^ ~x != -1 for x=%r", x))
182        eq(-x, 1 + ~x, Frm("not -x == 1 + ~x for x=%r", x))
183        eq(-x, ~(x-1), Frm("not -x == ~(x-1) forx =%r", x))
184        for n in xrange(2*SHIFT):
185            p2 = 2L ** n
186            eq(x << n >> n, x,
187                Frm("x << n >> n != x for x=%r, n=%r", (x, n)))
188            eq(x // p2, x >> n,
189                Frm("x // p2 != x >> n for x=%r n=%r p2=%r", (x, n, p2)))
190            eq(x * p2, x << n,
191                Frm("x * p2 != x << n for x=%r n=%r p2=%r", (x, n, p2)))
192            eq(x & -p2, x >> n << n,
193                Frm("not x & -p2 == x >> n << n for x=%r n=%r p2=%r", (x, n, p2)))
194            eq(x & -p2, x & ~(p2 - 1),
195                Frm("not x & -p2 == x & ~(p2 - 1) for x=%r n=%r p2=%r", (x, n, p2)))
196
197    def check_bitop_identities_2(self, x, y):
198        eq = self.assertEqual
199        eq(x & y, y & x, Frm("x & y != y & x for x=%r, y=%r", (x, y)))
200        eq(x | y, y | x, Frm("x | y != y | x for x=%r, y=%r", (x, y)))
201        eq(x ^ y, y ^ x, Frm("x ^ y != y ^ x for x=%r, y=%r", (x, y)))
202        eq(x ^ y ^ x, y, Frm("x ^ y ^ x != y for x=%r, y=%r", (x, y)))
203        eq(x & y, ~(~x | ~y), Frm("x & y != ~(~x | ~y) for x=%r, y=%r", (x, y)))
204        eq(x | y, ~(~x & ~y), Frm("x | y != ~(~x & ~y) for x=%r, y=%r", (x, y)))
205        eq(x ^ y, (x | y) & ~(x & y),
206             Frm("x ^ y != (x | y) & ~(x & y) for x=%r, y=%r", (x, y)))
207        eq(x ^ y, (x & ~y) | (~x & y),
208             Frm("x ^ y == (x & ~y) | (~x & y) for x=%r, y=%r", (x, y)))
209        eq(x ^ y, (x | y) & (~x | ~y),
210             Frm("x ^ y == (x | y) & (~x | ~y) for x=%r, y=%r", (x, y)))
211
212    def check_bitop_identities_3(self, x, y, z):
213        eq = self.assertEqual
214        eq((x & y) & z, x & (y & z),
215             Frm("(x & y) & z != x & (y & z) for x=%r, y=%r, z=%r", (x, y, z)))
216        eq((x | y) | z, x | (y | z),
217             Frm("(x | y) | z != x | (y | z) for x=%r, y=%r, z=%r", (x, y, z)))
218        eq((x ^ y) ^ z, x ^ (y ^ z),
219             Frm("(x ^ y) ^ z != x ^ (y ^ z) for x=%r, y=%r, z=%r", (x, y, z)))
220        eq(x & (y | z), (x & y) | (x & z),
221             Frm("x & (y | z) != (x & y) | (x & z) for x=%r, y=%r, z=%r", (x, y, z)))
222        eq(x | (y & z), (x | y) & (x | z),
223             Frm("x | (y & z) != (x | y) & (x | z) for x=%r, y=%r, z=%r", (x, y, z)))
224
225    def test_bitop_identities(self):
226        for x in special:
227            self.check_bitop_identities_1(x)
228        digits = xrange(1, MAXDIGITS+1)
229        for lenx in digits:
230            x = self.getran(lenx)
231            self.check_bitop_identities_1(x)
232            for leny in digits:
233                y = self.getran(leny)
234                self.check_bitop_identities_2(x, y)
235                self.check_bitop_identities_3(x, y, self.getran((lenx + leny)//2))
236
237    def slow_format(self, x, base):
238        if (x, base) == (0, 8):
239            # this is an oddball!
240            return "0L"
241        digits = []
242        sign = 0
243        if x < 0:
244            sign, x = 1, -x
245        while x:
246            x, r = divmod(x, base)
247            digits.append(int(r))
248        digits.reverse()
249        digits = digits or [0]
250        return '-'[:sign] + \
251               {8: '0', 10: '', 16: '0x'}[base] + \
252               "".join(map(lambda i: "0123456789abcdef"[i], digits)) + "L"
253
254    def check_format_1(self, x):
255        for base, mapper in (8, oct), (10, repr), (16, hex):
256            got = mapper(x)
257            expected = self.slow_format(x, base)
258            msg = Frm("%s returned %r but expected %r for %r",
259                mapper.__name__, got, expected, x)
260            self.assertEqual(got, expected, msg)
261            self.assertEqual(long(got, 0), x, Frm('long("%s", 0) != %r', got, x))
262        # str() has to be checked a little differently since there's no
263        # trailing "L"
264        got = str(x)
265        expected = self.slow_format(x, 10)[:-1]
266        msg = Frm("%s returned %r but expected %r for %r",
267            mapper.__name__, got, expected, x)
268        self.assertEqual(got, expected, msg)
269
270    def test_format(self):
271        for x in special:
272            self.check_format_1(x)
273        for i in xrange(10):
274            for lenx in xrange(1, MAXDIGITS+1):
275                x = self.getran(lenx)
276                self.check_format_1(x)
277
278    def test_long(self):
279        self.assertEqual(long(314), 314L)
280        self.assertEqual(long(3.14), 3L)
281        self.assertEqual(long(314L), 314L)
282        # Check that long() of basic types actually returns a long
283        self.assertEqual(type(long(314)), long)
284        self.assertEqual(type(long(3.14)), long)
285        self.assertEqual(type(long(314L)), long)
286        # Check that conversion from float truncates towards zero
287        self.assertEqual(long(-3.14), -3L)
288        self.assertEqual(long(3.9), 3L)
289        self.assertEqual(long(-3.9), -3L)
290        self.assertEqual(long(3.5), 3L)
291        self.assertEqual(long(-3.5), -3L)
292        self.assertEqual(long("-3"), -3L)
293        if test_support.have_unicode:
294            self.assertEqual(long(unicode("-3")), -3L)
295        # Different base:
296        self.assertEqual(long("10",16), 16L)
297        if test_support.have_unicode:
298            self.assertEqual(long(unicode("10"),16), 16L)
299        # Check conversions from string (same test set as for int(), and then some)
300        LL = [
301                ('1' + '0'*20, 10L**20),
302                ('1' + '0'*100, 10L**100)
303        ]
304        L2 = L[:]
305        if test_support.have_unicode:
306            L2 += [
307                (unicode('1') + unicode('0')*20, 10L**20),
308                (unicode('1') + unicode('0')*100, 10L**100),
309        ]
310        for s, v in L2 + LL:
311            for sign in "", "+", "-":
312                for prefix in "", " ", "\t", "  \t\t  ":
313                    ss = prefix + sign + s
314                    vv = v
315                    if sign == "-" and v is not ValueError:
316                        vv = -v
317                    try:
318                        self.assertEqual(long(ss), long(vv))
319                    except v:
320                        pass
321
322        self.assertRaises(ValueError, long, '123\0')
323        self.assertRaises(ValueError, long, '53', 40)
324        self.assertRaises(TypeError, long, 1, 12)
325
326        # SF patch #1638879: embedded NULs were not detected with
327        # explicit base
328        self.assertRaises(ValueError, long, '123\0', 10)
329        self.assertRaises(ValueError, long, '123\x00 245', 20)
330
331        self.assertEqual(long('100000000000000000000000000000000', 2),
332                         4294967296)
333        self.assertEqual(long('102002022201221111211', 3), 4294967296)
334        self.assertEqual(long('10000000000000000', 4), 4294967296)
335        self.assertEqual(long('32244002423141', 5), 4294967296)
336        self.assertEqual(long('1550104015504', 6), 4294967296)
337        self.assertEqual(long('211301422354', 7), 4294967296)
338        self.assertEqual(long('40000000000', 8), 4294967296)
339        self.assertEqual(long('12068657454', 9), 4294967296)
340        self.assertEqual(long('4294967296', 10), 4294967296)
341        self.assertEqual(long('1904440554', 11), 4294967296)
342        self.assertEqual(long('9ba461594', 12), 4294967296)
343        self.assertEqual(long('535a79889', 13), 4294967296)
344        self.assertEqual(long('2ca5b7464', 14), 4294967296)
345        self.assertEqual(long('1a20dcd81', 15), 4294967296)
346        self.assertEqual(long('100000000', 16), 4294967296)
347        self.assertEqual(long('a7ffda91', 17), 4294967296)
348        self.assertEqual(long('704he7g4', 18), 4294967296)
349        self.assertEqual(long('4f5aff66', 19), 4294967296)
350        self.assertEqual(long('3723ai4g', 20), 4294967296)
351        self.assertEqual(long('281d55i4', 21), 4294967296)
352        self.assertEqual(long('1fj8b184', 22), 4294967296)
353        self.assertEqual(long('1606k7ic', 23), 4294967296)
354        self.assertEqual(long('mb994ag', 24), 4294967296)
355        self.assertEqual(long('hek2mgl', 25), 4294967296)
356        self.assertEqual(long('dnchbnm', 26), 4294967296)
357        self.assertEqual(long('b28jpdm', 27), 4294967296)
358        self.assertEqual(long('8pfgih4', 28), 4294967296)
359        self.assertEqual(long('76beigg', 29), 4294967296)
360        self.assertEqual(long('5qmcpqg', 30), 4294967296)
361        self.assertEqual(long('4q0jto4', 31), 4294967296)
362        self.assertEqual(long('4000000', 32), 4294967296)
363        self.assertEqual(long('3aokq94', 33), 4294967296)
364        self.assertEqual(long('2qhxjli', 34), 4294967296)
365        self.assertEqual(long('2br45qb', 35), 4294967296)
366        self.assertEqual(long('1z141z4', 36), 4294967296)
367
368        self.assertEqual(long('100000000000000000000000000000001', 2),
369                         4294967297)
370        self.assertEqual(long('102002022201221111212', 3), 4294967297)
371        self.assertEqual(long('10000000000000001', 4), 4294967297)
372        self.assertEqual(long('32244002423142', 5), 4294967297)
373        self.assertEqual(long('1550104015505', 6), 4294967297)
374        self.assertEqual(long('211301422355', 7), 4294967297)
375        self.assertEqual(long('40000000001', 8), 4294967297)
376        self.assertEqual(long('12068657455', 9), 4294967297)
377        self.assertEqual(long('4294967297', 10), 4294967297)
378        self.assertEqual(long('1904440555', 11), 4294967297)
379        self.assertEqual(long('9ba461595', 12), 4294967297)
380        self.assertEqual(long('535a7988a', 13), 4294967297)
381        self.assertEqual(long('2ca5b7465', 14), 4294967297)
382        self.assertEqual(long('1a20dcd82', 15), 4294967297)
383        self.assertEqual(long('100000001', 16), 4294967297)
384        self.assertEqual(long('a7ffda92', 17), 4294967297)
385        self.assertEqual(long('704he7g5', 18), 4294967297)
386        self.assertEqual(long('4f5aff67', 19), 4294967297)
387        self.assertEqual(long('3723ai4h', 20), 4294967297)
388        self.assertEqual(long('281d55i5', 21), 4294967297)
389        self.assertEqual(long('1fj8b185', 22), 4294967297)
390        self.assertEqual(long('1606k7id', 23), 4294967297)
391        self.assertEqual(long('mb994ah', 24), 4294967297)
392        self.assertEqual(long('hek2mgm', 25), 4294967297)
393        self.assertEqual(long('dnchbnn', 26), 4294967297)
394        self.assertEqual(long('b28jpdn', 27), 4294967297)
395        self.assertEqual(long('8pfgih5', 28), 4294967297)
396        self.assertEqual(long('76beigh', 29), 4294967297)
397        self.assertEqual(long('5qmcpqh', 30), 4294967297)
398        self.assertEqual(long('4q0jto5', 31), 4294967297)
399        self.assertEqual(long('4000001', 32), 4294967297)
400        self.assertEqual(long('3aokq95', 33), 4294967297)
401        self.assertEqual(long('2qhxjlj', 34), 4294967297)
402        self.assertEqual(long('2br45qc', 35), 4294967297)
403        self.assertEqual(long('1z141z5', 36), 4294967297)
404
405
406    def test_conversion(self):
407        # Test __long__()
408        class ClassicMissingMethods:
409            pass
410        self.assertRaises(AttributeError, long, ClassicMissingMethods())
411
412        class MissingMethods(object):
413            pass
414        self.assertRaises(TypeError, long, MissingMethods())
415
416        class Foo0:
417            def __long__(self):
418                return 42L
419
420        class Foo1(object):
421            def __long__(self):
422                return 42L
423
424        class Foo2(long):
425            def __long__(self):
426                return 42L
427
428        class Foo3(long):
429            def __long__(self):
430                return self
431
432        class Foo4(long):
433            def __long__(self):
434                return 42
435
436        class Foo5(long):
437            def __long__(self):
438                return 42.
439
440        self.assertEqual(long(Foo0()), 42L)
441        self.assertEqual(long(Foo1()), 42L)
442        self.assertEqual(long(Foo2()), 42L)
443        self.assertEqual(long(Foo3()), 0)
444        self.assertEqual(long(Foo4()), 42)
445        self.assertRaises(TypeError, long, Foo5())
446
447        class Classic:
448            pass
449        for base in (object, Classic):
450            class LongOverridesTrunc(base):
451                def __long__(self):
452                    return 42
453                def __trunc__(self):
454                    return -12
455            self.assertEqual(long(LongOverridesTrunc()), 42)
456
457            class JustTrunc(base):
458                def __trunc__(self):
459                    return 42
460            self.assertEqual(long(JustTrunc()), 42)
461
462            for trunc_result_base in (object, Classic):
463                class Integral(trunc_result_base):
464                    def __int__(self):
465                        return 42
466
467                class TruncReturnsNonLong(base):
468                    def __trunc__(self):
469                        return Integral()
470                self.assertEqual(long(TruncReturnsNonLong()), 42)
471
472                class NonIntegral(trunc_result_base):
473                    def __trunc__(self):
474                        # Check that we avoid infinite recursion.
475                        return NonIntegral()
476
477                class TruncReturnsNonIntegral(base):
478                    def __trunc__(self):
479                        return NonIntegral()
480                try:
481                    long(TruncReturnsNonIntegral())
482                except TypeError as e:
483                    self.assertEquals(str(e),
484                                      "__trunc__ returned non-Integral"
485                                      " (type NonIntegral)")
486                else:
487                    self.fail("Failed to raise TypeError with %s" %
488                              ((base, trunc_result_base),))
489
490    def test_misc(self):
491
492        # check the extremes in int<->long conversion
493        hugepos = sys.maxint
494        hugeneg = -hugepos - 1
495        hugepos_aslong = long(hugepos)
496        hugeneg_aslong = long(hugeneg)
497        self.assertEqual(hugepos, hugepos_aslong, "long(sys.maxint) != sys.maxint")
498        self.assertEqual(hugeneg, hugeneg_aslong,
499            "long(-sys.maxint-1) != -sys.maxint-1")
500
501        # long -> int should not fail for hugepos_aslong or hugeneg_aslong
502        x = int(hugepos_aslong)
503        try:
504            self.assertEqual(x, hugepos,
505                  "converting sys.maxint to long and back to int fails")
506        except OverflowError:
507            self.fail("int(long(sys.maxint)) overflowed!")
508        if not isinstance(x, int):
509            raise TestFailed("int(long(sys.maxint)) should have returned int")
510        x = int(hugeneg_aslong)
511        try:
512            self.assertEqual(x, hugeneg,
513                  "converting -sys.maxint-1 to long and back to int fails")
514        except OverflowError:
515            self.fail("int(long(-sys.maxint-1)) overflowed!")
516        if not isinstance(x, int):
517            raise TestFailed("int(long(-sys.maxint-1)) should have "
518                             "returned int")
519        # but long -> int should overflow for hugepos+1 and hugeneg-1
520        x = hugepos_aslong + 1
521        try:
522            y = int(x)
523        except OverflowError:
524            self.fail("int(long(sys.maxint) + 1) mustn't overflow")
525        self.assert_(isinstance(y, long),
526            "int(long(sys.maxint) + 1) should have returned long")
527
528        x = hugeneg_aslong - 1
529        try:
530            y = int(x)
531        except OverflowError:
532            self.fail("int(long(-sys.maxint-1) - 1) mustn't overflow")
533        self.assert_(isinstance(y, long),
534               "int(long(-sys.maxint-1) - 1) should have returned long")
535
536        class long2(long):
537            pass
538        x = long2(1L<<100)
539        y = int(x)
540        self.assert_(type(y) is long,
541            "overflowing int conversion must return long not long subtype")
542
543        # long -> Py_ssize_t conversion
544        class X(object):
545            def __getslice__(self, i, j):
546                return i, j
547
548        self.assertEqual(X()[-5L:7L], (-5, 7))
549        # use the clamping effect to test the smallest and largest longs
550        # that fit a Py_ssize_t
551        slicemin, slicemax = X()[-2L**100:2L**100]
552        self.assertEqual(X()[slicemin:slicemax], (slicemin, slicemax))
553
554# ----------------------------------- tests of auto int->long conversion
555
556    def test_auto_overflow(self):
557        import math, sys
558
559        special = [0, 1, 2, 3, sys.maxint-1, sys.maxint, sys.maxint+1]
560        sqrt = int(math.sqrt(sys.maxint))
561        special.extend([sqrt-1, sqrt, sqrt+1])
562        special.extend([-i for i in special])
563
564        def checkit(*args):
565            # Heavy use of nested scopes here!
566            self.assertEqual(got, expected,
567                Frm("for %r expected %r got %r", args, expected, got))
568
569        for x in special:
570            longx = long(x)
571
572            expected = -longx
573            got = -x
574            checkit('-', x)
575
576            for y in special:
577                longy = long(y)
578
579                expected = longx + longy
580                got = x + y
581                checkit(x, '+', y)
582
583                expected = longx - longy
584                got = x - y
585                checkit(x, '-', y)
586
587                expected = longx * longy
588                got = x * y
589                checkit(x, '*', y)
590
591                if y:
592                    expected = longx / longy
593                    got = x / y
594                    checkit(x, '/', y)
595
596                    expected = longx // longy
597                    got = x // y
598                    checkit(x, '//', y)
599
600                    expected = divmod(longx, longy)
601                    got = divmod(longx, longy)
602                    checkit(x, 'divmod', y)
603
604                if abs(y) < 5 and not (x == 0 and y < 0):
605                    expected = longx ** longy
606                    got = x ** y
607                    checkit(x, '**', y)
608
609                    for z in special:
610                        if z != 0 :
611                            if y >= 0:
612                                expected = pow(longx, longy, long(z))
613                                got = pow(x, y, z)
614                                checkit('pow', x, y, '%', z)
615                            else:
616                                self.assertRaises(TypeError, pow,longx, longy, long(z))
617
618    def test_float_overflow(self):
619        import math
620
621        for x in -2.0, -1.0, 0.0, 1.0, 2.0:
622            self.assertEqual(float(long(x)), x)
623
624        shuge = '12345' * 120
625        huge = 1L << 30000
626        mhuge = -huge
627        namespace = {'huge': huge, 'mhuge': mhuge, 'shuge': shuge, 'math': math}
628        for test in ["float(huge)", "float(mhuge)",
629                     "complex(huge)", "complex(mhuge)",
630                     "complex(huge, 1)", "complex(mhuge, 1)",
631                     "complex(1, huge)", "complex(1, mhuge)",
632                     "1. + huge", "huge + 1.", "1. + mhuge", "mhuge + 1.",
633                     "1. - huge", "huge - 1.", "1. - mhuge", "mhuge - 1.",
634                     "1. * huge", "huge * 1.", "1. * mhuge", "mhuge * 1.",
635                     "1. // huge", "huge // 1.", "1. // mhuge", "mhuge // 1.",
636                     "1. / huge", "huge / 1.", "1. / mhuge", "mhuge / 1.",
637                     "1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
638                     "math.sin(huge)", "math.sin(mhuge)",
639                     "math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
640                     "math.floor(huge)", "math.floor(mhuge)"]:
641
642            self.assertRaises(OverflowError, eval, test, namespace)
643
644            # XXX Perhaps float(shuge) can raise OverflowError on some box?
645            # The comparison should not.
646            self.assertNotEqual(float(shuge), int(shuge),
647                "float(shuge) should not equal int(shuge)")
648
649    def test_logs(self):
650        import math
651
652        LOG10E = math.log10(math.e)
653
654        for exp in range(10) + [100, 1000, 10000]:
655            value = 10 ** exp
656            log10 = math.log10(value)
657            self.assertAlmostEqual(log10, exp)
658
659            # log10(value) == exp, so log(value) == log10(value)/log10(e) ==
660            # exp/LOG10E
661            expected = exp / LOG10E
662            log = math.log(value)
663            self.assertAlmostEqual(log, expected)
664
665        for bad in -(1L << 10000), -2L, 0L:
666            self.assertRaises(ValueError, math.log, bad)
667            self.assertRaises(ValueError, math.log10, bad)
668
669    def test_mixed_compares(self):
670        eq = self.assertEqual
671        import math
672
673        # We're mostly concerned with that mixing floats and longs does the
674        # right stuff, even when longs are too large to fit in a float.
675        # The safest way to check the results is to use an entirely different
676        # method, which we do here via a skeletal rational class (which
677        # represents all Python ints, longs and floats exactly).
678        class Rat:
679            def __init__(self, value):
680                if isinstance(value, (int, long)):
681                    self.n = value
682                    self.d = 1
683                elif isinstance(value, float):
684                    # Convert to exact rational equivalent.
685                    f, e = math.frexp(abs(value))
686                    assert f == 0 or 0.5 <= f < 1.0
687                    # |value| = f * 2**e exactly
688
689                    # Suck up CHUNK bits at a time; 28 is enough so that we suck
690                    # up all bits in 2 iterations for all known binary double-
691                    # precision formats, and small enough to fit in an int.
692                    CHUNK = 28
693                    top = 0
694                    # invariant: |value| = (top + f) * 2**e exactly
695                    while f:
696                        f = math.ldexp(f, CHUNK)
697                        digit = int(f)
698                        assert digit >> CHUNK == 0
699                        top = (top << CHUNK) | digit
700                        f -= digit
701                        assert 0.0 <= f < 1.0
702                        e -= CHUNK
703
704                    # Now |value| = top * 2**e exactly.
705                    if e >= 0:
706                        n = top << e
707                        d = 1
708                    else:
709                        n = top
710                        d = 1 << -e
711                    if value < 0:
712                        n = -n
713                    self.n = n
714                    self.d = d
715                    assert float(n) / float(d) == value
716                else:
717                    raise TypeError("can't deal with %r" % val)
718
719            def __cmp__(self, other):
720                if not isinstance(other, Rat):
721                    other = Rat(other)
722                return cmp(self.n * other.d, self.d * other.n)
723
724        cases = [0, 0.001, 0.99, 1.0, 1.5, 1e20, 1e200]
725        # 2**48 is an important boundary in the internals.  2**53 is an
726        # important boundary for IEEE double precision.
727        for t in 2.0**48, 2.0**50, 2.0**53:
728            cases.extend([t - 1.0, t - 0.3, t, t + 0.3, t + 1.0,
729                          long(t-1), long(t), long(t+1)])
730        cases.extend([0, 1, 2, sys.maxint, float(sys.maxint)])
731        # 1L<<20000 should exceed all double formats.  long(1e200) is to
732        # check that we get equality with 1e200 above.
733        t = long(1e200)
734        cases.extend([0L, 1L, 2L, 1L << 20000, t-1, t, t+1])
735        cases.extend([-x for x in cases])
736        for x in cases:
737            Rx = Rat(x)
738            for y in cases:
739                Ry = Rat(y)
740                Rcmp = cmp(Rx, Ry)
741                xycmp = cmp(x, y)
742                eq(Rcmp, xycmp, Frm("%r %r %d %d", x, y, Rcmp, xycmp))
743                eq(x == y, Rcmp == 0, Frm("%r == %r %d", x, y, Rcmp))
744                eq(x != y, Rcmp != 0, Frm("%r != %r %d", x, y, Rcmp))
745                eq(x < y, Rcmp < 0, Frm("%r < %r %d", x, y, Rcmp))
746                eq(x <= y, Rcmp <= 0, Frm("%r <= %r %d", x, y, Rcmp))
747                eq(x > y, Rcmp > 0, Frm("%r > %r %d", x, y, Rcmp))
748                eq(x >= y, Rcmp >= 0, Frm("%r >= %r %d", x, y, Rcmp))
749
750    def test_nan_inf(self):
751        self.assertRaises(OverflowError, long, float('inf'))
752        self.assertRaises(OverflowError, long, float('-inf'))
753        self.assertRaises(ValueError, long, float('nan'))
754
755def test_main():
756    test_support.run_unittest(LongTest)
757
758if __name__ == "__main__":
759    test_main()