python3-cypari2: rebuild for Python 3.12

This commit is contained in:
Gonzalo Tornaría 2023-09-23 21:01:55 -04:00 committed by Andrew J. Hesford
parent 55936387f4
commit 66a183b400
2 changed files with 215 additions and 1 deletions

View File

@ -0,0 +1,214 @@
From 0c7e9a1749d67ef1b880283112e968f644e24341 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Gonzalo=20Tornar=C3=ADa?= <tornaria@cmat.edu.uy>
Date: Mon, 2 Oct 2023 07:47:14 -0300
Subject: [PATCH] Support python 3.12
---
cypari2/Py_SET_SIZE.h | 8 ----
cypari2/convert.pyx | 27 ++++--------
cypari2/pycore_long.h | 98 +++++++++++++++++++++++++++++++++++++++++
cypari2/pycore_long.pxd | 9 ++++
4 files changed, 116 insertions(+), 26 deletions(-)
delete mode 100644 cypari2/Py_SET_SIZE.h
create mode 100644 cypari2/pycore_long.h
create mode 100644 cypari2/pycore_long.pxd
diff --git a/cypari2/Py_SET_SIZE.h b/cypari2/Py_SET_SIZE.h
deleted file mode 100644
index 5f18ab0..0000000
--- a/cypari2/Py_SET_SIZE.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#include "Python.h"
-
-#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 9)
-// The function Py_SET_SIZE is defined starting with python 3.9.
-void Py_SET_SIZE(PyVarObject *o, Py_ssize_t size){
- Py_SIZE(o) = size;
-}
-#endif
diff --git a/cypari2/convert.pyx b/cypari2/convert.pyx
index 7c2ed24..8d39c3c 100644
--- a/cypari2/convert.pyx
+++ b/cypari2/convert.pyx
@@ -54,14 +54,8 @@ from libc.math cimport INFINITY
from .paridecl cimport *
from .stack cimport new_gen, reset_avma
from .string_utils cimport to_string, to_bytes
-
-cdef extern from *:
- ctypedef struct PyLongObject:
- digit* ob_digit
-
-cdef extern from "Py_SET_SIZE.h":
- void Py_SET_SIZE(py_long o, Py_ssize_t size)
-
+from .pycore_long cimport (ob_digit, _PyLong_IsZero, _PyLong_IsNegative,
+ _PyLong_IsPositive, _PyLong_DigitCount, _PyLong_SetSignAndDigitCount)
########################################################################
# Conversion PARI -> Python
@@ -424,7 +418,7 @@ cdef PyLong_FromINT(GEN g):
cdef Py_ssize_t sizedigits_final = 0
cdef py_long x = _PyLong_New(sizedigits)
- cdef digit* D = x.ob_digit
+ cdef digit* D = ob_digit(x)
cdef digit d
cdef ulong w
@@ -452,10 +446,7 @@ cdef PyLong_FromINT(GEN g):
sizedigits_final = i+1
# Set correct size
- if signe(g) > 0:
- Py_SET_SIZE(x, sizedigits_final)
- else:
- Py_SET_SIZE(x, -sizedigits_final)
+ _PyLong_SetSignAndDigitCount(x, signe(g), sizedigits_final)
return x
@@ -465,18 +456,18 @@ cdef PyLong_FromINT(GEN g):
########################################################################
cdef GEN PyLong_AS_GEN(py_long x):
- cdef const digit* D = x.ob_digit
+ cdef const digit* D = ob_digit(x)
# Size of the input
cdef size_t sizedigits
cdef long sgn
- if Py_SIZE(x) == 0:
+ if _PyLong_IsZero(x):
return gen_0
- elif Py_SIZE(x) > 0:
- sizedigits = Py_SIZE(x)
+ elif _PyLong_IsPositive(x):
+ sizedigits = _PyLong_DigitCount(x)
sgn = evalsigne(1)
else:
- sizedigits = -Py_SIZE(x)
+ sizedigits = _PyLong_DigitCount(x)
sgn = evalsigne(-1)
# Size of the output, in bits and in words
diff --git a/cypari2/pycore_long.h b/cypari2/pycore_long.h
new file mode 100644
index 0000000..ff1a73d
--- /dev/null
+++ b/cypari2/pycore_long.h
@@ -0,0 +1,98 @@
+#include "Python.h"
+#include <stdbool.h>
+
+#if PY_VERSION_HEX >= 0x030C00A5
+#define ob_digit(o) (((PyLongObject*)o)->long_value.ob_digit)
+#else
+#define ob_digit(o) (((PyLongObject*)o)->ob_digit)
+#endif
+
+#if PY_VERSION_HEX >= 0x030C00A7
+// taken from cpython:Include/internal/pycore_long.h @ 3.12
+
+/* Long value tag bits:
+ * 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
+ * 2: Reserved for immortality bit
+ * 3+ Unsigned digit count
+ */
+#define SIGN_MASK 3
+#define SIGN_ZERO 1
+#define SIGN_NEGATIVE 2
+#define NON_SIZE_BITS 3
+
+static inline bool
+_PyLong_IsZero(const PyLongObject *op)
+{
+ return (op->long_value.lv_tag & SIGN_MASK) == SIGN_ZERO;
+}
+
+static inline bool
+_PyLong_IsNegative(const PyLongObject *op)
+{
+ return (op->long_value.lv_tag & SIGN_MASK) == SIGN_NEGATIVE;
+}
+
+static inline bool
+_PyLong_IsPositive(const PyLongObject *op)
+{
+ return (op->long_value.lv_tag & SIGN_MASK) == 0;
+}
+
+static inline Py_ssize_t
+_PyLong_DigitCount(const PyLongObject *op)
+{
+ assert(PyLong_Check(op));
+ return op->long_value.lv_tag >> NON_SIZE_BITS;
+}
+
+#define TAG_FROM_SIGN_AND_SIZE(sign, size) ((1 - (sign)) | ((size) << NON_SIZE_BITS))
+
+static inline void
+_PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size)
+{
+ assert(size >= 0);
+ assert(-1 <= sign && sign <= 1);
+ assert(sign != 0 || size == 0);
+ op->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sign, (size_t)size);
+}
+
+#else
+// fallback for < 3.12
+
+static inline bool
+_PyLong_IsZero(const PyLongObject *op)
+{
+ return Py_SIZE(op) == 0;
+}
+
+static inline bool
+_PyLong_IsNegative(const PyLongObject *op)
+{
+ return Py_SIZE(op) < 0;
+}
+
+static inline bool
+_PyLong_IsPositive(const PyLongObject *op)
+{
+ return Py_SIZE(op) > 0;
+}
+
+static inline Py_ssize_t
+_PyLong_DigitCount(const PyLongObject *op)
+{
+ Py_ssize_t size = Py_SIZE(op);
+ return size < 0 ? -size : size;
+}
+
+static inline void
+_PyLong_SetSignAndDigitCount(PyLongObject *op, int sign, Py_ssize_t size)
+{
+#if (PY_MAJOR_VERSION == 3) && (PY_MINOR_VERSION < 9)
+// The function Py_SET_SIZE is defined starting with python 3.9.
+ Py_SIZE(o) = size;
+#else
+ Py_SET_SIZE(op, sign < 0 ? -size : size);
+#endif
+}
+
+#endif
diff --git a/cypari2/pycore_long.pxd b/cypari2/pycore_long.pxd
new file mode 100644
index 0000000..41de637
--- /dev/null
+++ b/cypari2/pycore_long.pxd
@@ -0,0 +1,9 @@
+from cpython.longintrepr cimport py_long, digit
+
+cdef extern from "pycore_long.h":
+ digit* ob_digit(py_long o)
+ bint _PyLong_IsZero(py_long o)
+ bint _PyLong_IsNegative(py_long o)
+ bint _PyLong_IsPositive(py_long o)
+ Py_ssize_t _PyLong_DigitCount(py_long o)
+ void _PyLong_SetSignAndDigitCount(py_long o, int sign, Py_ssize_t size)

View File

@ -1,7 +1,7 @@
# Template file for 'python3-cypari2'
pkgname=python3-cypari2
version=2.1.3
revision=4
revision=5
build_style=python3-module
hostmakedepends="python3-setuptools python3-Cython pari perl"
makedepends="python3-devel python3-cysignals pari-devel gmp-devel"