Skip to content

Commit

Permalink
Merge pull request #442 from skirpichev/improve-coverage
Browse files Browse the repository at this point in the history
Improve test coverage
  • Loading branch information
casevh authored Oct 25, 2023
2 parents ff2ec3d + 9c21e09 commit ac1e151
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 96 deletions.
31 changes: 20 additions & 11 deletions .github/workflows/pip_install_gmpy2.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,27 +26,35 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.11]
python-version: [3.8, 3.11]
os: [ubuntu-22.04]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- run: |
- name: Install Libs
run: |
sudo apt-get update
sudo apt-get install libmpc-dev texlive texlive-latex-extra latexmk lcov
- run: pip install --upgrade pip
- run: pip --verbose install --editable .[docs,tests]
- run: python test/runtests.py
- run: PYTHONPATH=`pwd`/gmpy2 python test_cython/runtests.py
- run: sphinx-build --color -W --keep-going -b doctest docs build/sphinx/doctest
- run: sphinx-build --color -W --keep-going -b html docs build/sphinx/html
- run: sphinx-build --color -W --keep-going -b latex docs build/sphinx/latex
- run: make -C build/sphinx/latex all-pdf
- name: Install dependencies
run: |
pip install --upgrade pip
pip --verbose install --editable .[docs,tests]
- name: Tests
run: |
python test/runtests.py
PYTHONPATH=`pwd`/gmpy2 python test_cython/runtests.py
- name: Building docs
if: matrix.python-version == 3.11
run: |
sphinx-build --color -W --keep-going -b doctest docs build/sphinx/doctest
sphinx-build --color -W --keep-going -b html docs build/sphinx/html
sphinx-build --color -W --keep-going -b latex docs build/sphinx/latex
make -C build/sphinx/latex all-pdf
# XXX: why this doesn't work with pip install --editable above?
- name: Run coverage tests
# XXX: why this doesn't work with pip install --editable above?
run: |
pip uninstall -y gmpy2
python setup.py clean
Expand All @@ -62,6 +70,7 @@ jobs:
gcov_args: --no-external
- name: Archive build artifacts
uses: actions/upload-artifact@v3
if: matrix.python-version == 3.11
with:
path: |
build/sphinx/doctest/
Expand Down
44 changes: 0 additions & 44 deletions src/gmpy2_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@
static Py_hash_t
GMPy_MPZ_Hash_Slot(MPZ_Object *self)
{
#ifdef _PyHASH_MODULUS
Py_hash_t hash;

if (self->hash_cache != -1) {
Expand All @@ -47,28 +46,11 @@ GMPy_MPZ_Hash_Slot(MPZ_Object *self)
hash = -2;
}
return (self->hash_cache = hash);
#else
unsigned long x;

if (self->hash_cache != -1) {
return self->hash_cache;
}

x = (unsigned long)mpn_mod_1(self->z->_mp_d, mpz_size(self->z), ULONG_MAX);
if (mpz_sgn(self->z) < 0) {
x = x * -1;
}
if (x == (unsigned long)-1) {
x = (unsigned long)-2;
}
return (self->hash_cache = (long)x);
#endif
}

static Py_hash_t
GMPy_MPQ_Hash_Slot(MPQ_Object *self)
{
#ifdef _PyHASH_MODULUS
Py_hash_t hash = 0;
mpz_t temp, temp1, mask;

Expand Down Expand Up @@ -113,27 +95,11 @@ GMPy_MPQ_Hash_Slot(MPQ_Object *self)
mpz_clear(mask);
self->hash_cache = hash;
return hash;
#else
PyObject *temp;

if (self->hash_cache != -1) {
return self->hash_cache;
}

if (!(temp = GMPy_PyFloat_From_MPQ(self, NULL))) {
SYSTEM_ERROR("Could not convert 'mpq' to float.");
return -1;
}
self->hash_cache = PyObject_Hash(temp);
Py_DECREF(temp);
return self->hash_cache;
#endif
}

static Py_hash_t
_mpfr_hash(mpfr_t f)
{
#ifdef _PyHASH_MODULUS
Py_uhash_t hash = 0;
Py_ssize_t exp;
size_t msize;
Expand All @@ -151,7 +117,6 @@ _mpfr_hash(mpfr_t f)
}
else {
#if PY_VERSION_HEX >= 0x030A00A0
// Python 3.10
return _Py_HashPointer(f);
#else
return _PyHASH_NAN;
Expand Down Expand Up @@ -185,14 +150,6 @@ _mpfr_hash(mpfr_t f)
hash = (Py_uhash_t)(-2);
}
return (Py_hash_t)hash;
#else
double temp;
CTXT_Object *context = NULL;

CHECK_CONTEXT(context);
temp = mpfr_get_d(f, GET_MPFR_ROUND(context));
return _Py_HashDouble(temp);
#endif
}

static Py_hash_t
Expand Down Expand Up @@ -228,4 +185,3 @@ GMPy_MPC_Hash_Slot(MPC_Object *self)
self->hash_cache = combined;
return (Py_hash_t)combined;
}

1 change: 0 additions & 1 deletion src/gmpy2_mod.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,4 +361,3 @@ GMPy_Context_Mod(PyObject *self, PyObject *args)
PyTuple_GET_ITEM(args, 1),
context);
}

2 changes: 0 additions & 2 deletions src/gmpy2_mpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,5 +263,3 @@ static PyTypeObject MPC_Type =
GMPy_MPC_NewInit, /* tp_new */
0, /* tp_free */
};


8 changes: 8 additions & 0 deletions src/gmpy2_mpfr_misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -448,9 +448,11 @@ GMPy_MPFR_Integer_Ratio_Method(PyObject *self, PyObject *args)
num = GMPy_MPZ_New(context);
den = GMPy_MPZ_New(context);
if (!num || !den) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)num);
Py_XDECREF((PyObject*)den);
return NULL;
/* LCOV_EXCL_STOP */
}

if (mpfr_zero_p(MPFR(self))) {
Expand All @@ -472,8 +474,10 @@ GMPy_MPFR_Integer_Ratio_Method(PyObject *self, PyObject *args)
}
result = Py_BuildValue("(NN)", (PyObject*)num, (PyObject*)den);
if (!result) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)num);
Py_DECREF((PyObject*)den);
/* LCOV_EXCL_STOP */
}
return result;
}
Expand Down Expand Up @@ -505,9 +509,11 @@ GMPy_MPFR_Mantissa_Exp_Method(PyObject *self, PyObject *args)
mantissa = GMPy_MPZ_New(context);
exponent = GMPy_MPZ_New(context);
if (!mantissa || !exponent) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)mantissa);
Py_XDECREF((PyObject*)exponent);
return NULL;
/* LCOV_EXCL_STOP */
}

if (mpfr_zero_p(MPFR(self))) {
Expand All @@ -520,8 +526,10 @@ GMPy_MPFR_Mantissa_Exp_Method(PyObject *self, PyObject *args)
}
result = Py_BuildValue("(NN)", (PyObject*)mantissa, (PyObject*)exponent);
if (!result) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)mantissa);
Py_DECREF((PyObject*)exponent);
/* LCOV_EXCL_STOP */
}
return result;
}
Expand Down
26 changes: 26 additions & 0 deletions src/gmpy2_mpmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,24 +33,30 @@ mpmath_build_mpf(long sign, MPZ_Object *man, PyObject *exp, mp_bitcnt_t bc)
PyObject *tup, *tsign, *tbc;

if (!(tup = PyTuple_New(4))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
return NULL;
/* LCOV_EXCL_STOP */
}

if (!(tsign = PyLong_FromLong(sign))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
Py_DECREF(tup);
return NULL;
/* LCOV_EXCL_STOP */
}

if (!(tbc = GMPy_PyLong_FromMpBitCnt(bc))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF(exp);
Py_DECREF(tup);
Py_DECREF(tsign);
return NULL;
/* LCOV_EXCL_STOP */
}

PyTuple_SET_ITEM(tup, 0, tsign);
Expand Down Expand Up @@ -148,9 +154,11 @@ Pympz_mpmath_normalize_fast(PyObject *self, PyObject *const *args, Py_ssize_t na
}

if (!(upper = GMPy_MPZ_New(NULL)) || !(lower = GMPy_MPZ_New(NULL))) {
/* LCOV_EXCL_START */
Py_XDECREF((PyObject*)upper);
Py_XDECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}

if (bc > prec) {
Expand Down Expand Up @@ -201,16 +209,20 @@ Pympz_mpmath_normalize_fast(PyObject *self, PyObject *const *args, Py_ssize_t na
}

if (!(tmp = PyLong_FromUnsignedLong((unsigned long)shift))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}

if (!(newexp = PyNumber_Add(exp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(tmp);
bc = prec;
Expand All @@ -226,17 +238,21 @@ Pympz_mpmath_normalize_fast(PyObject *self, PyObject *const *args, Py_ssize_t na
mpz_tdiv_q_2exp(upper->z, upper->z, zbits);

if (!(tmp = GMPy_PyLong_FromMpBitCnt(zbits))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(newexp);
Py_DECREF(tmp);
Expand Down Expand Up @@ -298,10 +314,12 @@ Pympz_mpmath_create_fast(PyObject *self, PyObject *const *args, Py_ssize_t nargs
upper = GMPy_MPZ_New(NULL);
lower = GMPy_MPZ_New(NULL);
if (!upper || !lower) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_XDECREF((PyObject*)upper);
Py_XDECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}

/* Extract sign, make man positive, and set bit count */
Expand Down Expand Up @@ -362,16 +380,20 @@ Pympz_mpmath_create_fast(PyObject *self, PyObject *const *args, Py_ssize_t nargs
}
}
if (!(tmp = PyLong_FromUnsignedLong((unsigned long)shift))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp = PyNumber_Add(exp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(tmp);
bc = prec;
Expand All @@ -386,19 +408,23 @@ Pympz_mpmath_create_fast(PyObject *self, PyObject *const *args, Py_ssize_t nargs
mpz_tdiv_q_2exp(upper->z, upper->z, zbits);

if (!(tmp = GMPy_PyLong_FromMpBitCnt(zbits))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
if (!(newexp2 = PyNumber_Add(newexp, tmp))) {
/* LCOV_EXCL_START */
Py_DECREF((PyObject*)man);
Py_DECREF((PyObject*)upper);
Py_DECREF((PyObject*)lower);
Py_DECREF(tmp);
Py_DECREF(newexp);
return NULL;
/* LCOV_EXCL_STOP */
}
Py_DECREF(newexp);
Py_DECREF(tmp);
Expand Down
37 changes: 35 additions & 2 deletions test/test_functions.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import pytest

import gmpy2
from gmpy2 import (root, rootn, zero, mpz, mpq, mpfr, mpc, is_nan, maxnum,
minnum, fma, fms, ieee, fmma, fmms)
from gmpy2 import (can_round, fac, fma, fmma, fmms, fms, get_exp, ieee, is_nan,
maxnum, minnum, mpc, mpfr, mpq, mpz, root, rootn, set_exp,
zero)


def test_root():
Expand Down Expand Up @@ -133,3 +134,35 @@ def test_trigonometric():
assert gmpy2.atanh(mpc(2.0, 3.0)) == gmpy2.atanh(complex(2, 3))

assert gmpy2.tanh(mpc(4,5)) == mpc('1.0005630461157933-0.00036520305451130409j')


def test_get_exp():
ctx = gmpy2.get_context()
ctx.trap_erange = True

pytest.raises(gmpy2.RangeError, lambda: get_exp(mpfr('inf')))


def test_set_exp():
pytest.raises(ValueError, lambda: set_exp(mpfr('1.0'), int(fac(100))))

gmpy2.set_context(gmpy2.ieee(32))
ctx = gmpy2.get_context()
ctx.trap_erange = True

pytest.raises(gmpy2.RangeError, lambda: set_exp(mpfr('1.0'), 1000))

ctx.trap_erange = False
assert set_exp(mpfr('1.0'), 1000) == mpfr('1.0')


def test_can_round():
pytest.raises(TypeError, lambda: can_round(mpfr('1.1'), 10, "spam"))
pytest.raises(ValueError, lambda: can_round(mpfr('1.1'), 10, 111, 111, 111))
pytest.raises(ValueError, lambda: can_round(mpfr('1.1'), 10, 1, 111, 111))
pytest.raises(ValueError, lambda: can_round(mpfr('1.1'), 10, 1, 1, -111))

x = mpfr('-1.112')

assert can_round(x, 10, 1, 1, 1)
assert not can_round(x, 10, 1, 1, 10)
Loading

0 comments on commit ac1e151

Please sign in to comment.