Skip to content

Commit

Permalink
Merge pull request #499 from skirpichev/misc
Browse files Browse the repository at this point in the history
Misc fixes
  • Loading branch information
casevh authored Jul 26, 2024
2 parents 30f6ef6 + 44e879d commit 7bd27fe
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 14 deletions.
2 changes: 1 addition & 1 deletion docs/contexts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ that contexts are mutable: modifying the reference returned by `get_context()`
will modify the active context until a new context is enabled with
`set_context()`. The `context.copy()` method will return a copy of the
context. Contexts that implement the standard *single*, *double*, and
*quadruple* precision floating point types can be created using `ieee()`.
*quadruple* precision floating-point types can be created using `ieee()`.

Context Type
------------
Expand Down
2 changes: 1 addition & 1 deletion docs/history.rst
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ Changes in gmpy2 2.1.0a1
* Context methods have been added for MPFR/MPC related functions.
* A new context option (`~context.rational_division`) has been added that
changes the behavior of integer division involving `mpz` instances to return
a rational result instead of a floating point result.
a rational result instead of a floating-point result.
* gmpy2 types are now registered in the numeric tower of the
:mod:`numbers` module.
* In previous versions of gmpy2, ``mpz()`` was a factory function that
Expand Down
6 changes: 3 additions & 3 deletions src/gmpy2_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ GMPy_CTXT_Exit(PyObject *self, PyObject *args)

PyDoc_STRVAR(GMPy_doc_context_ieee,
"ieee(size, /, subnormalize=True) -> context\n\n"
"Return a new context corresponding to a standard IEEE floating point\n"
"Return a new context corresponding to a standard IEEE floating-point\n"
"format. The supported sizes are 16, 32, 64, 128, and multiples of\n"
"32 greater than 128.");

Expand Down Expand Up @@ -706,10 +706,10 @@ GETSET_BOOLEAN(rational_division)
GETSET_BOOLEAN(allow_release_gil)

PyDoc_STRVAR(GMPy_doc_CTXT_subnormalize,
"The usual IEEE-754 floating point representation supports gradual\n"
"The usual IEEE-754 floating-point representation supports gradual\n"
"underflow when the minimum exponent is reached. The MFPR library\n"
"does not enable gradual underflow by default but it can be enabled\n"
"to precisely mimic the results of IEEE-754 floating point operations.");
"to precisely mimic the results of IEEE-754 floating-point operations.");

PyDoc_STRVAR(GMPy_doc_CTXT_trap_underflow,
"If set to `False`, a result that is smaller than the smallest possible\n"
Expand Down
19 changes: 14 additions & 5 deletions src/gmpy2_convert_gmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -789,16 +789,25 @@ GMPy_PyStr_From_MPQ(MPQ_Object *obj, int base, int option, CTXT_Object *context)
static PyObject *
GMPy_PyFloat_From_MPQ(MPQ_Object *obj, CTXT_Object *context)
{
double res;
MPFR_Object *tmp;

res = mpq_get_d(obj->q);
CHECK_CONTEXT(context);

if (isinf(res)) {
OVERFLOW_ERROR("'mpq' too large to convert to float");
if (!(tmp = GMPy_MPFR_New(53, context))) {
/* LCOV_EXCL_START */
return NULL;
/* LCOV_EXCL_STOP */
}

return PyFloat_FromDouble(res);
mpfr_clear_flags();
tmp->rc = mpfr_set_q(tmp->f, obj->q, MPFR_RNDN);
GMPY_MPFR_CHECK_RANGE(tmp, context);
GMPY_MPFR_SUBNORMALIZE(tmp, context);
GMPY_MPFR_EXCEPTIONS(tmp, context);

PyObject *res = GMPy_PyFloat_From_MPFR(tmp, context);
Py_DECREF(tmp);
return res;
}

static PyObject *
Expand Down
2 changes: 1 addition & 1 deletion src/gmpy2_convert_mpfr.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
* If bits (or prec) is set to 1, the precision of the result depends on the
* type of the source.
*
* If the source number is already a radix-2 floating point number,
* If the source number is already a radix-2 floating-point number,
* the precision is not changed. In practical terms, this only applies
* to sources operands that are either an mpfr or Python double.
*
Expand Down
4 changes: 3 additions & 1 deletion src/gmpy2_macros.h
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,9 @@ GMPy_RealWithType_##NAME(PyObject *x, int xtype, CTXT_Object *context) \
result->rc = mpfr_##FUNC(result->f, tempx->f); \
Py_DECREF((PyObject*)tempx); \
_GMPy_MPFR_Cleanup(&result, context); \
return (PyObject*)result; \
MPZ_Object *mpz_result = GMPy_MPZ_From_MPFR(result, context); \
Py_DECREF((PyObject*)result); \
return (PyObject*)mpz_result; \
} \
static PyObject * \
GMPy_Number_##NAME(PyObject *x, CTXT_Object *context) \
Expand Down
2 changes: 1 addition & 1 deletion src/gmpy2_mpfr.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ PyDoc_STRVAR(GMPy_doc_mpfr,
"the specified context or the current context is used.\n"
"A precision of 1 minimizes the loss of precision by following\n"
"these rules:\n\n"
" 1) If n is a radix-2 floating point number, then the full\n"
" 1) If n is a radix-2 floating-point number, then the full\n"
" precision of n is retained.\n"
" 2) If n is an integer, then the precision is the bit length\n"
" of the integer.\n");
Expand Down
3 changes: 3 additions & 0 deletions src/gmpy2_mpmath.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,14 +287,17 @@ Pympz_mpmath_create_fast(PyObject *self, PyObject *const *args, Py_ssize_t nargs
switch (nargs) {
case 4:
rnd = PyString_1Char(args[3]);
/* fallthrough */
case 3:
prec = GMPy_Integer_AsLong(args[2]);
if (prec == (mp_bitcnt_t)(-1)) {
VALUE_ERROR("could not convert prec to positive int");
return NULL;
}
/* fallthrough */
case 2:
exp = args[1];
/* fallthrough */
case 1:
man = GMPy_MPZ_From_Integer(args[0], NULL);
if (!man) {
Expand Down
37 changes: 36 additions & 1 deletion test/test_mpfr.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import pytest
from hypothesis import example, given, settings
from hypothesis.strategies import floats
from hypothesis.strategies import floats, integers
from supportclasses import a, b, c, d, q, r, z

import gmpy2
Expand Down Expand Up @@ -872,3 +872,38 @@ def test_mpfr_pickle():
assert pickle.loads(pickle.dumps(mpfr("-inf"))) == mpfr('-inf')
assert is_nan(pickle.loads(pickle.dumps(mpfr("nan"))))
assert pickle.loads(pickle.dumps(mpfr(0))) == mpfr('0.0')


def test_mpfr_floor():
a = mpfr('12.34')

ctx = get_context()
r = ctx.floor(a)

assert r == mpz(12) and isinstance(r, mpz)


def test_mpfr_ceil():
a = mpfr('12.34')

ctx = get_context()
r = ctx.ceil(a)

assert r == mpz(13) and isinstance(r, mpz)


def test_mpfr_trunc():
a = mpfr('12.34')

ctx = get_context()
r = ctx.trunc(a)

assert r == mpz(12) and isinstance(r, mpz)


@given(floats(allow_nan=False, allow_infinity=False),
integers(-10, 40))
def test_mpfr_round_roundtrip_bulk(x, n):
q = mpq(*x.as_integer_ratio())
assert float(round(q, n)) == round(x, n)
assert mpfr(round(q, n)) == round(mpfr(x), n)
4 changes: 4 additions & 0 deletions test/test_mpq.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ def test_mpq_from_float():
assert mpq.from_float(3.2) == mpq(3602879701896397, 1125899906842624)


def test_mpq_float():
assert float(mpq(9, 5)) == 1.8


def test_mpq_from_Decimal():
assert mpq(Decimal("5e-3")) == mpq(5, 1000)
assert mpq(Decimal(1)) == mpq(1) # issue 327
Expand Down

0 comments on commit 7bd27fe

Please sign in to comment.