Coverage Report

Created: 2025-07-04 06:49

/src/cpython-install/include/python3.15/cpython/longintrepr.h
Line
Count
Source (jump to first uncovered line)
1
#ifndef Py_LIMITED_API
2
#ifndef Py_LONGINTREPR_H
3
#define Py_LONGINTREPR_H
4
#ifdef __cplusplus
5
extern "C" {
6
#endif
7
8
9
/* This is published for the benefit of "friends" marshal.c and _decimal.c. */
10
11
/* Parameters of the integer representation.  There are two different
12
   sets of parameters: one set for 30-bit digits, stored in an unsigned 32-bit
13
   integer type, and one set for 15-bit digits with each digit stored in an
14
   unsigned short.  The value of PYLONG_BITS_IN_DIGIT, defined either at
15
   configure time or in pyport.h, is used to decide which digit size to use.
16
17
   Type 'digit' should be able to hold 2*PyLong_BASE-1, and type 'twodigits'
18
   should be an unsigned integer type able to hold all integers up to
19
   PyLong_BASE*PyLong_BASE-1.  x_sub assumes that 'digit' is an unsigned type,
20
   and that overflow is handled by taking the result modulo 2**N for some N >
21
   PyLong_SHIFT.  The majority of the code doesn't care about the precise
22
   value of PyLong_SHIFT, but there are some notable exceptions:
23
24
   - PyLong_{As,From}ByteArray require that PyLong_SHIFT be at least 8
25
26
   - long_hash() requires that PyLong_SHIFT is *strictly* less than the number
27
     of bits in an unsigned long, as do the PyLong <-> long (or unsigned long)
28
     conversion functions
29
30
   - the Python int <-> size_t/Py_ssize_t conversion functions expect that
31
     PyLong_SHIFT is strictly less than the number of bits in a size_t
32
33
   - the marshal code currently expects that PyLong_SHIFT is a multiple of 15
34
35
   - NSMALLNEGINTS and NSMALLPOSINTS should be small enough to fit in a single
36
     digit; with the current values this forces PyLong_SHIFT >= 9
37
38
  The values 15 and 30 should fit all of the above requirements, on any
39
  platform.
40
*/
41
42
#if PYLONG_BITS_IN_DIGIT == 30
43
typedef uint32_t digit;
44
typedef int32_t sdigit; /* signed variant of digit */
45
typedef uint64_t twodigits;
46
typedef int64_t stwodigits; /* signed variant of twodigits */
47
#define PyLong_SHIFT    30
48
#define _PyLong_DECIMAL_SHIFT   9 /* max(e such that 10**e fits in a digit) */
49
#define _PyLong_DECIMAL_BASE    ((digit)1000000000) /* 10 ** DECIMAL_SHIFT */
50
#elif PYLONG_BITS_IN_DIGIT == 15
51
typedef unsigned short digit;
52
typedef short sdigit; /* signed variant of digit */
53
typedef unsigned long twodigits;
54
typedef long stwodigits; /* signed variant of twodigits */
55
#define PyLong_SHIFT    15
56
#define _PyLong_DECIMAL_SHIFT   4 /* max(e such that 10**e fits in a digit) */
57
#define _PyLong_DECIMAL_BASE    ((digit)10000) /* 10 ** DECIMAL_SHIFT */
58
#else
59
#error "PYLONG_BITS_IN_DIGIT should be 15 or 30"
60
#endif
61
#define PyLong_BASE     ((digit)1 << PyLong_SHIFT)
62
#define PyLong_MASK     ((digit)(PyLong_BASE - 1))
63
64
/* Long integer representation.
65
66
   Long integers are made up of a number of 30- or 15-bit digits, depending on
67
   the platform. The number of digits (ndigits) is stored in the high bits of
68
   the lv_tag field (lvtag >> _PyLong_NON_SIZE_BITS).
69
70
   The absolute value of a number is equal to
71
        SUM(for i=0 through ndigits-1) ob_digit[i] * 2**(PyLong_SHIFT*i)
72
73
   The sign of the value is stored in the lower 2 bits of lv_tag.
74
75
    - 0: Positive
76
    - 1: Zero
77
    - 2: Negative
78
79
   The third lowest bit of lv_tag is
80
   set to 1 for the small ints.
81
82
   In a normalized number, ob_digit[ndigits-1] (the most significant
83
   digit) is never zero.  Also, in all cases, for all valid i,
84
        0 <= ob_digit[i] <= PyLong_MASK.
85
86
   The allocation function takes care of allocating extra memory
87
   so that ob_digit[0] ... ob_digit[ndigits-1] are actually available.
88
   We always allocate memory for at least one digit, so accessing ob_digit[0]
89
   is always safe. However, in the case ndigits == 0, the contents of
90
   ob_digit[0] may be undefined.
91
*/
92
93
typedef struct _PyLongValue {
94
    uintptr_t lv_tag; /* Number of digits, sign and flags */
95
    digit ob_digit[1];
96
} _PyLongValue;
97
98
struct _longobject {
99
    PyObject_HEAD
100
    _PyLongValue long_value;
101
};
102
103
Py_DEPRECATED(3.14) PyAPI_FUNC(PyLongObject*) _PyLong_New(Py_ssize_t);
104
105
// Return a copy of src.
106
PyAPI_FUNC(PyObject*) _PyLong_Copy(PyLongObject *src);
107
108
Py_DEPRECATED(3.14) PyAPI_FUNC(PyLongObject*) _PyLong_FromDigits(
109
    int negative,
110
    Py_ssize_t digit_count,
111
    digit *digits);
112
113
114
/* Inline some internals for speed. These should be in pycore_long.h
115
 * if user code didn't need them inlined. */
116
117
#define _PyLong_SIGN_MASK 3
118
#define _PyLong_NON_SIZE_BITS 3
119
120
121
static inline int
122
0
_PyLong_IsCompact(const PyLongObject* op) {
123
0
    assert(PyType_HasFeature(op->ob_base.ob_type, Py_TPFLAGS_LONG_SUBCLASS));
124
0
    return op->long_value.lv_tag < (2 << _PyLong_NON_SIZE_BITS);
125
0
}
126
127
#define PyUnstable_Long_IsCompact _PyLong_IsCompact
128
129
static inline Py_ssize_t
130
_PyLong_CompactValue(const PyLongObject *op)
131
0
{
132
0
    Py_ssize_t sign;
133
0
    assert(PyType_HasFeature(op->ob_base.ob_type, Py_TPFLAGS_LONG_SUBCLASS));
134
0
    assert(PyUnstable_Long_IsCompact(op));
135
0
    sign = 1 - (op->long_value.lv_tag & _PyLong_SIGN_MASK);
136
0
    return sign * (Py_ssize_t)op->long_value.ob_digit[0];
137
0
}
138
139
#define PyUnstable_Long_CompactValue _PyLong_CompactValue
140
141
142
/* --- Import/Export API -------------------------------------------------- */
143
144
typedef struct PyLongLayout {
145
    uint8_t bits_per_digit;
146
    uint8_t digit_size;
147
    int8_t digits_order;
148
    int8_t digit_endianness;
149
} PyLongLayout;
150
151
PyAPI_FUNC(const PyLongLayout*) PyLong_GetNativeLayout(void);
152
153
typedef struct PyLongExport {
154
    int64_t value;
155
    uint8_t negative;
156
    Py_ssize_t ndigits;
157
    const void *digits;
158
    // Member used internally, must not be used for other purpose.
159
    Py_uintptr_t _reserved;
160
} PyLongExport;
161
162
PyAPI_FUNC(int) PyLong_Export(
163
    PyObject *obj,
164
    PyLongExport *export_long);
165
PyAPI_FUNC(void) PyLong_FreeExport(
166
    PyLongExport *export_long);
167
168
169
/* --- PyLongWriter API --------------------------------------------------- */
170
171
typedef struct PyLongWriter PyLongWriter;
172
173
PyAPI_FUNC(PyLongWriter*) PyLongWriter_Create(
174
    int negative,
175
    Py_ssize_t ndigits,
176
    void **digits);
177
PyAPI_FUNC(PyObject*) PyLongWriter_Finish(PyLongWriter *writer);
178
PyAPI_FUNC(void) PyLongWriter_Discard(PyLongWriter *writer);
179
180
#ifdef __cplusplus
181
}
182
#endif
183
#endif /* !Py_LONGINTREPR_H */
184
#endif /* Py_LIMITED_API */