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