Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
121 changes: 68 additions & 53 deletions gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,49 +180,12 @@ MPZ_from_str(PyObject *obj, int base)
return res;
}

static zz_err zz_set_bytes(const unsigned char *buffer, size_t length,
bool is_signed, zz_t *u);

static MPZ_Object *
MPZ_from_int(PyObject *obj)
{
#if defined(ON_CPYTHON) && !defined(Py_LIMITED_API)
PyLongExport long_export = {0, 0, 0, 0, 0};
const zz_layout *int_layout = (zz_layout *)PyLong_GetNativeLayout();
MPZ_Object *res = NULL;

if (PyLong_Export(obj, &long_export) < 0) {
return res; /* LCOV_EXCL_LINE */
}
if (long_export.digits) {
res = MPZ_new();
if (!res) {
return NULL; /* LCOV_EXCL_LINE */
}

zz_err ret = zz_import((size_t)long_export.ndigits,
long_export.digits, *int_layout, &res->z);

if (ret) {
/* LCOV_EXCL_START */
if (ret == ZZ_MEM) {
return (MPZ_Object *)PyErr_NoMemory();
}
PyErr_SetString(PyExc_OverflowError,
"too many digits in integer");
return NULL;
/* LCOV_EXCL_STOP */
}
if (long_export.negative) {
(void)zz_neg(&res->z, &res->z);
}
PyLong_FreeExport(&long_export);
}
else {
res = MPZ_new();
if (res && zz_set(long_export.value, &res->z)) {
PyErr_NoMemory(); /* LCOV_EXCL_LINE */
}
}
return res;
#else
int64_t value;

if (!PyLong_AsInt64(obj, &value)) {
Expand All @@ -235,6 +198,50 @@ MPZ_from_int(PyObject *obj)
}
PyErr_Clear();

#if defined(ON_CPYTHON) && PY_VERSION_HEX > 0x030D00A0 \
&& !defined(Py_LIMITED_API)
Py_ssize_t expected = PyLong_AsNativeBytes(obj, NULL, 0, 0);

if (expected < 0) {
return NULL; /* LCOV_EXCL_LINE */
}

unsigned char *buffer = malloc((size_t)expected);

if (!buffer) {
return (MPZ_Object *)PyErr_NoMemory(); /* LCOV_EXCL_LINE */
}

expected = PyLong_AsNativeBytes(obj, buffer, expected, 0);
if (expected < 0) {
free:
/* LCOV_EXCL_START */
free(buffer);
return NULL;
/* LCOV_EXCL_STOP */
}

MPZ_Object *res = MPZ_new();

if (!res) {
goto free; /* LCOV_EXCL_LINE */
}

zz_err ret = zz_set_bytes(buffer, (size_t)expected, true, &res->z);

free(buffer);
if (ret) {
/* LCOV_EXCL_START */
if (ret == ZZ_MEM) {
return (MPZ_Object *)PyErr_NoMemory();
}
PyErr_SetString(PyExc_OverflowError,
"too many digits in integer");
return NULL;
/* LCOV_EXCL_STOP */
}
return res;
#else
PyObject *str = PyNumber_ToBase(obj, 16);

if (!str) {
Expand All @@ -245,9 +252,14 @@ MPZ_from_int(PyObject *obj)

Py_DECREF(str);
return res;
#endif /* defined(ON_CPYTHON) && !defined(Py_LIMITED_API) */
#endif /* defined(ON_CPYTHON) && PY_VERSION_HEX > 0x030D00A0
&& !defined(Py_LIMITED_API) */
}

static zz_err zz_get_bytes(const zz_t *u, size_t length,
bool is_signed, unsigned char **buffer);
static void revstr(unsigned char *s, Py_ssize_t l, Py_ssize_t r);

static PyObject *
MPZ_to_int(MPZ_Object *u)
{
Expand All @@ -257,19 +269,21 @@ MPZ_to_int(MPZ_Object *u)
return PyLong_FromInt64(value);
}

#if defined(ON_CPYTHON) && !defined(Py_LIMITED_API)
const zz_layout *int_layout = (zz_layout *)PyLong_GetNativeLayout();
size_t size = (zz_bitlen(&u->z) + int_layout->bits_per_digit
- 1)/int_layout->bits_per_digit;
void *digits;
PyLongWriter *writer = PyLongWriter_Create(zz_isneg(&u->z),
(Py_ssize_t)size, &digits);
#if defined(ON_CPYTHON) && PY_VERSION_HEX > 0x030D00A0 \
&& !defined(Py_LIMITED_API)
size_t size = (zz_bitlen(&u->z) + 7)/8 + 1;
unsigned char *buffer = malloc(size);

if (!writer) {
return NULL; /* LCOV_EXCL_LINE */
if (!buffer) {
return PyErr_NoMemory(); /* LCOV_EXCL_LINE */
}
(void)zz_export(&u->z, *int_layout, size, digits);
return PyLongWriter_Finish(writer);
(void)zz_get_bytes(&u->z, size, true, &buffer);
revstr(buffer, 0, (Py_ssize_t)size - 1);

PyObject *res = PyLong_FromNativeBytes(buffer, size, -1);

free(buffer);
return res;
#else
size_t len;

Expand All @@ -289,7 +303,8 @@ MPZ_to_int(MPZ_Object *u)

free(buf);
return res;
#endif /* defined(ON_CPYTHON) && !defined(Py_LIMITED_API) */
#endif /* defined(ON_CPYTHON) && PY_VERSION_HEX > 0x030D00A0
&& !defined(Py_LIMITED_API) */
}

static void
Expand Down