File: longintrepr.pyx

package info (click to toggle)
cython 3.0.11%2Bdfsg-2
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 19,092 kB
  • sloc: python: 83,539; ansic: 18,831; cpp: 1,402; xml: 1,031; javascript: 511; makefile: 403; sh: 204; sed: 11
file content (55 lines) | stat: -rw-r--r-- 1,405 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# mode: run

# Test longintrepr declarations by implementing a simple function

from cpython.longintrepr cimport *
cimport cython

@cython.cdivision(True)
def lshift(long a, unsigned long n):
    """
    Return a * 2^n as Python long.

    >>> print(lshift(3, 1))
    6
    >>> print(lshift(1, 30))
    1073741824
    >>> print(lshift(-12345, 115))
    512791237748899576593671817473776680960
    >>> print(-12345 << 115)
    -512791237748899576593671817473776680960
    >>> [i for i in range(100) if (65535 << i) != lshift(65535, i)]
    []
    >>> print(lshift(0, 12345))
    0
    >>> print(lshift(2**62, 0))   # doctest: +ELLIPSIS
    Traceback (most recent call last):
    ...
    OverflowError...
    """
    if not a:
        return _PyLong_New(0)
    cdef unsigned long apos = a if a > 0 else -a
    if (apos >> 1) >= <unsigned long>PyLong_BASE:
        raise OverflowError

    cdef unsigned long index = n // PyLong_SHIFT
    cdef unsigned long shift = n % PyLong_SHIFT

    cdef digit d = apos
    cdef digit low = (d << shift) & PyLong_MASK
    cdef digit high = (d >> (PyLong_SHIFT - shift))

    if high == 0:
        ret = _PyLong_New(index + 1)
        ret.ob_digit[index] = low
    else:
        ret = _PyLong_New(index + 2)
        ret.ob_digit[index] = low
        ret.ob_digit[index + 1] = high

    while index >= 1:
        index -= 1
        ret.ob_digit[index] = 0

    return ret