File: pythonsupport.c

package info (click to toggle)
python-librt 0.6.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 524 kB
  • sloc: ansic: 8,544; cpp: 478; python: 216; makefile: 8
file content (106 lines) | stat: -rw-r--r-- 2,343 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
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// Collects code that was copied in from cpython, for a couple of different reasons:
//  * We wanted to modify it to produce a more efficient version for our uses
//  * We needed to call it and it was static :(
//  * We wanted to call it and needed to backport it

#include "pythonsupport.h"

#if CPY_3_12_FEATURES

// Slow path of CPyLong_AsSsize_tAndOverflow (non-inlined)
Py_ssize_t
CPyLong_AsSsize_tAndOverflow_(PyObject *vv, int *overflow)
{
    PyLongObject *v = (PyLongObject *)vv;
    size_t x, prev;
    Py_ssize_t res;
    Py_ssize_t i;
    int sign;

    *overflow = 0;

    res = -1;
    i = CPY_LONG_TAG(v);

    sign = 1;
    x = 0;
    if (i & CPY_SIGN_NEGATIVE) {
        sign = -1;
    }
    i >>= CPY_NON_SIZE_BITS;
    while (--i >= 0) {
        prev = x;
        x = (x << PyLong_SHIFT) + CPY_LONG_DIGIT(v, i);
        if ((x >> PyLong_SHIFT) != prev) {
            *overflow = sign;
            goto exit;
        }
    }
    /* Haven't lost any bits, but casting to long requires extra
     * care.
     */
    if (x <= (size_t)CPY_TAGGED_MAX) {
        res = (Py_ssize_t)x * sign;
    }
    else if (sign < 0 && x == CPY_TAGGED_ABS_MIN) {
        res = CPY_TAGGED_MIN;
    }
    else {
        *overflow = sign;
        /* res is already set to -1 */
    }
  exit:
    return res;
}

#else

// Slow path of CPyLong_AsSsize_tAndOverflow (non-inlined, Python 3.11 and earlier)
Py_ssize_t
CPyLong_AsSsize_tAndOverflow_(PyObject *vv, int *overflow)
{
    /* This version by Tim Peters */
    PyLongObject *v = (PyLongObject *)vv;
    size_t x, prev;
    Py_ssize_t res;
    Py_ssize_t i;
    int sign;

    *overflow = 0;

    res = -1;
    i = Py_SIZE(v);

    sign = 1;
    x = 0;
    if (i < 0) {
        sign = -1;
        i = -(i);
    }
    while (--i >= 0) {
        prev = x;
        x = (x << PyLong_SHIFT) + CPY_LONG_DIGIT(v, i);
        if ((x >> PyLong_SHIFT) != prev) {
            *overflow = sign;
            goto exit;
        }
    }
    /* Haven't lost any bits, but casting to long requires extra
     * care.
     */
    if (x <= (size_t)CPY_TAGGED_MAX) {
        res = (Py_ssize_t)x * sign;
    }
    else if (sign < 0 && x == CPY_TAGGED_ABS_MIN) {
        res = CPY_TAGGED_MIN;
    }
    else {
        *overflow = sign;
        /* res is already set to -1 */
    }
  exit:
    return res;
}


#endif