LCOV - code coverage report
Current view: | top level - Include/internal - pycore_long.h (source / functions) |  |  | Hit | Total | Coverage
Test: | CPython 3.12 LCOV report [commit 5e6661bce9] |  | Lines: | 9 | 9 | 100.0 %
Date: | 2023-03-20 08:15:36 |  | Functions: | 4 | 4 | 100.0 %
|  |  | Branches: | 0 | 0 | -

               Branch data     Line data    Source code
           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                 :      16411 : static inline PyObject* _PyLong_GetZero(void)
          69                 :      16411 : { return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS]; }
          70                 :            :
          71                 :            : // Return a borrowed reference to the one singleton.
          72                 :            : // The function cannot return NULL.
          73                 :     100731 : static inline PyObject* _PyLong_GetOne(void)
          74                 :     100731 : { return (PyObject *)&_PyLong_SMALL_INTS[_PY_NSMALLNEGINTS+1]; }
          75                 :            :
          76                 :     686811 : static inline PyObject* _PyLong_FromUnsignedChar(unsigned char i)
          77                 :            : {
          78                 :     686811 :     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                 :            : int _PyLong_AssignValue(PyObject **target, Py_ssize_t value);
          86                 :            :
          87                 :            : /* Used by Python/mystrtoul.c, _PyBytes_FromHex(),
          88                 :            :    _PyBytes_DecodeEscape(), etc. */
          89                 :            : PyAPI_DATA(unsigned char) _PyLong_DigitValue[256];
          90                 :            :
          91                 :            : /* Format the object based on the format_spec, as defined in PEP 3101
          92                 :            :    (Advanced String Formatting). */
          93                 :            : PyAPI_FUNC(int) _PyLong_FormatAdvancedWriter(
          94                 :            :     _PyUnicodeWriter *writer,
          95                 :            :     PyObject *obj,
          96                 :            :     PyObject *format_spec,
          97                 :            :     Py_ssize_t start,
          98                 :            :     Py_ssize_t end);
          99                 :            :
         100                 :            : PyAPI_FUNC(int) _PyLong_FormatWriter(
         101                 :            :     _PyUnicodeWriter *writer,
         102                 :            :     PyObject *obj,
         103                 :            :     int base,
         104                 :            :     int alternate);
         105                 :            :
         106                 :            : PyAPI_FUNC(char*) _PyLong_FormatBytesWriter(
         107                 :            :     _PyBytesWriter *writer,
         108                 :            :     char *str,
         109                 :            :     PyObject *obj,
         110                 :            :     int base,
         111                 :            :     int alternate);
         112                 :            :
         113                 :            : /* Return 1 if the argument is positive single digit int */
         114                 :            : static inline int
         115                 :    1071107 : _PyLong_IsPositiveSingleDigit(PyObject* sub) {
         116                 :            :     /*  For a positive single digit int, the value of Py_SIZE(sub) is 0 or 1.
         117                 :            :
         118                 :            :         We perform a fast check using a single comparison by casting from int
         119                 :            :         to uint which casts negative numbers to large positive numbers.
         120                 :            :         For details see Section 14.2 "Bounds Checking" in the Agner Fog
         121                 :            :         optimization manual found at:
         122                 :            :         https://www.agner.org/optimize/optimizing_cpp.pdf
         123                 :            :
         124                 :            :         The function is not affected by -fwrapv, -fno-wrapv and -ftrapv
         125                 :            :         compiler options of GCC and clang
         126                 :            :     */
         127                 :            :     assert(PyLong_CheckExact(sub));
         128                 :    1071107 :     Py_ssize_t signed_size = Py_SIZE(sub);
         129                 :    1071107 :     return ((size_t)signed_size) <= 1;
         130                 :            : }
         131                 :            :
         132                 :            : #ifdef __cplusplus
         133                 :            : }
         134                 :            : #endif
         135                 :            : #endif /* !Py_INTERNAL_LONG_H */

Generated by: LCOV version 1.14