blob: e53fd058cf36953d4a410d1586fc632d30e3da2c [file] [log] [blame]
Walter Dörwalda0021592005-06-13 21:44:48 +00001import unittest
2from test import test_support
Benjamin Peterson979395b2008-05-03 21:35:18 +00003import sys
Walter Dörwalda0021592005-06-13 21:44:48 +00004
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
Guido van Rossum4365cab1998-08-13 14:20:17 +000015
16# SHIFT should match the value in longintrepr.h for best testing.
17SHIFT = 15
18BASE = 2 ** SHIFT
19MASK = BASE - 1
Tim Petersdaec9612004-08-30 23:18:23 +000020KARATSUBA_CUTOFF = 70 # from longobject.c
Guido van Rossum4365cab1998-08-13 14:20:17 +000021
22# Max number of base BASE digits to use in test cases. Doubling
Tim Peters28b0e2a2002-08-13 02:17:11 +000023# this will more than double the runtime.
24MAXDIGITS = 15
Guido van Rossum4365cab1998-08-13 14:20:17 +000025
Guido van Rossum4581a0c1998-10-02 01:19:48 +000026# 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
Benjamin Peterson979395b2008-05-03 21:35:18 +000040L = [
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
Guido van Rossum4365cab1998-08-13 14:20:17 +000080
Walter Dörwalda0021592005-06-13 21:44:48 +000081class LongTest(unittest.TestCase):
Guido van Rossum4365cab1998-08-13 14:20:17 +000082
Walter Dörwalda0021592005-06-13 21:44:48 +000083 # 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.
Guido van Rossum4365cab1998-08-13 14:20:17 +000088
Walter Dörwalda0021592005-06-13 21:44:48 +000089 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
Guido van Rossum4581a0c1998-10-02 01:19:48 +0000109
Walter Dörwalda0021592005-06-13 21:44:48 +0000110 # Get random long consisting of ndigits random digits (relative to base
111 # BASE). The sign bit is also random.
Guido van Rossum4581a0c1998-10-02 01:19:48 +0000112
Walter Dörwalda0021592005-06-13 21:44:48 +0000113 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
Guido van Rossum4365cab1998-08-13 14:20:17 +0000120
Walter Dörwalda0021592005-06-13 21:44:48 +0000121 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))
Guido van Rossum4365cab1998-08-13 14:20:17 +0000134
Walter Dörwalda0021592005-06-13 21:44:48 +0000135 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)
Guido van Rossum4365cab1998-08-13 14:20:17 +0000144
Walter Dörwalda0021592005-06-13 21:44:48 +0000145 def test_karatsuba(self):
146 digits = range(1, 5) + range(KARATSUBA_CUTOFF, KARATSUBA_CUTOFF + 10)
147 digits.extend([KARATSUBA_CUTOFF * 10, KARATSUBA_CUTOFF * 100])
Guido van Rossum4365cab1998-08-13 14:20:17 +0000148
Walter Dörwalda0021592005-06-13 21:44:48 +0000149 bits = [digit * SHIFT for digit in digits]
Guido van Rossum4365cab1998-08-13 14:20:17 +0000150
Walter Dörwalda0021592005-06-13 21:44:48 +0000151 # 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))
Tim Peters7f270ba2002-08-13 21:06:55 +0000166
Walter Dörwalda0021592005-06-13 21:44:48 +0000167 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)))
Tim Peters7f270ba2002-08-13 21:06:55 +0000196
Walter Dörwalda0021592005-06-13 21:44:48 +0000197 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)))
Tim Peters7f270ba2002-08-13 21:06:55 +0000211
Walter Dörwalda0021592005-06-13 21:44:48 +0000212 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)))
Tim Peters7f270ba2002-08-13 21:06:55 +0000224
Walter Dörwalda0021592005-06-13 21:44:48 +0000225 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))
Guido van Rossum4365cab1998-08-13 14:20:17 +0000236
Walter Dörwalda0021592005-06-13 21:44:48 +0000237 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] + \
Raymond Hettinger3296e692005-06-29 23:29:56 +0000252 "".join(map(lambda i: "0123456789abcdef"[i], digits)) + "L"
Guido van Rossum4365cab1998-08-13 14:20:17 +0000253
Walter Dörwalda0021592005-06-13 21:44:48 +0000254 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)
Guido van Rossum4365cab1998-08-13 14:20:17 +0000269
Walter Dörwalda0021592005-06-13 21:44:48 +0000270 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)
Guido van Rossum4365cab1998-08-13 14:20:17 +0000277
Benjamin Peterson979395b2008-05-03 21:35:18 +0000278 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 conversion from float truncates towards zero
283 self.assertEqual(long(-3.14), -3L)
284 self.assertEqual(long(3.9), 3L)
285 self.assertEqual(long(-3.9), -3L)
286 self.assertEqual(long(3.5), 3L)
287 self.assertEqual(long(-3.5), -3L)
288 self.assertEqual(long("-3"), -3L)
289 if test_support.have_unicode:
290 self.assertEqual(long(unicode("-3")), -3L)
291 # Different base:
292 self.assertEqual(long("10",16), 16L)
293 if test_support.have_unicode:
294 self.assertEqual(long(unicode("10"),16), 16L)
295 # Check conversions from string (same test set as for int(), and then some)
296 LL = [
297 ('1' + '0'*20, 10L**20),
298 ('1' + '0'*100, 10L**100)
299 ]
300 L2 = L[:]
301 if test_support.have_unicode:
302 L2 += [
303 (unicode('1') + unicode('0')*20, 10L**20),
304 (unicode('1') + unicode('0')*100, 10L**100),
305 ]
306 for s, v in L2 + LL:
307 for sign in "", "+", "-":
308 for prefix in "", " ", "\t", " \t\t ":
309 ss = prefix + sign + s
310 vv = v
311 if sign == "-" and v is not ValueError:
312 vv = -v
313 try:
314 self.assertEqual(long(ss), long(vv))
315 except v:
316 pass
317
318 self.assertRaises(ValueError, long, '123\0')
319 self.assertRaises(ValueError, long, '53', 40)
320 self.assertRaises(TypeError, long, 1, 12)
321
322 # SF patch #1638879: embedded NULs were not detected with
323 # explicit base
324 self.assertRaises(ValueError, long, '123\0', 10)
325 self.assertRaises(ValueError, long, '123\x00 245', 20)
326
327 self.assertEqual(long('100000000000000000000000000000000', 2),
328 4294967296)
329 self.assertEqual(long('102002022201221111211', 3), 4294967296)
330 self.assertEqual(long('10000000000000000', 4), 4294967296)
331 self.assertEqual(long('32244002423141', 5), 4294967296)
332 self.assertEqual(long('1550104015504', 6), 4294967296)
333 self.assertEqual(long('211301422354', 7), 4294967296)
334 self.assertEqual(long('40000000000', 8), 4294967296)
335 self.assertEqual(long('12068657454', 9), 4294967296)
336 self.assertEqual(long('4294967296', 10), 4294967296)
337 self.assertEqual(long('1904440554', 11), 4294967296)
338 self.assertEqual(long('9ba461594', 12), 4294967296)
339 self.assertEqual(long('535a79889', 13), 4294967296)
340 self.assertEqual(long('2ca5b7464', 14), 4294967296)
341 self.assertEqual(long('1a20dcd81', 15), 4294967296)
342 self.assertEqual(long('100000000', 16), 4294967296)
343 self.assertEqual(long('a7ffda91', 17), 4294967296)
344 self.assertEqual(long('704he7g4', 18), 4294967296)
345 self.assertEqual(long('4f5aff66', 19), 4294967296)
346 self.assertEqual(long('3723ai4g', 20), 4294967296)
347 self.assertEqual(long('281d55i4', 21), 4294967296)
348 self.assertEqual(long('1fj8b184', 22), 4294967296)
349 self.assertEqual(long('1606k7ic', 23), 4294967296)
350 self.assertEqual(long('mb994ag', 24), 4294967296)
351 self.assertEqual(long('hek2mgl', 25), 4294967296)
352 self.assertEqual(long('dnchbnm', 26), 4294967296)
353 self.assertEqual(long('b28jpdm', 27), 4294967296)
354 self.assertEqual(long('8pfgih4', 28), 4294967296)
355 self.assertEqual(long('76beigg', 29), 4294967296)
356 self.assertEqual(long('5qmcpqg', 30), 4294967296)
357 self.assertEqual(long('4q0jto4', 31), 4294967296)
358 self.assertEqual(long('4000000', 32), 4294967296)
359 self.assertEqual(long('3aokq94', 33), 4294967296)
360 self.assertEqual(long('2qhxjli', 34), 4294967296)
361 self.assertEqual(long('2br45qb', 35), 4294967296)
362 self.assertEqual(long('1z141z4', 36), 4294967296)
363
364 self.assertEqual(long('100000000000000000000000000000001', 2),
365 4294967297)
366 self.assertEqual(long('102002022201221111212', 3), 4294967297)
367 self.assertEqual(long('10000000000000001', 4), 4294967297)
368 self.assertEqual(long('32244002423142', 5), 4294967297)
369 self.assertEqual(long('1550104015505', 6), 4294967297)
370 self.assertEqual(long('211301422355', 7), 4294967297)
371 self.assertEqual(long('40000000001', 8), 4294967297)
372 self.assertEqual(long('12068657455', 9), 4294967297)
373 self.assertEqual(long('4294967297', 10), 4294967297)
374 self.assertEqual(long('1904440555', 11), 4294967297)
375 self.assertEqual(long('9ba461595', 12), 4294967297)
376 self.assertEqual(long('535a7988a', 13), 4294967297)
377 self.assertEqual(long('2ca5b7465', 14), 4294967297)
378 self.assertEqual(long('1a20dcd82', 15), 4294967297)
379 self.assertEqual(long('100000001', 16), 4294967297)
380 self.assertEqual(long('a7ffda92', 17), 4294967297)
381 self.assertEqual(long('704he7g5', 18), 4294967297)
382 self.assertEqual(long('4f5aff67', 19), 4294967297)
383 self.assertEqual(long('3723ai4h', 20), 4294967297)
384 self.assertEqual(long('281d55i5', 21), 4294967297)
385 self.assertEqual(long('1fj8b185', 22), 4294967297)
386 self.assertEqual(long('1606k7id', 23), 4294967297)
387 self.assertEqual(long('mb994ah', 24), 4294967297)
388 self.assertEqual(long('hek2mgm', 25), 4294967297)
389 self.assertEqual(long('dnchbnn', 26), 4294967297)
390 self.assertEqual(long('b28jpdn', 27), 4294967297)
391 self.assertEqual(long('8pfgih5', 28), 4294967297)
392 self.assertEqual(long('76beigh', 29), 4294967297)
393 self.assertEqual(long('5qmcpqh', 30), 4294967297)
394 self.assertEqual(long('4q0jto5', 31), 4294967297)
395 self.assertEqual(long('4000001', 32), 4294967297)
396 self.assertEqual(long('3aokq95', 33), 4294967297)
397 self.assertEqual(long('2qhxjlj', 34), 4294967297)
398 self.assertEqual(long('2br45qc', 35), 4294967297)
399 self.assertEqual(long('1z141z5', 36), 4294967297)
400
401
402 def test_conversion(self):
403 # Test __long__()
404 class ClassicMissingMethods:
405 pass
406 self.assertRaises(AttributeError, long, ClassicMissingMethods())
407
408 class MissingMethods(object):
409 pass
410 self.assertRaises(TypeError, long, MissingMethods())
411
412 class Foo0:
413 def __long__(self):
414 return 42L
415
416 class Foo1(object):
417 def __long__(self):
418 return 42L
419
420 class Foo2(long):
421 def __long__(self):
422 return 42L
423
424 class Foo3(long):
425 def __long__(self):
426 return self
427
428 class Foo4(long):
429 def __long__(self):
430 return 42
431
432 class Foo5(long):
433 def __long__(self):
434 return 42.
435
436 self.assertEqual(long(Foo0()), 42L)
437 self.assertEqual(long(Foo1()), 42L)
438 self.assertEqual(long(Foo2()), 42L)
439 self.assertEqual(long(Foo3()), 0)
440 self.assertEqual(long(Foo4()), 42)
441 self.assertRaises(TypeError, long, Foo5())
442
443 class Classic:
444 pass
445 for base in (object, Classic):
446 class LongOverridesTrunc(base):
447 def __long__(self):
448 return 42
449 def __trunc__(self):
450 return -12
451 self.assertEqual(long(LongOverridesTrunc()), 42)
452
453 class JustTrunc(base):
454 def __trunc__(self):
455 return 42
456 self.assertEqual(long(JustTrunc()), 42)
457
458 for trunc_result_base in (object, Classic):
459 class Integral(trunc_result_base):
460 def __int__(self):
461 return 42
462
463 class TruncReturnsNonLong(base):
464 def __trunc__(self):
465 return Integral()
466 self.assertEqual(long(TruncReturnsNonLong()), 42)
467
468 class NonIntegral(trunc_result_base):
469 def __trunc__(self):
470 # Check that we avoid infinite recursion.
471 return NonIntegral()
472
473 class TruncReturnsNonIntegral(base):
474 def __trunc__(self):
475 return NonIntegral()
476 try:
477 long(TruncReturnsNonIntegral())
478 except TypeError as e:
479 self.assertEquals(str(e),
480 "__trunc__ returned non-Integral"
481 " (type NonIntegral)")
482 else:
483 self.fail("Failed to raise TypeError with %s" %
484 ((base, trunc_result_base),))
485
Walter Dörwalda0021592005-06-13 21:44:48 +0000486 def test_misc(self):
Guido van Rossum4365cab1998-08-13 14:20:17 +0000487
Walter Dörwalda0021592005-06-13 21:44:48 +0000488 # check the extremes in int<->long conversion
489 hugepos = sys.maxint
490 hugeneg = -hugepos - 1
491 hugepos_aslong = long(hugepos)
492 hugeneg_aslong = long(hugeneg)
493 self.assertEqual(hugepos, hugepos_aslong, "long(sys.maxint) != sys.maxint")
494 self.assertEqual(hugeneg, hugeneg_aslong,
495 "long(-sys.maxint-1) != -sys.maxint-1")
Guido van Rossum4365cab1998-08-13 14:20:17 +0000496
Walter Dörwalda0021592005-06-13 21:44:48 +0000497 # long -> int should not fail for hugepos_aslong or hugeneg_aslong
Armin Rigo7ccbca92006-10-04 12:17:45 +0000498 x = int(hugepos_aslong)
Walter Dörwalda0021592005-06-13 21:44:48 +0000499 try:
Armin Rigo7ccbca92006-10-04 12:17:45 +0000500 self.assertEqual(x, hugepos,
Walter Dörwalda0021592005-06-13 21:44:48 +0000501 "converting sys.maxint to long and back to int fails")
502 except OverflowError:
503 self.fail("int(long(sys.maxint)) overflowed!")
Armin Rigo7ccbca92006-10-04 12:17:45 +0000504 if not isinstance(x, int):
505 raise TestFailed("int(long(sys.maxint)) should have returned int")
506 x = int(hugeneg_aslong)
Walter Dörwalda0021592005-06-13 21:44:48 +0000507 try:
Armin Rigo7ccbca92006-10-04 12:17:45 +0000508 self.assertEqual(x, hugeneg,
Walter Dörwalda0021592005-06-13 21:44:48 +0000509 "converting -sys.maxint-1 to long and back to int fails")
510 except OverflowError:
511 self.fail("int(long(-sys.maxint-1)) overflowed!")
Armin Rigo7ccbca92006-10-04 12:17:45 +0000512 if not isinstance(x, int):
513 raise TestFailed("int(long(-sys.maxint-1)) should have "
514 "returned int")
Walter Dörwalda0021592005-06-13 21:44:48 +0000515 # but long -> int should overflow for hugepos+1 and hugeneg-1
516 x = hugepos_aslong + 1
517 try:
518 y = int(x)
519 except OverflowError:
520 self.fail("int(long(sys.maxint) + 1) mustn't overflow")
521 self.assert_(isinstance(y, long),
522 "int(long(sys.maxint) + 1) should have returned long")
Guido van Rossum4365cab1998-08-13 14:20:17 +0000523
Walter Dörwalda0021592005-06-13 21:44:48 +0000524 x = hugeneg_aslong - 1
525 try:
526 y = int(x)
527 except OverflowError:
528 self.fail("int(long(-sys.maxint-1) - 1) mustn't overflow")
529 self.assert_(isinstance(y, long),
530 "int(long(-sys.maxint-1) - 1) should have returned long")
Guido van Rossum4365cab1998-08-13 14:20:17 +0000531
Walter Dörwalda0021592005-06-13 21:44:48 +0000532 class long2(long):
533 pass
534 x = long2(1L<<100)
Walter Dörwaldf1715402002-11-19 20:49:15 +0000535 y = int(x)
Walter Dörwalda0021592005-06-13 21:44:48 +0000536 self.assert_(type(y) is long,
537 "overflowing int conversion must return long not long subtype")
Guido van Rossum4581a0c1998-10-02 01:19:48 +0000538
Armin Rigo7ccbca92006-10-04 12:17:45 +0000539 # long -> Py_ssize_t conversion
540 class X(object):
541 def __getslice__(self, i, j):
542 return i, j
543
544 self.assertEqual(X()[-5L:7L], (-5, 7))
545 # use the clamping effect to test the smallest and largest longs
546 # that fit a Py_ssize_t
547 slicemin, slicemax = X()[-2L**100:2L**100]
548 self.assertEqual(X()[slicemin:slicemax], (slicemin, slicemax))
549
Tim Peters26c7fa32001-08-23 22:56:21 +0000550# ----------------------------------- tests of auto int->long conversion
551
Walter Dörwalda0021592005-06-13 21:44:48 +0000552 def test_auto_overflow(self):
553 import math, sys
Tim Peters26c7fa32001-08-23 22:56:21 +0000554
Walter Dörwalda0021592005-06-13 21:44:48 +0000555 special = [0, 1, 2, 3, sys.maxint-1, sys.maxint, sys.maxint+1]
556 sqrt = int(math.sqrt(sys.maxint))
557 special.extend([sqrt-1, sqrt, sqrt+1])
558 special.extend([-i for i in special])
Tim Peters26c7fa32001-08-23 22:56:21 +0000559
Walter Dörwalda0021592005-06-13 21:44:48 +0000560 def checkit(*args):
561 # Heavy use of nested scopes here!
562 self.assertEqual(got, expected,
563 Frm("for %r expected %r got %r", args, expected, got))
Tim Peters26c7fa32001-08-23 22:56:21 +0000564
Walter Dörwalda0021592005-06-13 21:44:48 +0000565 for x in special:
566 longx = long(x)
Tim Peters26c7fa32001-08-23 22:56:21 +0000567
Walter Dörwalda0021592005-06-13 21:44:48 +0000568 expected = -longx
569 got = -x
570 checkit('-', x)
Tim Peters26c7fa32001-08-23 22:56:21 +0000571
Walter Dörwalda0021592005-06-13 21:44:48 +0000572 for y in special:
573 longy = long(y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000574
Walter Dörwalda0021592005-06-13 21:44:48 +0000575 expected = longx + longy
576 got = x + y
577 checkit(x, '+', y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000578
Walter Dörwalda0021592005-06-13 21:44:48 +0000579 expected = longx - longy
580 got = x - y
581 checkit(x, '-', y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000582
Walter Dörwalda0021592005-06-13 21:44:48 +0000583 expected = longx * longy
584 got = x * y
585 checkit(x, '*', y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000586
Walter Dörwalda0021592005-06-13 21:44:48 +0000587 if y:
588 expected = longx / longy
589 got = x / y
590 checkit(x, '/', y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000591
Walter Dörwalda0021592005-06-13 21:44:48 +0000592 expected = longx // longy
593 got = x // y
594 checkit(x, '//', y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000595
Walter Dörwalda0021592005-06-13 21:44:48 +0000596 expected = divmod(longx, longy)
597 got = divmod(longx, longy)
598 checkit(x, 'divmod', y)
Tim Petersa3653092001-08-23 23:02:57 +0000599
Walter Dörwalda0021592005-06-13 21:44:48 +0000600 if abs(y) < 5 and not (x == 0 and y < 0):
601 expected = longx ** longy
602 got = x ** y
603 checkit(x, '**', y)
Tim Peters26c7fa32001-08-23 22:56:21 +0000604
Walter Dörwalda0021592005-06-13 21:44:48 +0000605 for z in special:
606 if z != 0 :
607 if y >= 0:
608 expected = pow(longx, longy, long(z))
609 got = pow(x, y, z)
610 checkit('pow', x, y, '%', z)
Tim Peters32f453e2001-09-03 08:35:41 +0000611 else:
Walter Dörwalda0021592005-06-13 21:44:48 +0000612 self.assertRaises(TypeError, pow,longx, longy, long(z))
Tim Peters26c7fa32001-08-23 22:56:21 +0000613
Walter Dörwalda0021592005-06-13 21:44:48 +0000614 def test_float_overflow(self):
615 import math
Tim Peters9fffa3e2001-09-04 05:14:19 +0000616
Walter Dörwalda0021592005-06-13 21:44:48 +0000617 for x in -2.0, -1.0, 0.0, 1.0, 2.0:
618 self.assertEqual(float(long(x)), x)
Tim Peters9fffa3e2001-09-04 05:14:19 +0000619
Walter Dörwalda0021592005-06-13 21:44:48 +0000620 shuge = '12345' * 120
621 huge = 1L << 30000
622 mhuge = -huge
623 namespace = {'huge': huge, 'mhuge': mhuge, 'shuge': shuge, 'math': math}
624 for test in ["float(huge)", "float(mhuge)",
625 "complex(huge)", "complex(mhuge)",
626 "complex(huge, 1)", "complex(mhuge, 1)",
627 "complex(1, huge)", "complex(1, mhuge)",
628 "1. + huge", "huge + 1.", "1. + mhuge", "mhuge + 1.",
629 "1. - huge", "huge - 1.", "1. - mhuge", "mhuge - 1.",
630 "1. * huge", "huge * 1.", "1. * mhuge", "mhuge * 1.",
631 "1. // huge", "huge // 1.", "1. // mhuge", "mhuge // 1.",
632 "1. / huge", "huge / 1.", "1. / mhuge", "mhuge / 1.",
633 "1. ** huge", "huge ** 1.", "1. ** mhuge", "mhuge ** 1.",
634 "math.sin(huge)", "math.sin(mhuge)",
635 "math.sqrt(huge)", "math.sqrt(mhuge)", # should do better
Jeffrey Yasskin9871d8f2008-01-05 08:47:13 +0000636 "math.floor(huge)", "math.floor(mhuge)"]:
Tim Peters9fffa3e2001-09-04 05:14:19 +0000637
Walter Dörwalda0021592005-06-13 21:44:48 +0000638 self.assertRaises(OverflowError, eval, test, namespace)
Tim Peters9fffa3e2001-09-04 05:14:19 +0000639
Walter Dörwalda0021592005-06-13 21:44:48 +0000640 # XXX Perhaps float(shuge) can raise OverflowError on some box?
641 # The comparison should not.
642 self.assertNotEqual(float(shuge), int(shuge),
643 "float(shuge) should not equal int(shuge)")
Tim Peters83e7ccc2001-09-04 06:37:28 +0000644
Walter Dörwalda0021592005-06-13 21:44:48 +0000645 def test_logs(self):
646 import math
Tim Peters78526162001-09-05 00:53:45 +0000647
Walter Dörwalda0021592005-06-13 21:44:48 +0000648 LOG10E = math.log10(math.e)
Tim Peters307fa782004-09-23 08:06:40 +0000649
Walter Dörwalda0021592005-06-13 21:44:48 +0000650 for exp in range(10) + [100, 1000, 10000]:
651 value = 10 ** exp
652 log10 = math.log10(value)
653 self.assertAlmostEqual(log10, exp)
Tim Peters78526162001-09-05 00:53:45 +0000654
Walter Dörwalda0021592005-06-13 21:44:48 +0000655 # log10(value) == exp, so log(value) == log10(value)/log10(e) ==
656 # exp/LOG10E
657 expected = exp / LOG10E
658 log = math.log(value)
659 self.assertAlmostEqual(log, expected)
Tim Peters78526162001-09-05 00:53:45 +0000660
Walter Dörwalda0021592005-06-13 21:44:48 +0000661 for bad in -(1L << 10000), -2L, 0L:
662 self.assertRaises(ValueError, math.log, bad)
663 self.assertRaises(ValueError, math.log10, bad)
Tim Peters78526162001-09-05 00:53:45 +0000664
Walter Dörwalda0021592005-06-13 21:44:48 +0000665 def test_mixed_compares(self):
666 eq = self.assertEqual
667 import math
Tim Peters78526162001-09-05 00:53:45 +0000668
Walter Dörwalda0021592005-06-13 21:44:48 +0000669 # We're mostly concerned with that mixing floats and longs does the
670 # right stuff, even when longs are too large to fit in a float.
671 # The safest way to check the results is to use an entirely different
672 # method, which we do here via a skeletal rational class (which
673 # represents all Python ints, longs and floats exactly).
674 class Rat:
675 def __init__(self, value):
676 if isinstance(value, (int, long)):
677 self.n = value
678 self.d = 1
679 elif isinstance(value, float):
680 # Convert to exact rational equivalent.
681 f, e = math.frexp(abs(value))
682 assert f == 0 or 0.5 <= f < 1.0
683 # |value| = f * 2**e exactly
Tim Peters78526162001-09-05 00:53:45 +0000684
Walter Dörwalda0021592005-06-13 21:44:48 +0000685 # Suck up CHUNK bits at a time; 28 is enough so that we suck
686 # up all bits in 2 iterations for all known binary double-
687 # precision formats, and small enough to fit in an int.
688 CHUNK = 28
689 top = 0
690 # invariant: |value| = (top + f) * 2**e exactly
691 while f:
692 f = math.ldexp(f, CHUNK)
693 digit = int(f)
694 assert digit >> CHUNK == 0
695 top = (top << CHUNK) | digit
696 f -= digit
697 assert 0.0 <= f < 1.0
698 e -= CHUNK
Tim Peters78526162001-09-05 00:53:45 +0000699
Walter Dörwalda0021592005-06-13 21:44:48 +0000700 # Now |value| = top * 2**e exactly.
701 if e >= 0:
702 n = top << e
703 d = 1
704 else:
705 n = top
706 d = 1 << -e
707 if value < 0:
708 n = -n
709 self.n = n
710 self.d = d
711 assert float(n) / float(d) == value
Tim Peters307fa782004-09-23 08:06:40 +0000712 else:
Walter Dörwalda0021592005-06-13 21:44:48 +0000713 raise TypeError("can't deal with %r" % val)
Tim Peters307fa782004-09-23 08:06:40 +0000714
Walter Dörwalda0021592005-06-13 21:44:48 +0000715 def __cmp__(self, other):
716 if not isinstance(other, Rat):
717 other = Rat(other)
718 return cmp(self.n * other.d, self.d * other.n)
Tim Peters307fa782004-09-23 08:06:40 +0000719
Walter Dörwalda0021592005-06-13 21:44:48 +0000720 cases = [0, 0.001, 0.99, 1.0, 1.5, 1e20, 1e200]
721 # 2**48 is an important boundary in the internals. 2**53 is an
722 # important boundary for IEEE double precision.
723 for t in 2.0**48, 2.0**50, 2.0**53:
724 cases.extend([t - 1.0, t - 0.3, t, t + 0.3, t + 1.0,
725 long(t-1), long(t), long(t+1)])
726 cases.extend([0, 1, 2, sys.maxint, float(sys.maxint)])
727 # 1L<<20000 should exceed all double formats. long(1e200) is to
728 # check that we get equality with 1e200 above.
729 t = long(1e200)
730 cases.extend([0L, 1L, 2L, 1L << 20000, t-1, t, t+1])
731 cases.extend([-x for x in cases])
732 for x in cases:
733 Rx = Rat(x)
734 for y in cases:
735 Ry = Rat(y)
736 Rcmp = cmp(Rx, Ry)
737 xycmp = cmp(x, y)
738 eq(Rcmp, xycmp, Frm("%r %r %d %d", x, y, Rcmp, xycmp))
739 eq(x == y, Rcmp == 0, Frm("%r == %r %d", x, y, Rcmp))
740 eq(x != y, Rcmp != 0, Frm("%r != %r %d", x, y, Rcmp))
741 eq(x < y, Rcmp < 0, Frm("%r < %r %d", x, y, Rcmp))
742 eq(x <= y, Rcmp <= 0, Frm("%r <= %r %d", x, y, Rcmp))
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))
Tim Peters307fa782004-09-23 08:06:40 +0000745
Christian Heimes8267d1d2008-01-04 00:37:34 +0000746 def test_nan_inf(self):
747 self.assertRaises(OverflowError, long, float('inf'))
Mark Dickinsonb6467572008-08-04 21:30:09 +0000748 self.assertRaises(OverflowError, long, float('-inf'))
749 self.assertRaises(ValueError, long, float('nan'))
Christian Heimes8267d1d2008-01-04 00:37:34 +0000750
Walter Dörwalda0021592005-06-13 21:44:48 +0000751def test_main():
752 test_support.run_unittest(LongTest)
Tim Peters307fa782004-09-23 08:06:40 +0000753
Walter Dörwalda0021592005-06-13 21:44:48 +0000754if __name__ == "__main__":
755 test_main()