summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2023-02-13 10:22:37 +0100
committerStefan Behnel <stefan_ml@behnel.de>2023-02-13 13:37:03 +0100
commit1c3a212084744ab52c3e928857a636c312c8f20e (patch)
tree24bea86c4d1e5d1544865d0faea19be4c1e7dab0
parent58d5fed61cc4fa4718d50bfee42bdcf8071c5636 (diff)
downloadcython-1c3a212084744ab52c3e928857a636c312c8f20e.tar.gz
Fix PyLong digits access in CPython 3.12.
Needed after https://github.com/python/cpython/pull/101292 See https://github.com/cython/cython/issues/5238
-rw-r--r--Cython/Utility/Builtins.c2
-rw-r--r--Cython/Utility/Optimize.c8
-rw-r--r--Cython/Utility/StringTools.c2
-rw-r--r--Cython/Utility/TypeConversion.c16
4 files changed, 18 insertions, 10 deletions
diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c
index 1018eccf5..b9de4104c 100644
--- a/Cython/Utility/Builtins.c
+++ b/Cython/Utility/Builtins.c
@@ -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
{
diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c
index 7a3e3cd3d..6e5c6e0c8 100644
--- a/Cython/Utility/Optimize.c
+++ b/Cython/Utility/Optimize.c
@@ -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)) {
@@ -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)}}
@@ -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
@@ -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;
diff --git a/Cython/Utility/StringTools.c b/Cython/Utility/StringTools.c
index 6b192a1d9..5d757fd35 100644
--- a/Cython/Utility/StringTools.c
+++ b/Cython/Utility/StringTools.c
@@ -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
diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c
index a4befa79f..115e73187 100644
--- a/Cython/Utility/TypeConversion.c
+++ b/Cython/Utility/TypeConversion.c
@@ -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) {
@@ -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)) {
@@ -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;
@@ -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])
@@ -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]))