76 lines
2.5 KiB
C
76 lines
2.5 KiB
C
#ifndef Py_INTERNAL_LONG_H
|
|
#define Py_INTERNAL_LONG_H
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
#ifndef Py_BUILD_CORE
|
|
# error "this header requires Py_BUILD_CORE define"
|
|
#endif
|
|
|
|
#include "pycore_interp.h" // PyInterpreterState.small_ints
|
|
#include "pycore_pystate.h" // _PyThreadState_GET()
|
|
|
|
/*
|
|
* Default int base conversion size limitation: Denial of Service prevention.
|
|
*
|
|
* Chosen such that this isn't wildly slow on modern hardware and so that
|
|
* everyone's existing deployed numpy test suite passes before
|
|
* https://github.com/numpy/numpy/issues/22098 is widely available.
|
|
*
|
|
* $ python -m timeit -s 's = "1"*4300' 'int(s)'
|
|
* 2000 loops, best of 5: 125 usec per loop
|
|
* $ python -m timeit -s 's = "1"*4300; v = int(s)' 'str(v)'
|
|
* 1000 loops, best of 5: 311 usec per loop
|
|
* (zen2 cloud VM)
|
|
*
|
|
* 4300 decimal digits fits a ~14284 bit number.
|
|
*/
|
|
#define _PY_LONG_DEFAULT_MAX_STR_DIGITS 4300
|
|
/*
|
|
* Threshold for max digits check. For performance reasons int() and
|
|
* int.__str__() don't checks values that are smaller than this
|
|
* threshold. Acts as a guaranteed minimum size limit for bignums that
|
|
* applications can expect from CPython.
|
|
*
|
|
* % python -m timeit -s 's = "1"*640; v = int(s)' 'str(int(s))'
|
|
* 20000 loops, best of 5: 12 usec per loop
|
|
*
|
|
* "640 digits should be enough for anyone." - gps
|
|
* fits a ~2126 bit decimal number.
|
|
*/
|
|
#define _PY_LONG_MAX_STR_DIGITS_THRESHOLD 640
|
|
|
|
#if ((_PY_LONG_DEFAULT_MAX_STR_DIGITS != 0) && \
|
|
(_PY_LONG_DEFAULT_MAX_STR_DIGITS < _PY_LONG_MAX_STR_DIGITS_THRESHOLD))
|
|
# error "_PY_LONG_DEFAULT_MAX_STR_DIGITS smaller than threshold."
|
|
#endif
|
|
|
|
// Don't call this function but _PyLong_GetZero() and _PyLong_GetOne()
|
|
static inline PyObject* __PyLong_GetSmallInt_internal(int value)
|
|
{
|
|
PyInterpreterState *interp = _PyInterpreterState_GET();
|
|
assert(-_PY_NSMALLNEGINTS <= value && value < _PY_NSMALLPOSINTS);
|
|
size_t index = _PY_NSMALLNEGINTS + value;
|
|
PyObject *obj = (PyObject*)interp->small_ints[index];
|
|
// _PyLong_GetZero(), _PyLong_GetOne() and get_small_int() must not be
|
|
// called before _PyLong_Init() nor after _PyLong_Fini().
|
|
assert(obj != NULL);
|
|
return obj;
|
|
}
|
|
|
|
// Return a borrowed reference to the zero singleton.
|
|
// The function cannot return NULL.
|
|
static inline PyObject* _PyLong_GetZero(void)
|
|
{ return __PyLong_GetSmallInt_internal(0); }
|
|
|
|
// Return a borrowed reference to the one singleton.
|
|
// The function cannot return NULL.
|
|
static inline PyObject* _PyLong_GetOne(void)
|
|
{ return __PyLong_GetSmallInt_internal(1); }
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
#endif /* !Py_INTERNAL_LONG_H */
|