Skip to content
Merged
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
- run: echo "PKG_CONFIG_PATH=${{ github.workspace }}/.local/lib/pkgconfig" >> $env:GITHUB_ENV
if: ${{ startsWith(matrix.os, 'windows') }}
- name: Build wheels
uses: pypa/cibuildwheel@v4.0.0
uses: pypa/cibuildwheel@v4.1.0
- uses: actions/upload-artifact@v7
with:
name: wheels-${{ matrix.os }}
Expand Down
2 changes: 0 additions & 2 deletions .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ build:
python:
install:
- path: .
extra_requirements:
- docs
sphinx:
fail_on_warning: true
configuration: docs/conf.py
15 changes: 3 additions & 12 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,9 @@ Homepage = "https://github.com/diofant/python-gmp"
Documentation = "https://python-gmp.readthedocs.io/en/latest/"

[project.optional-dependencies]
tests = ["pytest", "hypothesis", "mpmath"]
tests = ["pytest", "hypothesis"]
ci = ["python-gmp[tests]", "pytest-xdist"]
docs = ["sphinx>=8.2"]
develop = ["python-gmp[tests,docs]", "pre-commit", "pyperf"]

[tool.meson-python.args]
compile = ["--verbose"]

[tool.pytest.ini_options]
xfail_strict = true
develop = ["python-gmp[tests]", "prek", "pyperf"]

[tool.ruff]
line-length = 79
Expand All @@ -79,10 +72,8 @@ CFLAGS = "-Wall -Wpedantic -Werror -Wconversion"
[tool.cibuildwheel.windows]
archs = ["auto64"]
before-all = "msys2 -c scripts/cibw_before_all.sh"
before-build = "pip install delvewheel"
repair-wheel-command = """delvewheel repair -w {dest_dir} {wheel} \
--add-path .local/bin"""

[tool.cibuildwheel.windows.environment]
PYTEST_ADDOPTS = "-n 2"
CFLAGS = ""
PATH = ".\\\\.local\\\\bin;$PATH"
8 changes: 4 additions & 4 deletions tests/test_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
from hypothesis.strategies import booleans, integers, lists, sampled_from
from utils import (
bigints,
mpmath_from_man_exp,
mpmath_normalize,
python_gcdext,
python_isqrtrem,
)
Expand Down Expand Up @@ -137,11 +139,10 @@ def test_lcm_nary(xs):
@example(1, 6277101735386680763495507056286727952638980837032266301441,
0, 64, "f")
def test_mpmath_normalize(sign, man, exp, prec, rnd):
mpmath = pytest.importorskip("mpmath")
mman = mpz(man)
sign = int(sign)
bc = mman.bit_length()
res = mpmath.libmp.libmpf._normalize(sign, man, exp, bc, prec, rnd)
res = mpmath_normalize(sign, man, exp, bc, prec, rnd)
assert all(type(_) is int for _ in res)
assert _mpmath_normalize(sign, mman, exp, bc, prec, rnd) == res

Expand All @@ -152,9 +153,8 @@ def test_mpmath_normalize(sign, man, exp, prec, rnd):
@example(-6277101735386680763495507056286727952638980837032266301441,
0, 64, "f")
def test_mpmath_create(man, exp, prec, rnd):
mpmath = pytest.importorskip("mpmath")
mman = mpz(man)
res = mpmath.libmp.from_man_exp(man, exp, prec, rnd)
res = mpmath_from_man_exp(man, exp, prec, rnd)
assert all(type(_) is int for _ in res)
assert _mpmath_create(mman, exp, prec, rnd) == res
assert mman == man
Expand Down
51 changes: 51 additions & 0 deletions tests/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,54 @@ def numbers(draw):
if draw(booleans()):
return draw(floats())
return draw(complex_numbers())


def mpmath_normalize(sign, man, exp, bc, prec, rnd):
"""
Create a raw mpf tuple with value (-1)**sign * man * 2**exp and
normalized mantissa. The mantissa is rounded in the specified
direction if its size exceeds the precision. Trailing zero bits
are also stripped from the mantissa to ensure that the
representation is canonical.
"""
if not man:
return 0, 0, 0, 0
# Cut mantissa down to size if larger than target precision
n = bc - prec
if n > 0:
# The >> operator rounds to floor. shifts_down[rnd][sign]
# tells whether this is the right direction to use, or if the
# number should be negated before shifting
shifts_down = {"f": (1, 0), "c": (0, 1), "d": (1, 1), "u": (0, 0)}
if rnd == "n":
t = man >> (n - 1)
if t & 1 and ((t & 2) or (man & ((1 << (n - 1)) - 1))):
man = (t >> 1) + 1
else:
man = t >> 1
elif shifts_down[rnd][sign]:
man >>= n
else:
man = -((-man) >> n)
exp += n
# Strip trailing bits
while man & 1 == 0:
man >>= 1
exp += 1
return sign, man, exp, man.bit_length()


def mpmath_from_man_exp(man, exp, prec=0, rnd="d"):
"""
Create raw mpf from (man, exp) pair. The mantissa may be signed.
If no precision is specified, the mantissa is stored exactly.
"""
if man < 0:
sign = 1
man = -man
else:
sign = 0
bc = man.bit_length()
if not prec:
prec = bc
return mpmath_normalize(sign, man, exp, bc, prec, rnd)