1 #ifndef Py_INTERNAL_LONG_H
2 #define Py_INTERNAL_LONG_H
3 #ifdef __cplusplus
4 extern "C" {
5 #endif
6
7 #ifndef Py_BUILD_CORE
8 # error "this header requires Py_BUILD_CORE define"
9 #endif
10
11 #include "pycore_global_objects.h" // _PY_NSMALLNEGINTS
12 #include "pycore_runtime.h" // _PyRuntime
13
14 /*
15 * Default int base conversion size limitation: Denial of Service prevention.
16 *
17 * Chosen such that this isn't wildly slow on modern hardware and so that
18 * everyone's existing deployed numpy test suite passes before
19 * https://github.com/numpy/numpy/issues/22098 is widely available.
20 *
21 * $ python -m timeit -s 's = "1"*4300' 'int(s)'
22 * 2000 loops, best of 5: 125 usec per loop
23 * $ python -m timeit -s 's = "1"*4300; v = int(s)' 'str(v)'
24 * 1000 loops, best of 5: 311 usec per loop
25 * (zen2 cloud VM)
26 *
27 * 4300 decimal digits fits a ~14284 bit number.
28 */
29 #define _PY_LONG_DEFAULT_MAX_STR_DIGITS 4300
30 /*
31 * Threshold for max digits check. For performance reasons int() and
32 * int.__str__() don't checks values that are smaller than this
33 * threshold. Acts as a guaranteed minimum size limit for bignums that
34 * applications can expect from CPython.
35 *
36 * % python -m timeit -s 's = "1"*640; v = int(s)' 'str(int(s))'
37 * 20000 loops, best of 5: 12 usec per loop
38 *
39 * "640 digits should be enough for anyone." - gps
40 * fits a ~2126 bit decimal number.
41 */
42 #define _PY_LONG_MAX_STR_DIGITS_THRESHOLD 640
43
44 #if ((_PY_LONG_DEFAULT_MAX_STR_DIGITS != 0) && \
45 (_PY_LONG_DEFAULT_MAX_STR_DIGITS < _PY_LONG_MAX_STR_DIGITS_THRESHOLD))
46 # error "_PY_LONG_DEFAULT_MAX_STR_DIGITS smaller than threshold."
47 #endif
48
49
50 /* runtime lifecycle */
51
52 extern PyStatus _PyLong_InitTypes(PyInterpreterState *);
53 extern void _PyLong_FiniTypes(PyInterpreterState *interp);
54
55
56 /* other API */
57
58 #define _PyLong_SMALL_INTS _Py_SINGLETON(small_ints)
59
60 // _PyLong_GetZero() and _PyLong_GetOne() must always be available
61 // _PyLong_FromUnsignedChar must always be available
62 #if _PY_NSMALLPOSINTS < 257
63 # error "_PY_NSMALLPOSINTS must be greater than or equal to 257"
64 #endif
65
66 // Return a borrowed reference to the zero singleton.
67 // The function cannot return NULL.
68 static inline PyObject* _PyLong_GetZero(void)
69 { return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS]; }
70
71 // Return a borrowed reference to the one singleton.
72 // The function cannot return NULL.
73 static inline PyObject* _PyLong_GetOne(void)
74 { return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+1]; }
75
76 static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
77 {
78 return Py_NewRef((PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+i]);
79 }
80
81 PyObject *_PyLong_Add(PyLongObject *left, PyLongObject *right);
82 PyObject *_PyLong_Multiply(PyLongObject *left, PyLongObject *right);
83 PyObject *_PyLong_Subtract(PyLongObject *left, PyLongObject *right);
84
85 /* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
86 _PyBytes_DecodeEscape(), etc. */
87 PyAPI_DATA(unsigned char) _PyLong_DigitValue[256];
88
89 /* Format the object based on the format_spec, as defined in PEP 3101
90 (Advanced String Formatting). */
91 PyAPI_FUNC(int) _PyLong_FormatAdvancedWriter(
92 _PyUnicodeWriter *writer,
93 PyObject *obj,
94 PyObject *format_spec,
95 Py_ssize_t start,
96 Py_ssize_t end);
97
98 PyAPI_FUNC(int) _PyLong_FormatWriter(
99 _PyUnicodeWriter *writer,
100 PyObject *obj,
101 int base,
102 int alternate);
103
104 PyAPI_FUNC(char*) _PyLong_FormatBytesWriter(
105 _PyBytesWriter *writer,
106 char *str,
107 PyObject *obj,
108 int base,
109 int alternate);
110
111 /* Long value tag bits:
112 * 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
113 * 2: Reserved for immortality bit
114 * 3+ Unsigned digit count
115 */
116 #define SIGN_MASK 3
117 #define SIGN_ZERO 1
118 #define SIGN_NEGATIVE 2
119 #define NON_SIZE_BITS 3
120
121 /* The functions _PyLong_IsCompact and _PyLong_CompactValue are defined
122 * in Include/cpython/longobject.h, since they need to be inline.
123 *
124 * "Compact" values have at least one bit to spare,
125 * so that addition and subtraction can be performed on the values
126 * without risk of overflow.
127 *
128 * The inline functions need tag bits.
129 * For readability, rather than do `#define SIGN_MASK _PyLong_SIGN_MASK`
130 * we define them to the numbers in both places and then assert that
131 * they're the same.
132 */
133 static_assert(SIGN_MASK == _PyLong_SIGN_MASK, "SIGN_MASK does not match _PyLong_SIGN_MASK");
134 static_assert(NON_SIZE_BITS == _PyLong_NON_SIZE_BITS, "NON_SIZE_BITS does not match _PyLong_NON_SIZE_BITS");
135
136 /* All *compact" values are guaranteed to fit into
137 * a Py_ssize_t with at least one bit to spare.
138 * In other words, for 64 bit machines, compact
139 * will be signed 63 (or fewer) bit values
140 */
141
142 /* Return 1 if the argument is compact int */
143 static inline int
144 _PyLong_IsNonNegativeCompact(const PyLongObject* op) {
145 assert(PyLong_Check(op));
146 return op->long_value.lv_tag <= (1 << NON_SIZE_BITS);
147 }
148
149
150 static inline int
151 _PyLong_BothAreCompact(const PyLongObject* a, const PyLongObject* b) {
152 assert(PyLong_Check(a));
153 assert(PyLong_Check(b));
154 return (a->long_value.lv_tag | b->long_value.lv_tag) < (2 << NON_SIZE_BITS);
155 }
156
157 static inline bool
158 _PyLong_IsZero(const PyLongObject *op)
159 {
160 return (op->long_value.lv_tag & SIGN_MASK) == SIGN_ZERO;
161 }
162
163 static inline bool
164 _PyLong_IsNegative(const PyLongObject *op)
165 {
166 return (op->long_value.lv_tag & SIGN_MASK) == SIGN_NEGATIVE;
167 }
168
169 static inline bool
170 _PyLong_IsPositive(const PyLongObject *op)
171 {
172 return (op->long_value.lv_tag & SIGN_MASK) == 0;
173 }
174
175 static inline Py_ssize_t
176 _PyLong_DigitCount(const PyLongObject *op)
177 {
178 assert(PyLong_Check(op));
179 return op->long_value.lv_tag >> NON_SIZE_BITS;
180 }
181
182 /* Equivalent to _PyLong_DigitCount(op) * _PyLong_NonCompactSign(op) */
183 static inline Py_ssize_t
184 _PyLong_SignedDigitCount(const PyLongObject *op)
185 {
186 assert(PyLong_Check(op));
187 Py_ssize_t sign = 1 - (op->long_value.lv_tag & SIGN_MASK);
188 return sign * (Py_ssize_t)(op->long_value.lv_tag >> NON_SIZE_BITS);
189 }
190
191 static inline int
192 _PyLong_CompactSign(const PyLongObject *op)
193 {
194 assert(PyLong_Check(op));
195 assert(_PyLong_IsCompact(op));
196 return 1 - (op->long_value.lv_tag & SIGN_MASK);
197 }
198
199 static inline int
200 _PyLong_NonCompactSign(const PyLongObject *op)
201 {
202 assert(PyLong_Check(op));
203 assert(!_PyLong_IsCompact(op));
204 return 1 - (op->long_value.lv_tag & SIGN_MASK);
205 }
206
207 /* Do a and b have the same sign? */
208 static inline int
209 _PyLong_SameSign(const PyLongObject *a, const PyLongObject *b)
210 {
211 return (a->long_value.lv_tag & SIGN_MASK) == (b->long_value.lv_tag & SIGN_MASK);
212 }
213
214 #define TAG_FROM_SIGN_AND_SIZE(sign, size) ((1 - (sign)) | ((size) << NON_SIZE_BITS))
215
216 static inline void
217 _PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size)
218 {
219 assert(size >= 0);
220 assert(-1 <= sign && sign <= 1);
221 assert(sign != 0 || size == 0);
222 op->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sign, (size_t)size);
223 }
224
225 static inline void
226 _PyLong_SetDigitCount(PyLongObject *op, Py_ssize_t size)
227 {
228 assert(size >= 0);
229 op->long_value.lv_tag = (((size_t)size) << NON_SIZE_BITS) | (op->long_value.lv_tag & SIGN_MASK);
230 }
231
232 #define NON_SIZE_MASK ~((1 << NON_SIZE_BITS) - 1)
233
234 static inline void
235 _PyLong_FlipSign(PyLongObject *op) {
236 unsigned int flipped_sign = 2 - (op->long_value.lv_tag & SIGN_MASK);
237 op->long_value.lv_tag &= NON_SIZE_MASK;
238 op->long_value.lv_tag |= flipped_sign;
239 }
240
241 #define _PyLong_DIGIT_INIT(val) \
242 { \
243 .ob_base = _PyObject_HEAD_INIT(&PyLong_Type) \
244 .long_value = { \
245 .lv_tag = TAG_FROM_SIGN_AND_SIZE( \
246 (val) == 0 ? 0 : ((val) < 0 ? -1 : 1), \
247 (val) == 0 ? 0 : 1), \
248 { ((val) >= 0 ? (val) : -(val)) }, \
249 } \
250 }
251
252 #define _PyLong_FALSE_TAG TAG_FROM_SIGN_AND_SIZE(0, 0)
253 #define _PyLong_TRUE_TAG TAG_FROM_SIGN_AND_SIZE(1, 1)
254
255 #ifdef __cplusplus
256 }
257 #endif
258 #endif /* !Py_INTERNAL_LONG_H */