cython
1# mode: run
2
3# Test longintrepr declarations by implementing a simple function
4
5from cpython.longintrepr cimport *
6cimport cython
7
8@cython.cdivision(True)
9def lshift(long a, unsigned long n):
10"""
11Return a * 2^n as Python long.
12
13>>> print(lshift(3, 1))
146
15>>> print(lshift(1, 30))
161073741824
17>>> print(lshift(-12345, 115))
18512791237748899576593671817473776680960
19>>> print(-12345 << 115)
20-512791237748899576593671817473776680960
21>>> [i for i in range(100) if (65535 << i) != lshift(65535, i)]
22[]
23>>> print(lshift(0, 12345))
240
25>>> print(lshift(2**62, 0)) # doctest: +ELLIPSIS
26Traceback (most recent call last):
27...
28OverflowError...
29"""
30if not a:
31return _PyLong_New(0)
32cdef unsigned long apos = a if a > 0 else -a
33if (apos >> 1) >= <unsigned long>PyLong_BASE:
34raise OverflowError
35
36cdef unsigned long index = n // PyLong_SHIFT
37cdef unsigned long shift = n % PyLong_SHIFT
38
39cdef digit d = apos
40cdef digit low = (d << shift) & PyLong_MASK
41cdef digit high = (d >> (PyLong_SHIFT - shift))
42
43if high == 0:
44ret = _PyLong_New(index + 1)
45ret.ob_digit[index] = low
46else:
47ret = _PyLong_New(index + 2)
48ret.ob_digit[index] = low
49ret.ob_digit[index + 1] = high
50
51while index >= 1:
52index -= 1
53ret.ob_digit[index] = 0
54
55return ret
56