Skip to content

Commit

Permalink
Fix PyLong digits access in CPython 3.12.
Browse files Browse the repository at this point in the history
  • Loading branch information
scoder committed Feb 13, 2023
1 parent 1dba3d3 commit 9b7c357
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Cython/Utility/Builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);/*proto*/
static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
if (likely(Py_SIZE(n) == -1)) {
// digits are unsigned
return PyLong_FromLong(((PyLongObject*)n)->ob_digit[0]);
return PyLong_FromLong(__Pyx_PyLong_Digits(n)[0]);
}
#if CYTHON_COMPILING_IN_CPYTHON
{
Expand Down
8 changes: 4 additions & 4 deletions Cython/Utility/Optimize.c
Original file line number Diff line number Diff line change
Expand Up @@ -977,7 +977,7 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject
const Py_ssize_t size = Py_SIZE(exp);
// tuned to optimise branch prediction
if (likely(size == 1)) {
shiftby = ((PyLongObject*)exp)->ob_digit[0];
shiftby = __Pyx_PyLong_Digits(exp)[0];
} else if (size == 0) {
return PyInt_FromLong(1L);
} else if (unlikely(size < 0)) {
Expand Down Expand Up @@ -1058,7 +1058,7 @@ static CYTHON_INLINE {{c_ret_type}} __Pyx_PyInt_{{'' if ret_type.is_pyobject els
int unequal;
unsigned long uintval;
Py_ssize_t size = Py_SIZE({{pyval}});
const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
const digit* digits = __Pyx_PyLong_Digits({{pyval}});
if (intval == 0) {
// == 0 => Py_SIZE(pyval) == 0
{{return_compare('size', '0', c_op)}}
Expand Down Expand Up @@ -1237,7 +1237,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, long intval,
PY_LONG_LONG ll{{ival}}, llx;
#endif
{{endif}}
const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
const digit* digits = __Pyx_PyLong_Digits({{pyval}});
const Py_ssize_t size = Py_SIZE({{pyval}});
{{if c_op == '&'}}
// special case for &-ing arbitrarily large numbers with known single digit operands
Expand Down Expand Up @@ -1492,7 +1492,7 @@ static {{c_ret_type}} {{cfunc_name}}(PyObject *op1, PyObject *op2, double floatv

if (likely(PyLong_CheckExact({{pyval}}))) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*){{pyval}})->ob_digit;
const digit* digits = __Pyx_PyLong_Digits({{pyval}});
const Py_ssize_t size = Py_SIZE({{pyval}});
switch (size) {
case 0: {{fval}} = 0.0; {{zerodiv_check(fval)}} break;
Expand Down
2 changes: 1 addition & 1 deletion Cython/Utility/StringTools.c
Original file line number Diff line number Diff line change
Expand Up @@ -1065,7 +1065,7 @@ static CYTHON_INLINE int __Pyx_PyByteArray_AppendObject(PyObject* bytearray, PyO
if (Py_SIZE(value) == 0) {
ival = 0;
} else {
ival = ((PyLongObject*)value)->ob_digit[0];
ival = __Pyx_PyLong_Digits(value)[0];
if (unlikely(ival > 255)) goto bad_range;
}
} else
Expand Down
16 changes: 12 additions & 4 deletions Cython/Utility/TypeConversion.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,14 @@ static CYTHON_INLINE Py_hash_t __Pyx_PyIndex_AsHash_t(PyObject*);
// __Pyx_PyNumber_Float is now in it's own section since it has dependencies (needed to make
// string conversion work the same in all circumstances)

#if CYTHON_USE_PYLONG_INTERNALS
#if PY_VERSION_HEX >= 0x030C00A5
#define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->long_value.ob_digit)
#else
#define __Pyx_PyLong_Digits(x) (((PyLongObject*)x)->ob_digit)
#endif
#endif

#if PY_MAJOR_VERSION < 3 && __PYX_DEFAULT_STRING_ENCODING_IS_ASCII
static int __Pyx_sys_getdefaultencoding_not_ascii;
static int __Pyx_init_sys_getdefaultencoding_params(void) {
Expand Down Expand Up @@ -405,7 +413,7 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) {
#endif
if (likely(PyLong_CheckExact(b))) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)b)->ob_digit;
const digit* digits = __Pyx_PyLong_Digits(b);
const Py_ssize_t size = Py_SIZE(b);
// handle most common case first to avoid indirect branch and optimise branch prediction
if (likely(__Pyx_sst_abs(size) <= 1)) {
Expand Down Expand Up @@ -478,7 +486,7 @@ static CYTHON_INLINE PyObject* __Pyx__PyNumber_Float(PyObject* obj) {
double val;
if (PyLong_CheckExact(obj)) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)obj)->ob_digit;
const digit* digits = __Pyx_PyLong_Digits(obj);
switch (Py_SIZE(obj)) {
case 0:
val = 0.0;
Expand Down Expand Up @@ -968,7 +976,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
if (likely(PyLong_Check(x))) {
if (is_unsigned) {
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)x)->ob_digit;
const digit* digits = __Pyx_PyLong_Digits(x);
switch (Py_SIZE(x)) {
case 0: return ({{TYPE}}) 0;
case 1: __PYX_VERIFY_RETURN_INT({{TYPE}}, digit, digits[0])
Expand Down Expand Up @@ -1009,7 +1017,7 @@ static CYTHON_INLINE {{TYPE}} {{FROM_PY_FUNCTION}}(PyObject *x) {
} else {
// signed
#if CYTHON_USE_PYLONG_INTERNALS
const digit* digits = ((PyLongObject*)x)->ob_digit;
const digit* digits = __Pyx_PyLong_Digits(x);
switch (Py_SIZE(x)) {
case 0: return ({{TYPE}}) 0;
case -1: __PYX_VERIFY_RETURN_INT({{TYPE}}, sdigit, (sdigit) (-(sdigit)digits[0]))
Expand Down

0 comments on commit 9b7c357

Please sign in to comment.