(root)/
Python-3.12.0/
Include/
internal/
pycore_long.h
       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 */