1c15d4c
--- src/_fastmath.c
1c15d4c
+++ src/_fastmath.c
d41955b
@@ -58,6 +58,20 @@
d41955b
 #define INLINE inline
d41955b
 #endif
d41955b
 
d41955b
+#if PY_VERSION_HEX >= 0x030C0000
d41955b
+/* Code cribbed from python's internal/pycore_long.h */
d41955b
+/* Long value tag bits:
d41955b
+ *  * 0-1: Sign bits value = (1-sign), ie. negative=2, positive=0, zero=1.
d41955b
+ *   * 2: Reserved for immortality bit
d41955b
+ *    * 3+ Unsigned digit count
d41955b
+ *     */
d41955b
+#define SIGN_MASK 3
d41955b
+#define SIGN_ZERO 1
d41955b
+#define SIGN_NEGATIVE 2
d41955b
+#define NON_SIZE_BITS 3
d41955b
+#define TAG_FROM_SIGN_AND_SIZE(sign, size) ((1 - (sign)) | ((size) << NON_SIZE_BITS))
d41955b
+#endif
d41955b
+
d41955b
 static unsigned int sieve_base[10000];
d41955b
 static int rabinMillerTest (mpz_t n, int rounds, PyObject *randfunc);
d41955b
 
d41955b
@@ -70,13 +84,24 @@ longObjToMPZ (mpz_t m, PyLongObject * p)
1c15d4c
 	mpz_init (temp);
1c15d4c
 	mpz_init (temp2);
1c15d4c
 #ifdef IS_PY3K
1c15d4c
-	if (p->ob_base.ob_size > 0) {
1c15d4c
-		size = p->ob_base.ob_size;
d41955b
+#if PY_VERSION_HEX < 0x030C0000
1c15d4c
+	if (Py_SIZE(p) > 0) {
1c15d4c
+		size = Py_SIZE(p);
1c15d4c
 		negative = 1;
1c15d4c
 	} else {
1c15d4c
-		size = -p->ob_base.ob_size;
1c15d4c
+		size = -Py_SIZE(p);
d41955b
+		negative = -1;
d41955b
+	}
d41955b
+#else
d41955b
+	size = p->long_value.lv_tag >> NON_SIZE_BITS;
d41955b
+	if ((p->long_value.lv_tag & SIGN_MASK) == SIGN_NEGATIVE) {
1c15d4c
 		negative = -1;
d41955b
+	} else if ((p->long_value.lv_tag & SIGN_MASK) == SIGN_ZERO) {
d41955b
+		negative = 0;
d41955b
+	} else {
d41955b
+		negative = 1;
1c15d4c
 	}
d41955b
+#endif
1c15d4c
 #else
d41955b
 	if (p->ob_size > 0) {
d41955b
 		size = p->ob_size;
d41955b
@@ -89,7 +114,11 @@ longObjToMPZ (mpz_t m, PyLongObject * p)
1c15d4c
 	mpz_set_ui (m, 0);
1c15d4c
 	for (i = 0; i < size; i++)
1c15d4c
 	{
1c15d4c
+#if PY_VERSION_HEX < 0x030C0000
1c15d4c
 		mpz_set_ui (temp, p->ob_digit[i]);
1c15d4c
+#else
1c15d4c
+		mpz_set_ui (temp, p->long_value.ob_digit[i]);
1c15d4c
+#endif
1c15d4c
 #ifdef IS_PY3K
1c15d4c
 		mpz_mul_2exp (temp2, temp, PyLong_SHIFT * i);
1c15d4c
 #else
d41955b
@@ -123,7 +152,11 @@ mpzToLongObj (mpz_t m)
1c15d4c
 	for (i = 0; i < size; i++)
1c15d4c
 	{
1c15d4c
 #ifdef IS_PY3K
1c15d4c
+#if PY_VERSION_HEX < 0x030C0000
1c15d4c
 		l->ob_digit[i] = (digit) (mpz_get_ui (temp) & PyLong_MASK);
1c15d4c
+#else
1c15d4c
+		l->long_value.ob_digit[i] = (digit) (mpz_get_ui (temp) & PyLong_MASK);
1c15d4c
+#endif
1c15d4c
 		mpz_fdiv_q_2exp (temp, temp, PyLong_SHIFT);
1c15d4c
 #else
1c15d4c
 		l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK);
d41955b
@@ -131,11 +164,19 @@ mpzToLongObj (mpz_t m)
1c15d4c
 #endif
1c15d4c
 	}
1c15d4c
 	i = size;
1c15d4c
+#if PY_VERSION_HEX < 0x030C0000
1c15d4c
 	while ((i > 0) && (l->ob_digit[i - 1] == 0))
1c15d4c
+#else
1c15d4c
+	while ((i > 0) && (l->long_value.ob_digit[i - 1] == 0))
1c15d4c
+#endif
1c15d4c
 		i--;
1c15d4c
 #ifdef IS_PY3K
d41955b
+#if PY_VERSION_HEX < 0x030C0000
1c15d4c
 	l->ob_base.ob_size = i * sgn;
1c15d4c
 #else
d41955b
+	l->long_value.lv_tag = TAG_FROM_SIGN_AND_SIZE(sgn, (size_t)i);
1c15d4c
+#endif
1c15d4c
+#else
1c15d4c
 	l->ob_size = i * sgn;
1c15d4c
 #endif
1c15d4c
 	mpz_clear (temp);