summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Behnel <stefan_ml@behnel.de>2023-04-14 08:56:12 +0200
committerStefan Behnel <stefan_ml@behnel.de>2023-04-14 08:56:23 +0200
commitd3f8684423999483b29a0333b826f02fc391d667 (patch)
tree5cf9de3e83a2d886aebc39d1fbfe34fd8d1bf842
parenta2d514a180c5238cac56e5fd6d8c8a27b22ae8a5 (diff)
downloadcython-d3f8684423999483b29a0333b826f02fc391d667.tar.gz
Fix optimised PyLong abs() implementation in Py3.12.
-rw-r--r--Cython/Utility/Builtins.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c
index 5cc786c4b..b77f95105 100644
--- a/Cython/Utility/Builtins.c
+++ b/Cython/Utility/Builtins.c
@@ -245,16 +245,27 @@ static PyObject *__Pyx_PyLong_AbsNeg(PyObject *num);/*proto*/
#if CYTHON_USE_PYLONG_INTERNALS
static PyObject *__Pyx_PyLong_AbsNeg(PyObject *n) {
+#if PY_VERSION_HEX >= 0x030C00A7
+ if (likely(__Pyx_PyLong_IsCompact(n))) {
+ return PyLong_FromSize_t(__Pyx_PyLong_CompactValueUnsigned(n));
+ }
+#else
if (likely(Py_SIZE(n) == -1)) {
// digits are unsigned
- return PyLong_FromLong(__Pyx_PyLong_Digits(n)[0]);
+ return PyLong_FromUnsignedLong(__Pyx_PyLong_Digits(n)[0]);
}
+#endif
#if CYTHON_COMPILING_IN_CPYTHON
{
PyObject *copy = _PyLong_Copy((PyLongObject*)n);
if (likely(copy)) {
+ #if PY_VERSION_HEX >= 0x030C00A7
+ // clear the sign bits to set the sign from SIGN_NEGATIVE (2) to positive (0)
+ ((PyLongObject*)copy)->long_value.lv_tag = ((PyLongObject*)copy)->long_value.lv_tag & ~3;
+ #else
// negate the size to swap the sign
__Pyx_SET_SIZE(copy, -Py_SIZE(copy));
+ #endif
}
return copy;
}