Files
mpmath--mpmath/mpmath/tests/test_basic_ops.py
T
2026-07-13 12:32:53 +08:00

786 lines
26 KiB
Python

import collections
import decimal
import math
import operator
import random
import sys
from concurrent.futures import ThreadPoolExecutor
import pytest
from hypothesis import example, given, settings
from hypothesis import strategies as st
import mpmath
from mpmath import (ceil, fadd, fdiv, floor, fmul, fneg, fp, frac, fsub, inf,
isinf, isint, isnan, isnormal, iv, monitor, mp, mpc, mpf,
mpi, nan, ninf, nint, nint_distance, nstr, pi, rand,
workprec)
from mpmath.libmp import (MPZ, finf, fnan, fninf, fnone, fone, from_float,
from_int, from_str, mpf_add, mpf_mul, mpf_sub,
round_down, round_nearest, round_up, to_float,
to_int, to_man_exp)
from mpmath.libmp.backend import MPQ
from mpmath.libmp.libintmath import isprime, jacobi_symbol
def test_type_compare():
assert mpf(2) == mpc(2,0)
assert mpf(0) == mpc(0)
assert mpf(2) != mpc(2, 0.00001)
assert mpf(2) == 2.0
assert mpf(2) != 3.0
assert mpf(2) == 2
assert mpf(2) != '2.0'
assert mpc(2) != '2.0'
def test_add():
assert mpf(2.5) + mpf(3) == 5.5
assert mpf(2.5) + 3 == 5.5
assert mpf(2.5) + 3.0 == 5.5
assert 3 + mpf(2.5) == 5.5
assert 3.0 + mpf(2.5) == 5.5
assert (3+0j) + mpf(2.5) == 5.5
assert mpc(2.5) + mpf(3) == 5.5
assert mpc(2.5) + 3 == 5.5
assert mpc(2.5) + 3.0 == 5.5
assert mpc(2.5) + (3+0j) == 5.5
assert 3 + mpc(2.5) == 5.5
assert 3.0 + mpc(2.5) == 5.5
assert (3+0j) + mpc(2.5) == 5.5
def test_sub():
assert mpf(2.5) - mpf(3) == -0.5
assert mpf(2.5) - 3 == -0.5
assert mpf(2.5) - 3.0 == -0.5
assert 3 - mpf(2.5) == 0.5
assert 3.0 - mpf(2.5) == 0.5
assert (3+0j) - mpf(2.5) == 0.5
assert mpc(2.5) - mpf(3) == -0.5
assert mpc(2.5) - 3 == -0.5
assert mpc(2.5) - 3.0 == -0.5
assert mpc(2.5) - (3+0j) == -0.5
assert 3 - mpc(2.5) == 0.5
assert 3.0 - mpc(2.5) == 0.5
assert (3+0j) - mpc(2.5) == 0.5
def test_mul():
assert mpf(2.5) * mpf(3) == 7.5
assert mpf(2.5) * 3 == 7.5
assert mpf(2.5) * 3.0 == 7.5
assert 3 * mpf(2.5) == 7.5
assert 3.0 * mpf(2.5) == 7.5
assert (3+0j) * mpf(2.5) == 7.5
assert mpc(2.5) * mpf(3) == 7.5
assert mpc(2.5) * 3 == 7.5
assert mpc(2.5) * 3.0 == 7.5
assert mpc(2.5) * (3+0j) == 7.5
assert 3 * mpc(2.5) == 7.5
assert 3.0 * mpc(2.5) == 7.5
assert (3+0j) * mpc(2.5) == 7.5
def test_div():
assert mpf(6) / mpf(3) == 2.0
assert mpf(6) / 3 == 2.0
assert mpf(6) / 3.0 == 2.0
assert 6 / mpf(3) == 2.0
assert 6.0 / mpf(3) == 2.0
assert (6+0j) / mpf(3.0) == 2.0
assert mpc(6) / mpf(3) == 2.0
assert mpc(6) / 3 == 2.0
assert mpc(6) / 3.0 == 2.0
assert mpc(6) / (3+0j) == 2.0
assert 6 / mpc(3) == 2.0
assert 6.0 / mpc(3) == 2.0
assert (6+0j) / mpc(3) == 2.0
assert 1/mpc(inf, 1) == 0.0
assert (1+1j)/mpc(2, inf) == 0.0
assert mpc(inf, 1)**-1 == 0.0
def test_mod():
assert mpf(3.1) % decimal.Decimal(5.3) == mpf('3.1000000000000001')
assert mpf(2.53) % inf == mpf(2.53)
assert mpf(2.53) % ninf == mpf(2.53)
def test_floordiv():
assert mpf(30.21) // mpf(2.53) == mpf(11)
def test_divmod():
assert divmod(mpf(30.21), mpf(2.53)) == (mpf(11), mpf(2.380000000000003))
def test_pow():
assert mpf(6) ** mpf(3) == 216.0
assert mpf(6) ** 3 == 216.0
assert mpf(6) ** 3.0 == 216.0
assert 6 ** mpf(3) == 216.0
assert 6.0 ** mpf(3) == 216.0
assert (6+0j) ** mpf(3.0) == 216.0
assert mpc(6) ** mpf(3) == 216.0
assert mpc(6) ** 3 == 216.0
assert mpc(6) ** 3.0 == 216.0
assert mpc(6) ** (3+0j) == 216.0
assert 6 ** mpc(3) == 216.0
assert 6.0 ** mpc(3) == 216.0
assert (6+0j) ** mpc(3) == 216.0
assert inf ** mpf(0) == mpf(1)
assert ninf ** mpf(0) == mpf(1)
assert nan ** mpf(0) == mpf(1)
assert mpc(1, -inf)**3 == mpc(-inf, inf)
assert mpc(1, -inf)**4 == mpc(inf, inf)
def test_mixed_misc():
assert 1 + mpf(3) == mpf(3) + 1 == 4
assert 1 - mpf(3) == -(mpf(3) - 1) == -2
assert 3 * mpf(2) == mpf(2) * 3 == 6
assert 6 / mpf(2) == mpf(6) / 2 == 3
assert 1.0 + mpf(3) == mpf(3) + 1.0 == 4
assert 1.0 - mpf(3) == -(mpf(3) - 1.0) == -2
assert 3.0 * mpf(2) == mpf(2) * 3.0 == 6
assert 6.0 / mpf(2) == mpf(6) / 2.0 == 3
def test_add_misc():
assert mpf(4) + mpf(-70) == -66
assert mpf(1) + mpf(1.1)/80 == 1 + 1.1/80
assert mpf((1, 10000000000)) + mpf(3) == mpf((1, 10000000000))
assert mpf(3) + mpf((1, 10000000000)) == mpf((1, 10000000000))
assert mpf((1, -10000000000)) + mpf(3) == mpf(3)
assert mpf(3) + mpf((1, -10000000000)) == mpf(3)
assert mpf(1) + 1e-15 != 1
assert mpf(1) + 1e-20 == 1
assert mpf(1.07e-22) + 0 == mpf(1.07e-22)
assert mpf(0) + mpf(1.07e-22) == mpf(1.07e-22)
def test_mpf_init():
a1 = mpf(0.3, prec=20)
a2 = mpf(0.3, dps=5)
a3 = mpf(0.3)
assert a1 == a2
assert a1 != a3
assert str(a1) == '0.300000190734863'
assert str(a3) == '0.3'
pytest.raises(ValueError, lambda: mpf((1,)))
pytest.raises(ValueError, lambda: mpf(mpi(1, 2)))
pytest.raises(TypeError, lambda: mpf(object()))
pytest.raises(TypeError, lambda: mpf(1 + 1j))
class SomethingReal:
def _mpmath_(self, prec, rounding):
return mp.make_mpf(from_str('1.3', prec, rounding))
class SomethingComplex:
def _mpmath_(self, prec, rounding):
return mp.make_mpc((from_str('1.3', prec, rounding), \
from_str('1.7', prec, rounding)))
class mympf:
@property
def _mpf_(self):
return mpf(3.5)._mpf_
assert mpf(SomethingReal(), prec=20) == mpf('1.3', prec=20)
pytest.raises(TypeError, lambda: mpf(SomethingComplex()))
assert mpf(mympf()) == mpf(3.5)
assert mympf() - mpf(0.5) == mpf(3.0)
assert mpf(decimal.Decimal('1.5')) == mpf('1.5')
assert mpf(decimal.Decimal('+inf')) == +inf
assert mpf(decimal.Decimal('-inf')) == -inf
assert isnan(mpf(decimal.Decimal('nan')))
assert mpf(decimal.Decimal(1).exp(), dps=5) == mpf('2.7182807922363281', dps=5)
assert mpf(decimal.Decimal(1).exp(), prec=0) == mpf('2.718281828459045235360287471', prec=93)
assert mpf('0x1.4ace478p+33') == mpf(11100000000.0)
assert mpf('0x1.4ace478p+33', base=0) == mpf(11100000000.0)
assert mpf('1.4ace478p+33', base=16) == mpf(11100000000.0)
assert mpf((1, 17813873926281399, -78, 54), prec=5,
rounding='u') == mpf('-5.9604644775390625e-8')
assert mpf(float('+inf')) == +inf
assert mpf(float('-inf')) == -inf
assert isnan(mpf(float('nan')))
def test_mpc_init():
class mympc:
@property
def _mpc_(self):
return (mpf(7)._mpf_, mpf(-1)._mpf_)
assert mpc(3+1j, 7-1j) == mpc(real='4.0', imag='8.0')
assert mpc(3+1j, mympc()) == mpc(real='4.0', imag='8.0')
assert mpc('(1+2j)') == mpc(real='1.0', imag='2.0')
def test_mpf_props():
a = mpf(0.5)
assert a.man_exp == (1, -1)
pytest.raises(ValueError, lambda: inf.man_exp)
pytest.raises(ValueError, lambda: nan.man_exp)
assert a.man == 1
assert a.exp == -1
assert a.bc == 1
def test_mpf_methods():
assert mpf(0.5).as_integer_ratio() == (1, 2)
assert mpf('0.3').as_integer_ratio() == (5404319552844595,
18014398509481984)
def test_mpf_magic():
assert complex(mpf(0.5)) == complex(0.5)
def test_complex_misc():
# many more tests needed
assert 1 + mpc(2) == 3
assert not mpc(2).ae(2 + 1e-13)
assert mpc(2+1e-15j).ae(2)
def test_complex_zeros():
for a in [0,2]:
for b in [0,3]:
for c in [0,4]:
for d in [0,5]:
assert mpc(a,b)*mpc(c,d) == complex(a,b)*complex(c,d)
def test_hash():
for i in range(-256, 256):
assert hash(mpf(i)) == hash(i)
assert hash(mpf(0.5)) == hash(0.5)
assert hash(mpc(2,3)) == hash(2+3j)
# Check that this doesn't fail
assert hash(inf)
hash(nan)
# Check that overflow doesn't assign equal hashes to large numbers
assert hash(mpf('1e1000')) != hash('1e10000')
assert hash(mpc(100,'1e1000')) != hash(mpc(200,'1e1000'))
assert hash(MPQ(1,3))
assert hash(MPQ(0,1)) == 0
assert hash(MPQ(-1,1)) == hash(-1)
assert hash(MPQ(1,1)) == hash(1)
assert hash(MPQ(5,1)) == hash(5)
assert hash(MPQ(1,2)) == hash(0.5)
assert hash(mpf(1)*2**2000) == hash(2**2000)
assert hash(mpf(1)/2**2000) == hash(MPQ(1,2**2000))
# Advanced rounding test
def test_add_rounding():
a = from_float(1e-50)
assert mpf_sub(mpf_add(fone, a, 53, round_up), fone, 53, round_up) == from_float(2.2204460492503131e-16)
assert mpf_sub(fone, a, 53, round_up) == fone
assert mpf_sub(fone, mpf_sub(fone, a, 53, round_down), 53, round_down) == from_float(1.1102230246251565e-16)
assert mpf_add(fone, a, 53, round_down) == fone
def test_almost_equal():
assert mpf(1.2).ae(mpf(1.20000001), 1e-7)
assert not mpf(1.2).ae(mpf(1.20000001), 1e-9)
assert not mpf(-0.7818314824680298).ae(mpf(-0.774695868667929))
assert inf.ae(inf)
assert not inf.ae(-inf)
assert not mpf(1.2).ae(nan)
assert not mpf(1.2).ae(inf)
assert not nan.ae(nan)
assert not nan.ae(inf)
def test_arithmetic_functions():
ops = [(operator.add, fadd), (operator.sub, fsub), (operator.mul, fmul),
(operator.truediv, fdiv)]
a = mpf(0.27)
b = mpf(1.13)
c = mpc(0.51+2.16j)
d = mpc(1.08-0.99j)
for x in [a,b,c,d]:
for y in [a,b,c,d]:
for op, fop in ops:
if fop is not fdiv:
mp.prec = 200
z0 = op(x,y)
mp.prec = 60
z1 = op(x,y)
mp.prec = 53
z2 = op(x,y)
assert fop(x, y, prec=60) == z1
assert fop(x, y) == z2
if fop is not fdiv:
assert fop(x, y, prec=inf) == z0
assert fop(x, y, dps=inf) == z0
assert fop(x, y, exact=True) == z0
assert fneg(fneg(z1, exact=True), prec=inf) == z1
assert fneg(z1) == -(+z1)
def test_exact_integer_arithmetic():
random.seed(0)
for prec in [6, 10, 25, 40, 100, 250, 725]:
for rounding in ['d', 'u', 'f', 'c', 'n']:
mp.dps = prec
mp.rounding = rounding
M = 10**(prec-2)
M2 = 10**(prec//2-2)
for i in range(10):
a = random.randint(-M, M)
b = random.randint(-M, M)
assert mpf(a, rounding=rounding) == a
assert int(mpf(a, rounding=rounding)) == a
assert int(mpf(str(a), rounding=rounding)) == a
assert mpf(a) + mpf(b) == a + b
assert mpf(a) - mpf(b) == a - b
assert -mpf(a) == -a
a = random.randint(-M2, M2)
b = random.randint(-M2, M2)
assert mpf(a) * mpf(b) == a*b
assert mpf_mul(from_int(a), from_int(b), mp.prec, rounding) == from_int(a*b)
def test_odd_int_bug():
assert to_int(from_int(3), round_nearest) == 3
def test_str_1000_digits():
mp.dps = 1001
# last digit may be wrong
assert str(mpf(2)**0.5)[-10:-1] == '9518488472'[:9]
assert str(pi)[-10:-1] == '2164201989'[:9]
def test_str_10000_digits():
mp.dps = 10001
# last digit may be wrong
assert str(mpf(2)**0.5)[-10:-1] == '5873258351'[:9]
assert str(pi)[-10:-1] == '5256375678'[:9]
def test_monitor():
f = lambda x: x**2
a = []
b = []
g = monitor(f, a.append, b.append)
assert g(3) == 9
assert g(4) == 16
assert a[0] == ((3,), {})
assert b[0] == 9
def test_nint_distance():
assert nint_distance(mpf(-3)) == (-3, -inf)
assert nint_distance(mpc(-3)) == (-3, -inf)
assert nint_distance(mpf(-3.1)) == (-3, -3)
assert nint_distance(mpf(-3.01)) == (-3, -6)
assert nint_distance(mpf(-3.001)) == (-3, -9)
assert nint_distance(mpf(-3.0001)) == (-3, -13)
assert nint_distance(mpf(-2.9)) == (-3, -3)
assert nint_distance(mpf(-2.99)) == (-3, -6)
assert nint_distance(mpf(-2.999)) == (-3, -9)
assert nint_distance(mpf(-2.9999)) == (-3, -13)
assert nint_distance(mpc(-3+0.1j)) == (-3, -3)
assert nint_distance(mpc(-3+0.01j)) == (-3, -6)
assert nint_distance(mpc(-3.1+0.1j)) == (-3, -3)
assert nint_distance(mpc(-3.01+0.01j)) == (-3, -6)
assert nint_distance(mpc(-3.001+0.001j)) == (-3, -9)
assert nint_distance(mpf(0)) == (0, -inf)
assert nint_distance(mpf(0.01)) == (0, -6)
assert nint_distance(mpf('1e-100')) == (0, -332)
pytest.raises(ValueError, lambda: nint_distance(mpc(1, inf)))
pytest.raises(ValueError, lambda: nint_distance(mpc(inf, 1)))
def test_floor_ceil_nint_frac():
for n in range(-10,10):
assert floor(n) == n
assert floor(n+0.5) == n
assert ceil(n) == n
assert ceil(n+0.5) == n+1
assert nint(n) == n
# nint rounds to even
if n % 2 == 1:
assert nint(n+0.5) == n+1
else:
assert nint(n+0.5) == n
assert floor(inf) == inf
assert floor(ninf) == ninf
assert isnan(floor(nan))
assert ceil(inf) == inf
assert ceil(ninf) == ninf
assert isnan(ceil(nan))
assert nint(inf) == inf
assert nint(ninf) == ninf
assert isnan(nint(nan))
assert floor(0.1) == 0
assert floor(0.9) == 0
assert floor(-0.1) == -1
assert floor(-0.9) == -1
assert floor(10000000000.1) == 10000000000
assert floor(10000000000.9) == 10000000000
assert floor(-10000000000.1) == -10000000000-1
assert floor(-10000000000.9) == -10000000000-1
assert floor(1e-100) == 0
assert floor(-1e-100) == -1
assert floor(1e100) == 1e100
assert floor(-1e100) == -1e100
assert ceil(0.1) == 1
assert ceil(0.9) == 1
assert ceil(-0.1) == 0
assert ceil(-0.9) == 0
assert ceil(10000000000.1) == 10000000000+1
assert ceil(10000000000.9) == 10000000000+1
assert ceil(-10000000000.1) == -10000000000
assert ceil(-10000000000.9) == -10000000000
assert ceil(1e-100) == 1
assert ceil(-1e-100) == 0
assert ceil(1e100) == 1e100
assert ceil(-1e100) == -1e100
assert nint(0.1) == 0
assert nint(0.9) == 1
assert nint(-0.1) == 0
assert nint(-0.9) == -1
assert nint(10000000000.1) == 10000000000
assert nint(10000000000.9) == 10000000000+1
assert nint(-10000000000.1) == -10000000000
assert nint(-10000000000.9) == -10000000000-1
assert nint(1e-100) == 0
assert nint(-1e-100) == 0
assert nint(1e100) == 1e100
assert nint(-1e100) == -1e100
assert floor(3.2+4.6j) == 3+4j
assert ceil(3.2+4.6j) == 4+5j
assert nint(3.2+4.6j) == 3+5j
for n in range(-10,10):
assert frac(n) == 0
assert frac(0.25) == 0.25
assert frac(1.25) == 0.25
assert frac(2.25) == 0.25
assert frac(-0.25) == 0.75
assert frac(-1.25) == 0.75
assert frac(-2.25) == 0.75
assert frac('1e100000000000000') == 0
u = mpf('1e-100000000000000')
assert frac(u) == u
assert frac(-u) == 1 # rounding!
u = mpf('1e-400')
assert frac(-u, prec=0) == fsub(1, u, exact=True)
assert frac(3.25+4.75j) == 0.25+0.75j
def test_isnan_etc():
assert isnan(nan) is True
assert isnan(3) is False
assert isnan(mpf(3)) is False
assert isnan(inf) is False
assert isnan(mpc(2, nan)) is True
assert isnan(mpc(2, nan)) is True
assert isnan(mpc(nan, nan)) is True
assert isnan(mpc(2, 2)) is False
assert isnan(mpc(nan, inf)) is True
assert isnan(mpc(inf, inf)) is False
assert isnan(MPQ(3, 2)) is False
assert isnan(MPQ(0, 1)) is False
assert isinf(inf) is True
assert isinf(-inf) is True
assert isinf(3) is False
assert isinf(nan) is False
assert isinf(3 + 4j) is False
assert isinf(mpc(inf)) is True
assert isinf(mpc(3, inf)) is True
assert isinf(mpc(inf, 3)) is True
assert isinf(mpc(inf, inf)) is True
assert isinf(mpc(nan, inf)) is True
assert isinf(mpc(inf, nan)) is True
assert isinf(mpc(nan, nan)) is False
assert isinf(MPQ(3, 2)) is False
assert isinf(MPQ(0, 1)) is False
pytest.raises(TypeError, lambda: isinf(object()))
assert isnormal(3) is True
assert isnormal(3.5) is True
assert isnormal(mpf(3.5)) is True
assert isnormal(0) is False
assert isnormal(mpf(0)) is False
assert isnormal(0.0) is False
assert isnormal(inf) is False
assert isnormal(-inf) is False
assert isnormal(nan) is False
assert isnormal(float(inf)) is False
assert isnormal(mpc(0, 0)) is False
assert isnormal(mpc(3, 0)) is True
assert isnormal(mpc(0, 3)) is True
assert isnormal(mpc(3, 3)) is True
assert isnormal(mpc(0, nan)) is False
assert isnormal(mpc(0, inf)) is False
assert isnormal(mpc(3, nan)) is False
assert isnormal(mpc(3, inf)) is False
assert isnormal(mpc(3, -inf)) is False
assert isnormal(mpc(nan, 0)) is False
assert isnormal(mpc(inf, 0)) is False
assert isnormal(mpc(nan, 3)) is False
assert isnormal(mpc(inf, 3)) is False
assert isnormal(mpc(inf, nan)) is False
assert isnormal(mpc(nan, inf)) is False
assert isnormal(mpc(nan, nan)) is False
assert isnormal(mpc(inf, inf)) is False
assert isnormal(MPQ(3, 2)) is True
assert isnormal(MPQ(0, 1)) is False
pytest.raises(TypeError, lambda: isnormal(object()))
assert isnormal(math.nextafter(0, 1)) is True # issue 946
assert fp.isnormal(math.nextafter(0, 1)) is False
assert fp.isnormal(0.0) is False
assert fp.isnormal(-0.0) is False
assert fp.isnormal(fp.nan) is False
assert fp.isnormal(fp.inf) is False
assert fp.isnormal(fp.ninf) is False
assert fp.isnormal(1.0) is True
assert fp.isnormal(sys.float_info.min) is True
assert fp.isnormal(1+0j) is True
assert fp.isnormal(0j) is False
assert fp.isnormal(-0j) is False
assert fp.isnormal(1+1j) is True
assert fp.isnormal(complex('inf+1j')) is False
assert isint(3) is True
assert isint(0) is True
assert isint(int(3)) is True
assert isint(int(0)) is True
assert isint(mpf(3)) is True
assert isint(mpf(0)) is True
assert isint(mpf(-3)) is True
assert isint(mpf(3.2)) is False
assert isint(3.2) is False
assert isint(nan) is False
assert isint(inf) is False
assert isint(-inf) is False
assert isint(mpc(0)) is True
assert isint(mpc(3)) is True
assert isint(mpc(3.2)) is False
assert isint(mpc(3, inf)) is False
assert isint(mpc(inf)) is False
assert isint(mpc(3, 2)) is False
assert isint(mpc(0, 2)) is False
assert isint(mpc(3, 2), gaussian=True) is True
assert isint(mpc(3, 0), gaussian=True) is True
assert isint(mpc(0, 3), gaussian=True) is True
assert isint(3 + 4j) is False
assert isint(3 + 4j, gaussian=True) is True
assert isint(3 + 0j) is True
assert isint(MPQ(3, 2)) is False
assert isint(MPQ(3, 9)) is False
assert isint(MPQ(9, 3)) is True
assert isint(MPQ(0, 4)) is True
assert isint(MPQ(1, 1)) is True
assert isint(MPQ(-1, 1)) is True
pytest.raises(TypeError, lambda: isint(object()))
assert mp.isnpint(0) is True
assert mp.isnpint(1) is False
assert mp.isnpint(-1) is True
assert mp.isnpint(-1.1) is False
assert mp.isnpint(-1.0) is True
assert mp.isnpint(MPQ(1, 2)) is False
assert mp.isnpint(MPQ(-1, 2)) is False
assert mp.isnpint(MPQ(-3, 1)) is True
assert mp.isnpint(MPQ(0, 1)) is True
assert mp.isnpint(MPQ(1, 1)) is False
assert mp.isnpint(0 + 0j) is True
assert mp.isnpint(-1 + 0j) is True
assert mp.isnpint(-1.1 + 0j) is False
assert mp.isnpint(-1 + 0.1j) is False
assert mp.isnpint(0 + 0.1j) is False
assert mp.isnpint(inf) is False
def test_isprime():
assert isprime(MPZ(2))
assert not isprime(MPZ(4))
def test_issue_438():
assert mpf(finf) == mpf('inf')
assert mpf(fninf) == mpf('-inf')
assert mpf(fnan)._mpf_ == mpf('nan')._mpf_
def test_ctx_mag():
assert mp.mag(MPQ(1, 2)) == 0
assert mp.mag(MPQ(2)) == 2
assert mp.mag(MPQ(0)) == mpf('-inf')
def test_to_man_exp():
assert to_man_exp(fnone, signed=False) == (1, 0)
def test_rand_precision():
"""
Test precision of rand()
"""
def get_remainder(x, bits):
"""
Return ``(x % 2**-bits) * (2**bits)``.
If this is nonzero, we know for sure that x was generated with a resolution greater than ``bits``.
"""
x = x * 2 ** bits
return x - int(x)
# Python float (to test the tests)
random.seed(42)
x = random.random()
assert x == 0.6394267984578837, "failed to initialize random() reproducibly"
assert get_remainder(x, 53) == 0
assert get_remainder(x, 52) != 0 # Note: this is only true for specific random seeds!
# fp:
random.seed(42)
x = fp.rand()
assert get_remainder(x, 53) == 0
assert get_remainder(x, 52) != 0 # Note: this is only true for specific random seeds!
# mp:
with workprec(123):
random.seed(43)
x = mp.rand()
assert get_remainder(x, 123) == 0
assert get_remainder(x, 122) != 0 # Note: this is only true for specific random seeds!
# iv:
oldprec = iv.prec # REMOVE ME LATER - workaround for the bug that workprec doesn't work for iv
iv.prec=123 # REMOVE ME LATER - workaround for the bug that workprec doesn't work for iv
with workprec(123):
random.seed(43)
x = iv.rand()
assert get_remainder(x, 123) == 0
assert get_remainder(x, 122) != 0 # Note: this is only true for specific random seeds!
iv.prec = oldprec # REMOVE ME LATER - workaround for the bug that workprec doesn't work for iv
def test_issue_260():
assert mpc(str(mpc(1j))) == mpc(1j)
@settings(max_examples=10000)
@given(st.floats(allow_nan=True,
allow_infinity=True,
allow_subnormal=True),
st.integers(min_value=0, max_value=15))
@example(0.5, 0)
@example(-0.5, 0)
@example(1.5, 0)
@example(-1.5, 0)
@example(2.675, 2)
@example(math.inf, 3)
@example(-math.inf, 1)
@example(8.9884656743115795e+307, 0)
def test_round_bulk(x, n):
mp.prec = fp.prec
m = mpf(x)
mr = round(m, n)
xr = round(x, n)
if isnan(x):
assert isnan(mr)
assert isnan(xr)
else:
assert float(mr) == xr
# mp context doesn't support negative zero
if not xr and math.copysign(1., xr) == -1.:
return
assert nstr(mr, n=14, base=16, strip_zeros=False,
show_zero_exponent=True, binary_exp=True) == xr.hex()
try:
xr = round(x)
except ValueError:
pytest.raises(ValueError, lambda: round(m))
except OverflowError:
pytest.raises(OverflowError, lambda: round(m))
else:
mr = round(m)
assert type(mr) is int
assert mr == xr
def test_rounding_prop():
assert mp.rounding == 'n'
assert mp.sin(1) == mpf('0x1.aed548f090ceep-1')
mp.rounding = 'u'
assert mp.rounding == 'u'
assert mp.sin(1) == mpf('0x1.aed548f090cefp-1')
with pytest.raises(ValueError):
mp.rounding = 'x'
def test_from_man_exp():
with pytest.raises(TypeError):
mp.mpf(("!", 1))
def test_issue_985():
assert hash(mpc(-1)) == -2
assert hash(mpmath.mpc(-1000004, 1)) == -2
assert mpc(-1) in {1, -1}
def test_issue_975():
def worker():
mp = mpmath.MPContext()
mp.quad(lambda x: mp.exp(-x**2), [-mp.inf, mp.inf]) ** 2
sz = 100
tpe = ThreadPoolExecutor(max_workers=4)
futures = [None]*sz
for i in range(sz):
futures[i] = tpe.submit(worker)
assert len(collections.Counter(f.result() for f in futures))
def test_to_float():
# coverage tests
mp.dps = 1000
x = mpf('0b1.1111111111111111111111111111111111111'
'11111111111111011p-1023')
assert float(x).hex() == '0x0.fffffffffffffp-1022'
x = mpf('0b1.1111111111111111111111111111111111111'
'11111111111111111p-1023')
assert float(x).hex() == '0x1.0000000000000p-1022'
assert math.isnan(float(mpf('nan')))
assert float(-mpf('0x1.1p-1075')) == float.fromhex('-0x0.0000000000001p-1022')
assert float(mpf('0x1.1p-1075')) == float.fromhex('0x0.0000000000001p-1022')
assert to_float(mpf('0x1p3000')._mpf_) == sys.float_info.max
assert to_float((-mpf('0x1p3000'))._mpf_) == -sys.float_info.max
pytest.raises(OverflowError, lambda: to_float(mpf('0x1p3000')._mpf_,
strict=True,
rnd=round_nearest))
pytest.raises(OverflowError, lambda: to_float((-mpf('0x1p3000'))._mpf_,
strict=True,
rnd=round_nearest))
def test_issue_1078():
mp.dps = 5000 # way too large
# These are adjacent denormals (in 64-bit doubles)
lo = mpf("0x0.0000000000001p-1022")
hi = mpf("0x0.0000000000002p-1022")
# Take a value that's a tiny bit below the
# midpoint (i.e. closer to `lo`):
mid = (lo + hi) / 2
# Offset of 2^-52 ULP: correctly rounds to lo
val_ok = mid - mpf(2) ** -(1074 + 52)
# Offset of 2^-53 ULP: was incorrectly rounded to hi (even)
val_bad = mid - mpf(2) ** -(1074 + 53)
assert float(val_ok) == float(val_bad) == float(lo)
def test_jacobi_symbol():
assert jacobi_symbol(25, 41) == 1
assert jacobi_symbol(-23, 83) == -1
assert jacobi_symbol(3, 9) == 0
assert jacobi_symbol(42, 97) == -1
assert jacobi_symbol(3, 5) == -1
assert jacobi_symbol(7, 9) == 1
assert jacobi_symbol(0, 3) == 0
assert jacobi_symbol(0, 1) == 1
assert jacobi_symbol(2, 1) == 1
assert jacobi_symbol(1, 3) == 1
pytest.raises(ValueError, lambda: jacobi_symbol(3, 8))
assert jacobi_symbol(10, 3) == 1
assert jacobi_symbol(10, -3) == 1
assert jacobi_symbol(-10, 3) == -1
assert jacobi_symbol(-10, -3) == 1
assert jacobi_symbol(11, 3) == -1
assert jacobi_symbol(11, -3) == -1
assert jacobi_symbol(-11, 3) == 1
assert jacobi_symbol(-11, -3) == -1
def test_issue_1116():
mp.prec = 54
x = mpf('0x1.d55368e2bef2p-4')
assert repr(x) != "mpf('0.11458149882303958')"
assert eval(repr(x)) == x
def test_eval_repr_roundtrip():
for _ in range(10):
prec = random.randint(10, 1001)
with workprec(prec):
for _ in range(1000):
x = rand()
assert eval(repr(x)) == x, (prec, x)
n = random.randint(-100, 300)
if n > 0:
x *= 10**n
elif x < 0:
x /= 10**n
assert eval(repr(x)) == x, (prec, x)