786 lines
26 KiB
Python
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)
|