chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:32:53 +08:00
commit 2a16f2f53b
247 changed files with 69150 additions and 0 deletions
+785
View File
@@ -0,0 +1,785 @@
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)
+183
View File
@@ -0,0 +1,183 @@
"""
Test bit-level integer and mpf operations
"""
from mpmath import eps, fadd, ldexp, mp, mpc, mpf
from mpmath.libmp import (MPZ, fone, from_float, from_man_exp, fzero, mpf_add,
mpf_neg, mpf_sub, round_ceiling, round_down,
round_floor, round_nearest, round_up, to_float)
from mpmath.libmp.libintmath import trailing
from mpmath.libmp.libmpf import mpf_perturb
def test_trailing():
assert trailing(0) == 0
assert trailing(1) == 0
assert trailing(2) == 1
assert trailing(7) == 0
assert trailing(8) == 3
assert trailing(2**100) == 100
assert trailing(2**100-1) == 0
def test_round_down():
assert from_man_exp(MPZ(0), -4, 4, round_down)[:3] == (0, 0, 0)
assert from_man_exp(MPZ(0xf0), -4, 4, round_down)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xf1), -4, 4, round_down)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xff), -4, 4, round_down)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(-0xf0), -4, 4, round_down)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xf1), -4, 4, round_down)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xff), -4, 4, round_down)[:3] == (1, 15, 0)
def test_round_up():
assert from_man_exp(MPZ(0), -4, 4, round_up)[:3] == (0, 0, 0)
assert from_man_exp(MPZ(0xf0), -4, 4, round_up)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xf1), -4, 4, round_up)[:3] == (0, 1, 4)
assert from_man_exp(MPZ(0xff), -4, 4, round_up)[:3] == (0, 1, 4)
assert from_man_exp(MPZ(-0xf0), -4, 4, round_up)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xf1), -4, 4, round_up)[:3] == (1, 1, 4)
assert from_man_exp(MPZ(-0xff), -4, 4, round_up)[:3] == (1, 1, 4)
def test_round_floor():
assert from_man_exp(MPZ(0), -4, 4, round_floor)[:3] == (0, 0, 0)
assert from_man_exp(MPZ(0xf0), -4, 4, round_floor)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xf1), -4, 4, round_floor)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xff), -4, 4, round_floor)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(-0xf0), -4, 4, round_floor)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xf1), -4, 4, round_floor)[:3] == (1, 1, 4)
assert from_man_exp(MPZ(-0xff), -4, 4, round_floor)[:3] == (1, 1, 4)
def test_round_ceiling():
assert from_man_exp(MPZ(0), -4, 4, round_ceiling)[:3] == (0, 0, 0)
assert from_man_exp(MPZ(0xf0), -4, 4, round_ceiling)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xf1), -4, 4, round_ceiling)[:3] == (0, 1, 4)
assert from_man_exp(MPZ(0xff), -4, 4, round_ceiling)[:3] == (0, 1, 4)
assert from_man_exp(MPZ(-0xf0), -4, 4, round_ceiling)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xf1), -4, 4, round_ceiling)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xff), -4, 4, round_ceiling)[:3] == (1, 15, 0)
def test_round_nearest():
assert from_man_exp(MPZ(0), -4, 4, round_nearest)[:3] == (0, 0, 0)
assert from_man_exp(MPZ(0xf0), -4, 4, round_nearest)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xf7), -4, 4, round_nearest)[:3] == (0, 15, 0)
assert from_man_exp(MPZ(0xf8), -4, 4, round_nearest)[:3] == (0, 1, 4) # 1111.1000 -> 10000.0
assert from_man_exp(MPZ(0xf9), -4, 4, round_nearest)[:3] == (0, 1, 4) # 1111.1001 -> 10000.0
assert from_man_exp(MPZ(0xe8), -4, 4, round_nearest)[:3] == (0, 7, 1) # 1110.1000 -> 1110.0
assert from_man_exp(MPZ(0xe9), -4, 4, round_nearest)[:3] == (0, 15, 0) # 1110.1001 -> 1111.0
assert from_man_exp(MPZ(-0xf0), -4, 4, round_nearest)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xf7), -4, 4, round_nearest)[:3] == (1, 15, 0)
assert from_man_exp(MPZ(-0xf8), -4, 4, round_nearest)[:3] == (1, 1, 4)
assert from_man_exp(MPZ(-0xf9), -4, 4, round_nearest)[:3] == (1, 1, 4)
assert from_man_exp(MPZ(-0xe8), -4, 4, round_nearest)[:3] == (1, 7, 1)
assert from_man_exp(MPZ(-0xe9), -4, 4, round_nearest)[:3] == (1, 15, 0)
def test_rounding_bugs():
# 1 less than power-of-two cases
assert from_man_exp(MPZ(72057594037927935), -56, 53, round_up)[:3] == (0, 1, 0)
assert from_man_exp(MPZ(73786976294838205979), -65, 53, round_nearest)[:3] == (0, 1, 1)
assert from_man_exp(MPZ(31), 0, 4, round_up)[:3] == (0, 1, 5)
assert from_man_exp(MPZ(-31), 0, 4, round_floor)[:3] == (1, 1, 5)
assert from_man_exp(MPZ(255), 0, 7, round_up)[:3] == (0, 1, 8)
assert from_man_exp(MPZ(-255), 0, 7, round_floor)[:3] == (1, 1, 8)
def test_rounding_issue_200():
a = from_man_exp(MPZ(9867),-100)
b = from_man_exp(MPZ(9867),-200)
c = from_man_exp(MPZ(-1),0)
z = (1, 1023, -10)
assert mpf_add(a, c, 10, 'd')[:3] == z
assert mpf_add(b, c, 10, 'd')[:3] == z
assert mpf_add(c, a, 10, 'd')[:3] == z
assert mpf_add(c, b, 10, 'd')[:3] == z
def test_perturb():
a = fone
b = from_float(0.99999999999999989)
c = from_float(1.0000000000000002)
assert mpf_perturb(a, 0, 53, round_nearest) == a
assert mpf_perturb(a, 1, 53, round_nearest) == a
assert mpf_perturb(a, 0, 53, round_up) == c
assert mpf_perturb(a, 0, 53, round_ceiling) == c
assert mpf_perturb(a, 0, 53, round_down) == a
assert mpf_perturb(a, 0, 53, round_floor) == a
assert mpf_perturb(a, 1, 53, round_up) == a
assert mpf_perturb(a, 1, 53, round_ceiling) == a
assert mpf_perturb(a, 1, 53, round_down) == b
assert mpf_perturb(a, 1, 53, round_floor) == b
a = mpf_neg(a)
b = mpf_neg(b)
c = mpf_neg(c)
assert mpf_perturb(a, 0, 53, round_nearest) == a
assert mpf_perturb(a, 1, 53, round_nearest) == a
assert mpf_perturb(a, 0, 53, round_up) == a
assert mpf_perturb(a, 0, 53, round_floor) == a
assert mpf_perturb(a, 0, 53, round_down) == b
assert mpf_perturb(a, 0, 53, round_ceiling) == b
assert mpf_perturb(a, 1, 53, round_up) == c
assert mpf_perturb(a, 1, 53, round_floor) == c
assert mpf_perturb(a, 1, 53, round_down) == a
assert mpf_perturb(a, 1, 53, round_ceiling) == a
def test_add_exact():
ff = from_float
assert mpf_add(ff(3.0), ff(2.5)) == ff(5.5)
assert mpf_add(ff(3.0), ff(-2.5)) == ff(0.5)
assert mpf_add(ff(-3.0), ff(2.5)) == ff(-0.5)
assert mpf_add(ff(-3.0), ff(-2.5)) == ff(-5.5)
assert mpf_sub(mpf_add(fone, ff(1e-100)), fone) == ff(1e-100)
assert mpf_sub(mpf_add(ff(1e-100), fone), fone) == ff(1e-100)
assert mpf_sub(mpf_add(fone, ff(-1e-100)), fone) == ff(-1e-100)
assert mpf_sub(mpf_add(ff(-1e-100), fone), fone) == ff(-1e-100)
assert mpf_add(fone, fzero) == fone
assert mpf_add(fzero, fone) == fone
assert mpf_add(fzero, fzero) == fzero
def test_long_exponent_shifts():
# Check for possible bugs due to exponent arithmetic overflow
# in a C implementation
x = mpf(1)
for p in [32, 64]:
a = ldexp(1,2**(p-1))
b = ldexp(1,2**p)
c = ldexp(1,2**(p+1))
d = ldexp(1,-2**(p-1))
e = ldexp(1,-2**p)
f = ldexp(1,-2**(p+1))
assert (x+a) == a
assert (x+b) == b
assert (x+c) == c
assert (x+d) == x
assert (x+e) == x
assert (x+f) == x
assert (a+x) == a
assert (b+x) == b
assert (c+x) == c
assert (d+x) == x
assert (e+x) == x
assert (f+x) == x
assert (x-a) == -a
assert (x-b) == -b
assert (x-c) == -c
assert (x-d) == x
assert (x-e) == x
assert (x-f) == x
assert (a-x) == a
assert (b-x) == b
assert (c-x) == c
assert (d-x) == -x
assert (e-x) == -x
assert (f-x) == -x
def test_float_rounding():
mp.prec = 64
for x in [mpf(1), mpf(1)+eps, mpf(1)-eps, -mpf(1)+eps, -mpf(1)-eps]:
fa = float(x)
fb = float(fadd(x,0,prec=53,rounding='n'))
assert fa == fb
z = mpc(x,x)
ca = complex(z)
cb = complex(fadd(z,0,prec=53,rounding='n'))
assert ca == cb
for rnd in ['n', 'd', 'u', 'f', 'c']:
fa = to_float(x._mpf_, rnd=rnd)
fb = to_float(fadd(x,0,prec=53,rounding=rnd)._mpf_, rnd=rnd)
assert fa == fb
+278
View File
@@ -0,0 +1,278 @@
import pytest
from mpmath import (arange, chebyfit, cos, cosm, differint, e, euler, exp,
expm, fourier, fourierval, inf, invertlaplace, j, limit,
log, matrix, mp, mpf, norm, pade, pi, polyroots, polyval,
sin, sinm, sqrt, logm)
def test_approximation():
f = lambda x: cos(2-2*x)/x
p, err = chebyfit(f, [2, 4], 8, error=True)
assert err < 1e-5
for i in range(10):
x = 2 + i/5.
assert abs(polyval(p, x) - f(x)) < err
def test_chebyfit():
f = lambda x: cos(2-2*x)/x
p, err = chebyfit(f, [2, 4], 8, error=True, asc=False)
assert err < 1e-5
p = p[::-1]
for i in range(10):
x = 2 + i/5.
assert abs(polyval(p, x) - f(x)) < err
def test_chebyfit_nonpositive_N():
with pytest.raises(ValueError):
chebyfit(sin, [-1, 1], 0)
def test_limits():
assert limit(lambda x: (x-sin(x))/x**3, 0).ae(mpf(1)/6)
assert limit(lambda n: (1+1/n)**n, inf).ae(e)
def test_polyval():
assert polyval([], 3) == 0
assert polyval([0], 3) == 0
assert polyval([5], 3) == 5
# 4x^3 - 2x + 5
p = [5, -2, 0, 4]
assert polyval(p, 4) == 253
assert polyval(p, 4, derivative=True) == (253, 190)
assert polyval([1, 2, 3], 2, asc=False) == 11
assert polyval(list(reversed(p)), 4, asc=False) == 253
def test_polyroots():
p = polyroots([-4,1])
assert p[0].ae(4)
p, q = polyroots([3,2,1])
assert p.ae(-1 - sqrt(2)*j)
assert q.ae(-1 + sqrt(2)*j)
#this is not a real test, it only tests a specific case
assert polyroots([1]) == []
pytest.raises(ValueError, lambda: polyroots([0]))
p, q = polyroots([1,2,3], asc=False)
assert p.ae(-1 - sqrt(2)*j)
assert q.ae(-1 + sqrt(2)*j)
def test_polyroots_legendre():
n = 64
coeffs = [916312070471295267, 0, -1905929106580294155360, 0,
659769125727878493447120, 0, -91048139350447232095702560, 0,
6695289961520387531608984680, 0, -304114948474392713657972548576,
0, 9330799555464321896324157740400, 0,
-205277590220215081719131470288800, 0,
3378527005707706553294038781836500, 0,
-42927166660756742088912492757452000, 0,
431305058712550634988073414073557200, 0,
-3491517141958743235617737161547844000, 0,
23112325428835593809686977515028663000, 0,
-126584428502545713788439446082310831200, 0,
579006552594977616773047095969088431600, 0,
-2228176940331017311443863996901733412640, 0,
7255051932731034189479516844750603752850, 0,
-20071017111583894941305187420771723751200, 0,
47310254620162038075933656063247634556400, 0,
-95158890516229191805647495979277603503200, 0,
163356095386193445933028201431093219347160, 0,
-239057700565161140389797367947941296605600, 0,
297432255354328395601259515935229287637200, 0,
-313237834141273382807123548182995095192800, 0,
277415422258095841688223780704620656114900, 0,
-204721258548015217049921875719981284186016, 0,
124284021969194758465450309166353645376880, 0,
-60969520211303089058522793175947071316960, 0,
23556405536185284408974715545252277554280, 0,
-6897338342113537600691931230430793911840, 0,
1437919688271127330313741595496589239248, 0,
-190100434726484311252477736051902332000, 0,
11975573020964041433067793888190275875]
with mp.workdps(3):
with pytest.raises(mp.NoConvergence):
polyroots(coeffs, maxsteps=5, cleanup=True, error=False,
extraprec=n*10)
roots = polyroots(coeffs, maxsteps=50, cleanup=True, error=False,
extraprec=n*10)
roots = [str(r) for r in roots]
assert roots == \
['-0.999', '-0.996', '-0.991', '-0.983', '-0.973', '-0.961',
'-0.946', '-0.93', '-0.911', '-0.889', '-0.866', '-0.841',
'-0.813', '-0.784', '-0.753', '-0.72', '-0.685', '-0.649',
'-0.611', '-0.572', '-0.531', '-0.489', '-0.446', '-0.402',
'-0.357', '-0.311', '-0.265', '-0.217', '-0.17', '-0.121',
'-0.073', '-0.0243', '0.0243', '0.073', '0.121', '0.17', '0.217',
'0.265', '0.311', '0.357', '0.402', '0.446', '0.489', '0.531',
'0.572', '0.611', '0.649', '0.685', '0.72', '0.753', '0.784',
'0.813', '0.841', '0.866', '0.889', '0.911', '0.93', '0.946',
'0.961', '0.973', '0.983', '0.991', '0.996', '0.999']
def test_polyroots_legendre_init():
extra_prec = 100
coeffs = [916312070471295267, 0, -1905929106580294155360, 0,
659769125727878493447120, 0, -91048139350447232095702560, 0,
6695289961520387531608984680, 0, -304114948474392713657972548576,
0, 9330799555464321896324157740400, 0,
-205277590220215081719131470288800, 0,
3378527005707706553294038781836500, 0,
-42927166660756742088912492757452000, 0,
431305058712550634988073414073557200, 0,
-3491517141958743235617737161547844000, 0,
23112325428835593809686977515028663000, 0,
-126584428502545713788439446082310831200, 0,
579006552594977616773047095969088431600, 0,
-2228176940331017311443863996901733412640, 0,
7255051932731034189479516844750603752850, 0,
-20071017111583894941305187420771723751200, 0,
47310254620162038075933656063247634556400, 0,
-95158890516229191805647495979277603503200, 0,
163356095386193445933028201431093219347160, 0,
-239057700565161140389797367947941296605600, 0,
297432255354328395601259515935229287637200, 0,
-313237834141273382807123548182995095192800, 0,
277415422258095841688223780704620656114900, 0,
-204721258548015217049921875719981284186016, 0,
124284021969194758465450309166353645376880, 0,
-60969520211303089058522793175947071316960, 0,
23556405536185284408974715545252277554280, 0,
-6897338342113537600691931230430793911840, 0,
1437919688271127330313741595496589239248, 0,
-190100434726484311252477736051902332000, 0,
11975573020964041433067793888190275875]
roots_init = matrix(['-0.999', '-0.996', '-0.991', '-0.983', '-0.973',
'-0.961', '-0.946', '-0.93', '-0.911', '-0.889',
'-0.866', '-0.841', '-0.813', '-0.784', '-0.753',
'-0.72', '-0.685', '-0.649', '-0.611', '-0.572',
'-0.531', '-0.489', '-0.446', '-0.402', '-0.357',
'-0.311', '-0.265', '-0.217', '-0.17', '-0.121',
'-0.073', '-0.0243', '0.0243', '0.073', '0.121',
'0.17', '0.217', '0.265', ' 0.311', '0.357',
'0.402', '0.446', '0.489', '0.531', '0.572',
'0.611', '0.649', '0.685', '0.72', '0.753',
'0.784', '0.813', '0.841', '0.866', '0.889',
'0.911', '0.93', '0.946', '0.961', '0.973',
'0.983', '0.991', '0.996', '0.999', '1.0'])
with mp.workdps(2*mp.dps):
roots_exact = polyroots(coeffs, maxsteps=50, cleanup=True, error=False,
extraprec=2*extra_prec)
with pytest.raises(mp.NoConvergence):
polyroots(coeffs, maxsteps=5, cleanup=True, error=False,
extraprec=extra_prec)
roots,err = polyroots(coeffs, maxsteps=5, cleanup=True, error=True,
extraprec=extra_prec,roots_init=roots_init)
assert max(matrix(roots_exact)-matrix(roots).apply(abs)) < err
roots1,err1 = polyroots(coeffs, maxsteps=25, cleanup=True, error=True,
extraprec=extra_prec,roots_init=roots_init[:60])
assert max(matrix(roots_exact)-matrix(roots1).apply(abs)) < err1
def test_pade():
one = mpf(1)
mp.dps = 20
N = 10
a = [one]
k = 1
for i in range(1, N+1):
k *= i
a.append(one/k)
p, q = pade(a, N//2, N//2)
for x in arange(0, 1, 0.1):
r = polyval(p, x)/polyval(q, x)
assert r.ae(exp(x), 1.0e-10)
def test_fourier():
c, s = fourier(lambda x: x+1, [-1, 2], 2)
#plot([lambda x: x+1, lambda x: fourierval((c, s), [-1, 2], x)], [-1, 2])
assert c[0].ae(1.5)
assert c[1].ae(-3*sqrt(3)/(2*pi))
assert c[2].ae(3*sqrt(3)/(4*pi))
assert s[0] == 0
assert s[1].ae(3/(2*pi))
assert s[2].ae(3/(4*pi))
assert fourierval((c, s), [-1, 2], 1).ae(1.9134966715663442)
def test_differint():
assert differint(lambda t: t, 2, -0.5).ae(8*sqrt(2/pi)/3)
def test_invlap():
t = 0.01
fp = lambda p: 1/(p+1)**2
ft = lambda t: t*exp(-t)
ftt = ft(t)
assert invertlaplace(fp,t,method='talbot').ae(ftt)
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
assert invertlaplace(fp,t,method='cohen').ae(ftt)
t = 1.0
ftt = ft(t)
assert invertlaplace(fp,t,method='talbot').ae(ftt)
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
assert invertlaplace(fp,t,method='cohen').ae(ftt)
t = 0.01
fp = lambda p: log(p)/p
ft = lambda t: -euler-log(t)
ftt = ft(t)
assert invertlaplace(fp,t,method='talbot').ae(ftt)
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
assert invertlaplace(fp,t,method='cohen').ae(ftt)
t = 1.0
ftt = ft(t)
assert invertlaplace(fp,t,method='talbot').ae(ftt)
assert invertlaplace(fp,t,method='stehfest').ae(ftt)
assert invertlaplace(fp,t,method='dehoog').ae(ftt)
assert invertlaplace(fp,t,method='cohen').ae(ftt)
def test_expm():
# Simple tests with known exact results
A = matrix([[2, 0], [0, 1]])
A = expm(A)
B = matrix([[e**2, 0], [0, e]])
assert norm(A-B, inf) < 1e-15
A = matrix([[0, -pi], [pi, 0]])
A = expm(A)
B = matrix([[-1, 0], [0, -1]])
assert norm(A-B, inf) < 1e-15
# Test with input as list of lists
A = [[1, 0], [0, 2]]
A = expm(A)
B = matrix([[e, 0], [0, e**2]])
assert norm(A-B, inf) < 1e-15
# Test non-square matrix input
A = [[1, 0], [0, 1], [0, 0]]
pytest.raises(ValueError, lambda: expm(A))
def test_cosm_sinm():
# Simple test with known exact result
A = matrix([[-pi, 0], [0, pi]])
C = cosm(A)
S = sinm(A)
C_exact = matrix([[cos(-pi), 0], [0, cos(pi)]])
S_exact = matrix([[0, 0], [0, 0]])
assert norm(C-C_exact, inf) < 1e-15
assert norm(S-S_exact, inf) < 1e-15
# Test with input as list of lists
A = [[-pi, 0], [0, pi]]
C = cosm(A)
S = sinm(A)
C_exact = matrix([[cos(-pi), 0], [0, cos(pi)]])
S_exact = matrix([[0, 0], [0, 0]])
assert norm(C-C_exact, inf) < 1e-15
assert norm(S-S_exact, inf) < 1e-15
# Test non-square matrix input
A = [[1, 0], [0, 1], [0, 0]]
pytest.raises(ValueError, lambda: cosm(A))
pytest.raises(ValueError, lambda: sinm(A))
def test_logm():
# Test for zero matrix
A = [[0, 0], [0, 0]]
pytest.raises(ValueError, lambda: logm(A))
+138
View File
@@ -0,0 +1,138 @@
"""Tests for the Command-Line Interface."""
import platform
import sys
import pexpect
import pytest
from mpmath.tests.test_demos import Console
if platform.python_implementation() == 'PyPy':
pytest.skip("Don't run CLI tests on PyPy.",
allow_module_level=True)
if sys.version_info >= (3, 15):
pytestmark = pytest.mark.filterwarnings("ignore:.*:DeprecationWarning")
def test_bare_console_no_bare_division():
c = Console(f'{sys.executable} -m mpmath --no-ipython '
'--no-wrap-floats --int-limits') # for coverage
assert c.expect_exact('>>> ') == 0
assert c.send('1 + 2\r\n') == 7
assert c.expect_exact('3\r\n>>> ') == 0
assert c.send('1/2\r\n') == 5
assert c.expect_exact('Fraction(1, 2)\r\n>>> ') == 0
assert c.send('-1/2\r\n') == 6
assert c.expect_exact('Fraction(-1, 2)\r\n>>> ') == 0
assert c.send('2**3/7\r\n') == 8
assert c.expect_exact('Fraction(8, 7)\r\n>>> ') == 0
assert c.send('(3 + 5)/7\r\n') == 11
assert c.expect_exact('Fraction(8, 7)\r\n>>> ') == 0
assert c.send('(0.5 + 1)/2\r\n') == 13
assert c.expect_exact('0.75\r\n>>> ') == 0
def test_bare_console_bare_division():
c = Console(f'{sys.executable} -m mpmath --no-ipython --no-wrap-division '
'--no-wrap-floats')
assert c.expect_exact('>>> ') == 0
assert c.send('1/2\r\n') == 5
assert c.expect_exact('0.5\r\n>>> ') == 0
def test_bare_console_without_ipython():
try:
import IPython
del IPython
pytest.skip('IPython is available')
except ImportError:
pass
c = Console(f'{sys.executable} -m mpmath')
assert c.expect_exact('>>> ') == 0
assert c.send('1 + 2\r\n') == 7
assert c.expect_exact('3\r\n>>> ') == 0
assert c.send('1/2\r\n') == 5
assert c.expect_exact('\r\nFraction(1, 2)\r\n>>> ') == 0
def test_ipython_console_bare_division_noauto():
pytest.importorskip('IPython')
c = Console(f'{sys.executable} -m mpmath --simple-prompt --no-wrap-floats '
"--no-wrap-division --colors 'NoColor' ")
assert c.expect_exact('\r\nIn [1]: ') == 0
assert c.send('1/2\r\n') == 5
assert c.expect_exact('\r\nOut[1]: 0.5\r\n\r\nIn [2]: ') == 0
def test_ipython_console_wrap_floats():
pytest.importorskip('IPython')
c = Console(f'{sys.executable} -m mpmath --simple-prompt --prec 100 '
"--colors 'NoColor' --no-pretty")
assert c.expect_exact('\r\nIn [1]: ') == 0
assert c.send('10.9\r\n') == 6
assert c.expect_exact("\r\nOut[1]: mpf('10.899999999999999999999999999995')\r\n\r\nIn [2]: ") == 0
assert c.send('def f():\r\n x = 1.1\n return x + 1\n\r\n\n') == 42
assert c.expect_exact("\r\n\r\nIn [3]: ") == 0
assert c.send('f()\r\n') == 5
assert c.expect_exact("\r\nOut[3]: mpf('2.0999999999999999999999999999987')\r\n\r\nIn [4]: ") == 0
def test_bare_console_wrap_floats():
c = Console(f'{sys.executable} -m mpmath --simple-prompt --no-ipython --prec 100 '
"--colors 'NoColor' --no-pretty")
assert c.expect_exact('>>> ') == 0
assert c.send("10.9\r\n") == 6
assert c.expect_exact("mpf('10.899999999999999999999999999995')\r\n>>> ") == 0
assert c.send("1e100\r\n") == 7
assert c.expect_exact("mpf('9.9999999999999999999999999999997e+99')\r\n>>> ") == 0
assert c.send("1E100\r\n") == 7
assert c.expect_exact("mpf('9.9999999999999999999999999999997e+99')\r\n>>> ") == 0
assert c.send("1+10.9j\r\n") == 9
assert c.expect_exact("mpc(real='1.0', imag='10.899999999999999999999999999995')\r\n>>> ") == 0
assert c.send("1+10.9J\r\n") == 9
assert c.expect_exact("mpc(real='1.0', imag='10.899999999999999999999999999995')\r\n>>> ") == 0
assert c.send('mpf(10.9)\r\n') == 11
assert c.expect_exact("mpf('10.899999999999999999999999999995')\r\n>>> ") == 0
assert c.send('0x1p-1\r\n') == 8
assert c.expect_exact("mpf('0.5')\r\n>>> ") == 0
assert c.send('0b1p+1\r\n') == 8
assert c.expect_exact("mpf('2.0')\r\n>>> ") == 0
@pytest.mark.skipif(sys.version_info < (3, 13),
reason="XXX: uses new REPL")
def test_bare_console_pretty():
c = Console(f'{sys.executable} -m mpmath --simple-prompt --no-ipython --prec 100 '
"--colors 'NoColor'", _dumb=False)
assert c.expect('>>> ') == 0
assert c.send("10.9\r\n") == 6
assert c.expect("10.899999999999999999999999999995") == 0
assert c.send("def f():\r\n x = ?\r\n\r\n") == 21
assert c.expect('SyntaxError:') == 0
assert c.send('def f():\r\n return 1.1\r\n\r\n') == 26
assert c.expect('>>> ') == 0
assert c.send("f()\r\n") == 5
assert c.expect('1.1000000000000000000000000000003') == 0
assert c.send("a = 2.1; a\r\n") == 12
assert c.expect('2.0999999999999999999999999999987') == 0
def test_mpmath_version():
c = Console(f'{sys.executable} -m mpmath --version')
assert c.expect(pexpect.EOF) == 0
assert c.before.startswith('1.')
+77
View File
@@ -0,0 +1,77 @@
import math
from random import randint, random, seed
from mpmath import ceil, floor, mp, mpf
# Test compatibility with Python floats, which are
# IEEE doubles (53-bit)
N = 5000
seed(1)
# Choosing exponents between roughly -140, 140 ensures that
# the Python floats don't overflow or underflow
xs = [(random()-1) * 10**randint(-140, 140) for x in range(N)]
ys = [(random()-1) * 10**randint(-140, 140) for x in range(N)]
# include some equal values
ys[int(N*0.8):] = xs[int(N*0.8):]
# Detect whether Python is compiled to use 80-bit floating-point
# instructions, in which case the double compatibility test breaks
uses_x87 = -4.1974624032366689e+117 / -8.4657370748010221e-47 \
== 4.9581771393902231e+163
def test_double_compatibility():
for x, y in zip(xs, ys):
mpx = mpf(x)
mpy = mpf(y)
assert mpf(x) == x
assert (mpx < mpy) == (x < y)
assert (mpx > mpy) == (x > y)
assert (mpx == mpy) == (x == y)
assert (mpx != mpy) == (x != y)
assert (mpx <= mpy) == (x <= y)
assert (mpx >= mpy) == (x >= y)
assert mpx == mpx
if uses_x87:
mp.prec = 64
a = mpx + mpy
b = mpx * mpy
c = mpx / mpy
d = mpx % mpy
mp.prec = 53
assert +a == x + y
assert +b == x * y
assert +c == x / y
assert +d == x % y
else:
assert mpx + mpy == x + y
assert mpx * mpy == x * y
assert mpx / mpy == x / y
assert mpx % mpy == x % y
assert abs(mpx) == abs(x)
assert mpf(repr(x)) == x
assert ceil(mpx) == math.ceil(x)
assert floor(mpx) == math.floor(x)
def test_sqrt():
# this fails quite often. it appers to be float
# that rounds the wrong way, not mpf
fail = 0
for x in xs:
x = abs(x)
mp.prec = 100
mp_high = mpf(x)**0.5
mp.prec = 53
mp_low = mpf(x)**0.5
fp = x**0.5
assert abs(mp_low-mp_high) <= abs(fp-mp_high)
fail += mp_low != fp
assert fail < N/10
def test_bugs():
# particular bugs
assert mpf(4.4408920985006262E-16) < mpf(1.7763568394002505E-15)
assert mpf(-4.4408920985006262E-16) > mpf(-1.7763568394002505E-15)
+291
View File
@@ -0,0 +1,291 @@
import decimal
import random
from decimal import Decimal
from fractions import Fraction
import pytest
from mpmath import inf, isnan, iv, mp, mpc, mpf, mpi, mpmathify, sqrt
from mpmath.libmp import (fhalf, from_float, from_rational, from_str,
round_ceiling, round_floor, round_nearest,
to_rational, to_str)
def test_basic_string():
"""
Test basic string conversion
"""
assert mpf('3') == mpf('3.0') == mpf('0003.') == mpf('0.03e2') == mpf(3.0)
assert mpf('30') == mpf('30.0') == mpf('00030.') == mpf(30.0)
for i in range(10):
for j in range(10):
assert mpf('%ie%i' % (i,j)) == i * 10**j
assert str(mpf('25000.0')) == '25000.0'
assert str(mpf('2500.0')) == '2500.0'
assert str(mpf('250.0')) == '250.0'
assert str(mpf('25.0')) == '25.0'
assert str(mpf('2.5')) == '2.5'
assert str(mpf('0.25')) == '0.25'
assert str(mpf('0.025')) == '0.025'
assert str(mpf('0.0025')) == '0.0025'
assert str(mpf('0.00025')) == '0.00025'
assert str(mpf('0.000025')) == '2.5e-5'
assert str(mpf(0)) == '0.0'
assert str(mpf('2.5e1000000000000000000000')) == '2.5e+1000000000000000000000'
assert str(mpf('2.6e-1000000000000000000000')) == '2.6e-1000000000000000000000'
assert str(mpf(1.23402834e-15)) == '1.23402834e-15'
assert str(mpf(-1.23402834e-15)) == '-1.23402834e-15'
assert str(mpf(-1.2344e-15)) == '-1.2344e-15'
assert repr(mpf(-1.2344e-15)) == "mpf('-1.2343999999999999e-15')"
assert str(mpf("2163048125L")) == '2163048125.0'
assert str(mpf("-2163048125l")) == '-2163048125.0'
assert str(mpf("-2163048125L/1088391168")) == '-1.98738118113799'
assert str(mpf("2163048125/1088391168l")) == '1.98738118113799'
assert str(mpf('inf')) == 'inf'
# issue 613
assert str(mpf('2_5_0_0.0')) == '2500.0'
# issue 377
assert to_str(from_str('1_234.567891', 80), 24) == '1234.567891'
assert to_str(from_str('1_234.567_891', 80), 24) == '1234.567891'
assert to_str(from_str('1_234.567_8_9_1', 80), 24) == '1234.567891'
assert to_str(from_str('1.0_0', 80), 24) == '1.0'
assert to_str(from_str('.000', 80), 24) == '0.0'
def test_from_str():
assert mpf(from_str('ABC.ABC', base=16)) == mpf(float.fromhex('ABC.ABC'))
assert mpf(from_str('0xABC.ABC')) == mpf(float.fromhex('ABC.ABC'))
assert mpf(from_str('0x3.a7p10')) == mpf(float.fromhex('0x3.a7p10'))
assert mpf(from_str('0x1.4ace478p+33')) == mpf(float.fromhex('0x1.4ace478p+33'))
assert mpf(from_str('0x1.4ace478@+33')) == mpf('7.0354608312666732e+39')
assert mpf(from_str('0b1101.100101')) == mpf('13.578125')
assert mpf(from_str('0o1101.100101')) == mpf('577.12524795532227')
assert mpf(from_str('1.99999999', prec=0)) == mpf('1.9999999901046976')
def test_eps_repr():
mp.dps = 24
assert repr(mp.eps) == '<epsilon of working precision: 2.06795e-25~>'
def test_to_str():
assert to_str(from_str('ABC.ABC', base=16), 6, base=16) == '0xabc.abc'
assert to_str(from_str('0x3.a7p10', base=16), 3, base=16) == '0xe9c.0'
assert to_str(from_str('0x1.4ace478p+33'), 7, base=16) == '0x2.959c8f@+8'
assert to_str(from_str('0o1101.100101'), 8, base=8) == '0o1101.1001'
assert to_str(from_str('0b1101.100101'), 10, base=2) == '0b1101.100101'
assert to_str(from_str('0x1.4ace478p+33'), 8, base=16, binary_exp=True) == '0x1.4ace478p+33'
assert to_str(from_str('0x1.4ace478p+33'), 7, base=16, binary_exp=True) == '0x1.4ace48p+33'
assert to_str(from_str('0x1.4ace478p+33'), 5, base=16, binary_exp=True) == '0x1.4acep+33'
assert to_str(from_str('1', base=16), 6, base=16, binary_exp=True) == '0x1.0'
x = mpf('1234.567891')._mpf_
pytest.raises(ValueError, lambda: to_str(x, 6, binary_exp=True))
pytest.raises(ValueError, lambda: to_str(x, 6, rnd='Y'))
pytest.raises(ValueError, lambda: to_str('1e400e2', 6))
assert to_str(x, 5, rnd='n') == '1234.6'
assert to_str(x, 5, rnd='d') == '1234.5'
assert to_str(x, 5, rnd='u') == '1234.6'
def test_pretty():
mp.pretty = True
assert repr(mpf(2.5)) == '2.5'
assert repr(mpc(2.5,3.5)) == '(2.5 + 3.5j)'
iv.pretty = True
assert repr(mpi(2.5,3.5)) == '[2.5, 3.5]'
def test_str_whitespace():
assert mpf('1.26 ') == 1.26
def test_str_format():
assert to_str(from_float(0.1),15,strip_zeros=False) == '0.100000000000000'
assert to_str(from_float(0.0),15,show_zero_exponent=True) == '0.0e+0'
assert to_str(from_float(0.0),0,show_zero_exponent=True) == '.0e+0'
assert to_str(from_float(0.0),0,show_zero_exponent=False) == '.0'
assert to_str(from_float(0.0),1,show_zero_exponent=True) == '0.0e+0'
assert to_str(from_float(0.0),1,show_zero_exponent=False) == '0.0'
assert to_str(from_float(1.23),3,show_zero_exponent=True) == '1.23e+0'
assert to_str(from_float(1.23456789000000e-2),15,strip_zeros=False,min_fixed=0,max_fixed=0) == '1.23456789000000e-2'
assert to_str(from_float(1.23456789000000e+2),15,strip_zeros=False,min_fixed=0,max_fixed=0) == '1.23456789000000e+2'
assert to_str(from_float(2.1287e14), 15, max_fixed=1000) == '212870000000000.0'
assert to_str(from_float(2.1287e15), 15, max_fixed=1000) == '2128700000000000.0'
assert to_str(from_float(2.1287e16), 15, max_fixed=1000) == '21287000000000000.0'
assert to_str(from_float(2.1287e30), 15, max_fixed=1000) == '2128700000000000000000000000000.0'
def test_tight_string_conversion():
# In an old version, '0.5' wasn't recognized as representing
# an exact binary number and was erroneously rounded up or down
assert from_str('0.5', 10, round_floor) == fhalf
assert from_str('0.5', 10, round_ceiling) == fhalf
def test_eval_repr_invariant():
"""Test that eval(repr(x)) == x"""
random.seed(123)
for dps in [10, 15, 20, 50, 100]:
mp.dps = dps
for i in range(1000):
a = mpf(random.random())**0.5 * 10**random.randint(-100, 100)
assert eval(repr(a)) == a
def test_str_bugs():
# Decimal rounding used to give the wrong exponent in some cases
assert str(mpf('1e600')) == '1.0e+600'
assert str(mpf('1e10000')) == '1.0e+10000'
def test_str_prec0():
assert to_str(from_float(1.234), 0) == '.0e+0'
assert to_str(from_float(1e-15), 0) == '.0e-15'
assert to_str(from_float(1e+15), 0) == '.0e+15'
assert to_str(from_float(-1e-15), 0) == '-.0e-15'
assert to_str(from_float(-1e+15), 0) == '-.0e+15'
def test_convert_rational():
assert from_rational(30, 5, 53, round_nearest)[:3] == (0, 3, 1)
assert from_rational(-7, 4, 53, round_nearest)[:3] == (1, 7, -2)
assert to_rational(mpf('0.5')._mpf_) == (1, 2)
assert to_rational(mpf('1')._mpf_) == (1, 1)
pytest.raises(ValueError, lambda: to_rational(mpf('nan')._mpf_))
pytest.raises(OverflowError, lambda: to_rational(mpf('inf')._mpf_))
pytest.raises(OverflowError, lambda: to_rational(mpf('-inf')._mpf_))
def test_custom_class():
class mympf:
@property
def _mpf_(self):
return mpf(3.5)._mpf_
class mympc:
@property
def _mpc_(self):
return mpf(3.5)._mpf_, mpf(2.5)._mpf_
assert mpf(2) + mympf() == 5.5
assert mympf() + mpf(2) == 5.5
assert mpf(mympf()) == 3.5
assert mympc() + mpc(2) == mpc(5.5, 2.5)
assert mpc(2) + mympc() == mpc(5.5, 2.5)
assert mpc(mympc()) == (3.5+2.5j)
assert mpmathify(mympf()) == mpf(3.5)
assert mpmathify(mympc()) == mpc(3.5, 2.5)
def test_conversion_methods():
class SomethingRandom:
pass
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)))
x = mpf(3)
z = mpc(3)
a = SomethingRandom()
y = SomethingReal()
w = SomethingComplex()
for d in [15, 45]:
mp.dps = d
assert (x+y).ae(mpf('4.3'))
assert (y+x).ae(mpf('4.3'))
assert (x+w).ae(mpc('4.3', '1.7'))
assert (w+x).ae(mpc('4.3', '1.7'))
assert (z+y).ae(mpc('4.3'))
assert (y+z).ae(mpc('4.3'))
assert (z+w).ae(mpc('4.3', '1.7'))
assert (w+z).ae(mpc('4.3', '1.7'))
x-y; y-x; x-w; w-x; z-y; y-z; z-w; w-z
x*y; y*x; x*w; w*x; z*y; y*z; z*w; w*z
x/y; y/x; x/w; w/x; z/y; y/z; z/w; w/z
x**y; y**x; x**w; w**x; z**y; y**z; z**w; w**z
x==y; y==x; x==w; w==x; z==y; y==z; z==w; w==z
mp.dps = 15
assert x.__add__(a) is NotImplemented
assert x.__radd__(a) is NotImplemented
assert x.__lt__(a) is NotImplemented
assert x.__gt__(a) is NotImplemented
assert x.__le__(a) is NotImplemented
assert x.__ge__(a) is NotImplemented
assert x.__eq__(a) is NotImplemented
assert x.__ne__(a) is NotImplemented
assert x.__sub__(a) is NotImplemented
assert x.__rsub__(a) is NotImplemented
assert x.__mul__(a) is NotImplemented
assert x.__rmul__(a) is NotImplemented
assert x.__truediv__(a) is NotImplemented
assert x.__rtruediv__(a) is NotImplemented
assert x.__mod__(a) is NotImplemented
assert x.__rmod__(a) is NotImplemented
assert x.__pow__(a) is NotImplemented
assert x.__rpow__(a) is NotImplemented
assert z.__add__(a) is NotImplemented
assert z.__radd__(a) is NotImplemented
assert z.__eq__(a) is NotImplemented
assert z.__ne__(a) is NotImplemented
assert z.__sub__(a) is NotImplemented
assert z.__rsub__(a) is NotImplemented
assert z.__mul__(a) is NotImplemented
assert z.__rmul__(a) is NotImplemented
assert z.__truediv__(a) is NotImplemented
assert z.__rtruediv__(a) is NotImplemented
assert z.__pow__(a) is NotImplemented
assert z.__rpow__(a) is NotImplemented
def test_mpmathify():
assert mpmathify('1/2') == 0.5
assert mpmathify('(1.0+1.0j)') == mpc(1, 1)
assert mpmathify('(1.2e-10 - 3.4e5j)') == mpc('1.2e-10', '-3.4e5')
assert mpmathify('1j') == mpc(1j)
assert mpmathify('oo') == mpf('inf')
assert mpmathify('+oo') == mpf('inf')
assert mpmathify('-oo') == mpf('-inf')
assert mpmathify('2+3*I') == mpc(2, 3)
assert mpmathify('2+3I') == mpc(2, 3)
assert mpmathify('2/3 + 4/5j') == mpc(2/3, 4/5)
def test_issue548():
try:
# This expression is invalid, but may trigger the ReDOS vulnerability
# in the regular expression for parsing complex numbers.
mpmathify('(' + '1' * 5000 + '!j')
except:
return
# The expression is invalid and should raise an exception.
assert False
def test_compatibility():
from packaging.version import Version, parse
np = pytest.importorskip("numpy")
# numpy types
for typecode in (np.typecodes['AllInteger']
+ np.typecodes['Float']
+ np.typecodes['Complex']):
nptype = np.dtype(typecode).type
if issubclass(nptype, np.complexfloating):
x = nptype(complex(0.5, -0.5))
elif issubclass(nptype, np.floating):
x = nptype(0.5)
elif issubclass(nptype, np.integer):
x = nptype(2)
# Handle the weird types
try: diff = np.abs(type(np.sqrt(x))(sqrt(x)) - np.sqrt(x))
except: continue
assert diff < np.float64(2.0**-53)
assert mpf(np.float64('inf')) == inf
assert isnan(mp.npconvert(np.float64('nan')))
if hasattr(np, "float128"):
mp.prec = 64
assert (mp.npconvert(np.float128('0.841470984807896506652502321630298954')) ==
mpf('0.841470984807896506653'))
mp.prec = 53
# issues 382 and 539
assert mp.sqrt(np.int64(1)) == mpf('1.0')
assert mpf(np.int64(1)) == mpf('1.0')
#Fraction and Decimal
oldprec = mp.prec
mp.prec = 1000
decimal.getcontext().prec = mp.dps
assert sqrt(Fraction(2, 3)).ae(sqrt(mpf('2/3')))
assert sqrt(Decimal(2)/Decimal(3)).ae(sqrt(mpf('2/3')))
mp.prec = oldprec
assert mpmathify(np.array(123)) == mpf(123)
assert mpmathify(np.array(1.25)) == mpf(1.25)
assert mpmathify(np.array(0.5+1j)) == mpc(0.5+1j)
pytest.raises(TypeError, lambda: mpmathify(np.array([1])))
def test_issue465():
assert mpf(Fraction(1, 3)) == mpf('0.33333333333333331')
+140
View File
@@ -0,0 +1,140 @@
"""Tests for demo scripts."""
import os
import subprocess
import sys
import time
import pexpect
import pytest
class Console(pexpect.spawn):
"""Spawned console for testing."""
def __init__(self, command, timeout=60, _dumb=True):
env = os.environ.copy()
if _dumb:
env['TERM'] = 'dumb'
else:
env['TERM'] = 'xterm'
env['NO_COLOR'] = '1'
super().__init__(command, timeout=timeout, encoding='utf-8', env=env)
def __del__(self):
self.send('exit()\r\n')
time.sleep(10) # a delay to allow coverage finish work
if self.isalive():
self.terminate(force=True)
# TODO: how to test plots? // mandelbrot.py and plotting.py
def test_manydigits():
expected = r"""
This script prints answers to a selection of the "Many Digits"
competition problems: http://www.cs.ru.nl/~milad/manydigits/problems.php
The output for each problem is the first 100 digits after the
decimal point in the result.
C01: sin(tan(cos(1)))
56451092986195980582768640645029648577648661582588
56955552147245934844803576138875921296745208522197
C02: sqrt(e/pi)
93019136710263285866812462363333155602971092070428
87264450006489855422345460234483872155723942699765
C03: sin((e+1)^3)
90949524105726624718554721945217426889396524221380
80108799599078079083693175099387713504636663839042
C04: exp(pi*sqrt(2011))
08911292681099318912549002226654964403231616008375
14260187657441716605755144354088871641544234358651
C05: exp(exp(exp(1/2)))
33130360854569351505757451265398380886369247851475
92794392700131812592190818654155341658216570329325
C06: arctanh(1-arctanh(1-arctanh(1-arctanh(1/pi))))
12376761044118329658639748452701440281087636723733
55412845934779398491016984592299074199915669907895
C07: pi^1000
96790874439619754260235142488458363174182234378720
67532446047250097144332075967536835025898399733192
C08: sin(6^(6^6))
95395374345732063524921114340552534258118576365118
22065161716596988369691845451204872928519972839961
C09: sin(10*arctan(tanh(pi*(2011^(1/2))/3)))
99999999999999999999999999999999999999999999999999
99999999999999999999999999999868216408727535391618
C10: (7+2^(1/5)-5*(8^(1/5)))^(1/3) + 4^(1/5)-2^(1/5)
00000000000000000000000000000000000000000000000000
00000000000000000000000000000000000000000000000000
C11: tan(2^(1/2))+arctanh(sin(1))
56031033792570862486989423169964262718414115287379
65510969436882273871745968195963502918253580384966
C12: arcsin(1/e^2) + arcsinh(e^2)
83344680806041761874543293615785770019293386147122
63906848335142800750122119140978807925425237483497
C17: S= -4*Zeta(2) - 2*Zeta(3) + 4*Zeta(2)*Zeta(3) + 2*Zeta(5)
99922283776383000876193574924756988603699551613617
09442048984358627610229735501242221963535035597647
C18: Catalan G = Sum{i=0}{\infty}(-1)^i/(2i+1)^2
91596559417721901505460351493238411077414937428167
21342664981196217630197762547694793565129261151062
C21: Equation exp(cos(x)) = x
30296400121601255253211430697335802538621997810467
85962942111799929657676507417868401302803638230948
C22: J = integral(sin(sin(sin(x)))), x=0..1
40783902635001567262733691845249456720742376991339
01533400692321748591761662552762179981626145798049
"""
result = subprocess.run([f'{sys.executable}',
'demo/manydigits.py'],
capture_output=True, text=True)
assert result.stdout == expected
@pytest.mark.filterwarnings("ignore:.*:DeprecationWarning")
def test_pidigits():
c = Console(f'{sys.executable} demo/pidigits.py')
assert c.expect_exact('> ') == 0
assert c.send('10\n') == 3
assert c.expect_exact('> ') == 0
assert c.send('100\n') == 4
assert c.expect_exact('> ') == 0
assert c.send('\n') == 1
assert c.expect('5820974944 5923078164 0628620899 '
'8628034825 3421170679 : 100') == 0
def test_sofa():
result = subprocess.run([f'{sys.executable}',
'demo/sofa.py'],
capture_output=True, text=True)
assert result.stdout == '2.2195316688719674255462841007968\n'
@pytest.mark.filterwarnings("ignore:.*:DeprecationWarning")
def test_taylor():
c = Console(f'{sys.executable} demo/taylor.py')
assert c.expect_exact('Enter the value of x (e.g. 3.5): ') == 0
assert c.send('1\n') == 2
assert c.expect_exact('Enter the number of terms n (e.g. 10): ') == 0
assert c.send('10\n') == 3
assert c.expect_exact('[2.7182818011463827368, 2.7182818011463862895]') == 0
+59
View File
@@ -0,0 +1,59 @@
from mpmath import (chop, cos, diff, diffs, diffun, e, exp, j, log, sin, sqrt,
taylor)
def test_diff():
assert diff(log, 2.0, n=0).ae(log(2))
assert diff(cos, 1.0).ae(-sin(1))
assert diff(abs, 0.0) == 0
assert diff(abs, 0.0, direction=1) == 1
assert diff(abs, 0.0, direction=-1) == -1
assert diff(exp, 1.0).ae(e)
assert diff(exp, 1.0, n=5).ae(e)
assert diff(exp, 2.0, n=5, direction=3*j).ae(e**2)
assert diff(lambda x: x**2, 3.0, method='quad').ae(6)
assert diff(lambda x: 3+x**5, 3.0, n=2, method='quad').ae(540)
assert diff(lambda x: 3+x**5, 3.0, n=2, method='step').ae(540)
assert diffun(sin)(2).ae(cos(2))
assert diffun(sin, n=2)(2).ae(-sin(2))
def test_diffs():
assert [chop(d) for d in diffs(sin, 0, 1)] == [0, 1]
assert [chop(d) for d in diffs(sin, 0, 1, method='quad')] == [0, 1]
assert [chop(d) for d in diffs(sin, 0, 2)] == [0, 1, 0]
assert [chop(d) for d in diffs(sin, 0, 2, method='quad')] == [0, 1, 0]
def test_taylor():
# Easy to test since the coefficients are exact in floating-point
assert taylor(sqrt, 1, 4) == [1, 0.5, -0.125, 0.0625, -0.0390625]
def test_diff_partial():
x,y,z = xyz = 2,3,7
f = lambda x,y,z: 3*x**2 * (y+2)**3 * z**5
assert diff(f, xyz, (0,0,0)).ae(25210500)
assert diff(f, xyz, (0,0,1)).ae(18007500)
assert diff(f, xyz, (0,0,2)).ae(10290000)
assert diff(f, xyz, (0,1,0)).ae(15126300)
assert diff(f, xyz, (0,1,1)).ae(10804500)
assert diff(f, xyz, (0,1,2)).ae(6174000)
assert diff(f, xyz, (0,2,0)).ae(6050520)
assert diff(f, xyz, (0,2,1)).ae(4321800)
assert diff(f, xyz, (0,2,2)).ae(2469600)
assert diff(f, xyz, (1,0,0)).ae(25210500)
assert diff(f, xyz, (1,0,1)).ae(18007500)
assert diff(f, xyz, (1,0,2)).ae(10290000)
assert diff(f, xyz, (1,1,0)).ae(15126300)
assert diff(f, xyz, (1,1,1)).ae(10804500)
assert diff(f, xyz, (1,1,2)).ae(6174000)
assert diff(f, xyz, (1,2,0)).ae(6050520)
assert diff(f, xyz, (1,2,1)).ae(4321800)
assert diff(f, xyz, (1,2,2)).ae(2469600)
assert diff(f, xyz, (2,0,0)).ae(12605250)
assert diff(f, xyz, (2,0,1)).ae(9003750)
assert diff(f, xyz, (2,0,2)).ae(5145000)
assert diff(f, xyz, (2,1,0)).ae(7563150)
assert diff(f, xyz, (2,1,1)).ae(5402250)
assert diff(f, xyz, (2,1,2)).ae(3087000)
assert diff(f, xyz, (2,2,0)).ae(3025260)
assert diff(f, xyz, (2,2,1)).ae(2160900)
assert diff(f, xyz, (2,2,2)).ae(1234800)
+139
View File
@@ -0,0 +1,139 @@
from random import choice, randint, seed
from mpmath import mpf
from mpmath.libmp import (from_int, from_str, mpf_div, mpf_mul, round_ceiling,
round_down, round_floor, round_nearest, round_up)
from mpmath.libmp.libintmath import trailing
from mpmath.libmp.libmpf import mpf_rdiv_int
def test_div_1_3():
a = from_int(1)
b = from_int(3)
c = from_int(-1)
# floor rounds down, ceiling rounds up
assert mpf_div(a, b, 7, round_floor) == from_str('0.01010101', base=2)
assert mpf_div(a, b, 7, round_ceiling) == from_str('0.01010110', base=2)
assert mpf_div(a, b, 7, round_down) == from_str('0.01010101', base=2)
assert mpf_div(a, b, 7, round_up) == from_str('0.01010110', base=2)
assert mpf_div(a, b, 7, round_nearest) == from_str('0.01010101', base=2)
# floor rounds up, ceiling rounds down
assert mpf_div(c, b, 7, round_floor) == from_str('-0.01010110', base=2)
assert mpf_div(c, b, 7, round_ceiling) == from_str('-0.01010101', base=2)
assert mpf_div(c, b, 7, round_down) == from_str('-0.01010101', base=2)
assert mpf_div(c, b, 7, round_up) == from_str('-0.01010110', base=2)
assert mpf_div(c, b, 7, round_nearest) == from_str('-0.01010101', base=2)
def test_mpf_divi_1_3():
a = 1
b = from_int(3)
c = -1
assert mpf_rdiv_int(a, b, 7, round_floor) == from_str('0.01010101', base=2)
assert mpf_rdiv_int(a, b, 7, round_ceiling) == from_str('0.01010110', base=2)
assert mpf_rdiv_int(a, b, 7, round_down) == from_str('0.01010101', base=2)
assert mpf_rdiv_int(a, b, 7, round_up) == from_str('0.01010110', base=2)
assert mpf_rdiv_int(a, b, 7, round_nearest) == from_str('0.01010101', base=2)
assert mpf_rdiv_int(c, b, 7, round_floor) == from_str('-0.01010110', base=2)
assert mpf_rdiv_int(c, b, 7, round_ceiling) == from_str('-0.01010101', base=2)
assert mpf_rdiv_int(c, b, 7, round_down) == from_str('-0.01010101', base=2)
assert mpf_rdiv_int(c, b, 7, round_up) == from_str('-0.01010110', base=2)
assert mpf_rdiv_int(c, b, 7, round_nearest) == from_str('-0.01010101', base=2)
def test_div_300():
q = from_int(1000000)
a = from_int(300499999) # a/q is a little less than a half-integer
b = from_int(300500000) # b/q exactly a half-integer
c = from_int(300500001) # c/q is a little more than a half-integer
# Check nearest integer rounding (prec=9 as 2**8 < 300 < 2**9)
assert mpf_div(a, q, 9, round_down) == from_int(300)
assert mpf_div(b, q, 9, round_down) == from_int(300)
assert mpf_div(c, q, 9, round_down) == from_int(300)
assert mpf_div(a, q, 9, round_up) == from_int(301)
assert mpf_div(b, q, 9, round_up) == from_int(301)
assert mpf_div(c, q, 9, round_up) == from_int(301)
# Nearest even integer is down
assert mpf_div(a, q, 9, round_nearest) == from_int(300)
assert mpf_div(b, q, 9, round_nearest) == from_int(300)
assert mpf_div(c, q, 9, round_nearest) == from_int(301)
# Nearest even integer is up
a = from_int(301499999)
b = from_int(301500000)
c = from_int(301500001)
assert mpf_div(a, q, 9, round_nearest) == from_int(301)
assert mpf_div(b, q, 9, round_nearest) == from_int(302)
assert mpf_div(c, q, 9, round_nearest) == from_int(302)
def test_tight_integer_division():
# Test that integer division at tightest possible precision is exact
N = 100
seed(1)
for i in range(N):
a = choice([1, -1]) * randint(1, 1<<randint(10, 100))
b = choice([1, -1]) * randint(1, 1<<randint(10, 100))
p = a * b
width = b.bit_length() - trailing(b)
a = from_int(a); b = from_int(b); p = from_int(p)
for mode in [round_floor, round_ceiling, round_down,
round_up, round_nearest]:
assert mpf_div(p, a, int(width), mode) == b
def test_epsilon_rounding():
# Verify that mpf_div uses infinite precision; this result will
# appear to be exactly 0.101 to a near-sighted algorithm
a = from_str('0.101' + ('0'*200) + '1', base=2)
b = from_str('1.10101', base=2)
c = mpf_mul(a, b, 250, round_floor) # exact
assert mpf_div(c, b, a[1].bit_length(), round_floor) == a # exact
assert mpf_div(c, b, 2, round_down) == from_str('0.10', base=2)
assert mpf_div(c, b, 3, round_down) == from_str('0.101', base=2)
assert mpf_div(c, b, 2, round_up) == from_str('0.11', base=2)
assert mpf_div(c, b, 3, round_up) == from_str('0.110', base=2)
assert mpf_div(c, b, 2, round_floor) == from_str('0.10', base=2)
assert mpf_div(c, b, 3, round_floor) == from_str('0.101', base=2)
assert mpf_div(c, b, 2, round_ceiling) == from_str('0.11', base=2)
assert mpf_div(c, b, 3, round_ceiling) == from_str('0.110', base=2)
# The same for negative numbers
a = from_str('-0.101' + ('0'*200) + '1', base=2)
b = from_str('1.10101', base=2)
c = mpf_mul(a, b, 250, round_floor)
assert mpf_div(c, b, a[1].bit_length(), round_floor) == a
assert mpf_div(c, b, 2, round_down) == from_str('-0.10', base=2)
assert mpf_div(c, b, 3, round_up) == from_str('-0.110', base=2)
# Floor goes up, ceiling goes down
assert mpf_div(c, b, 2, round_floor) == from_str('-0.11', base=2)
assert mpf_div(c, b, 3, round_floor) == from_str('-0.110', base=2)
assert mpf_div(c, b, 2, round_ceiling) == from_str('-0.10', base=2)
assert mpf_div(c, b, 3, round_ceiling) == from_str('-0.101', base=2)
def test_mod():
assert mpf(234) % 1 == 0
assert mpf(-3) % 256 == 253
assert mpf(0.25) % 23490.5 == 0.25
assert mpf(0.25) % -23490.5 == -23490.25
assert mpf(-0.25) % 23490.5 == 23490.25
assert mpf(-0.25) % -23490.5 == -0.25
# Check that these cases are handled efficiently
assert mpf('1e10000000000') % 1 == 0
assert mpf('1.23e-1000000000') % 1 == mpf('1.23e-1000000000')
# test __rmod__
assert 3 % mpf('1.75') == 1.25
def test_div_negative_rnd_bug():
assert (-3) / mpf('0.1531879017645047') == mpf('-19.583791966887116')
assert mpf('-2.6342475750861301') / mpf('0.35126216427941814') == mpf('-7.4993775104985909')
+185
View File
@@ -0,0 +1,185 @@
from mpmath import fp, mp
def run_hessenberg(A, verbose = 0):
if verbose > 1:
print("original matrix (hessenberg):\n", A)
n = A.rows
Q, H = mp.hessenberg(A)
if verbose > 1:
print("Q:\n",Q)
print("H:\n",H)
B = Q * H * Q.transpose_conj()
eps = mp.exp(0.8 * mp.log(mp.eps))
err0 = 0
for x in range(n):
for y in range(n):
err0 += abs(A[y,x] - B[y,x])
err0 /= n * n
err1 = 0
for x in range(n):
for y in range(x + 2, n):
err1 += abs(H[y,x])
if verbose > 0:
print("difference (H):", err0, err1)
if verbose > 1:
print("B:\n", B)
assert err0 < eps
assert err1 == 0
def run_schur(A, verbose = 0):
if verbose > 1:
print("original matrix (schur):\n", A)
n = A.rows
Q, R = mp.schur(A)
if verbose > 1:
print("Q:\n", Q)
print("R:\n", R)
B = Q * R * Q.transpose_conj()
C = Q * Q.transpose_conj()
eps = mp.exp(0.8 * mp.log(mp.eps))
err0 = 0
for x in range(n):
for y in range(n):
err0 += abs(A[y,x] - B[y,x])
err0 /= n * n
err1 = 0
for x in range(n):
for y in range(n):
if x == y:
C[y,x] -= 1
err1 += abs(C[y,x])
err1 /= n * n
err2 = 0
for x in range(n):
for y in range(x + 1, n):
err2 += abs(R[y,x])
if verbose > 0:
print("difference (S):", err0, err1, err2)
if verbose > 1:
print("B:\n", B)
assert err0 < eps
assert err1 < eps
assert err2 == 0
def run_eig(A, verbose = 0):
if verbose > 1:
print("original matrix (eig):\n", A)
n = A.rows
E, EL, ER = mp.eig(A, left = True, right = True)
if verbose > 1:
print("E:\n", E)
print("EL:\n", EL)
print("ER:\n", ER)
eps = mp.exp(0.8 * mp.log(mp.eps))
err0 = 0
for i in range(n):
B = A * ER[:,i] - E[i] * ER[:,i]
err0 = max(err0, mp.mnorm(B))
B = EL[i,:] * A - EL[i,:] * E[i]
err0 = max(err0, mp.mnorm(B))
err0 /= n * n
if verbose > 0:
print("difference (E):", err0)
assert err0 < eps
#####################
def test_eig_dyn():
v = 0
for i in range(5):
n = 1 + int(mp.rand() * 5)
if mp.rand() > 0.5:
# real
A = 2 * mp.randmatrix(n, n) - 1
if mp.rand() > 0.5:
A *= 10
for x in range(n):
for y in range(n):
A[x,y] = int(A[x,y])
else:
A = (2 * mp.randmatrix(n, n) - 1) + 1j * (2 * mp.randmatrix(n, n) - 1)
if mp.rand() > 0.5:
A *= 10
for x in range(n):
for y in range(n):
A[x,y] = int(mp.re(A[x,y])) + 1j * int(mp.im(A[x,y]))
run_hessenberg(A, verbose = v)
run_schur(A, verbose = v)
run_eig(A, verbose = v)
def test_eig():
v = 0
AS = []
A = mp.matrix([[2, 1, 0], # jordan block of size 3
[0, 2, 1],
[0, 0, 2]])
AS.append(A)
AS.append(A.transpose())
A = mp.matrix([[2, 0, 0], # jordan block of size 2
[0, 2, 1],
[0, 0, 2]])
AS.append(A)
AS.append(A.transpose())
A = mp.matrix([[2, 0, 1], # jordan block of size 2
[0, 2, 0],
[0, 0, 2]])
AS.append(A)
AS.append(A.transpose())
A = mp.matrix([[0, 0, 1], # cyclic
[1, 0, 0],
[0, 1, 0]])
AS.append(A)
AS.append(A.transpose())
for A in AS:
run_hessenberg(A, verbose = v)
run_schur(A, verbose = v)
run_eig(A, verbose = v)
A = mp.matrix(1)
assert mp.eig(A, left=False, right=False) == [0]
def test_fp_eig():
A = fp.matrix([[1, 2],
[3, 4]])
E, ER = fp.eig(A)
assert all(_ == 0 for _ in fp.chop(A * ER[:,0] - E[0] * ER[:,0]))
assert all(_ == 0 for _ in fp.chop(A * ER[:,1] - E[1] * ER[:,1]))
+352
View File
@@ -0,0 +1,352 @@
from mpmath import mp
def run_eigsy(A, verbose = False):
if verbose:
print("original matrix:\n", str(A))
D, Q = mp.eigsy(A)
B = Q * mp.diag(D) * Q.transpose()
C = A - B
E = Q * Q.transpose() - mp.eye(A.rows)
if verbose:
print("eigenvalues:\n", D)
print("eigenvectors:\n", Q)
NC = mp.mnorm(C)
NE = mp.mnorm(E)
if verbose:
print("difference:", NC, "\n", C, "\n")
print("difference:", NE, "\n", E, "\n")
eps = mp.exp( 0.8 * mp.log(mp.eps))
assert NC < eps
assert NE < eps
return NC
def run_eighe(A, verbose = False):
if verbose:
print("original matrix:\n", str(A))
D, Q = mp.eighe(A)
B = Q * mp.diag(D) * Q.transpose_conj()
C = A - B
E = Q * Q.transpose_conj() - mp.eye(A.rows)
if verbose:
print("eigenvalues:\n", D)
print("eigenvectors:\n", Q)
NC = mp.mnorm(C)
NE = mp.mnorm(E)
if verbose:
print("difference:", NC, "\n", C, "\n")
print("difference:", NE, "\n", E, "\n")
eps = mp.exp( 0.8 * mp.log(mp.eps))
assert NC < eps
assert NE < eps
return NC
def run_svd_r(A, full_matrices = False, verbose = True):
m, n = A.rows, A.cols
eps = mp.exp(0.8 * mp.log(mp.eps))
if verbose:
print("original matrix:\n", str(A))
print("full", full_matrices)
U, S0, V = mp.svd_r(A, full_matrices = full_matrices)
S = mp.zeros(U.cols, V.rows)
for j in range(min(m, n)):
S[j,j] = S0[j]
if verbose:
print("U:\n", str(U))
print("S:\n", str(S0))
print("V:\n", str(V))
C = U * S * V - A
err = mp.mnorm(C)
if verbose:
print("C\n", str(C), "\n", err)
assert err < eps
D = V * V.transpose() - mp.eye(V.rows)
err = mp.mnorm(D)
if verbose:
print("D:\n", str(D), "\n", err)
assert err < eps
E = U.transpose() * U - mp.eye(U.cols)
err = mp.mnorm(E)
if verbose:
print("E:\n", str(E), "\n", err)
assert err < eps
def run_svd_c(A, full_matrices = False, verbose = True):
m, n = A.rows, A.cols
eps = mp.exp(0.8 * mp.log(mp.eps))
if verbose:
print("original matrix:\n", str(A))
print("full", full_matrices)
U, S0, V = mp.svd_c(A, full_matrices = full_matrices)
S = mp.zeros(U.cols, V.rows)
for j in range(min(m, n)):
S[j,j] = S0[j]
if verbose:
print("U:\n", str(U))
print("S:\n", str(S0))
print("V:\n", str(V))
C = U * S * V - A
err = mp.mnorm(C)
if verbose:
print("C\n", str(C), "\n", err)
assert err < eps
D = V * V.transpose_conj() - mp.eye(V.rows)
err = mp.mnorm(D)
if verbose:
print("D:\n", str(D), "\n", err)
assert err < eps
E = U.transpose_conj() * U - mp.eye(U.cols)
err = mp.mnorm(E)
if verbose:
print("E:\n", str(E), "\n", err)
assert err < eps
def run_gauss(qtype, a, b):
eps = 1e-5
d, e = mp.gauss_quadrature(len(a), qtype)
d -= mp.matrix(a)
e -= mp.matrix(b)
assert mp.mnorm(d) < eps
assert mp.mnorm(e) < eps
def irandmatrix(n, r=10):
"""
random matrix with integer entries
"""
A = mp.matrix(n, n)
for i in range(n):
for j in range(n):
A[i,j] = int((2 * mp.rand() - 1) * r)
return A
#######################
def test_eighe_fixed_matrix():
A = mp.matrix([[2, 3], [3, 5]])
run_eigsy(A)
run_eighe(A)
A = mp.matrix([[7, -11], [-11, 13]])
run_eigsy(A)
run_eighe(A)
A = mp.matrix([[2, 11, 7], [11, 3, 13], [7, 13, 5]])
run_eigsy(A)
run_eighe(A)
A = mp.matrix([[2, 0, 7], [0, 3, 1], [7, 1, 5]])
run_eigsy(A)
run_eighe(A)
#
A = mp.matrix([[2, 3+7j], [3-7j, 5]])
run_eighe(A)
A = mp.matrix([[2, -11j, 0], [+11j, 3, 29j], [0, -29j, 5]])
run_eighe(A)
A = mp.matrix([[2, 11 + 17j, 7 + 19j], [11 - 17j, 3, -13 + 23j], [7 - 19j, -13 - 23j, 5]])
run_eighe(A)
def test_eigsy_randmatrix():
N = 5
for a in range(10):
A = 2 * mp.randmatrix(N, N) - 1
for i in range(0, N):
for j in range(i + 1, N):
A[j,i] = A[i,j]
run_eigsy(A)
def test_eighe_randmatrix():
N = 5
for a in range(10):
A = (2 * mp.randmatrix(N, N) - 1) + 1j * (2 * mp.randmatrix(N, N) - 1)
for i in range(0, N):
A[i,i] = mp.re(A[i,i])
for j in range(i + 1, N):
A[j,i] = mp.conj(A[i,j])
run_eighe(A)
def test_eigsy_irandmatrix():
N = 4
R = 4
for a in range(10):
A=irandmatrix(N, R)
for i in range(0, N):
for j in range(i + 1, N):
A[j,i] = A[i,j]
run_eigsy(A)
def test_eighe_irandmatrix():
N = 4
R = 4
for a in range(10):
A=irandmatrix(N, R) + 1j * irandmatrix(N, R)
for i in range(0, N):
A[i,i] = mp.re(A[i,i])
for j in range(i + 1, N):
A[j,i] = mp.conj(A[i,j])
run_eighe(A)
def test_svd_r_rand():
for i in range(5):
full = mp.rand() > 0.5
m = 1 + int(mp.rand() * 10)
n = 1 + int(mp.rand() * 10)
A = 2 * mp.randmatrix(m, n) - 1
if mp.rand() > 0.5:
A *= 10
for x in range(m):
for y in range(n):
A[x,y]=int(A[x,y])
run_svd_r(A, full_matrices = full, verbose = False)
def test_svd_c_rand():
for i in range(5):
full = mp.rand() > 0.5
m = 1 + int(mp.rand() * 10)
n = 1 + int(mp.rand() * 10)
A = (2 * mp.randmatrix(m, n) - 1) + 1j * (2 * mp.randmatrix(m, n) - 1)
if mp.rand() > 0.5:
A *= 10
for x in range(m):
for y in range(n):
A[x,y]=int(mp.re(A[x,y])) + 1j * int(mp.im(A[x,y]))
run_svd_c(A, full_matrices=full, verbose=False)
def test_svd_test_case():
# a test case from Golub and Reinsch
# (see wilkinson/reinsch: handbook for auto. comp., vol ii-linear algebra, 134-151(1971).)
eps = mp.exp(0.8 * mp.log(mp.eps))
a = [[22, 10, 2, 3, 7],
[14, 7, 10, 0, 8],
[-1, 13, -1, -11, 3],
[-3, -2, 13, -2, 4],
[ 9, 8, 1, -2, 4],
[ 9, 1, -7, 5, -1],
[ 2, -6, 6, 5, 1],
[ 4, 5, 0, -2, 2]]
a = mp.matrix(a)
b = mp.matrix([mp.sqrt(1248), 20, mp.sqrt(384), 0, 0])
S = mp.svd_r(a, compute_uv = False)
S -= b
assert mp.mnorm(S) < eps
S = mp.svd_c(a, compute_uv = False)
S -= b
assert mp.mnorm(S) < eps
def test_gauss_quadrature_static():
a = [-0.57735027, 0.57735027]
b = [ 1, 1]
run_gauss("legendre", a , b)
a = [ -0.906179846, -0.538469310, 0, 0.538469310, 0.906179846]
b = [ 0.23692689, 0.47862867, 0.56888889, 0.47862867, 0.23692689]
run_gauss("legendre", a , b)
a = [ 0.06943184, 0.33000948, 0.66999052, 0.93056816]
b = [ 0.17392742, 0.32607258, 0.32607258, 0.17392742]
run_gauss("legendre01", a , b)
a = [-0.70710678, 0.70710678]
b = [ 0.88622693, 0.88622693]
run_gauss("hermite", a , b)
a = [ -2.02018287, -0.958572465, 0, 0.958572465, 2.02018287]
b = [ 0.01995324, 0.39361932, 0.94530872, 0.39361932, 0.01995324]
run_gauss("hermite", a , b)
a = [ 0.41577456, 2.29428036, 6.28994508]
b = [ 0.71109301, 0.27851773, 0.01038926]
run_gauss("laguerre", a , b)
def test_gauss_quadrature_dynamic(verbose = False):
n = 5
A = mp.randmatrix(2 * n, 1)
def F(x):
r = 0
for i in range(len(A) - 1, -1, -1):
r = r * x + A[i]
return r
def run(qtype, FW, R, alpha = 0, beta = 0):
X, W = mp.gauss_quadrature(n, qtype, alpha = alpha, beta = beta)
a = 0
for i in range(len(X)):
a += W[i] * F(X[i])
b = mp.quad(lambda x: FW(x) * F(x), R)
c = mp.fabs(a - b)
if verbose:
print(qtype, c, a, b)
assert c < 1e-5
run("legendre", lambda x: 1, [-1, 1])
run("legendre01", lambda x: 1, [0, 1])
run("hermite", lambda x: mp.exp(-x*x), [-mp.inf, mp.inf])
run("laguerre", lambda x: mp.exp(-x), [0, mp.inf])
run("glaguerre", lambda x: mp.sqrt(x)*mp.exp(-x), [0, mp.inf], alpha = 1 / mp.mpf(2))
run("chebyshev1", lambda x: 1/mp.sqrt(1-x*x), [-1, 1])
run("chebyshev2", lambda x: mp.sqrt(1-x*x), [-1, 1])
run("jacobi", lambda x: (1-x)**(1/mp.mpf(3)) * (1+x)**(1/mp.mpf(5)), [-1, 1], alpha = 1 / mp.mpf(3), beta = 1 / mp.mpf(5) )
File diff suppressed because it is too large Load Diff
+163
View File
@@ -0,0 +1,163 @@
import pytest
from mpmath import (agm, eps, exp, factorial, fadd, fsub, gamma, j, log,
loggamma, mp, mpc, mpf, nstr, pi, rgamma, sqrt)
from mpmath.libmp import ifac
def check(name, func, z, y):
x = func(z)
xre = x.real
xim = x.imag
yre = y.real
yim = y.imag
tol = eps*8
err = 0
return abs(xre-yre) <= abs(yre)*tol and abs(xim-yim) <= abs(yim)*tol
testcases = []
# Basic values
for n in list(range(1,200)) + list(range(201,2000,17)):
testcases.append(["%s" % n, None])
for n in range(-200,200):
testcases.append(["%s+0.5" % n, None])
testcases.append(["%s+0.37" % n, None])
testcases += [
["(0.1+1j)", None],
["(-0.1+1j)", None],
["(0.1-1j)", None],
["(-0.1-1j)", None],
["10j", None],
["-10j", None],
["100j", None],
["10000j", None],
["-10000000j", None],
["(10**100)*j", None],
["125+(10**100)*j", None],
["-125+(10**100)*j", None],
["(10**10)*(1+j)", None],
["(10**10)*(-1+j)", None],
["(10**100)*(1+j)", None],
["(10**100)*(-1+j)", None],
["(1.5-1j)", None],
["(6+4j)", None],
["(4+1j)", None],
["(3.5+2j)", None],
["(1.5-1j)", None],
["(-6-4j)", None],
["(-2-3j)", None],
["(-2.5-2j)", None],
["(4+1j)", None],
["(3+3j)", None],
["(2-2j)", None],
["1", "0"],
["2", "0"],
["3", "log(2)"],
["4", "log(6)"],
["5", "log(24)"],
["0.5", "log(pi)/2"],
["1.5", "log(sqrt(pi)/2)"],
["2.5", "log(3*sqrt(pi)/4)"],
["mpf('0.37')", None],
["0.25", "log(sqrt(2*sqrt(2*pi**3)/agm(1,sqrt(2))))"],
["-0.4", None],
["mpf('-1.9')", None],
["mpf('12.8')", None],
["mpf('33.7')", None],
["mpf('95.2')", None],
["mpf('160.3')", None],
["mpf('2057.8')", None],
["25", "log(ifac(24))"],
["80", "log(ifac(79))"],
["500", "log(ifac(500-1))"],
["8000", "log(ifac(8000-1))"],
["8000.5", None],
["mpf('8000.1')", None],
["mpf('1.37e10')", None],
["mpf('1.37e10')*(1+j)", None],
["mpf('1.37e10')*(-1+j)", None],
["mpf('1.37e10')*(-1-j)", None],
["mpf('1.37e10')*(-1+j)", None],
["mpf('1.37e100')", None],
["mpf('1.37e100')*(1+j)", None],
["mpf('1.37e100')*(-1+j)", None],
["mpf('1.37e100')*(-1-j)", None],
["mpf('1.37e100')*(-1+j)", None],
["3+4j",
"mpc('"
"-1.7566267846037841105306041816232757851567066070613445016197619371316057169"
"4723618263960834804618463052988607348289672535780644470689771115236512106002"
"5970873471563240537307638968509556191696167970488390423963867031934333890838"
"8009531786948197210025029725361069435208930363494971027388382086721660805397"
"9163230643216054580167976201709951509519218635460317367338612500626714783631"
"7498317478048447525674016344322545858832610325861086336204591943822302971823"
"5161814175530618223688296232894588415495615809337292518431903058265147109853"
"1710568942184987827643886816200452860853873815413367529829631430146227470517"
"6579967222200868632179482214312673161276976117132204633283806161971389519137"
"1243359764435612951384238091232760634271570950240717650166551484551654327989"
"9360285030081716934130446150245110557038117075172576825490035434069388648124"
"6678152254554001586736120762641422590778766100376515737713938521275749049949"
"1284143906816424244705094759339932733567910991920631339597278805393743140853"
"391550313363278558195609260225928','"
"4.74266443803465792819488940755002274088830335171164611359052405215840070271"
"5906813009373171139767051863542508136875688550817670379002790304870822775498"
"2809996675877564504192565392367259119610438951593128982646945990372179860613"
"4294436498090428077839141927485901735557543641049637962003652638924845391650"
"9546290137755550107224907606529385248390667634297183361902055842228798984200"
"9591180450211798341715874477629099687609819466457990642030707080894518168924"
"6805549314043258530272479246115112769957368212585759640878745385160943755234"
"9398036774908108204370323896757543121853650025529763655312360354244898913463"
"7115955702828838923393113618205074162812089732064414530813087483533203244056"
"0546577484241423134079056537777170351934430586103623577814746004431994179990"
"5318522939077992613855205801498201930221975721246498720895122345420698451980"
"0051215797310305885845964334761831751370672996984756815410977750799748813563"
"8784405288158432214886648743541773208808731479748217023665577802702269468013"
"673719173759245720489020315779001')"],
]
for z in [4, 14, 34, 64]:
testcases.append(["(2+j)*%s/3" % z, None])
testcases.append(["(-2+j)*%s/3" % z, None])
testcases.append(["(1+2*j)*%s/3" % z, None])
testcases.append(["(2-j)*%s/3" % z, None])
testcases.append(["(20+j)*%s/3" % z, None])
testcases.append(["(-20+j)*%s/3" % z, None])
testcases.append(["(1+20*j)*%s/3" % z, None])
testcases.append(["(20-j)*%s/3" % z, None])
testcases.append(["(200+j)*%s/3" % z, None])
testcases.append(["(-200+j)*%s/3" % z, None])
testcases.append(["(1+200*j)*%s/3" % z, None])
testcases.append(["(200-j)*%s/3" % z, None])
# Poles
for n in [0,1,2,3,4,25,-1,-2,-3,-4,-20,-21,-50,-51,-200,-201,-20000,-20001]:
for t in ['1e-5', '1e-20', '1e-100', '1e-10000']:
testcases.append(["fadd(%s,'%s',exact=True)" % (n, t), None])
testcases.append(["fsub(%s,'%s',exact=True)" % (n, t), None])
testcases.append(["fadd(%s,'%sj',exact=True)" % (n, t), None])
testcases.append(["fsub(%s,'%sj',exact=True)" % (n, t), None])
@pytest.mark.parametrize("z,result", testcases)
def test_extra_gamma(z, result):
mp.dps = 1010
z = eval(z)
mp.dps = 1050
if result is None:
gamma_val = gamma(z)
loggamma_val = loggamma(z)
factorial_val = factorial(z)
rgamma_val = rgamma(z)
else:
loggamma_val = eval(result)
gamma_val = exp(loggamma_val)
factorial_val = z * gamma_val
rgamma_val = 1/gamma_val
for dps in [5, 10, 15, 25, 40, 60, 90, 120, 250, 600, 1000]:
mp.dps = dps
assert check("gamma", gamma, z, gamma_val)
assert check("rgamma", rgamma, z, rgamma_val)
assert check("loggamma", loggamma, z, loggamma_val)
assert check("factorial", factorial, z, factorial_val)
+28
View File
@@ -0,0 +1,28 @@
import pytest
from mpmath import fp, zetazero
@pytest.mark.parametrize("n,v",
[(399999999, 156762524.6750591511),
(241389216, 97490234.2276711795),
(526196239, 202950727.691229534),
(542964976, 209039046.578535272),
(1048449112, 388858885.231056486),
(1048449113, 388858885.384337406),
(1048449114, 388858886.002285122),
(1048449115, 388858886.00239369),
(1048449116, 388858886.690745053),
(3570918901, 1239587702.54745031),
(3570918902, 1239587702.54752387),
# Huge zeros (this may take hours):
# (8637740722917, 2124447368584.39296466152),
# (8637740722918, 2124447368584.39298170604),
])
def test_zetazero(n, v):
assert zetazero(n).ae(complex(0.5,v))
def test_zeta_param(capsys):
fp.zeta(0.5+100j, method="riemann-siegel", verbose=True)
captured = capsys.readouterr()
assert "Attempting to use the Riemann-Siegel algorithm" in captured.out
+914
View File
@@ -0,0 +1,914 @@
import cmath
import ctypes
import math
import sys
import hypothesis.strategies as st
import pytest
from hypothesis import example, given, settings
from mpmath import fp, inf, mp, nan, ninf, workdps
from mpmath.libmp.libmpf import read_format_spec
@st.composite
def fmt_str(draw, types='fFeE', for_complex=False):
res = ''
# fill_char and align
fill_char = draw(st.sampled_from(['']*3 + list('z;clxvjqwer')))
if fill_char:
skip_0_padding = True
if for_complex:
align = draw(st.sampled_from(list('<^>')))
else:
align = draw(st.sampled_from(list('<^>=')))
res += fill_char + align
else:
align = draw(st.sampled_from([''] + list('<^>=')))
if align == '=' and for_complex:
align = ''
if align:
skip_0_padding = True
res += align
else:
skip_0_padding = False
# sign character
res += draw(st.sampled_from([''] + list('-+ ')))
# no_neg_0 (not used yet.)
if sys.version_info >= (3, 11):
res += draw(st.sampled_from([''] + ['z']))
# alternate mode
res += draw(st.sampled_from(['', '#']))
# pad with 0s
pad0 = draw(st.sampled_from(['', '0']))
if pad0 and for_complex:
pad0 = ''
skip_thousand_separators = False
if pad0 and not skip_0_padding:
res += pad0
skip_thousand_separators = True
# Width
res += draw(st.sampled_from(['']*7 + list(map(str, range(1, 40)))
+ ([] if for_complex else ['0' + str(_)
for _ in range(40)])))
# grouping character (thousand_separators)
gchar = draw(st.sampled_from([''] + list(',_')))
if gchar and not skip_thousand_separators:
res += gchar
# Precision
prec = draw(st.sampled_from(['']*7 + list(map(str, range(40)))
+ ['0' + str(_) for _ in range(40)]))
if prec:
res += '.' + prec
if sys.version_info >= (3, 14):
gchar = draw(st.sampled_from([''] + list(',_')))
res += gchar
# Type
res += draw(st.sampled_from(types))
return res
def test_mpf_fmt_cpython():
'''
These tests assure that mpf.__format__ yields the same result as regular
float.__format__, when dps is default.
'''
# 'f' code formatting.
# zeros
assert f'{mp.mpf(0):.0f}' == '0'
assert f'{mp.mpf(0):.1f}' == '0.0'
assert f'{mp.mpf(0):.2f}' == '0.00'
assert f'{mp.mpf(0):.3f}' == '0.000'
assert f'{mp.mpf(0):.50f}' == '0.00000000000000000000000000000000000000000000000000'
# nan, infs
assert f'{inf:f}' == 'inf'
assert f'{inf:+f}' == '+inf'
assert f'{inf:F}' == 'INF'
assert f'{inf:+F}' == '+INF'
assert f'{ninf:f}' == '-inf'
assert f'{ninf:+f}' == '-inf'
assert f'{ninf:F}' == '-INF'
assert f'{ninf:+F}' == '-INF'
assert f'{nan:f}' == 'nan'
assert f'{nan:+f}' == '+nan'
assert f'{nan:F}' == 'NAN'
assert f'{nan:+F}' == '+NAN'
# precision 0; result should never include a .
assert f'{mp.mpf(1.5):.0f}' == '2'
assert f'{mp.mpf(2.5):.0f}' == '2'
assert f'{mp.mpf(3.5):.0f}' == '4'
assert f'{mp.mpf(0.0):.0f}' == '0'
assert f'{mp.mpf(0.1):.0f}' == '0'
assert f'{mp.mpf(0.001):.0f}' == '0'
assert f'{mp.mpf(10.0):.0f}' == '10'
assert f'{mp.mpf(10.1):.0f}' == '10'
assert f'{mp.mpf(10.01):.0f}' == '10'
assert f'{mp.mpf(123.456):.0f}' == '123'
assert f'{mp.mpf(1234.56):.0f}' == '1235'
assert f'{mp.mpf(1e49):.0f}' == '9999999999999999464902769475481793196872414789632'
assert f'{mp.mpf(9.9999999999999987e+49):.0f}' == '99999999999999986860582406952576489172979654066176'
assert f'{mp.mpf(1e50):.0f}' == '100000000000000007629769841091887003294964970946560'
# precision 1
assert f'{mp.mpf(0.0001):.1f}' == '0.0'
assert f'{mp.mpf(0.001):.1f}' == '0.0'
assert f'{mp.mpf(0.01):.1f}' == '0.0'
assert f'{mp.mpf(0.04):.1f}' == '0.0'
assert f'{mp.mpf(0.06):.1f}' == '0.1'
assert f'{mp.mpf(0.25):.1f}' == '0.2'
assert f'{mp.mpf(0.75):.1f}' == '0.8'
assert f'{mp.mpf(1.4):.1f}' == '1.4'
assert f'{mp.mpf(1.5):.1f}' == '1.5'
assert f'{mp.mpf(10.0):.1f}' == '10.0'
assert f'{mp.mpf(1000.03):.1f}' == '1000.0'
assert f'{mp.mpf(1234.5678):.1f}' == '1234.6'
assert f'{mp.mpf(1234.7499):.1f}' == '1234.7'
assert f'{mp.mpf(1234.75):.1f}' == '1234.8'
# precision 2
assert f'{mp.mpf(0.0001):.2f}' == '0.00'
assert f'{mp.mpf(0.001):.2f}' == '0.00'
assert f'{mp.mpf(0.004999):.2f}' == '0.00'
assert f'{mp.mpf(0.005001):.2f}' == '0.01'
assert f'{mp.mpf(0.01):.2f}' == '0.01'
assert f'{mp.mpf(0.125):.2f}' == '0.12'
assert f'{mp.mpf(0.375):.2f}' == '0.38'
assert f'{mp.mpf(1234500):.2f}' == '1234500.00'
assert f'{mp.mpf(1234560):.2f}' == '1234560.00'
assert f'{mp.mpf(1234567):.2f}' == '1234567.00'
assert f'{mp.mpf(1234567.8):.2f}' == '1234567.80'
assert f'{mp.mpf(1234567.89):.2f}' == '1234567.89'
assert f'{mp.mpf(1234567.891):.2f}' == '1234567.89'
assert f'{mp.mpf(1234567.8912):.2f}' == '1234567.89'
# alternate form always includes a decimal point. This only
# makes a difference when the precision is 0.
assert f'{mp.mpf(0):#.0f}' == '0.'
assert f'{mp.mpf(0):#.1f}' == '0.0'
assert f'{mp.mpf(1.5):#.0f}' == '2.'
assert f'{mp.mpf(2.5):#.0f}' == '2.'
assert f'{mp.mpf(10.1):#.0f}' == '10.'
assert f'{mp.mpf(1234.56):#.0f}' == '1235.'
assert f'{mp.mpf(1.4):#.1f}' == '1.4'
assert f'{mp.mpf(0.375):#.2f}' == '0.38'
# if precision is omitted it defaults to 6
assert f'{mp.mpf(0):f}' == '0.000000'
assert f'{mp.mpf(1230000):f}' == '1230000.000000'
assert f'{mp.mpf(1234567):f}' == '1234567.000000'
assert f'{mp.mpf(123.4567):f}' == '123.456700'
assert f'{mp.mpf(1.23456789):f}' == '1.234568'
assert f'{mp.mpf(0.00012):f}' == '0.000120'
assert f'{mp.mpf(0.000123):f}' == '0.000123'
assert f'{mp.mpf(0.00012345):f}' == '0.000123'
assert f'{mp.mpf(0.000001):f}' == '0.000001'
assert f'{mp.mpf(0.0000005001):f}' == '0.000001'
assert f'{mp.mpf(0.0000004999):f}' == '0.000000'
# grouping in fractional part
assert f'{mp.mpf(0.0000004999):.9_f}' == '0.000_000_500'
# 'e' code formatting with explicit precision (>= 0). Output should
# always have exactly the number of places after the point that were
# requested.
# zeros
assert f'{mp.mpf(0):.0e}' == '0e+00'
assert f'{mp.mpf(0):.1e}' == '0.0e+00'
assert f'{mp.mpf(0):.2e}' == '0.00e+00'
assert f'{mp.mpf(0):.10e}' == '0.0000000000e+00'
assert f'{mp.mpf(0):.50e}' == '0.00000000000000000000000000000000000000000000000000e+00'
# nan, infs
assert f'{inf:e}' == 'inf'
assert f'{inf:+e}' == '+inf'
assert f'{inf:E}' == 'INF'
assert f'{inf:+E}' == '+INF'
assert f'{ninf:e}' == '-inf'
assert f'{ninf:+e}' == '-inf'
assert f'{ninf:E}' == '-INF'
assert f'{ninf:+E}' == '-INF'
assert f'{nan:e}' == 'nan'
assert f'{nan:+e}' == '+nan'
assert f'{nan:E}' == 'NAN'
assert f'{nan:+E}' == '+NAN'
# precision 0. no decimal point in the output
assert f'{mp.mpf(0.01):.0e}' == '1e-02'
assert f'{mp.mpf(0.1):.0e}' == '1e-01'
assert f'{mp.mpf(1):.0e}' == '1e+00'
assert f'{mp.mpf(10):.0e}' == '1e+01'
assert f'{mp.mpf(100):.0e}' == '1e+02'
assert f'{mp.mpf(0.012):.0e}' == '1e-02'
assert f'{mp.mpf(0.12):.0e}' == '1e-01'
assert f'{mp.mpf(1.2):.0e}' == '1e+00'
assert f'{mp.mpf(12):.0e}' == '1e+01'
assert f'{mp.mpf(120):.0e}' == '1e+02'
assert f'{mp.mpf(123.456):.0e}' == '1e+02'
assert f'{mp.mpf(0.000123456):.0e}' == '1e-04'
assert f'{mp.mpf(123456000):.0e}' == '1e+08'
assert f'{mp.mpf(0.5):.0e}' == '5e-01'
assert f'{mp.mpf(1.4):.0e}' == '1e+00'
assert f'{mp.mpf(1.5):.0e}' == '2e+00'
assert f'{mp.mpf(1.6):.0e}' == '2e+00'
assert f'{mp.mpf(2.4999999):.0e}' == '2e+00'
assert f'{mp.mpf(2.5):.0e}' == '2e+00'
assert f'{mp.mpf(2.5000001):.0e}' == '3e+00'
assert f'{mp.mpf(3.499999999999):.0e}' == '3e+00'
assert f'{mp.mpf(3.5):.0e}' == '4e+00'
assert f'{mp.mpf(4.5):.0e}' == '4e+00'
assert f'{mp.mpf(5.5):.0e}' == '6e+00'
assert f'{mp.mpf(6.5):.0e}' == '6e+00'
assert f'{mp.mpf(7.5):.0e}' == '8e+00'
assert f'{mp.mpf(8.5):.0e}' == '8e+00'
assert f'{mp.mpf(9.4999):.0e}' == '9e+00'
assert f'{mp.mpf(9.5):.0e}' == '1e+01'
assert f'{mp.mpf(10.5):.0e}' == '1e+01'
assert f'{mp.mpf(14.999):.0e}' == '1e+01'
assert f'{mp.mpf(15):.0e}' == '2e+01'
# precision 1
assert f'{mp.mpf(0.0001):.1e}' == '1.0e-04'
assert f'{mp.mpf(0.001):.1e}' == '1.0e-03'
assert f'{mp.mpf(0.01):.1e}' == '1.0e-02'
assert f'{mp.mpf(0.1):.1e}' == '1.0e-01'
assert f'{mp.mpf(1):.1e}' == '1.0e+00'
assert f'{mp.mpf(10):.1e}' == '1.0e+01'
assert f'{mp.mpf(100):.1e}' == '1.0e+02'
assert f'{mp.mpf(120):.1e}' == '1.2e+02'
assert f'{mp.mpf(123):.1e}' == '1.2e+02'
assert f'{mp.mpf(123.4):.1e}' == '1.2e+02'
# precision 2
assert f'{mp.mpf(0.00013):.2e}' == '1.30e-04'
assert f'{mp.mpf(0.000135):.2e}' == '1.35e-04'
assert f'{mp.mpf(0.0001357):.2e}' == '1.36e-04'
assert f'{mp.mpf(0.0001):.2e}' == '1.00e-04'
assert f'{mp.mpf(0.001):.2e}' == '1.00e-03'
assert f'{mp.mpf(0.01):.2e}' == '1.00e-02'
assert f'{mp.mpf(0.1):.2e}' == '1.00e-01'
assert f'{mp.mpf(1):.2e}' == '1.00e+00'
assert f'{mp.mpf(10):.2e}' == '1.00e+01'
assert f'{mp.mpf(100):.2e}' == '1.00e+02'
assert f'{mp.mpf(1000):.2e}' == '1.00e+03'
assert f'{mp.mpf(1500):.2e}' == '1.50e+03'
assert f'{mp.mpf(1590):.2e}' == '1.59e+03'
assert f'{mp.mpf(1598):.2e}' == '1.60e+03'
assert f'{mp.mpf(1598.7):.2e}' == '1.60e+03'
assert f'{mp.mpf(1598.76):.2e}' == '1.60e+03'
assert f'{mp.mpf(9999):.2e}' == '1.00e+04'
# omitted precision defaults to 6
assert f'{mp.mpf(0):e}' == '0.000000e+00'
assert f'{mp.mpf(165):e}' == '1.650000e+02'
assert f'{mp.mpf(1234567):e}' == '1.234567e+06'
assert f'{mp.mpf(12345678):e}' == '1.234568e+07'
assert f'{mp.mpf(1.1):e}' == '1.100000e+00'
# alternate form always contains a decimal point. This only makes
# a difference when precision is 0.
assert f'{mp.mpf(0.01):#.0e}' == '1.e-02'
assert f'{mp.mpf(0.1):#.0e}' == '1.e-01'
assert f'{mp.mpf(1):#.0e}' == '1.e+00'
assert f'{mp.mpf(10):#.0e}' == '1.e+01'
assert f'{mp.mpf(100):#.0e}' == '1.e+02'
assert f'{mp.mpf(0.012):#.0e}' == '1.e-02'
assert f'{mp.mpf(0.12):#.0e}' == '1.e-01'
assert f'{mp.mpf(1.2):#.0e}' == '1.e+00'
assert f'{mp.mpf(12):#.0e}' == '1.e+01'
assert f'{mp.mpf(120):#.0e}' == '1.e+02'
assert f'{mp.mpf(123.456):#.0e}' == '1.e+02'
assert f'{mp.mpf(0.000123456):#.0e}' == '1.e-04'
assert f'{mp.mpf(123456000):#.0e}' == '1.e+08'
assert f'{mp.mpf(0.5):#.0e}' == '5.e-01'
assert f'{mp.mpf(1.4):#.0e}' == '1.e+00'
assert f'{mp.mpf(1.5):#.0e}' == '2.e+00'
assert f'{mp.mpf(1.6):#.0e}' == '2.e+00'
assert f'{mp.mpf(2.4999999):#.0e}' == '2.e+00'
assert f'{mp.mpf(2.5):#.0e}' == '2.e+00'
assert f'{mp.mpf(2.5000001):#.0e}' == '3.e+00'
assert f'{mp.mpf(3.499999999999):#.0e}' == '3.e+00'
assert f'{mp.mpf(3.5):#.0e}' == '4.e+00'
assert f'{mp.mpf(4.5):#.0e}' == '4.e+00'
assert f'{mp.mpf(5.5):#.0e}' == '6.e+00'
assert f'{mp.mpf(6.5):#.0e}' == '6.e+00'
assert f'{mp.mpf(7.5):#.0e}' == '8.e+00'
assert f'{mp.mpf(8.5):#.0e}' == '8.e+00'
assert f'{mp.mpf(9.4999):#.0e}' == '9.e+00'
assert f'{mp.mpf(9.5):#.0e}' == '1.e+01'
assert f'{mp.mpf(10.5):#.0e}' == '1.e+01'
assert f'{mp.mpf(14.999):#.0e}' == '1.e+01'
assert f'{mp.mpf(15):#.0e}' == '2.e+01'
assert f'{mp.mpf(123.4):#.1e}' == '1.2e+02'
assert f'{mp.mpf(0.0001357):#.2e}' == '1.36e-04'
# 'g' code formatting.
# zeros
assert f'{mp.mpf(0):.0g}' == '0'
assert f'{mp.mpf(0):.1g}' == '0'
assert f'{mp.mpf(0):.2g}' == '0'
assert f'{mp.mpf(0):.3g}' == '0'
assert f'{mp.mpf(0):.4g}' == '0'
assert f'{mp.mpf(0):.10g}' == '0'
assert f'{mp.mpf(0):.50g}' == '0'
assert f'{mp.mpf(0):.100g}' == '0'
# nan, infs
assert f'{inf:g}' == 'inf'
assert f'{inf:+g}' == '+inf'
assert f'{inf:G}' == 'INF'
assert f'{inf:+G}' == '+INF'
assert f'{ninf:g}' == '-inf'
assert f'{ninf:+g}' == '-inf'
assert f'{ninf:G}' == '-INF'
assert f'{ninf:+G}' == '-INF'
assert f'{nan:g}' == 'nan'
assert f'{nan:+g}' == '+nan'
assert f'{nan:G}' == 'NAN'
assert f'{nan:+G}' == '+NAN'
# precision 0 doesn't make a lot of sense for the 'g' code (what does
# it mean to have no significant digits?); in practice, it's interpreted
# as identical to precision 1
assert f'{mp.mpf(1000):.0g}' == '1e+03'
assert f'{mp.mpf(100):.0g}' == '1e+02'
assert f'{mp.mpf(10):.0g}' == '1e+01'
assert f'{mp.mpf(1):.0g}' == '1'
assert f'{mp.mpf(0.1):.0g}' == '0.1'
assert f'{mp.mpf(0.01):.0g}' == '0.01'
assert f'{mp.mpf(1e-3):.0g}' == '0.001'
assert f'{mp.mpf(1e-4):.0g}' == '0.0001'
assert f'{mp.mpf(1e-5):.0g}' == '1e-05'
assert f'{mp.mpf(1e-6):.0g}' == '1e-06'
assert f'{mp.mpf(12):.0g}' == '1e+01'
assert f'{mp.mpf(120):.0g}' == '1e+02'
assert f'{mp.mpf(1.2):.0g}' == '1'
assert f'{mp.mpf(0.12):.0g}' == '0.1'
assert f'{mp.mpf(0.012):.0g}' == '0.01'
assert f'{mp.mpf(0.0012):.0g}' == '0.001'
assert f'{mp.mpf(0.00012):.0g}' == '0.0001'
assert f'{mp.mpf(0.000012):.0g}' == '1e-05'
assert f'{mp.mpf(0.0000012):.0g}' == '1e-06'
# precision 1 identical to precision 0
assert f'{mp.mpf(1000):.1g}' == '1e+03'
assert f'{mp.mpf(100):.1g}' == '1e+02'
assert f'{mp.mpf(10):.1g}' == '1e+01'
assert f'{mp.mpf(1):.1g}' == '1'
assert f'{mp.mpf(0.1):.1g}' == '0.1'
assert f'{mp.mpf(0.01):.1g}' == '0.01'
assert f'{mp.mpf(1e-3):.1g}' == '0.001'
assert f'{mp.mpf(1e-4):.1g}' == '0.0001'
assert f'{mp.mpf(1e-5):.1g}' == '1e-05'
assert f'{mp.mpf(1e-6):.1g}' == '1e-06'
assert f'{mp.mpf(12):.1g}' == '1e+01'
assert f'{mp.mpf(120):.1g}' == '1e+02'
assert f'{mp.mpf(1.2):.1g}' == '1'
assert f'{mp.mpf(0.12):.1g}' == '0.1'
assert f'{mp.mpf(0.012):.1g}' == '0.01'
assert f'{mp.mpf(0.0012):.1g}' == '0.001'
assert f'{mp.mpf(0.00012):.1g}' == '0.0001'
assert f'{mp.mpf(0.000012):.1g}' == '1e-05'
assert f'{mp.mpf(0.0000012):.1g}' == '1e-06'
# precision 2
assert f'{mp.mpf(1000):.2g}' == '1e+03'
assert f'{mp.mpf(100):.2g}' == '1e+02'
assert f'{mp.mpf(10):.2g}' == '10'
assert f'{mp.mpf(1):.2g}' == '1'
assert f'{mp.mpf(0.1):.2g}' == '0.1'
assert f'{mp.mpf(0.01):.2g}' == '0.01'
assert f'{mp.mpf(0.001):.2g}' == '0.001'
assert f'{mp.mpf(1e-4):.2g}' == '0.0001'
assert f'{mp.mpf(1e-5):.2g}' == '1e-05'
assert f'{mp.mpf(1e-6):.2g}' == '1e-06'
assert f'{mp.mpf(1234):.2g}' == '1.2e+03'
assert f'{mp.mpf(123):.2g}' == '1.2e+02'
assert f'{mp.mpf(12.3):.2g}' == '12'
assert f'{mp.mpf(1.23):.2g}' == '1.2'
assert f'{mp.mpf(0.123):.2g}' == '0.12'
assert f'{mp.mpf(0.0123):.2g}' == '0.012'
assert f'{mp.mpf(0.00123):.2g}' == '0.0012'
assert f'{mp.mpf(0.000123):.2g}' == '0.00012'
assert f'{mp.mpf(0.0000123):.2g}' == '1.2e-05'
# bad cases from http://bugs.python.org/issue9980
assert f'{mp.mpf(38210.0):.12g}' == '38210'
assert f'{mp.mpf(37210.0):.12g}' == '37210'
assert f'{mp.mpf(36210.0):.12g}' == '36210'
# alternate g formatting: always include decimal point and
# exactly <precision> significant digits.
assert f'{mp.mpf(0):#.0g}' == '0.'
assert f'{mp.mpf(0):#.1g}' == '0.'
assert f'{mp.mpf(0):#.2g}' == '0.0'
assert f'{mp.mpf(0):#.3g}' == '0.00'
assert f'{mp.mpf(0):#.4g}' == '0.000'
assert f'{mp.mpf(0.2):#.0g}' == '0.2'
assert f'{mp.mpf(0.2):#.1g}' == '0.2'
assert f'{mp.mpf(0.2):#.2g}' == '0.20'
assert f'{mp.mpf(0.2):#.3g}' == '0.200'
assert f'{mp.mpf(0.2):#.4g}' == '0.2000'
assert f'{mp.mpf(0.2):#.10g}' == '0.2000000000'
assert f'{mp.mpf(2):#.0g}' == '2.'
assert f'{mp.mpf(2):#.1g}' == '2.'
assert f'{mp.mpf(2):#.2g}' == '2.0'
assert f'{mp.mpf(2):#.3g}' == '2.00'
assert f'{mp.mpf(2):#.4g}' == '2.000'
assert f'{mp.mpf(20):#.0g}' == '2.e+01'
assert f'{mp.mpf(20):#.1g}' == '2.e+01'
assert f'{mp.mpf(20):#.2g}' == '20.'
assert f'{mp.mpf(20):#.3g}' == '20.0'
assert f'{mp.mpf(20):#.4g}' == '20.00'
assert f'{mp.mpf(234.56):#.0g}' == '2.e+02'
assert f'{mp.mpf(234.56):#.1g}' == '2.e+02'
assert f'{mp.mpf(234.56):#.2g}' == '2.3e+02'
assert f'{mp.mpf(234.56):#.3g}' == '235.'
assert f'{mp.mpf(234.56):#.4g}' == '234.6'
assert f'{mp.mpf(234.56):#.5g}' == '234.56'
assert f'{mp.mpf(234.56):#.6g}' == '234.560'
# '%' code formatting.
# nan, infs
assert f'{inf:%}' == 'inf%'
assert f'{inf:+%}' == '+inf%'
assert f'{ninf:%}' == '-inf%'
assert f'{ninf:+%}' == '-inf%'
assert f'{nan:%}' == 'nan%'
assert f'{nan:+%}' == '+nan%'
# No formatting code.
assert f'{mp.mpf(0.0):.0}' == '0e+00'
assert f'{mp.pi}' == '3.14159265358979'
mp.pretty_dps = 'repr'
assert f'{mp.pi}' == '3.1415926535897931'
@given(fmt_str(types=list('fFeEgG%') + ['']),
st.floats(allow_nan=True,
allow_infinity=True,
allow_subnormal=True))
@example(fmt='.0g', x=9.995074823339339e-05) # issue 880
@example(fmt='.016f', x=0.1) # issue 915
@example(fmt='0030f', x=0.3)
@example(fmt='0=13,f', x=1.1) # issue 917
@example(fmt='013,f', x=1.1)
@example(fmt='013,.0%', x=1.1)
@example(fmt='010.6,f', x=0.1234567891)
@example(fmt='010.7,f', x=0.1234567891)
@example(fmt='010._f', x=0.1234567891)
def test_mpf_floats_bulk(fmt, x):
'''
These are additional random tests that check that mp.mpf and fp.mpf yield
the same results for default precision.
'''
mp.pretty_dps = "repr"
if not x and math.copysign(1, x) == -1:
return # skip negative zero
spec = read_format_spec(fmt)
if spec['frac_separators'] and sys.version_info < (3, 14):
mp.pretty_dps = "str"
return # see also python/cpython#130860
if not spec['type'] and spec['precision'] < 0 and math.isfinite(x):
# The mpmath could choose a different decimal
# representative (wrt CPython) for same binary
# floating-point number.
assert float(format(x)) == float(format(mp.mpf(x)))
else:
if spec['type'] == '%' and math.isinf(100*x):
return # mpf can't overflow
assert format(x, fmt) == format(mp.mpf(x), fmt)
@given(fmt_str(types=list('gGfFeE') + [''], for_complex=True),
st.complex_numbers(allow_nan=True,
allow_infinity=True,
allow_subnormal=True))
def test_mpc_complexes(fmt, z):
mp.pretty_dps = "repr"
if ((not z.real and math.copysign(1, z.real) == -1)
or (not z.imag and math.copysign(1, z.imag) == -1)):
return # skip negative zero
spec = read_format_spec(fmt)
if spec['frac_separators'] and sys.version_info < (3, 14):
return # see also python/cpython#130860
if spec['precision'] < 0 and any(math.isfinite(_) for _ in [z.real, z.imag]):
# The mpmath could choose a different decimal
# representative (wrt CPython) for same binary
# floating-point number.
if cmath.isnan(complex(format(z))):
assert cmath.isnan(complex(format(mp.mpc(z))))
else:
assert complex(format(z)) == complex(format(mp.mpc(z)))
else:
assert format(z, fmt) == format(mp.mpc(z), fmt)
def test_mpc_fmt():
pytest.raises(ValueError, lambda: f'{mp.mpc(1j):=10f}')
pytest.raises(ValueError, lambda: f'{mp.mpc(1j):010f}')
pytest.raises(ValueError, lambda: f'{mp.mpc(1j):%}')
assert f'{1+1j:.0g}' == f'{mp.mpc(1+1j):.0g}'
assert f'{1+1.1j:.2g}' == f'{mp.mpc(1+1.1j):.2g}'
def test_mpf_fmt():
'''
These tests are either specific tests to mpf, or tests that cover
code that is not covered in the CPython tests.
'''
with workdps(1000):
# Numbers with more than 15 significant digits
# fixed format
assert f"{mp.mpf('1.234567890123456789'):.20f}" == '1.23456789012345678900'
assert f"{mp.mpf('1.234567890123456789'):.25f}" == '1.2345678901234567890000000'
assert f"{mp.mpf('1.234567890123456789'):.30f}" == '1.234567890123456789000000000000'
assert f"{mp.mpf('1e-50'):.50f}" == '0.00000000000000000000000000000000000000000000000001'
# scientific notation
assert f"{mp.mpf('1.234567890123456789'):.20e}" == '1.23456789012345678900e+00'
assert f"{mp.mpf('1.234567890123456789'):.25e}" == '1.2345678901234567890000000e+00'
assert f"{mp.mpf('1.234567890123456789'):.30e}" == '1.234567890123456789000000000000e+00'
assert f"{mp.mpf('1e-50'):.50e}" == '1.00000000000000000000000000000000000000000000000000e-50'
# width and fill char
assert f"{mp.mpf('0.01'):z<10.5f}" == '0.01000zzz'
assert f"{mp.mpf('0.01'):z^10.5f}" == 'z0.01000zz'
assert f"{mp.mpf('0.01'):z>10.5f}" == 'zzz0.01000'
assert f"{mp.mpf('0.01'):z=10.5f}" == 'zzz0.01000'
assert f"{mp.mpf('0.01'):z<+10.5f}" == '+0.01000zz'
assert f"{mp.mpf('0.01'):z^+10.5f}" == 'z+0.01000z'
assert f"{mp.mpf('0.01'):z>+10.5f}" == 'zz+0.01000'
assert f"{mp.mpf('0.01'):z=+10.5f}" == '+zz0.01000'
assert f"{mp.mpf('-0.01'):z<10.5f}" == '-0.01000zz'
assert f"{mp.mpf('-0.01'):z^10.5f}" == 'z-0.01000z'
assert f"{mp.mpf('-0.01'):z>10.5f}" == 'zz-0.01000'
assert f"{mp.mpf('-0.01'):z=10.5f}" == '-zz0.01000'
assert f"{mp.mpf('0.01'):z<15.5e}" == '1.00000e-02zzzz'
assert f"{mp.mpf('0.01'):z^15.5e}" == 'zz1.00000e-02zz'
assert f"{mp.mpf('0.01'):z>15.5e}" == 'zzzz1.00000e-02'
assert f"{mp.mpf('0.01'):z=15.5e}" == 'zzzz1.00000e-02'
assert f"{mp.mpf('0.01'):z<+15.5e}" == '+1.00000e-02zzz'
assert f"{mp.mpf('0.01'):z^+15.5e}" == 'z+1.00000e-02zz'
assert f"{mp.mpf('0.01'):z>+15.5e}" == 'zzz+1.00000e-02'
assert f"{mp.mpf('0.01'):z=+15.5e}" == '+zzz1.00000e-02'
assert f"{mp.mpf('-0.01'):z<15.5e}" == '-1.00000e-02zzz'
assert f"{mp.mpf('-0.01'):z^15.5e}" == 'z-1.00000e-02zz'
assert f"{mp.mpf('-0.01'):z>15.5e}" == 'zzz-1.00000e-02'
assert f"{mp.mpf('-0.01'):z=15.5e}" == '-zzz1.00000e-02'
# capitalized scientific notation
assert f"{mp.mpf('-0.01'):z<15.5E}" == '-1.00000E-02zzz'
# generalized format
assert f"{mp.mpf('1.234567890123456789'):.20g}" == '1.234567890123456789'
assert f"{mp.mpf('1.234567890123456789'):.25g}" == '1.234567890123456789'
assert f"{mp.mpf('1.234567890123456789'):.30g}" == '1.234567890123456789'
assert f"{mp.mpf('1e-50'):.50g}" == '1e-50'
assert f"{mp.mpf('1e-50'):.50G}" == '1E-50'
assert f"{mp.mpf('1e-51'):}" == '1e-51'
# thousands separator
assert f"{mp.mpf('1e9'):,.0f}" == '1,000,000,000'
assert f"{mp.mpf('123456789.0123456'):,.4f}" == '123,456,789.0123'
assert f"{mp.mpf('1234567890.123456'):_.4f}" == '1_234_567_890.1235'
assert f"{mp.mpf('1234.5678'):_.4f}" == '1_234.5678'
assert f"{mp.mpf('1e9'):,.0e}" == '1e+09'
assert f"{mp.mpf('123456789.0123456'):,.4e}" == '1.2346e+08'
assert f"{mp.mpf('1234567890.123456'):_.4e}" == '1.2346e+09'
assert f"{mp.mpf('1234.5678'):_.4e}" == '1.2346e+03'
# Tests for no_neg_0
assert f"{mp.mpf('-1e-4'):,.2f}" == '-0.00'
assert f"{mp.mpf('-1e-4'):z,.2f}" == '0.00'
# Tests for = alignment
assert f"{mp.mpf('0.24'):=+20.2f}" == '+ 0.24'
assert f"{mp.mpf('0.24'):=+020.2e}" == '+000000000002.40e-01'
assert f"{mp.mpf('0.24'):=+020.2g}" == '+0000000000000000.24'
# Tests for different kinds of rounding
num = mp.mpf('-1.23456789999901234567')
assert f"{num:=.2Uf}" == "-1.23"
assert f"{num:=.2Df}" == "-1.24"
assert f"{num:=.2Zf}" == "-1.23"
assert f"{num:=.2Nf}" == "-1.23"
assert f"{num:=.2Yf}" == "-1.24"
assert f"{num:=.3Uf}" == "-1.234"
assert f"{num:=.3Df}" == "-1.235"
assert f"{num:=.3Zf}" == "-1.234"
assert f"{num:=.3Nf}" == "-1.235"
assert f"{num:=.3Yf}" == "-1.235"
assert f"{num:=.10Uf}" == "-1.2345678999"
assert f"{num:=.10Df}" == "-1.2345679000"
assert f"{num:=.10Zf}" == "-1.2345678999"
assert f"{num:=.10Nf}" == "-1.2345679000"
assert f"{num:=.10Yf}" == "-1.2345679000"
num = mp.mpf('1.23456789999901234567')
assert f"{num:=.2Uf}" == "1.24"
assert f"{num:=.2Df}" == "1.23"
assert f"{num:=.2Zf}" == "1.23"
assert f"{num:=.2Nf}" == "1.23"
assert f"{num:=.2Yf}" == "1.24"
assert f"{num:=.3Uf}" == "1.235"
assert f"{num:=.3Df}" == "1.234"
assert f"{num:=.3Zf}" == "1.234"
assert f"{num:=.3Nf}" == "1.235"
assert f"{num:=.3Yf}" == "1.235"
assert f"{num:=.10Uf}" == "1.2345679000"
assert f"{num:=.10Df}" == "1.2345678999"
assert f"{num:=.10Zf}" == "1.2345678999"
assert f"{num:=.10Nf}" == "1.2345679000"
assert f"{num:=.10Yf}" == "1.2345679000"
num = mp.mpf('-123.456789999901234567')
assert f"{num:=.2Ue}" == "-1.23e+02"
assert f"{num:=.2De}" == "-1.24e+02"
assert f"{num:=.2Ze}" == "-1.23e+02"
assert f"{num:=.2Ne}" == "-1.23e+02"
assert f"{num:=.2Ye}" == "-1.24e+02"
assert f"{num:=.3Ue}" == "-1.234e+02"
assert f"{num:=.3De}" == "-1.235e+02"
assert f"{num:=.3Ze}" == "-1.234e+02"
assert f"{num:=.3Ne}" == "-1.235e+02"
assert f"{num:=.3Ye}" == "-1.235e+02"
assert f"{num:=.10Ue}" == "-1.2345678999e+02"
assert f"{num:=.10De}" == "-1.2345679000e+02"
assert f"{num:=.10Ze}" == "-1.2345678999e+02"
assert f"{num:=.10Ne}" == "-1.2345679000e+02"
assert f"{num:=.10Ye}" == "-1.2345679000e+02"
num = mp.mpf('123456.789999901234567')
assert f"{num:=.2Ue}" == "1.24e+05"
assert f"{num:=.2De}" == "1.23e+05"
assert f"{num:=.2Ze}" == "1.23e+05"
assert f"{num:=.2Ne}" == "1.23e+05"
assert f"{num:=.2Ye}" == "1.24e+05"
assert f"{num:=.3Ue}" == "1.235e+05"
assert f"{num:=.3De}" == "1.234e+05"
assert f"{num:=.3Ze}" == "1.234e+05"
assert f"{num:=.3Ne}" == "1.235e+05"
assert f"{num:=.3Ye}" == "1.235e+05"
assert f"{num:=.10Ue}" == "1.2345679000e+05"
assert f"{num:=.10De}" == "1.2345678999e+05"
assert f"{num:=.10Ze}" == "1.2345678999e+05"
assert f"{num:=.10Ne}" == "1.2345679000e+05"
assert f"{num:=.10Ye}" == "1.2345679000e+05"
assert f"{mp.mpf('123.456'):.2Ug}" == "1.3e+02"
assert f"{mp.mpf('123.456'):.2Dg}" == "1.2e+02"
assert f"{mp.mpf('123.456'):.2Zg}" == "1.2e+02"
assert f"{mp.mpf('123.456'):.2Ng}" == "1.2e+02"
assert f"{mp.mpf('123.456'):.2Yg}" == "1.3e+02"
assert f"{mp.mpf('-123.456'):.2Ug}" == "-1.2e+02"
assert f"{mp.mpf('-123.456'):.2Dg}" == "-1.3e+02"
assert f"{mp.mpf('-123.456'):.2Zg}" == "-1.2e+02"
assert f"{mp.mpf('-123.456'):.2Ng}" == "-1.2e+02"
assert f"{mp.mpf('-123.456'):.2Yg}" == "-1.3e+02"
assert f"{mp.mpf('123.456'):.5Ug}" == "123.46"
assert f"{mp.mpf('123.456'):.5Dg}" == "123.45"
assert f"{mp.mpf('123.456'):.5Zg}" == "123.45"
assert f"{mp.mpf('123.456'):.5Ng}" == "123.46"
assert f"{mp.mpf('123.456'):.5Yg}" == "123.46"
assert f"{mp.mpf('-123.456'):.5Ug}" == "-123.45"
assert f"{mp.mpf('-123.456'):.5Dg}" == "-123.46"
assert f"{mp.mpf('-123.456'):.5Zg}" == "-123.45"
assert f"{mp.mpf('-123.456'):.5Ng}" == "-123.46"
assert f"{mp.mpf('-123.456'):.5Yg}" == "-123.46"
# Special cases were tying is relevant (cases involve exact floats)
assert f"{mp.mpf('0.25'):.1Nf}" == "0.2"
assert f"{mp.mpf('0.75'):.1Nf}" == "0.8"
num = mp.mpf('0.1')
assert f"{-num:=.2Df}" == "-0.11"
assert f"{-num:=.3Df}" == "-0.101"
assert f"{-num:=.4Df}" == "-0.1001"
assert f"{-num:=.5Df}" == "-0.10001"
assert f"{-num:=.6Df}" == "-0.100001"
assert f"{-num:=.7Df}" == "-0.1000001"
assert f"{-num:=.2De}" == "-1.01e-01"
assert f"{-num:=.3De}" == "-1.001e-01"
assert f"{-num:=.4De}" == "-1.0001e-01"
assert f"{-num:=.5De}" == "-1.00001e-01"
assert f"{-num:=.6De}" == "-1.000001e-01"
assert f"{-num:=.7De}" == "-1.0000001e-01"
assert f"{num:=.2Uf}" == "0.11"
assert f"{num:=.3Uf}" == "0.101"
assert f"{num:=.4Uf}" == "0.1001"
assert f"{num:=.5Uf}" == "0.10001"
assert f"{num:=.6Uf}" == "0.100001"
assert f"{num:=.7Uf}" == "0.1000001"
assert f"{num:=.2Ue}" == "1.01e-01"
assert f"{num:=.3Ue}" == "1.001e-01"
assert f"{num:=.4Ue}" == "1.0001e-01"
assert f"{num:=.5Ue}" == "1.00001e-01"
assert f"{num:=.6Ue}" == "1.000001e-01"
assert f"{num:=.7Ue}" == "1.0000001e-01"
num = mp.mpf('0.25')
assert f"{-num:=.2Df}" == "-0.25"
assert f"{-num:=.3Df}" == "-0.250"
assert f"{-num:=.4Df}" == "-0.2500"
assert f"{-num:=.5Df}" == "-0.25000"
assert f"{-num:=.6Df}" == "-0.250000"
assert f"{-num:=.7Df}" == "-0.2500000"
assert f"{-num:=.2De}" == "-2.50e-01"
assert f"{-num:=.3De}" == "-2.500e-01"
assert f"{-num:=.4De}" == "-2.5000e-01"
assert f"{-num:=.5De}" == "-2.50000e-01"
assert f"{-num:=.6De}" == "-2.500000e-01"
assert f"{-num:=.7De}" == "-2.5000000e-01"
assert f"{num:=.2Uf}" == "0.25"
assert f"{num:=.3Uf}" == "0.250"
assert f"{num:=.4Uf}" == "0.2500"
assert f"{num:=.5Uf}" == "0.25000"
assert f"{num:=.6Uf}" == "0.250000"
assert f"{num:=.7Uf}" == "0.2500000"
assert f"{num:=.2Ue}" == "2.50e-01"
assert f"{num:=.3Ue}" == "2.500e-01"
assert f"{num:=.4Ue}" == "2.5000e-01"
assert f"{num:=.5Ue}" == "2.50000e-01"
assert f"{num:=.6Ue}" == "2.500000e-01"
assert f"{num:=.7Ue}" == "2.5000000e-01"
# Changing the work precision changes the number printed (This is
# expected behavior)
with mp.workdps(20):
assert f"{mp.mpf('0.1'):=.4Uf}" == "0.1000"
assert f"{mp.mpf('-0.1'):=.4Df}" == "-0.1000"
def test_default_rounding():
x = mp.mpf(mp.pi)
assert f"{x:.3f}" == '3.142'
mp.rounding = 'd'
assert f"{x:.3f}" == '3.141'
mp.rounding = 'u'
assert f"{x:.3f}" == '3.142'
def test_issue_858():
for n in range(2, 15):
str_num = '0.' + (n)*'9'
fmt_str = '.' + str(n-1) + 'f'
assert format(mp.mpf(str_num), fmt_str) == format(fp.mpf(str_num), fmt_str)
assert format(mp.mpf(0.96875), '#.0g') == '1.'
def test_errors():
with pytest.raises(ValueError):
# wrong format type
f"{mp.mpf('-4'):22.15k}"
with pytest.raises(ValueError, match="Invalid format specifier '<z15.e'"):
# no precision specified after .
f"{mp.mpf('-0.01'):<z15.e}"
with pytest.raises(ValueError, match="Invalid format specifier '10.5fk'"):
f"{mp.mpf('4'):10.5fk}"
with pytest.raises(ValueError, match="Invalid format specifier '12.3 E '"):
f"{mp.mpf('4'):12.3 E }"
with pytest.raises(ValueError):
f"{mp.mpf(1):.f}"
with pytest.raises(ValueError):
f"{mp.mpf(1):._6f}"
@given(st.floats(allow_nan=True, allow_infinity=True,
allow_subnormal=False))
@example(float('nan'))
@example(float('inf'))
def test_hexadecimal_bulk(x):
if math.isnan(x):
assert math.isnan(float.fromhex(f"{mp.mpf(x):a}"))
else:
assert float.fromhex(f"{mp.mpf(x):a}") == x
try:
libc = ctypes.CDLL("libc.so.6")
except OSError:
libc = None
def float_print(d, i):
fmt = "%." + str(i) + "a\n"
a = ctypes.create_string_buffer(256)
libc.sprintf.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
libc.sprintf(a, bytes(fmt, 'utf-8'), ctypes.c_double(d))
return a.raw.decode('utf-8').split("\n")[0]
@pytest.mark.skipif(libc is None, reason='requires libc')
@given(st.floats(allow_nan=False, allow_infinity=False,
allow_subnormal=False),
st.integers(min_value=0, max_value=15))
def test_hexadecimal_with_libc_bulk(x, p):
fmt = '.' + str(p) + 'a'
x_hex = float_print(x, p)
m_hex = format(mp.mpf(x), fmt)
assert mp.mpf(m_hex) == mp.mpf(x_hex)
@given(st.floats(allow_nan=False, allow_infinity=False,
allow_subnormal=False),
st.integers(min_value=-3, max_value=15))
def test_binary_with_gmpy2_bulk(x, p):
gmpy2 = pytest.importorskip('gmpy2')
if not x and math.copysign(1, x) == -1:
return # skip negative zero
if p >= 0:
fmt = '.' + str(p) + 'b'
else:
fmt = 'b'
g_bin = format(gmpy2.mpfr(x), fmt)
m_bin = format(mp.mpf(x), fmt)
assert m_bin == g_bin
def test_binary_fmt():
x = mp.mpf(3)
assert f'{x:b}' == '1.1p+1'
assert f'{x:.2b}' == '1.10p+1'
assert f'{x:+.2b}' == '+1.10p+1'
assert f'{x:#.2b}' == '1.10p+1'
assert f'{x:.0b}' == '1p+2'
assert f'{x:#.0b}' == '1.p+2'
x = mp.mpf(0)
assert f'{x:.2b}' == '0.00p+0'
assert f'{x:b}' == '0p+0'
def test_hexadecimal_fmt():
with workdps(1000):
x = mp.mpf('1.234567890123456789')
assert f'{x:.20a}' == '0x1.3c0ca428c59fb71a4194p+0'
assert f'{x:.20A}' == '0X1.3C0CA428C59FB71A4194P+0'
assert f'{x:.0a}' == '0x1p+0'
assert f'{x:#.0a}' == '0x1.p+0'
assert f"{mp.mpf('1.234567890123456789'):+.0a}" == '+0x1p+0'
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+707
View File
@@ -0,0 +1,707 @@
import pytest
from mpmath import (altzeta, apery, barnesg, bell, bernfrac, bernoulli,
bernpoly, beta, binomial, catalan, digamma, e, euler,
eulerpoly, fac, fac2, factorial, fadd, ff, findroot, fp,
fraction, gamma, gammaprod, harmonic, hyperfac, inf, isnan,
j, log, loggamma, mp, mpc, mpf, mpmathify, nan, pi,
polyexp, polylog, primezeta, psi, rf, rgamma, sech,
secondzeta, siegelz, sinc, sqrt, stieltjes, superfac, zeta)
from mpmath.libmp import from_float, round_up
from mpmath.libmp.gammazeta import mpf_zeta_int
def test_zeta_int_bug():
assert mpf_zeta_int(0, 10) == from_float(-0.5)
@pytest.mark.parametrize('plus', [True, False])
def test_bernoulli(plus):
assert bernfrac(0, plus) == (1,1)
assert bernfrac(1, plus) == (1,2) if plus else (-1,2)
assert bernfrac(2, plus) == (1,6)
assert bernfrac(3, plus) == (0,1)
assert bernfrac(4, plus) == (-1,30)
assert bernfrac(5, plus) == (0,1)
assert bernfrac(6, plus) == (1,42)
assert bernfrac(8, plus) == (-1,30)
assert bernfrac(10, plus) == (5,66)
assert bernfrac(12, plus) == (-691,2730)
assert bernfrac(18, plus) == (43867,798)
p, q = bernfrac(228, plus)
assert p % 10**10 == 164918161
assert q == 625170
p, q = bernfrac(1000, plus)
assert p % 10**10 == 7950421099
assert q == 342999030
mp.dps = 15
assert bernoulli(0, plus) == 1
assert bernoulli(1, plus) == 0.5 if plus else -0.5
assert bernoulli(2, plus).ae(1./6)
assert bernoulli(3, plus) == 0
assert bernoulli(4, plus).ae(-1./30)
assert bernoulli(5, plus) == 0
assert bernoulli(6, plus).ae(1./42)
assert str(bernoulli(10, plus)) == '0.0757575757575758'
assert repr(bernoulli(10, plus)) == "mpf('0.07575757575757576')"
assert str(bernoulli(234, plus)) == '7.62772793964344e+267'
assert str(bernoulli(10**5, plus)) == '-5.82229431461335e+376755'
assert str(bernoulli(10**8+2, plus)) == '1.19570355039953e+676752584'
mp.dps = 50
assert str(bernoulli(10, plus)) == '0.075757575757575757575757575757575757575757575757576'
assert str(bernoulli(234, plus)) == '7.6277279396434392486994969020496121553385863373331e+267'
assert str(bernoulli(10**5, plus)) == '-5.8222943146133508236497045360612887555320691004308e+376755'
assert str(bernoulli(10**8+2, plus)) == '1.1957035503995297272263047884604346914602088317782e+676752584'
mp.dps = 1000
assert bernoulli(10, plus).ae(mpf(5)/66)
mp.dps = 50000
assert bernoulli(10, plus).ae(mpf(5)/66)
mp.dps = 15
def test_bernpoly_eulerpoly():
assert bernpoly(0,-1).ae(1)
assert bernpoly(0,0).ae(1)
assert bernpoly(0,'1/2').ae(1)
assert bernpoly(0,'3/4').ae(1)
assert bernpoly(0,1).ae(1)
assert bernpoly(0,2).ae(1)
assert bernpoly(1,-1).ae('-3/2')
assert bernpoly(1,0).ae('-1/2')
assert bernpoly(1,'1/2').ae(0)
assert bernpoly(1,'3/4').ae('1/4')
assert bernpoly(1,1).ae('1/2')
assert bernpoly(1,2).ae('3/2')
assert bernpoly(2,-1).ae('13/6')
assert bernpoly(2,0).ae('1/6')
assert bernpoly(2,'1/2').ae('-1/12')
assert bernpoly(2,'3/4').ae('-1/48')
assert bernpoly(2,1).ae('1/6')
assert bernpoly(2,2).ae('13/6')
assert bernpoly(3,-1).ae(-3)
assert bernpoly(3,0).ae(0)
assert bernpoly(3,'1/2').ae(0)
assert bernpoly(3,'3/4').ae('-3/64')
assert bernpoly(3,1).ae(0)
assert bernpoly(3,2).ae(3)
assert bernpoly(4,-1).ae('119/30')
assert bernpoly(4,0).ae('-1/30')
assert bernpoly(4,'1/2').ae('7/240')
assert bernpoly(4,'3/4').ae('7/3840')
assert bernpoly(4,1).ae('-1/30')
assert bernpoly(4,2).ae('119/30')
assert bernpoly(5,-1).ae(-5)
assert bernpoly(5,0).ae(0)
assert bernpoly(5,'1/2').ae(0)
assert bernpoly(5,'3/4').ae('25/1024')
assert bernpoly(5,1).ae(0)
assert bernpoly(5,2).ae(5)
assert bernpoly(10,-1).ae('665/66')
assert bernpoly(10,0).ae('5/66')
assert bernpoly(10,'1/2').ae('-2555/33792')
assert bernpoly(10,'3/4').ae('-2555/34603008')
assert bernpoly(10,1).ae('5/66')
assert bernpoly(10,2).ae('665/66')
assert bernpoly(11,-1).ae(-11)
assert bernpoly(11,0).ae(0)
assert bernpoly(11,'1/2').ae(0)
assert bernpoly(11,'3/4').ae('-555731/4194304')
assert bernpoly(11,1).ae(0)
assert bernpoly(11,2).ae(11)
assert eulerpoly(0,-1).ae(1)
assert eulerpoly(0,0).ae(1)
assert eulerpoly(0,'1/2').ae(1)
assert eulerpoly(0,'3/4').ae(1)
assert eulerpoly(0,1).ae(1)
assert eulerpoly(0,2).ae(1)
assert eulerpoly(1,-1).ae('-3/2')
assert eulerpoly(1,0).ae('-1/2')
assert eulerpoly(1,'1/2').ae(0)
assert eulerpoly(1,'3/4').ae('1/4')
assert eulerpoly(1,1).ae('1/2')
assert eulerpoly(1,2).ae('3/2')
assert eulerpoly(2,-1).ae(2)
assert eulerpoly(2,0).ae(0)
assert eulerpoly(2,'1/2').ae('-1/4')
assert eulerpoly(2,'3/4').ae('-3/16')
assert eulerpoly(2,1).ae(0)
assert eulerpoly(2,2).ae(2)
assert eulerpoly(3,-1).ae('-9/4')
assert eulerpoly(3,0).ae('1/4')
assert eulerpoly(3,'1/2').ae(0)
assert eulerpoly(3,'3/4').ae('-11/64')
assert eulerpoly(3,1).ae('-1/4')
assert eulerpoly(3,2).ae('9/4')
assert eulerpoly(4,-1).ae(2)
assert eulerpoly(4,0).ae(0)
assert eulerpoly(4,'1/2').ae('5/16')
assert eulerpoly(4,'3/4').ae('57/256')
assert eulerpoly(4,1).ae(0)
assert eulerpoly(4,2).ae(2)
assert eulerpoly(5,-1).ae('-3/2')
assert eulerpoly(5,0).ae('-1/2')
assert eulerpoly(5,'1/2').ae(0)
assert eulerpoly(5,'3/4').ae('361/1024')
assert eulerpoly(5,1).ae('1/2')
assert eulerpoly(5,2).ae('3/2')
assert eulerpoly(10,-1).ae(2)
assert eulerpoly(10,0).ae(0)
assert eulerpoly(10,'1/2').ae('-50521/1024')
assert eulerpoly(10,'3/4').ae('-36581523/1048576')
assert eulerpoly(10,1).ae(0)
assert eulerpoly(10,2).ae(2)
assert eulerpoly(11,-1).ae('-699/4')
assert eulerpoly(11,0).ae('691/4')
assert eulerpoly(11,'1/2').ae(0)
assert eulerpoly(11,'3/4').ae('-512343611/4194304')
assert eulerpoly(11,1).ae('-691/4')
assert eulerpoly(11,2).ae('699/4')
# Potential accuracy issues
assert bernpoly(10000,10000).ae('5.8196915936323387117e+39999')
assert bernpoly(200,17.5).ae(3.8048418524583064909e244)
assert eulerpoly(200,17.5).ae(-3.7309911582655785929e275)
def test_gamma():
assert gamma(0.25).ae(3.6256099082219083119)
assert gamma(0.0001).ae(9999.4228832316241908)
assert gamma(300).ae('1.0201917073881354535e612')
assert gamma(-0.5).ae(-3.5449077018110320546)
assert gamma(-7.43).ae(0.00026524416464197007186)
#assert gamma(Rational(1,2)) == gamma(0.5)
#assert gamma(Rational(-7,3)).ae(gamma(mpf(-7)/3))
assert gamma(1+1j).ae(0.49801566811835604271 - 0.15494982830181068512j)
assert gamma(-1+0.01j).ae(-0.422733904013474115 + 99.985883082635367436j)
assert gamma(20+30j).ae(-1453876687.5534810 + 1163777777.8031573j)
# Should always give exact factorials when they can
# be represented as mpfs under the current working precision
fact = 1
for i in range(1, 18):
assert gamma(i) == fact
fact *= i
for dps in [170, 600]:
fact = 1
mp.dps = dps
for i in range(1, 105):
assert gamma(i) == fact
fact *= i
mp.dps = 100
assert gamma(0.5).ae(sqrt(pi))
mp.dps = 15
assert factorial(0) == fac(0) == 1
assert factorial(3) == 6
assert isnan(gamma(nan))
assert gamma(1100).ae('4.8579168073569433667e2866')
assert rgamma(0) == 0
assert rgamma(-1) == 0
assert rgamma(2) == 1.0
assert rgamma(3) == 0.5
assert loggamma(2+8j).ae(-8.5205176753667636926 + 10.8569497125597429366j)
assert loggamma('1e10000').ae('2.302485092994045684017991e10004')
assert loggamma('1e10000j').ae(mpc('-1.570796326794896619231322e10000','2.302485092994045684017991e10004'))
def test_fac2():
assert [fac2(n) for n in range(10)] == [1,1,2,3,8,15,48,105,384,945]
assert fac2(-5).ae(1./3)
assert fac2(-11).ae(-1./945)
assert fac2(50).ae(5.20469842636666623e32)
assert fac2(0.5+0.75j).ae(0.81546769394688069176-0.34901016085573266889j)
assert fac2(inf) == inf
assert isnan(fac2(-inf))
def test_gamma_quotients():
h = 1e-8
ep = 1e-4
G = gamma
assert gammaprod([-1],[-3,-4]) == 0
assert gammaprod([-1,0],[-5]) == inf
assert abs(gammaprod([-1],[-2]) - G(-1+h)/G(-2+h)) < 1e-4
assert abs(gammaprod([-4,-3],[-2,0]) - G(-4+h)*G(-3+h)/G(-2+h)/G(0+h)) < 1e-4
assert rf(3,0) == 1
assert rf(2.5,1) == 2.5
assert rf(-5,2) == 20
assert rf(j,j).ae(gamma(2*j)/gamma(j))
assert rf('-255.5815971722918','-0.5119253100282322').ae('-0.1952720278805729485') # issue 421
assert ff(-2,0) == 1
assert ff(-2,1) == -2
assert ff(4,3) == 24
assert ff(3,4) == 0
assert binomial(0,0) == 1
assert binomial(1,0) == 1
assert binomial(0,-1) == 0
assert binomial(3,2) == 3
assert binomial(5,2) == 10
assert binomial(5,3) == 10
assert binomial(5,5) == 1
assert binomial(-1,0) == 1
assert binomial(-2,-4) == 3
assert binomial(4.5, 1.5) == 6.5625
assert binomial(1100,1) == 1100
assert binomial(1100,2) == 604450
assert beta(1,1) == 1
assert beta(0,0) == inf
assert beta(3,0) == inf
assert beta(-1,-1) == inf
assert beta(1.5,1).ae(2/3.)
assert beta(1.5,2.5).ae(pi/16)
assert (10**15*beta(10,100)).ae(2.3455339739604649879)
assert beta(inf,inf) == 0
assert isnan(beta(-inf,inf))
assert isnan(beta(-3,inf))
assert isnan(beta(0,inf))
assert beta(inf,0.5) == beta(0.5,inf) == 0
assert beta(inf,-1.5) == inf
assert beta(inf,-0.5) == -inf
assert beta(1+2j,-1-j/2).ae(1.16396542451069943086+0.08511695947832914640j)
assert beta(-0.5,0.5) == 0
assert beta(-3,3).ae(-1/3.)
assert beta('-255.5815971722918','-0.5119253100282322').ae('18.157330562703710339') # issue 421
def test_zeta():
assert zeta(2).ae(pi**2 / 6)
assert zeta(2.0).ae(pi**2 / 6)
assert zeta(mpc(2)).ae(pi**2 / 6)
assert zeta(100).ae(1)
assert zeta(0).ae(-0.5)
assert zeta(0.5).ae(-1.46035450880958681)
assert zeta(-1).ae(-mpf(1)/12)
assert zeta(-2) == 0
assert zeta(-3).ae(mpf(1)/120)
assert zeta(-4) == 0
assert zeta(-100) == 0
assert isnan(zeta(nan))
assert zeta(1e-30).ae(-0.5)
assert zeta(-1e-30).ae(-0.5)
# Zeros in the critical strip
assert zeta(mpc(0.5, 14.1347251417346937904)).ae(0)
assert zeta(mpc(0.5, 21.0220396387715549926)).ae(0)
assert zeta(mpc(0.5, 25.0108575801456887632)).ae(0)
assert zeta(mpc(1e-30,1e-40)).ae(-0.5)
assert zeta(mpc(-1e-30,1e-40)).ae(-0.5)
mp.dps = 50
im = '236.5242296658162058024755079556629786895294952121891237'
assert zeta(mpc(0.5, im)).ae(0, 1e-46)
mp.dps = 15
# Complex reflection formula
assert (zeta(-60+3j) / 10**34).ae(8.6270183987866146+15.337398548226238j)
# issue #358
assert zeta(0,0.5) == 0
assert zeta(0,0) == 0.5
assert zeta(0,0.5,1).ae(-0.34657359027997265)
# see issue #390
assert zeta(-1.5,0.5j).ae(-0.13671400162512768475 + 0.11411333638426559139j)
def test_altzeta():
assert altzeta(-2) == 0
assert altzeta(-4) == 0
assert altzeta(-100) == 0
assert altzeta(0) == 0.5
assert altzeta(-1) == 0.25
assert altzeta(-3) == -0.125
assert altzeta(-5) == 0.25
assert altzeta(-21) == 1180529130.25
assert altzeta(1).ae(log(2))
assert altzeta(2).ae(pi**2/12)
assert altzeta(10).ae(73*pi**10/6842880)
assert altzeta(50) < 1
assert altzeta(60, rounding='d') < 1
assert altzeta(60, rounding='u') == 1
assert altzeta(10000, rounding='d') < 1
assert altzeta(10000, rounding='u') == 1
assert altzeta(3+0j) == altzeta(3)
s = 3+4j
assert altzeta(s).ae((1-2**(1-s))*zeta(s))
s = -3+4j
assert altzeta(s).ae((1-2**(1-s))*zeta(s))
assert altzeta(-100.5).ae(4.58595480083585913e+108)
assert altzeta(1.3).ae(0.73821404216623045)
assert altzeta(1e-30).ae(0.5)
assert altzeta(-1e-30).ae(0.5)
assert altzeta(mpc(1e-30,1e-40)).ae(0.5)
assert altzeta(mpc(-1e-30,1e-40)).ae(0.5)
def test_zeta_huge():
assert zeta(inf) == 1
mp.dps = 50
assert zeta(100).ae('1.0000000000000000000000000000007888609052210118073522')
assert zeta(40*pi).ae('1.0000000000000000000000000000000000000148407238666182')
mp.dps = 10000
v = zeta(33000)
mp.dps = 15
assert str(v-1) == '1.02363019598118e-9934'
assert zeta(pi*1000, rounding=round_up) > 1
assert zeta(3000, rounding=round_up) > 1
assert zeta(pi*1000) == 1
assert zeta(3000) == 1
def test_zeta_negative():
mp.dps = 150
a = -pi*10**40
mp.dps = 15
assert str(zeta(a)) == '2.55880492708712e+1233536161668617575553892558646631323374078'
mp.dps = 50
assert str(zeta(a)) == '2.5588049270871154960875033337384432038436330847333e+1233536161668617575553892558646631323374078'
def test_polygamma():
psi0 = lambda z: psi(0,z)
psi1 = lambda z: psi(1,z)
assert psi0(3) == psi(0,3) == digamma(3)
#assert psi2(3) == psi(2,3) == tetragamma(3)
#assert psi3(3) == psi(3,3) == pentagamma(3)
assert psi0(pi).ae(0.97721330794200673)
assert psi0(-pi).ae(7.8859523853854902)
assert psi0(-pi+1).ae(7.5676424992016996)
assert psi0(pi+j).ae(1.04224048313859376 + 0.35853686544063749j)
assert psi0(-pi-j).ae(1.3404026194821986 - 2.8824392476809402j)
assert findroot(psi0, 1).ae(1.4616321449683622)
assert psi0(1e-10).ae(-10000000000.57722)
assert psi0(1e-40).ae(-1.000000000000000e+40)
assert psi0(1e-10+1e-10j).ae(-5000000000.577215 + 5000000000.000000j)
assert psi0(1e-40+1e-40j).ae(-5.000000000000000e+39 + 5.000000000000000e+39j)
assert psi0(inf) == inf
assert psi1(inf) == 0
assert psi(2,inf) == 0
assert psi1(pi).ae(0.37424376965420049)
assert psi1(-pi).ae(53.030438740085385)
assert psi1(pi+j).ae(0.32935710377142464 - 0.12222163911221135j)
assert psi1(-pi-j).ae(-0.30065008356019703 + 0.01149892486928227j)
assert (10**6*psi(4,1+10*pi*j)).ae(-6.1491803479004446 - 0.3921316371664063j)
assert psi0(1+10*pi*j).ae(3.4473994217222650 + 1.5548808324857071j)
assert isnan(psi0(nan))
assert isnan(psi0(-inf))
assert psi0(-100.5).ae(4.615124601338064)
assert psi0(3+0j).ae(psi0(3))
assert psi0(-100+3j).ae(4.6106071768714086321+3.1117510556817394626j)
assert isnan(psi(2,mpc(0,inf)))
assert isnan(psi(2,mpc(0,nan)))
assert isnan(psi(2,mpc(0,-inf)))
assert isnan(psi(2,mpc(1,inf)))
assert isnan(psi(2,mpc(1,nan)))
assert isnan(psi(2,mpc(1,-inf)))
assert isnan(psi(2,mpc(inf,inf)))
assert isnan(psi(2,mpc(nan,nan)))
assert isnan(psi(2,mpc(-inf,-inf)))
mp.dps = 30
# issue #534
assert digamma(-0.75+1j).ae(mpc('0.46317279488182026118963809283042317', '2.4821070143037957102007677817351115'))
# issue #647
mp.prec = 42
assert digamma(-0.5+0.5j).ae(mpc('0.131892637354523', '2.44065951997751'))
mp.prec = 53
assert digamma(1e300+1j).ae(690.77552789821368)
def test_polygamma_high_prec():
mp.dps = 100
assert str(psi(0,pi)) == "0.9772133079420067332920694864061823436408346099943256380095232865318105924777141317302075654362928734"
assert str(psi(10,pi)) == "-12.98876181434889529310283769414222588307175962213707170773803550518307617769657562747174101900659238"
def test_polygamma_identities():
psi0 = lambda z: psi(0,z)
psi1 = lambda z: psi(1,z)
psi2 = lambda z: psi(2,z)
assert psi0(0.5).ae(-euler-2*log(2))
assert psi0(1).ae(-euler)
assert psi1(0.5).ae(0.5*pi**2)
assert psi1(1).ae(pi**2/6)
assert psi1(0.25).ae(pi**2 + 8*catalan)
assert psi2(1).ae(-2*apery)
mp.dps = 20
u = -182*apery+4*sqrt(3)*pi**3
mp.dps = 15
assert psi(2,5/6.).ae(u)
assert psi(3,0.5).ae(pi**4)
def test_foxtrot_identity():
# A test of the complex digamma function.
# See http://mathworld.wolfram.com/FoxTrotSeries.html and
# http://mathworld.wolfram.com/DigammaFunction.html
psi0 = lambda z: psi(0,z)
mp.dps = 50
a = (-1)**fraction(1,3)
b = (-1)**fraction(2,3)
x = -psi0(0.5*a) - psi0(-0.5*b) + psi0(0.5*(1+a)) + psi0(0.5*(1-b))
y = 2*pi*sech(0.5*sqrt(3)*pi)
assert x.ae(y)
def test_polygamma_high_order():
mp.dps = 100
assert str(psi(50, pi)) == "-1344100348958402765749252447726432491812.641985273160531055707095989227897753035823152397679626136483"
assert str(psi(50, pi + 14*e)) == "-0.00000000000000000189793739550804321623512073101895801993019919886375952881053090844591920308111549337295143780341396"
assert str(psi(50, pi + 14*e*j)) == ("(-0.0000000000000000522516941152169248975225472155683565752375889510631513244785"
"9377385233700094871256507814151956624433 - 0.00000000000000001813157041407010184"
"702414110218205348527862196327980417757665282244728963891298080199341480881811613j)")
mp.dps = 15
assert str(psi(50, pi)) == "-1.34410034895841e+39"
assert str(psi(50, pi + 14*e)) == "-1.89793739550804e-18"
assert str(psi(50, pi + 14*e*j)) == "(-5.2251694115217e-17 - 1.81315704140701e-17j)"
def test_harmonic():
assert harmonic(0) == 0
assert harmonic(1) == 1
assert harmonic(2) == 1.5
assert harmonic(3).ae(1. + 1./2 + 1./3)
assert harmonic(10**10).ae(23.603066594891989701)
assert harmonic(10**1000).ae(2303.162308658947)
assert harmonic(0.5).ae(2-2*log(2))
assert harmonic(inf) == inf
assert harmonic(2+0j) == 1.5+0j
assert harmonic(1+2j).ae(1.4918071802755104+0.92080728264223022j)
def test_gamma_huge_1():
mp.dps = 500
x = mpf(10**10) / 7
mp.dps = 15
assert str(gamma(x)) == "6.26075321389519e+12458010678"
mp.dps = 50
assert str(gamma(x)) == "6.2607532138951929201303779291707455874010420783933e+12458010678"
def test_gamma_huge_2():
mp.dps = 500
x = mpf(10**100) / 19
mp.dps = 15
assert str(gamma(x)) == (\
"1.82341134776679e+5172997469323364168990133558175077136829182824042201886051511"
"9656908623426021308685461258226190190661")
mp.dps = 50
assert str(gamma(x)) == (\
"1.82341134776678875374414910350027596939980412984e+5172997469323364168990133558"
"1750771368291828240422018860515119656908623426021308685461258226190190661")
def test_gamma_huge_3():
mp.dps = 500
x = 10**80 // 3 + 10**70*j / 7
mp.dps = 15
y = gamma(x)
assert str(y.real) == (\
"-6.82925203918106e+2636286142112569524501781477865238132302397236429627932441916"
"056964386399485392600")
assert str(y.imag) == (\
"8.54647143678418e+26362861421125695245017814778652381323023972364296279324419160"
"56964386399485392600")
mp.dps = 50
y = gamma(x)
assert str(y.real) == (\
"-6.8292520391810548460682736226799637356016538421817e+26362861421125695245017814"
"77865238132302397236429627932441916056964386399485392600")
assert str(y.imag) == (\
"8.5464714367841748507479306948130687511711420234015e+263628614211256952450178147"
"7865238132302397236429627932441916056964386399485392600")
def test_gamma_huge_4():
x = 3200+11500j
assert str(gamma(x)) == \
"(8.95783268539713e+5164 - 1.94678798329735e+5164j)"
mp.dps = 50
assert str(gamma(x)) == (\
"(8.9578326853971339570292952697675570822206567327092e+5164"
" - 1.9467879832973509568895402139429643650329524144794e+51"
"64j)")
def test_gamma_huge_5():
mp.dps = 500
x = 10**60 * j / 3
mp.dps = 15
y = gamma(x)
assert str(y.real) == "-3.27753899634941e-227396058973640224580963937571892628368354580620654233316839"
assert str(y.imag) == "-7.1519888950416e-227396058973640224580963937571892628368354580620654233316841"
mp.dps = 50
y = gamma(x)
assert str(y.real) == (\
"-3.2775389963494132168950056995974690946983219123935e-22739605897364022458096393"
"7571892628368354580620654233316839")
assert str(y.imag) == (\
"-7.1519888950415979749736749222530209713136588885897e-22739605897364022458096393"
"7571892628368354580620654233316841")
def test_gamma_huge_7():
mp.dps = 100
a = 3 + j/mpf(10)**1000
mp.dps = 15
y = gamma(a)
assert str(y.real) == "2.0"
# wrong
#assert str(y.imag) == "2.16735365342606e-1000"
assert str(y.imag) == "1.84556867019693e-1000"
mp.dps = 50
y = gamma(a)
assert str(y.real) == "2.0"
#assert str(y.imag) == "2.1673536534260596065418805612488708028522563689298e-1000"
assert str(y.imag) == "1.8455686701969342787869758198351951379156813281202e-1000"
def test_stieltjes():
assert stieltjes(0).ae(+euler)
mp.dps = 25
assert stieltjes(1).ae('-0.07281584548367672486058637587')
assert stieltjes(2).ae('-0.009690363192872318484530386035')
assert stieltjes(3).ae('0.002053834420303345866160046543')
assert stieltjes(4).ae('0.002325370065467300057468170178')
mp.dps = 15
assert stieltjes(1).ae(-0.07281584548367672486058637587)
assert stieltjes(2).ae(-0.009690363192872318484530386035)
assert stieltjes(3).ae(0.002053834420303345866160046543)
assert stieltjes(4).ae(0.0023253700654673000574681701775)
def test_barnesg():
assert barnesg(0) == barnesg(-1) == 0
assert [superfac(i) for i in range(8)] == [1, 1, 2, 12, 288, 34560, 24883200, 125411328000]
assert str(superfac(1000)) == '3.24570818422368e+1177245'
assert isnan(barnesg(nan))
assert isnan(superfac(nan))
assert isnan(hyperfac(nan))
assert barnesg(inf) == inf
assert superfac(inf) == inf
assert hyperfac(inf) == inf
assert isnan(superfac(-inf))
assert barnesg(0.7).ae(0.8068722730141471)
assert barnesg(2+3j).ae(-0.17810213864082169+0.04504542715447838j)
assert [hyperfac(n) for n in range(7)] == [1, 1, 4, 108, 27648, 86400000, 4031078400000]
assert [hyperfac(n) for n in range(0,-7,-1)] == [1,1,-1,-4,108,27648,-86400000]
a = barnesg(-3+0j)
assert a == 0 and isinstance(a, mpc)
a = hyperfac(-3+0j)
assert a == -4 and isinstance(a, mpc)
def test_polylog():
zs = [mpmathify(z) for z in [0, 0.5, 0.99, 4, -0.5, -4, 1j, 3+4j]]
for z in zs: assert polylog(1, z).ae(-log(1-z))
for z in zs: assert polylog(0, z).ae(z/(1-z))
for z in zs: assert polylog(-1, z).ae(z/(1-z)**2)
for z in zs: assert polylog(-2, z).ae(z*(1+z)/(1-z)**3)
for z in zs: assert polylog(-3, z).ae(z*(1+4*z+z**2)/(1-z)**4)
assert polylog(3, 7).ae(5.3192579921456754382-5.9479244480803301023j)
assert polylog(3, -7).ae(-4.5693548977219423182)
assert polylog(2, 0.9).ae(1.2997147230049587252)
assert polylog(2, -0.9).ae(-0.75216317921726162037)
assert polylog(2, 0.9j).ae(-0.17177943786580149299+0.83598828572550503226j)
assert polylog(2, 1.1).ae(1.9619991013055685931-0.2994257606855892575j)
assert polylog(2, -1.1).ae(-0.89083809026228260587)
assert polylog(2, 1.1*sqrt(j)).ae(0.58841571107611387722+1.09962542118827026011j)
assert polylog(-2, 0.9).ae(1710)
assert polylog(-2, -0.9).ae(-90/6859.)
assert polylog(3, 0.9).ae(1.0496589501864398696)
assert polylog(-3, 0.9).ae(48690)
assert polylog(-3, -4).ae(-0.0064)
assert polylog(0.5+j/3, 0.5+j/2).ae(0.31739144796565650535 + 0.99255390416556261437j)
assert polylog(3+4j,1).ae(zeta(3+4j))
assert polylog(3+4j,-1).ae(-altzeta(3+4j))
# issue 390
assert polylog(1.5, -48.910886523731889).ae(-6.272992229311817)
assert polylog(1.5, 200).ae(-8.349608319033686529 - 8.159694826434266042j)
assert polylog(-2+0j, -2).ae(mpf(1)/13.5)
assert polylog(-2+0j, 1.25).ae(-180)
def test_bell_polyexp():
# TODO: more tests for polyexp
assert (polyexp(0,1e-10)*10**10).ae(1.00000000005)
assert (polyexp(1,1e-10)*10**10).ae(1.0000000001)
assert polyexp(5,3j).ae(-607.7044517476176454+519.962786482001476087j)
assert polyexp(-1,3.5).ae(12.09537536175543444)
# bell(0,x) = 1
assert bell(0,0) == 1
assert bell(0,1) == 1
assert bell(0,2) == 1
assert bell(0,inf) == 1
assert bell(0,-inf) == 1
assert isnan(bell(0,nan))
# bell(1,x) = x
assert bell(1,4) == 4
assert bell(1,0) == 0
assert bell(1,inf) == inf
assert bell(1,-inf) == -inf
assert isnan(bell(1,nan))
# bell(2,x) = x*(1+x)
assert bell(2,-1) == 0
assert bell(2,0) == 0
# large orders / arguments
assert bell(10) == 115975
assert bell(10,1) == 115975
assert bell(10, -8) == 11054008
assert bell(5,-50) == -253087550
assert bell(50,-50).ae('3.4746902914629720259e74')
mp.dps = 80
assert bell(50,-50) == 347469029146297202586097646631767227177164818163463279814268368579055777450
assert bell(40,50) == 5575520134721105844739265207408344706846955281965031698187656176321717550
assert bell(74) == 5006908024247925379707076470957722220463116781409659160159536981161298714301202
mp.dps = 15
assert bell(10,20j) == 7504528595600+15649605360020j
# continuity of the generalization
assert bell(0.5,0).ae(sinc(pi*0.5))
def test_primezeta():
assert primezeta(0.9).ae(1.8388316154446882243 + 3.1415926535897932385j)
assert primezeta(4).ae(0.076993139764246844943)
assert primezeta(1) == inf
assert primezeta(inf) == 0
assert isnan(primezeta(nan))
def test_secondzeta():
assert secondzeta(2, 0.6).ae(0.022849870007492626)
def test_rs_zeta():
assert zeta(0.5+100000j).ae(1.0730320148577531321 + 5.7808485443635039843j)
assert zeta(0.75+100000j).ae(1.837852337251873704 + 1.9988492668661145358j)
assert zeta(0.5+1000000j, derivative=3).ae(1647.7744105852674733 - 1423.1270943036622097j)
assert zeta(1+1000000j, derivative=3).ae(3.4085866124523582894 - 18.179184721525947301j)
assert zeta(1+1000000j, derivative=1).ae(-0.10423479366985452134 - 0.74728992803359056244j)
assert zeta(0.5-1000000j, derivative=1).ae(11.636804066002521459 + 17.127254072212996004j)
# Additional sanity tests using fp arithmetic.
# Some more high-precision tests are found in the docstrings
def ae(x, y, tol=1e-6):
return abs(x-y) < tol*abs(y)
assert ae(fp.zeta(0.5-100000j), 1.0730320148577531321 - 5.7808485443635039843j)
assert ae(fp.zeta(0.75-100000j), 1.837852337251873704 - 1.9988492668661145358j)
assert ae(fp.zeta(0.5+1e6j), 0.076089069738227100006 + 2.8051021010192989554j)
assert ae(fp.zeta(0.5+1e6j, derivative=1), 11.636804066002521459 - 17.127254072212996004j)
assert ae(fp.zeta(1+1e6j), 0.94738726251047891048 + 0.59421999312091832833j)
assert ae(fp.zeta(1+1e6j, derivative=1), -0.10423479366985452134 - 0.74728992803359056244j)
assert ae(fp.zeta(0.5+100000j, derivative=1), 10.766962036817482375 - 30.92705282105996714j)
assert ae(fp.zeta(0.5+100000j, derivative=2), -119.40515625740538429 + 217.14780631141830251j)
assert ae(fp.zeta(0.5+100000j, derivative=3), 1129.7550282628460881 - 1685.4736895169690346j)
assert ae(fp.zeta(0.5+100000j, derivative=4), -10407.160819314958615 + 13777.786698628045085j)
assert ae(fp.zeta(0.75+100000j, derivative=1), -0.41742276699594321475 - 6.4453816275049955949j)
assert ae(fp.zeta(0.75+100000j, derivative=2), -9.214314279161977266 + 35.07290795337967899j)
assert ae(fp.zeta(0.75+100000j, derivative=3), 110.61331857820103469 - 236.87847130518129926j)
assert ae(fp.zeta(0.75+100000j, derivative=4), -1054.334275898559401 + 1769.9177890161596383j)
def test_siegelz():
assert siegelz(100000).ae(5.87959246868176504171)
assert siegelz(100000, derivative=2).ae(-54.1172711010126452832)
assert siegelz(100000, derivative=3).ae(-278.930831343966552538)
assert siegelz(100000+j,derivative=1).ae(678.214511857070283307-379.742160779916375413j)
def test_zeta_near_1():
# Test for a former bug in mpf_zeta and mpc_zeta
s1 = fadd(1, '1e-10', exact=True)
s2 = fadd(1, '-1e-10', exact=True)
s3 = fadd(1, '1e-10j', exact=True)
assert zeta(s1).ae(1.000000000057721566490881444e10)
assert zeta(s2).ae(-9.99999999942278433510574872e9)
z = zeta(s3)
assert z.real.ae(0.57721566490153286060)
assert z.imag.ae(-9.9999999999999999999927184e9)
mp.dps = 30
s1 = fadd(1, '1e-50', exact=True)
s2 = fadd(1, '-1e-50', exact=True)
s3 = fadd(1, '1e-50j', exact=True)
assert zeta(s1).ae('1e50')
assert zeta(s2).ae('-1e50')
z = zeta(s3)
assert z.real.ae('0.57721566490153286060651209008240243104215933593992')
assert z.imag.ae('-1e50')
def test_issue_723():
mp.dps = 16
assert zeta(-0.01 + 1000j).ae(-8.971459529241107 + 8.732179332810066j)
mp.dps = 15
def test_issue_471():
assert bernpoly(4, inf) == inf
assert bernpoly(4, mpc(inf, 0)) == mpc(inf, 0)
assert isnan(bernpoly(4, nan))
def test_issue_472():
assert bernpoly(4, mpc(inf, 1e-50)) == mpc(inf, 0)
assert mpc(inf, 2)**4 == mpc(inf, 0)
+288
View File
@@ -0,0 +1,288 @@
"""
Check that the output from irrational functions is accurate for
high-precision input, from 5 to 200 digits. The reference values were
verified with Mathematica.
"""
from mpmath import cos, e, euler, exp, log, mp, mpc, mpf, pi, sin, sqrt, tan
precs = [5, 15, 28, 35, 57, 80, 100, 150, 200]
# sqrt(3) + pi/2
a = \
"3.302847134363773912758768033145623809041389953497933538543279275605"\
"841220051904536395163599428307109666700184672047856353516867399774243594"\
"67433521615861420725323528325327484262075464241255915238845599752675"
# e + 1/euler**2
b = \
"5.719681166601007617111261398629939965860873957353320734275716220045750"\
"31474116300529519620938123730851145473473708966080207482581266469342214"\
"824842256999042984813905047895479210702109260221361437411947323431"
# sqrt(a)
sqrt_a = \
"1.817373691447021556327498239690365674922395036495564333152483422755"\
"144321726165582817927383239308173567921345318453306994746434073691275094"\
"484777905906961689902608644112196725896908619756404253109722911487"
# sqrt(a+b*i).real
sqrt_abi_real = \
"2.225720098415113027729407777066107959851146508557282707197601407276"\
"89160998185797504198062911768240808839104987021515555650875977724230130"\
"3584116233925658621288393930286871862273400475179312570274423840384"
# sqrt(a+b*i).imag
sqrt_abi_imag = \
"1.2849057639084690902371581529110949983261182430040898147672052833653668"\
"0629534491275114877090834296831373498336559849050755848611854282001250"\
"1924311019152914021365263161630765255610885489295778894976075186"
# log(a)
log_a = \
"1.194784864491089550288313512105715261520511949410072046160598707069"\
"4336653155025770546309137440687056366757650909754708302115204338077595203"\
"83005773986664564927027147084436553262269459110211221152925732612"
# log(a+b*i).real
log_abi_real = \
"1.8877985921697018111624077550443297276844736840853590212962006811663"\
"04949387789489704203167470111267581371396245317618589339274243008242708"\
"014251531496104028712866224020066439049377679709216784954509456421"
# log(a+b*i).imag
log_abi_imag = \
"1.0471204952840802663567714297078763189256357109769672185219334169734948"\
"4265809854092437285294686651806426649541504240470168212723133326542181"\
"8300136462287639956713914482701017346851009323172531601894918640"
# exp(a)
exp_a = \
"27.18994224087168661137253262213293847994194869430518354305430976149"\
"382792035050358791398632888885200049857986258414049540376323785711941636"\
"100358982497583832083513086941635049329804685212200507288797531143"
# exp(a+b*i).real
exp_abi_real = \
"22.98606617170543596386921087657586890620262522816912505151109385026"\
"40160179326569526152851983847133513990281518417211964710397233157168852"\
"4963130831190142571659948419307628119985383887599493378056639916701"
# exp(a+b*i).imag
exp_abi_imag = \
"-14.523557450291489727214750571590272774669907424478129280902375851196283"\
"3377162379031724734050088565710975758824441845278120105728824497308303"\
"6065619788140201636218705414429933685889542661364184694108251449"
# a**b
pow_a_b = \
"928.7025342285568142947391505837660251004990092821305668257284426997"\
"361966028275685583421197860603126498884545336686124793155581311527995550"\
"580229264427202446131740932666832138634013168125809402143796691154"
# (a**(a+b*i)).real
pow_a_abi_real = \
"44.09156071394489511956058111704382592976814280267142206420038656267"\
"67707916510652790502399193109819563864568986234654864462095231138500505"\
"8197456514795059492120303477512711977915544927440682508821426093455"
# (a**(a+b*i)).imag
pow_a_abi_imag = \
"27.069371511573224750478105146737852141664955461266218367212527612279886"\
"9322304536553254659049205414427707675802193810711302947536332040474573"\
"8166261217563960235014674118610092944307893857862518964990092301"
# ((a+b*i)**(a+b*i)).real
pow_abi_abi_real = \
"-0.15171310677859590091001057734676423076527145052787388589334350524"\
"8084195882019497779202452975350579073716811284169068082670778986235179"\
"0813026562962084477640470612184016755250592698408112493759742219150452"\
# ((a+b*i)**(a+b*i)).imag
pow_abi_abi_imag = \
"1.2697592504953448936553147870155987153192995316950583150964099070426"\
"4736837932577176947632535475040521749162383347758827307504526525647759"\
"97547638617201824468382194146854367480471892602963428122896045019902"
# sin(a)
sin_a = \
"-0.16055653857469062740274792907968048154164433772938156243509084009"\
"38437090841460493108570147191289893388608611542655654723437248152535114"\
"528368009465836614227575701220612124204622383149391870684288862269631"
# sin(1000*a)
sin_1000a = \
"-0.85897040577443833776358106803777589664322997794126153477060795801"\
"09151695416961724733492511852267067419573754315098042850381158563024337"\
"216458577140500488715469780315833217177634490142748614625281171216863"
# sin(a+b*i)
sin_abi_real = \
"-24.4696999681556977743346798696005278716053366404081910969773939630"\
"7149215135459794473448465734589287491880563183624997435193637389884206"\
"02151395451271809790360963144464736839412254746645151672423256977064"
sin_abi_imag = \
"-150.42505378241784671801405965872972765595073690984080160750785565810981"\
"8314482499135443827055399655645954830931316357243750839088113122816583"\
"7169201254329464271121058839499197583056427233866320456505060735"
# cos
cos_a = \
"-0.98702664499035378399332439243967038895709261414476495730788864004"\
"05406821549361039745258003422386169330787395654908532996287293003581554"\
"257037193284199198069707141161341820684198547572456183525659969145501"
cos_1000a = \
"-0.51202523570982001856195696460663971099692261342827540426136215533"\
"52686662667660613179619804463250686852463876088694806607652218586060613"\
"951310588158830695735537073667299449753951774916401887657320950496820"
# tan
tan_a = \
"0.162666873675188117341401059858835168007137819495998960250142156848"\
"639654718809412181543343168174807985559916643549174530459883826451064966"\
"7996119428949951351938178809444268785629011625179962457123195557310"
tan_abi_real = \
"6.822696615947538488826586186310162599974827139564433912601918442911"\
"1026830824380070400102213741875804368044342309515353631134074491271890"\
"467615882710035471686578162073677173148647065131872116479947620E-6"
tan_abi_imag = \
"0.9999795833048243692245661011298447587046967777739649018690797625964167"\
"1446419978852235960862841608081413169601038230073129482874832053357571"\
"62702259309150715669026865777947502665936317953101462202542168429"
def test_hp():
for dps in precs:
mp.dps = dps + 8
aa = mpf(a)
bb = mpf(b)
a1000 = 1000*mpf(a)
abi = mpc(aa, bb)
mp.dps = dps
assert (sqrt(3) + pi/2).ae(aa)
assert (e + 1/euler**2).ae(bb)
assert sqrt(aa).ae(mpf(sqrt_a))
assert sqrt(abi).ae(mpc(sqrt_abi_real, sqrt_abi_imag))
assert log(aa).ae(mpf(log_a))
assert log(abi).ae(mpc(log_abi_real, log_abi_imag))
assert exp(aa).ae(mpf(exp_a))
assert exp(abi).ae(mpc(exp_abi_real, exp_abi_imag))
assert (aa**bb).ae(mpf(pow_a_b))
assert (aa**abi).ae(mpc(pow_a_abi_real, pow_a_abi_imag))
assert (abi**abi).ae(mpc(pow_abi_abi_real, pow_abi_abi_imag))
assert sin(a).ae(mpf(sin_a))
assert sin(a1000).ae(mpf(sin_1000a))
assert sin(abi).ae(mpc(sin_abi_real, sin_abi_imag))
assert cos(a).ae(mpf(cos_a))
assert cos(a1000).ae(mpf(cos_1000a))
assert tan(a).ae(mpf(tan_a))
assert tan(abi).ae(mpc(tan_abi_real, tan_abi_imag))
# check that complex cancellation is avoided so that both
# real and imaginary parts have high relative accuracy.
# abs_eps should be 0, but has to be set to 1e-205 to pass the
# 200-digit case, probably due to slight inaccuracy in the
# precomputed input
assert (tan(abi).real).ae(mpf(tan_abi_real), abs_eps=1e-205)
assert (tan(abi).imag).ae(mpf(tan_abi_imag), abs_eps=1e-205)
mp.dps = 460
assert str(log(3))[-20:] == '02166121184001409826'
# Since str(a) can differ in the last digit from rounded a, and I want
# to compare the last digits of big numbers with the results in Mathematica,
# I made this hack to get the last 20 digits of rounded a
def last_digits(a):
r = repr(a)
s = str(a)
#dps = mp.dps
#mp.dps += 3
m = 10
r = r.replace(s[:-m],'')
r = r.replace("mpf('",'').replace("')",'')
num0 = 0
for c in r:
if c == '0':
num0 += 1
else:
break
b = float(int(r))/10**(len(r) - m)
if b >= 10**m - 0.5: # pragma: no cover
raise NotImplementedError
n = round(b)
sn = str(n)
s = s[:-m] + '0'*num0 + sn
return s[-20:]
# values checked with Mathematica
def test_log_hp():
mp.dps = 2000
a = mpf(10)**15000/3
r = log(a)
res = last_digits(r)
# Mathematica N[Log[10^15000/3], 2000]
# ...7443804441768333470331
assert res == '43804441768333470331'
# see issue 145
r = log(mpf(3)/2)
# Mathematica N[Log[3/2], 2000]
# ...69653749808140753263288
res = last_digits(r)
assert res == '53749808140753263288'
mp.dps = 10000
r = log(2)
res = last_digits(r)
# Mathematica N[Log[2], 10000]
# ...695615913401856601359655561
assert res == '13401856601359655561'
r = log(mpf(10)**10/3)
res = last_digits(r)
# Mathematica N[Log[10^10/3], 10000]
# ...587087654020631943060007154
assert res == '54020631943060007154', res
r = log(mpf(10)**100/3)
res = last_digits(r)
# Mathematica N[Log[10^100/3], 10000]
# ,,,59246336539088351652334666
assert res == '36539088351652334666', res
mp.dps += 10
a = 1 - mpf(1)/10**10
mp.dps -= 10
r = log(a)
res = last_digits(r)
# ...3310334360482956137216724048322957404
# 372167240483229574038733026370
# Mathematica N[Log[1 - 10^-10]*10^10, 10000]
# ...60482956137216724048322957404
assert res == '37216724048322957404', res
mp.dps = 10000
mp.dps += 100
a = 1 + mpf(1)/10**100
mp.dps -= 100
r = log(a)
res = last_digits(+r)
# Mathematica N[Log[1 + 10^-100]*10^10, 10030]
# ...3994733877377412241546890854692521568292338268273 10^-91
assert res == '39947338773774122415', res
def test_exp_hp():
mp.dps = 4000
r = exp(mpf(1)/10)
# IntegerPart[N[Exp[1/10] * 10^4000, 4000]]
# ...92167105162069688129
assert int(r * 10**mp.dps) % 10**20 == 92167105162069688129
+22
View File
@@ -0,0 +1,22 @@
from mpmath import e, exp, findpoly, identify, log, mp, pi, pslq, sqrt, zeta
def test_pslq():
assert pslq([3*pi+4*e/7, pi, e, log(2)]) == [7, -21, -4, 0]
assert pslq([4.9999999999999991, 1]) == [1, -5]
assert pslq([2,1]) == [1, -2]
def test_identify():
mp.dps = 20
assert identify(zeta(4), ['log(2)', 'pi**4']) == '((1/90)*pi**4)'
mp.dps = 15
assert identify(exp(5)) == 'exp(5)'
assert identify(exp(4)) == 'exp(4)'
assert identify(log(5)) == 'log(5)'
assert identify(exp(3*pi), ['pi']) == 'exp((3*pi))'
assert identify(3, full=True) == ['3', '3', '1/(1/3)', 'sqrt(9)',
'1/sqrt((1/9))', '(sqrt(12)/2)**2', '1/(sqrt(12)/6)**2']
assert identify(pi+1, {'a':+pi}) == '(1 + 1*a)'
def test_findpoly_deprecated():
assert findpoly(1+sqrt(2), 2, asc=False) == [1, -2, -1]
+453
View File
@@ -0,0 +1,453 @@
import pytest
from mpmath import inf, iv, mp, mpf, mpi, pi, sqrt, workprec
def test_interval_identity():
assert mpi(2) == mpi(2, 2)
assert mpi(2) != mpi(-2, 2)
assert not (mpi(2) != mpi(2, 2))
assert mpi(-1, 1) == mpi(-1, 1)
assert str(mpi('0.1')) == "[0.099999999999999991673, 0.10000000000000000555]"
assert repr(mpi('0.1')) == "mpi('0.099999999999999992', '0.10000000000000001')"
u = mpi(-1, 3)
assert -1 in u
assert 2 in u
assert 3 in u
assert -1.1 not in u
assert 3.1 not in u
assert mpi(-1, 3) in u
assert mpi(0, 1) in u
assert mpi(-1.1, 2) not in u
assert mpi(2.5, 3.1) not in u
w = mpi(-inf, inf)
assert mpi(-5, 5) in w
assert mpi(2, inf) in w
assert mpi(0, 2) in mpi(0, 10)
assert 3 not in mpi(-inf, 0)
def test_interval_hash():
assert hash(mpi(3)) == hash(3)
assert hash(mpi(3.25)) == hash(3.25)
assert hash(mpi(3,4)) == hash(mpi(3,4))
assert hash(iv.mpc(3)) == hash(3)
assert hash(iv.mpc(3,4)) == hash(3+4j)
assert hash(iv.mpc((1,3),(2,4))) == hash(iv.mpc((1,3),(2,4)))
def test_interval_arithmetic():
assert mpi(2) + mpi(3,4) == mpi(5,6)
assert mpi(1, 2)**2 == mpi(1, 4)
assert mpi(1) + mpi(0, 1e-50) == mpi(1, mpf('1.0000000000000002'))
x = 1 / (1 / mpi(3))
assert x.a < 3 < x.b
x = mpi(2) ** mpi(0.5)
iv.dps += 5
sq = iv.sqrt(2)
iv.dps -= 5
assert x.a < sq < x.b
assert mpi(1) / mpi(1, inf)
assert mpi(2, 3) / inf == mpi(0, 0)
assert mpi(0) / inf == 0
assert mpi(0) / 0 == mpi(-inf, inf)
assert mpi(inf) / 0 == mpi(-inf, inf)
assert mpi(0) * inf == mpi(-inf, inf)
assert 1 / mpi(2, inf) == mpi(0, 0.5)
assert str((mpi(50, 50) * mpi(-10, -10)) / 3) == \
'[-166.66666666666668561, -166.66666666666665719]'
assert mpi(0, 4) ** 3 == mpi(0, 64)
assert mpi(2,4).mid == 3
iv.dps = 30
a = mpi(iv.pi)
iv.dps = 15
b = +a
assert b.a < a.a
assert b.b > a.b
a = mpi(iv.pi)
assert a == +a
assert abs(mpi(-1,2)) == mpi(0,2)
assert abs(mpi(0.5,2)) == mpi(0.5,2)
assert abs(mpi(-3,2)) == mpi(0,3)
assert abs(mpi(-3,-0.5)) == mpi(0.5,3)
assert mpi(0) * mpi(2,3) == mpi(0)
assert mpi(2,3) * mpi(0) == mpi(0)
assert mpi(1,3).delta == 2
assert mpi(1,2) - mpi(3,4) == mpi(-3,-1)
assert mpi(-inf,0) - mpi(0,inf) == mpi(-inf,0)
assert mpi(-inf,0) - mpi(-inf,inf) == mpi(-inf,inf)
assert mpi(0,inf) - mpi(-inf,1) == mpi(-1,inf)
def test_interval_mul():
assert mpi(-1, 0) * inf == mpi(-inf, 0)
assert mpi(-1, 0) * -inf == mpi(0, inf)
assert mpi(0, 1) * inf == mpi(0, inf)
assert mpi(0, 1) * mpi(0, inf) == mpi(0, inf)
assert mpi(-1, 1) * inf == mpi(-inf, inf)
assert mpi(-1, 1) * mpi(0, inf) == mpi(-inf, inf)
assert mpi(-1, 1) * mpi(-inf, inf) == mpi(-inf, inf)
assert mpi(-inf, 0) * mpi(0, 1) == mpi(-inf, 0)
assert mpi(-inf, 0) * mpi(0, 0) * mpi(-inf, 0)
assert mpi(-inf, 0) * mpi(-inf, inf) == mpi(-inf, inf)
assert mpi(-5,0)*mpi(-32,28) == mpi(-140,160)
assert mpi(2,3) * mpi(-1,2) == mpi(-3,6)
# Should be undefined?
assert mpi(inf, inf) * 0 == mpi(-inf, inf)
assert mpi(-inf, -inf) * 0 == mpi(-inf, inf)
assert mpi(0) * mpi(-inf,2) == mpi(-inf,inf)
assert mpi(0) * mpi(-2,inf) == mpi(-inf,inf)
assert mpi(-2,inf) * mpi(0) == mpi(-inf,inf)
assert mpi(-inf,2) * mpi(0) == mpi(-inf,inf)
def test_interval_pow():
assert mpi(3)**2 == mpi(9, 9)
assert mpi(-3)**2 == mpi(9, 9)
assert mpi(-3, 1)**2 == mpi(0, 9)
assert mpi(-3, -1)**2 == mpi(1, 9)
assert mpi(-3, -1)**3 == mpi(-27, -1)
assert mpi(-3, 1)**3 == mpi(-27, 1)
assert mpi(-2, 3)**2 == mpi(0, 9)
assert mpi(-3, 2)**2 == mpi(0, 9)
assert mpi(4) ** -1 == mpi(0.25, 0.25)
assert mpi(-4) ** -1 == mpi(-0.25, -0.25)
assert mpi(4) ** -2 == mpi(0.0625, 0.0625)
assert mpi(-4) ** -2 == mpi(0.0625, 0.0625)
assert mpi(0, 1) ** inf == mpi(0, 1)
assert mpi(0, 1) ** -inf == mpi(1, inf)
assert mpi(0, inf) ** inf == mpi(0, inf)
assert mpi(0, inf) ** -inf == mpi(0, inf)
assert mpi(1, inf) ** inf == mpi(1, inf)
assert mpi(1, inf) ** -inf == mpi(0, 1)
assert mpi(2, 3) ** 1 == mpi(2, 3)
assert mpi(2, 3) ** 0 == 1
assert mpi(1,3) ** mpi(2) == mpi(1,9)
def test_interval_sqrt():
assert mpi(4) ** 0.5 == mpi(2)
def test_interval_div():
assert mpi(0.5, 1) / mpi(-1, 0) == mpi(-inf, -0.5)
assert mpi(0, 1) / mpi(0, 1) == mpi(0, inf)
assert mpi(inf, inf) / mpi(inf, inf) == mpi(0, inf)
assert mpi(inf, inf) / mpi(2, inf) == mpi(0, inf)
assert mpi(inf, inf) / mpi(2, 2) == mpi(inf, inf)
assert mpi(0, inf) / mpi(2, inf) == mpi(0, inf)
assert mpi(0, inf) / mpi(2, 2) == mpi(0, inf)
assert mpi(2, inf) / mpi(2, 2) == mpi(1, inf)
assert mpi(2, inf) / mpi(2, inf) == mpi(0, inf)
assert mpi(-4, 8) / mpi(1, inf) == mpi(-4, 8)
assert mpi(-4, 8) / mpi(0.5, inf) == mpi(-8, 16)
assert mpi(-inf, 8) / mpi(0.5, inf) == mpi(-inf, 16)
assert mpi(-inf, inf) / mpi(0.5, inf) == mpi(-inf, inf)
assert mpi(8, inf) / mpi(0.5, inf) == mpi(0, inf)
assert mpi(-8, inf) / mpi(0.5, inf) == mpi(-16, inf)
assert mpi(-4, 8) / mpi(inf, inf) == mpi(0, 0)
assert mpi(0, 8) / mpi(inf, inf) == mpi(0, 0)
assert mpi(0, 0) / mpi(inf, inf) == mpi(0, 0)
assert mpi(-inf, 0) / mpi(inf, inf) == mpi(-inf, 0)
assert mpi(-inf, 8) / mpi(inf, inf) == mpi(-inf, 0)
assert mpi(-inf, inf) / mpi(inf, inf) == mpi(-inf, inf)
assert mpi(-8, inf) / mpi(inf, inf) == mpi(0, inf)
assert mpi(0, inf) / mpi(inf, inf) == mpi(0, inf)
assert mpi(8, inf) / mpi(inf, inf) == mpi(0, inf)
assert mpi(inf, inf) / mpi(inf, inf) == mpi(0, inf)
assert mpi(-1, 2) / mpi(0, 1) == mpi(-inf, +inf)
assert mpi(0, 1) / mpi(0, 1) == mpi(0.0, +inf)
assert mpi(-1, 0) / mpi(0, 1) == mpi(-inf, 0.0)
assert mpi(-0.5, -0.25) / mpi(0, 1) == mpi(-inf, -0.25)
assert mpi(0.5, 1) / mpi(0, 1) == mpi(0.5, +inf)
assert mpi(0.5, 4) / mpi(0, 1) == mpi(0.5, +inf)
assert mpi(-1, -0.5) / mpi(0, 1) == mpi(-inf, -0.5)
assert mpi(-4, -0.5) / mpi(0, 1) == mpi(-inf, -0.5)
assert mpi(-1, 2) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(0, 1) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(-1, 0) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(-0.5, -0.25) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(0.5, 1) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(0.5, 4) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(-1, -0.5) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(-4, -0.5) / mpi(-2, 0.5) == mpi(-inf, +inf)
assert mpi(-1, 2) / mpi(-1, 0) == mpi(-inf, +inf)
assert mpi(0, 1) / mpi(-1, 0) == mpi(-inf, 0.0)
assert mpi(-1, 0) / mpi(-1, 0) == mpi(0.0, +inf)
assert mpi(-0.5, -0.25) / mpi(-1, 0) == mpi(0.25, +inf)
assert mpi(0.5, 1) / mpi(-1, 0) == mpi(-inf, -0.5)
assert mpi(0.5, 4) / mpi(-1, 0) == mpi(-inf, -0.5)
assert mpi(-1, -0.5) / mpi(-1, 0) == mpi(0.5, +inf)
assert mpi(-4, -0.5) / mpi(-1, 0) == mpi(0.5, +inf)
assert mpi(-1, 2) / mpi(0.5, 1) == mpi(-2.0, 4.0)
assert mpi(0, 1) / mpi(0.5, 1) == mpi(0.0, 2.0)
assert mpi(-1, 0) / mpi(0.5, 1) == mpi(-2.0, 0.0)
assert mpi(-0.5, -0.25) / mpi(0.5, 1) == mpi(-1.0, -0.25)
assert mpi(0.5, 1) / mpi(0.5, 1) == mpi(0.5, 2.0)
assert mpi(0.5, 4) / mpi(0.5, 1) == mpi(0.5, 8.0)
assert mpi(-1, -0.5) / mpi(0.5, 1) == mpi(-2.0, -0.5)
assert mpi(-4, -0.5) / mpi(0.5, 1) == mpi(-8.0, -0.5)
assert mpi(-1, 2) / mpi(-2, -0.5) == mpi(-4.0, 2.0)
assert mpi(0, 1) / mpi(-2, -0.5) == mpi(-2.0, 0.0)
assert mpi(-1, 0) / mpi(-2, -0.5) == mpi(0.0, 2.0)
assert mpi(-0.5, -0.25) / mpi(-2, -0.5) == mpi(0.125, 1.0)
assert mpi(0.5, 1) / mpi(-2, -0.5) == mpi(-2.0, -0.25)
assert mpi(0.5, 4) / mpi(-2, -0.5) == mpi(-8.0, -0.25)
assert mpi(-1, -0.5) / mpi(-2, -0.5) == mpi(0.25, 2.0)
assert mpi(-4, -0.5) / mpi(-2, -0.5) == mpi(0.25, 8.0)
# Should be undefined?
assert mpi(0, 0) / mpi(0, 0) == mpi(-inf, inf)
assert mpi(0, 0) / mpi(0, 1) == mpi(-inf, inf)
def test_interval_cos_sin():
cos = iv.cos
sin = iv.sin
tan = iv.tan
pi = iv.pi
# Around 0
assert cos(mpi(0)) == 1
assert sin(mpi(0)) == 0
assert cos(mpi(0,1)) == mpi(0.54030230586813965399, 1.0)
assert sin(mpi(0,1)) == mpi(0, 0.8414709848078966159)
assert cos(mpi(1,2)) == mpi(-0.4161468365471424069, 0.54030230586813976501)
assert sin(mpi(1,2)) == mpi(0.84147098480789650488, 1.0)
assert sin(mpi(1,2.5)) == mpi(0.59847214410395643824, 1.0)
assert cos(mpi(-1, 1)) == mpi(0.54030230586813965399, 1.0)
assert cos(mpi(-1, 0.5)) == mpi(0.54030230586813965399, 1.0)
assert cos(mpi(-1, 1.5)) == mpi(0.070737201667702906405, 1.0)
assert sin(mpi(-1,1)) == mpi(-0.8414709848078966159, 0.8414709848078966159)
assert sin(mpi(-1,0.5)) == mpi(-0.8414709848078966159, 0.47942553860420300538)
assert mpi(-0.8414709848078966159, 1.00000000000000002e-100) in sin(mpi(-1,1e-100))
assert mpi(-2.00000000000000004e-100, 1.00000000000000002e-100) in sin(mpi(-2e-100,1e-100))
# Same interval
assert cos(mpi(2, 2.5))
assert cos(mpi(3.5, 4)) == mpi(-0.93645668729079634129, -0.65364362086361182946)
assert cos(mpi(5, 5.5)) == mpi(0.28366218546322624627, 0.70866977429126010168)
assert mpi(0.59847214410395654927, 0.90929742682568170942) in sin(mpi(2, 2.5))
assert sin(mpi(3.5, 4)) == mpi(-0.75680249530792831347, -0.35078322768961983646)
assert sin(mpi(5, 5.5)) == mpi(-0.95892427466313856499, -0.70554032557039181306)
# Higher roots
iv.dps = 55
w = 4*10**50 + mpi(0.5)
for p in [15, 40, 80]:
iv.dps = p
assert 0 in sin(4*mpi(pi))
assert 0 in sin(4*10**50*mpi(pi))
assert 0 in cos((4+0.5)*mpi(pi))
assert 0 in cos(w*mpi(pi))
assert 1 in cos(4*mpi(pi))
assert 1 in cos(4*10**50*mpi(pi))
iv.dps = 15
assert cos(mpi(2,inf)) == mpi(-1,1)
assert sin(mpi(2,inf)) == mpi(-1,1)
assert cos(mpi(-inf,2)) == mpi(-1,1)
assert sin(mpi(-inf,2)) == mpi(-1,1)
u = tan(mpi(0.5,1))
assert mpf(u.a).ae(mp.tan(0.5))
assert mpf(u.b).ae(mp.tan(1))
v = iv.cot(mpi(0.5,1))
assert mpf(v.a).ae(mp.cot(1))
assert mpf(v.b).ae(mp.cot(0.5))
# Sanity check of evaluation at n*pi and (n+1/2)*pi
for n in range(-5,7,2):
x = iv.cos(n*iv.pi)
assert -1 in x
assert x >= -1
assert x != -1
x = iv.sin((n+0.5)*iv.pi)
assert -1 in x
assert x >= -1
assert x != -1
for n in range(-6,8,2):
x = iv.cos(n*iv.pi)
assert 1 in x
assert x <= 1
if n:
assert x != 1
x = iv.sin((n+0.5)*iv.pi)
assert 1 in x
assert x <= 1
assert x != 1
for n in range(-6,7):
x = iv.cos((n+0.5)*iv.pi)
assert x.a < 0 < x.b
x = iv.sin(n*iv.pi)
if n:
assert x.a < 0 < x.b
def test_interval_complex():
# TODO: many more tests
assert iv.mpc(2,3) == 2+3j
assert iv.mpc(2,3) != 2+4j
assert iv.mpc(2,3) != 1+3j
assert 1+3j in iv.mpc([1,2],[3,4])
assert 2+5j not in iv.mpc([1,2],[3,4])
assert iv.mpc(1,2) + 1j == 1+3j
assert iv.mpc([1,2],[2,3]) + 2+3j == iv.mpc([3,4],[5,6])
assert iv.mpc([2,4],[4,8]) / 2 == iv.mpc([1,2],[2,4])
assert iv.mpc([1,2],[2,4]) * 2j == iv.mpc([-8,-4],[2,4])
assert iv.mpc([2,4],[4,8]) / 2j == iv.mpc([2,4],[-2,-1])
assert iv.exp(2+3j).ae(mp.exp(2+3j))
assert iv.log(2+3j).ae(mp.log(2+3j))
assert (iv.mpc(2,3) ** iv.mpc(0.5,2)).ae(mp.mpc(2,3) ** mp.mpc(0.5,2))
assert 1j in (iv.mpf(-1) ** 0.5)
assert 1j in (iv.mpc(-1) ** 0.5)
assert abs(iv.mpc(0)) == 0
assert abs(iv.mpc(inf)) == inf
assert abs(iv.mpc(3,4)) == 5
assert abs(iv.mpc(4)) == 4
assert abs(iv.mpc(0,4)) == 4
assert abs(iv.mpc(0,[2,3])) == iv.mpf([2,3])
assert abs(iv.mpc(0,[-3,2])) == iv.mpf([0,3])
assert abs(iv.mpc([3,5],[4,12])) == iv.mpf([5,13])
assert abs(iv.mpc([3,5],[-4,12])) == iv.mpf([3,13])
assert iv.mpc(2,3) ** 0 == 1
assert iv.mpc(2,3) ** 1 == (2+3j)
assert iv.mpc(2,3) ** 2 == (2+3j)**2
assert iv.mpc(2,3) ** 3 == (2+3j)**3
assert iv.mpc(2,3) ** 4 == (2+3j)**4
assert iv.mpc(2,3) ** 5 == (2+3j)**5
assert iv.mpc(2,2) ** (-1) == (2+2j) ** (-1)
assert iv.mpc(2,2) ** (-2) == (2+2j) ** (-2)
assert iv.cos(2).ae(mp.cos(2))
assert iv.sin(2).ae(mp.sin(2))
with workprec(54):
assert iv.cos(2+3j).ae(mp.cos(2+3j))
assert iv.sin(2+3j).ae(mp.sin(2+3j))
def test_interval_complex_arg():
assert iv.arg(3) == 0
assert iv.arg(0) == 0
assert iv.arg([0,3]) == 0
assert iv.arg(-3).ae(pi)
assert iv.arg(2+3j).ae(iv.arg(2+3j))
z = iv.mpc([-2,-1],[3,4])
t = iv.arg(z)
assert t.a.ae(mp.arg(-1+4j))
assert t.b.ae(mp.arg(-2+3j))
z = iv.mpc([-2,1],[3,4])
t = iv.arg(z)
assert t.a.ae(mp.arg(1+3j))
assert t.b.ae(mp.arg(-2+3j))
z = iv.mpc([1,2],[3,4])
t = iv.arg(z)
assert t.a.ae(mp.arg(2+3j))
assert t.b.ae(mp.arg(1+4j))
z = iv.mpc([1,2],[-2,3])
t = iv.arg(z)
assert t.a.ae(mp.arg(1-2j))
assert t.b.ae(mp.arg(1+3j))
z = iv.mpc([1,2],[-4,-3])
t = iv.arg(z)
assert t.a.ae(mp.arg(1-4j))
assert t.b.ae(mp.arg(2-3j))
z = iv.mpc([-1,2],[-4,-3])
t = iv.arg(z)
assert t.a.ae(mp.arg(-1-3j))
assert t.b.ae(mp.arg(2-3j))
z = iv.mpc([-2,-1],[-4,-3])
t = iv.arg(z)
assert t.a.ae(mp.arg(-2-3j))
assert t.b.ae(mp.arg(-1-4j))
z = iv.mpc([-2,-1],[-3,3])
t = iv.arg(z)
assert t.a.ae(-mp.pi)
assert t.b.ae(mp.pi)
z = iv.mpc([-2,2],[-3,3])
t = iv.arg(z)
assert t.a.ae(-mp.pi)
assert t.b.ae(mp.pi)
def test_interval_ae():
x = iv.mpf([1,2])
pytest.raises(ValueError, lambda: x.ae(1))
pytest.raises(ValueError, lambda: x.ae(1.5))
pytest.raises(ValueError, lambda: x.ae(2))
assert x.ae(2.01) is False
assert x.ae(0.99) is False
x = iv.mpf(3.5)
assert x.ae(3.5) is True
assert x.ae(3.5+1e-15) is True
assert x.ae(3.5-1e-15) is True
assert x.ae(3.501) is False
assert x.ae(3.499) is False
pytest.raises(ValueError, lambda: x.ae(iv.mpf([3.5,3.501])))
pytest.raises(ValueError, lambda: x.ae(iv.mpf([3.5,4.5+1e-15])))
def test_interval_nstr():
iv.dps = n = 30
x = mpi(1, 2)
assert iv.nstr(x, n, mode='plusminus') == '1.5 +- 0.5'
assert iv.nstr(x, n, mode='plusminus', use_spaces=False) == '1.5+-0.5'
assert iv.nstr(x, n, mode='percent') == '1.5 (33.33%)'
assert iv.nstr(x, n, mode='brackets', use_spaces=False) == '[1.0,2.0]'
assert iv.nstr(x, n, mode='brackets' , brackets=('<', '>')) == '<1.0, 2.0>'
x = mpi('5.2582327113062393041', '5.2582327113062749951')
assert iv.nstr(x, n, mode='diff') == '5.2582327113062[393041, 749951]'
assert iv.nstr(iv.cos(mpi(1)), n, mode='diff', use_spaces=False) == '0.54030230586813971740093660744[2955,3053]'
assert iv.nstr(mpi('1e123', '1e129'), n, mode='diff') == '[1.0e+123, 1.0e+129]'
exp = iv.exp
assert iv.nstr(iv.exp(mpi('5000.1')), n, mode='diff') == '3.2797365856787867069110487[0926, 1191]e+2171'
assert iv.nstr(iv.mpc(3, 4)) == '([3.0, 3.0] + [4.0, 4.0]*j)'
def test_mpi_from_str():
assert iv.convert('1.5 +- 0.5') == mpi(mpf('1.0'), mpf('2.0'))
assert mpi(1, 2) in iv.convert('1.5 (33.33333333333333333333333333333%)')
assert iv.convert('[1, 2]') == mpi(1, 2)
assert iv.convert('1[2, 3]') == mpi(12, 13)
assert iv.convert('1.[23,46]e-8') == mpi('1.23e-8', '1.46e-8')
assert iv.convert('12[3.4,5.9]e4') == mpi('123.4e+4', '125.9e4')
def test_interval_gamma():
# TODO: need many more tests
assert iv.rgamma(0) == 0
assert iv.fac(0) == 1
assert iv.fac(1) == 1
assert iv.fac(2) == 2
assert iv.fac(3) == 6
assert iv.gamma(0) == [-inf,inf]
assert iv.gamma(1) == 1
assert iv.gamma(2) == 1
assert iv.gamma(3) == 2
assert -3.5449077018110320546 in iv.gamma(-0.5)
assert 0.49801566811835601-0.1549498283018107j in iv.gamma(1+1j)
assert iv.loggamma(1) == 0
assert iv.loggamma(2) == 0
assert 0.69314718055994530942 in iv.loggamma(3)
# Test tight log-gamma endpoints based on monotonicity
xs = [iv.mpc([2,3],[1,4]),
iv.mpc([2,3],[-4,-1]),
iv.mpc([2,3],[-1,4]),
iv.mpc([2,3],[-4,1]),
iv.mpc([2,3],[-4,4]),
iv.mpc([-3,-2],[2,4]),
iv.mpc([-3,-2],[-4,-2])]
for x in xs:
ys = [mp.loggamma(mp.mpc(x.a,x.c)),
mp.loggamma(mp.mpc(x.b,x.c)),
mp.loggamma(mp.mpc(x.a,x.d)),
mp.loggamma(mp.mpc(x.b,x.d))]
if 0 in x.imag:
ys += [mp.loggamma(x.a), mp.loggamma(x.b)]
min_real = min([y.real for y in ys])
max_real = max([y.real for y in ys])
min_imag = min([y.imag for y in ys])
max_imag = max([y.imag for y in ys])
z = iv.loggamma(x)
assert z.a.ae(min_real)
assert z.b.ae(max_real)
assert z.c.ae(min_imag)
assert z.d.ae(max_imag)
def test_interval_conversions():
for a, b in ((-0.0, 0), (0.0, 0.5), (1.0, 1), \
('-inf', 20.5), ('-inf', float(sqrt(2)))):
r = mpi(a, b)
assert int(r.b) == int(b)
assert float(r.a) == float(a)
assert float(r.b) == float(b)
assert complex(r.a) == complex(a)
assert complex(r.b) == complex(b)
def test_issue_258():
a = iv.mpf([0, 1])
b = 0.5
pytest.raises(ValueError, lambda: min(a, b))
pytest.raises(ValueError, lambda: max(a, b))
def test_mpi_mag():
assert iv.mag(iv.mpc(3, 4)) == 4
+149
View File
@@ -0,0 +1,149 @@
from mpmath import mp
# Attention:
# These tests run with 15-20 decimal digits precision. For higher precision the
# working precision must be raised.
def test_levin_0():
mp.dps = 17
eps = mp.mpf(mp.eps)
with mp.extraprec(2 * mp.prec):
L = mp.levin(method = "levin", variant = "u")
S, s, n = [], 0, 1
while 1:
s += mp.one / (n * n)
n += 1
S.append(s)
v, e = L.update_psum(S)
if e < eps:
break
if n > 1000: raise RuntimeError("iteration limit exceeded")
eps = mp.exp(0.9 * mp.log(eps))
err = abs(v - mp.pi ** 2 / 6)
assert err < eps
w = mp.nsum(lambda n: 1/(n * n), [1, mp.inf], method = "levin", levin_variant = "u")
err = abs(v - w)
assert err < eps
def test_levin_1():
mp.dps = 17
eps = mp.mpf(mp.eps)
with mp.extraprec(2 * mp.prec):
L = mp.levin(method = "levin", variant = "v")
A, n = [], 1
while 1:
s = mp.mpf(n) ** (2 + 3j)
n += 1
A.append(s)
v, e = L.update(A)
if e < eps:
break
if n > 1000: raise RuntimeError("iteration limit exceeded")
eps = mp.exp(0.9 * mp.log(eps))
err = abs(v - mp.zeta(-2-3j))
assert err < eps
w = mp.nsum(lambda n: n ** (2 + 3j), [1, mp.inf], method = "levin", levin_variant = "v")
err = abs(v - w)
assert err < eps
def test_levin_2():
# [2] A. Sidi - "Pratical Extrapolation Methods" p.373
mp.dps = 17
z=mp.mpf(10)
eps = mp.mpf(mp.eps)
with mp.extraprec(2 * mp.prec):
L = mp.levin(method = "sidi", variant = "t")
n = 0
while 1:
s = (-1)**n * mp.fac(n) * z ** (-n)
v, e = L.step(s)
n += 1
if e < eps:
break
if n > 1000: raise RuntimeError("iteration limit exceeded")
eps = mp.exp(0.9 * mp.log(eps))
exact = mp.quad(lambda x: mp.exp(-x)/(1+x/z),[0,mp.inf])
# there is also a symbolic expression for the integral:
# exact = z * mp.exp(z) * mp.expint(1,z)
err = abs(v - exact)
assert err < eps
w = mp.nsum(lambda n: (-1) ** n * mp.fac(n) * z ** (-n), [0, mp.inf], method = "sidi", levin_variant = "t")
assert err < eps
def test_levin_3():
mp.dps = 17
z=mp.mpf(2)
eps = mp.mpf(mp.eps)
with mp.extraprec(7*mp.prec): # we need copious amount of precision to sum this highly divergent series
L = mp.levin(method = "levin", variant = "t")
n, s = 0, 0
while 1:
s += (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n))
n += 1
v, e = L.step_psum(s)
if e < eps:
break
if n > 1000: raise RuntimeError("iteration limit exceeded")
eps = mp.exp(0.8 * mp.log(eps))
exact = mp.quad(lambda x: mp.exp( -x * x / 2 - z * x ** 4), [0,mp.inf]) * 2 / mp.sqrt(2 * mp.pi)
# there is also a symbolic expression for the integral:
# exact = mp.exp(mp.one / (32 * z)) * mp.besselk(mp.one / 4, mp.one / (32 * z)) / (4 * mp.sqrt(z * mp.pi))
err = abs(v - exact)
assert err < eps
w = mp.nsum(lambda n: (-z)**n * mp.fac(4 * n) / (mp.fac(n) * mp.fac(2 * n) * (4 ** n)), [0, mp.inf],
method = "levin", levin_variant = "t", workprec = 8*mp.prec, steps = [2] + [1 for x in range(1000)])
err = abs(v - w)
assert err < eps
def test_levin_nsum():
mp.dps = 17
with mp.extraprec(mp.prec):
z = mp.mpf(10) ** (-10)
a = mp.nsum(lambda n: n**(-(1+z)), [1, mp.inf], method = "l") - 1 / z
assert abs(a - mp.euler) < 1e-10
eps = mp.exp(0.8 * mp.log(mp.eps))
a = mp.nsum(lambda n: (-1)**(n-1) / n, [1, mp.inf], method = "sidi")
assert abs(a - mp.log(2)) < eps
z = 2 + 1j
f = lambda n: mp.rf(2 / mp.mpf(3), n) * mp.rf(4 / mp.mpf(3), n) * z**n / (mp.rf(1 / mp.mpf(3), n) * mp.fac(n))
v = mp.nsum(f, [0, mp.inf], method = "levin", steps = [10 for x in range(1000)])
exact = mp.hyp2f1(2 / mp.mpf(3), 4 / mp.mpf(3), 1 / mp.mpf(3), z)
assert abs(exact - v) < eps
def test_cohen_alt_0():
mp.dps = 17
AC = mp.cohen_alt()
S, s, n = [], 0, 1
while 1:
s += -((-1) ** n) * mp.one / (n * n)
n += 1
S.append(s)
v, e = AC.update_psum(S)
if e < mp.eps:
break
if n > 1000: raise RuntimeError("iteration limit exceeded")
eps = mp.exp(0.9 * mp.log(mp.eps))
err = abs(v - mp.pi ** 2 / 12)
assert err < eps
def test_cohen_alt_1():
mp.dps = 17
A = []
AC = mp.cohen_alt()
n = 1
while 1:
A.append( mp.loggamma(1 + mp.one / (2 * n - 1)))
A.append(-mp.loggamma(1 + mp.one / (2 * n)))
n += 1
v, e = AC.update(A)
if e < mp.eps:
break
if n > 1000: raise RuntimeError("iteration limit exceeded")
v = mp.exp(v)
err = abs(v - 1.06215090557106)
assert err < 1e-12
+380
View File
@@ -0,0 +1,380 @@
# TODO: don't use round
import pytest
from mpmath import (cond, det, diag, exp, expm, extend, extradps, eye, fp,
hilbert, inf, inverse, iv, j, lu, lu_solve, matrix, mnorm,
mp, mpc, mpf, nint, norm, pi, pinv, qr, qr_solve, rand, rank,
randmatrix, residual, zeros, absmin, eps)
# XXX: these shouldn't be visible(?)
LU_decomp = mp.LU_decomp
L_solve = mp.L_solve
U_solve = mp.U_solve
householder = mp.householder
improve_solution = mp.improve_solution
A1 = matrix([[3, 1, 6],
[2, 1, 3],
[1, 1, 1]])
b1 = [2, 7, 4]
A2 = matrix([[ 2, -1, -1, 2],
[ 6, -2, 3, -1],
[-4, 2, 3, -2],
[ 2, 0, 4, -3]])
b2 = [3, -3, -2, -1]
A3 = matrix([[ 1, 0, -1, -1, 0],
[ 0, 1, 1, 0, -1],
[ 4, -5, 2, 0, 0],
[ 0, 0, -2, 9,-12],
[ 0, 5, 0, 0, 12]])
b3 = [0, 0, 0, 0, 50]
A4 = matrix([[10.235, -4.56, 0., -0.035, 5.67],
[-2.463, 1.27, 3.97, -8.63, 1.08],
[-6.58, 0.86, -0.257, 9.32, -43.6 ],
[ 9.83, 7.39, -17.25, 0.036, 24.86],
[-9.31, 34.9, 78.56, 1.07, 65.8 ]])
b4 = [8.95, 20.54, 7.42, 5.60, 58.43]
A5 = matrix([[ 1, 2, -4],
[-2, -3, 5],
[ 3, 5, -8]])
A6 = matrix([[ 1.377360, 2.481400, 5.359190],
[ 2.679280, -1.229560, 25.560210],
[-1.225280+1.e6, 9.910180, -35.049900-1.e6]])
b6 = [23.500000, -15.760000, 2.340000]
A7 = matrix([[1, -0.5],
[2, 1],
[-2, 6]])
b7 = [3, 2, -4]
A8 = matrix([[1, 2, 3],
[-1, 0, 1],
[-1, -2, -1],
[1, 0, -1]])
b8 = [1, 2, 3, 4]
A9 = matrix([[ 4, 2, -2],
[ 2, 5, -4],
[-2, -4, 5.5]])
b9 = [10, 16, -15.5]
A10 = matrix([[1.0 + 1.0j, 2.0, 2.0],
[4.0, 5.0, 6.0],
[7.0, 8.0, 9.0]])
b10 = [1.0, 1.0 + 1.0j, 1.0]
A11 = matrix([[4, 0, -2],
[2, 0, -4],
[2, 0, 5.5]])
A12 = matrix([[1,0,0],
[0,1,0],
[0,0,1.0j]])
A13 = matrix([[2, 6, 4],
[3, 8, 6],
[1, 1, 2]])
A14 = matrix(0, 0)
def test_LU_decomp():
A = A3.copy()
b = b3
A, p = LU_decomp(A)
y = L_solve(A, b, p)
x = U_solve(A, y)
assert p == [2, 1, 2, 3]
assert [round(i, 14) for i in x] == [3.78953107960742, 2.9989094874591098,
-0.081788440567070006, 3.8713195201744801, 2.9171210468920399]
A = A4.copy()
b = b4
A, p = LU_decomp(A)
y = L_solve(A, b, p)
x = U_solve(A, y)
assert p == [0, 3, 4, 3]
assert [round(i, 14) for i in x] == [2.6383625899619201, 2.6643834462368399,
0.79208015947958998, -2.5088376454101899, -1.0567657691375001]
A = randmatrix(3)
bak = A.copy()
LU_decomp(A, overwrite=1)
assert A != bak
pytest.raises(ZeroDivisionError, LU_decomp, A11)
def test_inverse():
for A in [A1, A2, A5]:
inv = inverse(A)
assert mnorm(A*inv - eye(A.rows), 1) < 1.e-14
def test_pinv():
# Test the Moore Penrose pseudoinverse for square matrices.
for A in [A1, A2, A5]:
inv = pinv(A)
assert mnorm(A*inv - eye(A.rows), 1) < 1.e-13
# Test the Moore Penrose pseudoinverse for non-square matrices.
A = matrix([[1, 0], [0, 1], [0, 1]])
Aplus = matrix([[1, 0, 0], [0, 0.5, 0.5]])
assert mnorm(pinv(A) - Aplus, 1) < 1.e-14
# Check with non-default tolerance.
assert mnorm(pinv(A, rtol=1e-20) - Aplus, 1) < 1.e-14
def test_householder():
A, b = A8, b8
H, p, x, r = householder(extend(A, b))
assert H == matrix(
[[mpf('3.0'), mpf('-2.0'), mpf('-1.0'), 0],
[-1.0,mpf('3.333333333333333'),mpf('-2.9999999999999991'),mpf('2.0')],
[-1.0, mpf('-0.66666666666666674'),mpf('2.8142135623730948'),
mpf('-2.8284271247461898')],
[1.0, mpf('-1.3333333333333333'),mpf('-0.20000000000000018'),
mpf('4.2426406871192857')]])
assert p == [-2, -2, mpf('-1.4142135623730949')]
assert round(norm(r, 2), 10) == 4.2426406870999998
y = [102.102, 58.344, 36.463, 24.310, 17.017, 12.376, 9.282, 7.140, 5.610,
4.488, 3.6465, 3.003]
def coeff(n):
# similiar to Hilbert matrix
A = []
for i in range(1, 13):
A.append([1. / (i + j - 1) for j in range(1, n + 1)])
return matrix(A)
residuals = []
refres = []
for n in range(2, 7):
A = coeff(n)
H, p, x, r = householder(extend(A, y))
x = matrix(x)
y = matrix(y)
residuals.append(norm(r, 2))
refres.append(norm(residual(A, x, y), 2))
assert [round(res, 10) for res in residuals] == [15.1733888877,
0.82378073210000002, 0.302645887, 0.0260109244,
0.00058653999999999998]
assert norm(matrix(residuals) - matrix(refres), inf) < 1.e-13
def hilbert_cmplx(n):
# Complexified Hilbert matrix
A = hilbert(2*n,n)
v = randmatrix(2*n, 2, min=-1, max=1)
v = v.apply(lambda x: exp(1J*pi()*x))
A = diag(v[:,0])*A*diag(v[:n,1])
return A
residuals_cmplx = []
refres_cmplx = []
for n in range(2, 10):
A = hilbert_cmplx(n)
H, p, x, r = householder(A.copy())
residuals_cmplx.append(norm(r, 2))
refres_cmplx.append(norm(residual(A[:,:n-1], x, A[:,n-1]), 2))
assert norm(matrix(residuals_cmplx) - matrix(refres_cmplx), inf) < 1.e-13
def test_factorization():
A = randmatrix(5)
P, L, U = lu(A)
assert mnorm(P*A - L*U, 1) < 1.e-15
def test_solve():
assert norm(residual(A6, lu_solve(A6, b6), b6), inf) < 1.e-10
assert norm(residual(A7, lu_solve(A7, b7), b7), inf) < 1.5
assert norm(residual(A8, lu_solve(A8, b8), b8), inf) <= 3 + 1.e-10
assert norm(residual(A6, qr_solve(A6, b6)[0], b6), inf) < 1.e-10
assert norm(residual(A7, qr_solve(A7, b7)[0], b7), inf) < 1.5
assert norm(residual(A8, qr_solve(A8, b8)[0], b8), 2) <= 4.3
assert norm(residual(A10, lu_solve(A10, b10), b10), 2) < 1.e-10
assert norm(residual(A10, qr_solve(A10, b10)[0], b10), 2) < 1.e-10
def test_solve_overdet_complex():
A = matrix([[1, 2j], [3, 4j], [5, 6]])
b = matrix([1 + j, 2, -j])
assert norm(residual(A, lu_solve(A, b), b)) < 1.0208
def test_qr_solve_issue_983():
A = matrix([[1, -pi/20, (-pi/20)**2, (-pi/20)**3],
[1, 0, 0, 0],
[1, pi / 20, (pi/20)**2, (pi/20)**3],
[1, pi/10, (pi/10)**2, (pi/10)**3]])
b = matrix([[mp.sin(-pi/20)],
[0],
[mp.sin(pi/20)],
[mp.sin(pi/20)]])
x, _ = qr_solve(A, b)
assert norm(residual(A, x, b), inf) < 1e-14
def test_singular():
A = [[5.6, 1.2], [7./15, .1]]
B = repr(zeros(2))
b = [1, 2]
for i in ['lu_solve(%s, %s)' % (A, b), 'lu_solve(%s, %s)' % (B, b),
'qr_solve(%s, %s)' % (A, b), 'qr_solve(%s, %s)' % (B, b)]:
pytest.raises((ZeroDivisionError, ValueError), lambda: eval(i))
def test_cholesky():
assert fp.cholesky(fp.matrix(A9)) == fp.matrix([[2, 0, 0], [1, 2, 0], [-1, -3/2, 3/2]])
x = fp.cholesky_solve(A9, b9)
assert fp.norm(fp.residual(A9, x, b9), fp.inf) == 0
a = fp.matrix([[1, 0.5j], [-0.5j, 0.5]])
b = fp.ones(2, 1)
x = fp.cholesky_solve(a, b)
assert fp.norm(fp.residual(a, x, b), fp.inf) == 0
def test_det():
assert det(A1) == 1
assert round(det(A2), 14) == 8
assert round(det(A3)) == 1834
assert round(det(A4)) == 4443376
assert det(A5) == 1
assert round(det(A6)) == 78356463
assert det(zeros(3)) == 0
assert det(A11) == 0
assert absmin(det(A12*1e-30) - 1e-30) < eps
assert det(A14) == 1
def test_cond():
A = matrix([[1.2969, 0.8648], [0.2161, 0.1441]])
assert cond(A, lambda x: mnorm(x,1)) == mpf('327065209.73817754')
assert cond(A, lambda x: mnorm(x,inf)) == mpf('327065209.73817754')
assert cond(A, lambda x: mnorm(x,'F')) == mpf('249729266.80008656')
@extradps(50)
def test_precision():
A = randmatrix(10, 10)
assert mnorm(inverse(inverse(A)) - A, 1) < 1.e-45
def test_interval_matrix():
a = iv.matrix([['0.1','0.3','1.0'],['7.1','5.5','4.8'],['3.2','4.4','5.6']])
b = iv.matrix(['4','0.6','0.5'])
c = iv.lu_solve(a, b)
assert c[0].delta < 1e-13
assert c[1].delta < 1e-13
assert c[2].delta < 1e-13
assert 5.25823271130625686059275 in c[0]
assert -13.155049396267837541163 in c[1]
assert 7.42069154774972557628979 in c[2]
def test_LU_cache():
A = randmatrix(3)
LU = LU_decomp(A)
assert A._LU == LU_decomp(A)
A[0,0] = -1000
assert A._LU is None
def test_improve_solution():
A = randmatrix(5, min=1e-20, max=1e20)
b = randmatrix(5, 1, min=-1000, max=1000)
x1 = lu_solve(A, b) + randmatrix(5, 1, min=-1e-5, max=1.e-5)
x2 = improve_solution(A, x1, b)
assert norm(residual(A, x2, b), 2) < norm(residual(A, x1, b), 2)
def test_exp_pade():
for i in range(3):
dps = 15
extra = 15
mp.dps = dps + extra
dm = 0
N = 3
dg = range(1,N+1)
a = diag(dg)
expa = diag([exp(x) for x in dg])
# choose a random matrix not close to be singular
# to avoid adding too much extra precision in computing
# m**-1 * M * m
while abs(dm) < 0.01:
m = randmatrix(N)
dm = det(m)
m = m/dm
a1 = m**-1 * a * m
e2 = m**-1 * expa * m
mp.dps = dps
e1 = expm(a1, method='pade')
mp.dps = dps + extra
d = e2 - e1
mp.dps = dps
assert norm(d, inf).ae(0)
def test_qr():
lowlimit = -9 # lower limit of matrix element value
uplimit = 9 # uppter limit of matrix element value
maxm = 4 # max matrix size
flg = False # toggle to create real vs complex matrix
zero = mpf('0.0')
for k in range(10):
exdps = 0
mode = 'full'
flg = bool(k % 2)
# generate arbitrary matrix size (2 to maxm)
num1 = nint(maxm*rand())
num2 = nint(maxm*rand())
m = int(max(num1, num2))
n = int(min(num1, num2))
# create matrix
A = mp.matrix(m,n)
# populate matrix values with arbitrary integers
if flg:
flg = False
dtype = 'complex'
for j in range(n):
for i in range(m):
val = nint(lowlimit + (uplimit-lowlimit)*rand())
val2 = nint(lowlimit + (uplimit-lowlimit)*rand())
A[i,j] = mpc(val, val2)
else:
flg = True
dtype = 'real'
for j in range(n):
for i in range(m):
val = nint(lowlimit + (uplimit-lowlimit)*rand())
A[i,j] = mpf(val)
# perform A -> QR decomposition
Q, R = qr(A, mode, edps = exdps)
maxnorm = mpf('1.0E-11')
n1 = norm(A - Q * R)
assert n1 <= maxnorm
if dtype == 'real':
n1 = norm(eye(m) - Q.T * Q)
assert n1 <= maxnorm
n1 = norm(eye(m) - Q * Q.T)
assert n1 <= maxnorm
if dtype == 'complex':
n1 = norm(eye(m) - Q.T * Q.conjugate())
assert n1 <= maxnorm
n1 = norm(eye(m) - Q.conjugate() * Q.T)
assert n1 <= maxnorm
def test_rank():
assert rank(A1) == 3
assert rank(A2) == 4
assert rank(A3) == 5
assert rank(A4) == 5
assert rank(A5) == 3
assert rank(A6) == 3
assert rank(zeros(3)) == 0
assert rank(A11) == 2
assert rank(A1*A11) == 2
assert rank(A11*A11) == 2
iszerofunc = lambda x: not bool(x)
assert rank(A13) == 2
assert rank(A13, iszerofunc) == 3
+306
View File
@@ -0,0 +1,306 @@
import sys
import pytest
from mpmath import (convert, diag, extend, eye, fp, hilbert, inf, inverse, iv,
j, matrix, mnorm, mp, mpc, mpf, mpi, norm, nstr, ones,
randmatrix, sqrt, swap_row, zeros)
def test_matrix_basic():
A1 = matrix(3)
for i in range(3):
A1[i,i] = 1
assert A1 == eye(3)
assert A1 == matrix(A1)
A2 = matrix(3, 2)
assert not A2._data
A3 = matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
assert list(A3) == list(range(1, 10))
A3[1,1] = 0
assert (1, 1) not in A3._data
A4 = matrix([[1, 2, 3], [4, 5, 6]])
A5 = matrix([[6, -1], [3, 2], [0, -3]])
assert A4 * A5 == matrix([[12, -6], [39, -12]])
assert A1 * A3 == A3 * A1 == A3
pytest.raises(ValueError, lambda: A2*A2)
l = [[10, 20, 30], [40, 0, 60], [70, 80, 90]]
A6 = matrix(l)
assert A6.tolist() == l
assert A6 == eval(repr(A6))
A6 = fp.matrix(A6)
assert A6 == eval(repr(A6))
assert A6*1j == eval(repr(A6*1j))
assert A3 * 10 == 10 * A3 == A6
assert A2.rows == 3
assert A2.cols == 2
A3.rows = 2
A3.cols = 2
assert len(A3._data) == 3
assert A4 + A4 == 2*A4
pytest.raises(ValueError, lambda: A4 + A2)
assert sum(A1 - A1) == 0
A7 = matrix([[1, 2], [3, 4], [5, 6], [7, 8]])
x = matrix([10, -10])
assert A7*x == matrix([-10, -10, -10, -10])
A8 = ones(5)
assert sum((A8 + 1) - (2 - zeros(5))) == 0
assert (1 + ones(4)) / 2 - 1 == zeros(4)
assert eye(3)**10 == eye(3)
pytest.raises(ValueError, lambda: A7**2)
A9 = randmatrix(3)
A10 = matrix(A9)
A9[0,0] = -100
assert A9 != A10
assert nstr(A9)
assert A9 != None # issue 283
pytest.raises(IndexError, lambda: zeros(1,1)[:, 1]) # issue 318
pytest.raises(IndexError, lambda: zeros(1,1)[1, :])
A10 = matrix([[1,2], [3,4], [5,6]])
assert A10[0, -1] == 2
assert A10[-1, -1] == 6
assert A10[1, -2] == 3
assert A10[-3, -2] == 1
A10[0, -1] = 3
assert A10[0, -1] == 3
A10[-1, -1] = 4
assert A10[-1, -1] == 4
A10[1, -2] = 5
assert A10[1, -2] == 5
A10[-3, -2] = 1
assert A10[-3, -2] == 1
pytest.raises(ValueError, lambda: matrix(-2))
pytest.raises(ValueError, lambda: matrix(2, -3))
def test_matmul():
"""
Test the PEP465 "@" matrix multiplication syntax.
"""
A4 = matrix([[1, 2, 3], [4, 5, 6]])
A5 = matrix([[6, -1], [3, 2], [0, -3]])
assert A4 @ A5 == A4 * A5
def test_matrix_slices():
A = matrix([ [1, 2, 3],
[4, 5 ,6],
[7, 8 ,9]])
V = matrix([1,2,3,4,5])
# Get slice
assert A[:,:] == A
assert A[:,1] == matrix([[2],[5],[8]])
assert A[2,:] == matrix([[7, 8 ,9]])
assert A[1:3,1:3] == matrix([[5,6],[8,9]])
assert A[0:2,0:2] == matrix([[1,2],[4,5]]) # issue 267
assert A[:2,:2] == matrix([[1,2],[4,5]])
assert V[2:4] == matrix([3,4])
assert A[-1, :] == A[2, :]
assert A[:, -1] == A[:, 2]
pytest.raises(IndexError, lambda: A[-4, 0])
pytest.raises(IndexError, lambda: A[0, -4])
pytest.raises(IndexError, lambda: A[:,1:6])
# Assign slice with matrix
A1 = matrix(3)
A1[:,:] = A
assert A1[:,:] == matrix([[1, 2, 3],
[4, 5 ,6],
[7, 8 ,9]])
A1[0,:] = matrix([[10, 11, 12]])
assert A1 == matrix([ [10, 11, 12],
[4, 5 ,6],
[7, 8 ,9]])
A1[:,2] = matrix([[13], [14], [15]])
assert A1 == matrix([ [10, 11, 13],
[4, 5 ,14],
[7, 8 ,15]])
A1[:2,:2] = matrix([[16, 17], [18 , 19]])
assert A1 == matrix([ [16, 17, 13],
[18, 19 ,14],
[7, 8 ,15]])
V[1:3] = 10
assert V == matrix([1,10,10,4,5])
with pytest.raises(ValueError):
A1[2,:] = A[:,1]
with pytest.raises(IndexError):
A1[2,1:20] = A[:,:]
# Assign slice with scalar
A1[:,2] = 10
assert A1 == matrix([ [16, 17, 10],
[18, 19 ,10],
[7, 8 ,10]])
A1[:,:] = 40
for x in A1:
assert x == 40
# test negative indexes
A2 = matrix(3)
A2[:,:] = A
A2[-3, :] = matrix([[10, 11, 12]])
assert A2 == matrix([[10, 11, 12],
[4, 5, 6],
[7, 8, 9]])
A2[:,-1] = matrix([[13], [14], [15]])
assert A2 == matrix([[10, 11, 13],
[4, 5, 14],
[7, 8, 15]])
A2[:-1,:-1] = matrix([[16, 17], [18, 19]])
assert A2 == matrix([[16, 17, 13],
[18, 19, 14],
[7, 8 ,15]])
with pytest.raises(IndexError):
A2[-123,1] = 123
with pytest.raises(IndexError):
A2[1,-123] = 123
def test_matrix_power():
A = matrix([[1, 2], [3, 4]])
assert A**2 == A*A
assert A**3 == A*A*A
assert A**-1 == inverse(A)
assert A**-2 == inverse(A*A)
def test_matrix_transform():
A = matrix([[1, 2], [3, 4], [5, 6]])
assert A.T == A.transpose() == matrix([[1, 3, 5], [2, 4, 6]])
swap_row(A, 1, 2)
assert A == matrix([[1, 2], [5, 6], [3, 4]])
l = [1, 2]
swap_row(l, 0, 1)
assert l == [2, 1]
assert extend(eye(3), [1,2,3]) == matrix([[1,0,0,1],[0,1,0,2],[0,0,1,3]])
def test_matrix_conjugate():
A = matrix([[1 + j, 0], [2, j]])
assert A.conjugate() == matrix([[mpc(1, -1), 0], [2, mpc(0, -1)]])
assert A.transpose_conj() == A.H == matrix([[mpc(1, -1), 2],
[0, mpc(0, -1)]])
def test_matrix_creation():
assert diag([1, 2, 3]) == matrix([[1, 0, 0], [0, 2, 0], [0, 0, 3]])
A1 = ones(2, 3)
assert A1.rows == 2 and A1.cols == 3
for a in A1:
assert a == 1
A2 = zeros(3, 2)
assert A2.rows == 3 and A2.cols == 2
for a in A2:
assert a == 0
assert randmatrix(10) != randmatrix(10)
one = mpf(1)
assert hilbert(3) == matrix([[one, one/2, one/3],
[one/2, one/3, one/4],
[one/3, one/4, one/5]])
def test_norms():
# matrix norms
A = matrix([[1, -2], [-3, -1], [2, 1]])
assert mnorm(A,1) == 6
assert mnorm(A,inf) == 4
assert mnorm(A,'F') == sqrt(20)
# vector norms
assert norm(-3) == 3
x = [1, -2, 7, -12]
assert norm(x, 1) == 22
assert round(norm(x, 2), 10) == 14.0712472795
assert round(norm(x, 10), 10) == 12.0054633727
assert norm(x, inf) == 12
def test_vector():
x = matrix([0, 1, 2, 3, 4])
assert x == matrix([[0], [1], [2], [3], [4]])
assert x[3] == 3
assert len(x._data) == 4
assert list(x) == list(range(5))
x[0] = -10
x[4] = 0
assert x[0] == -10
assert len(x) == len(x.T) == 5
assert x.T*x == matrix([[114]])
def test_matrix_copy():
A = ones(6)
B = A.copy()
C = +A
assert A == B
assert A == C
B[0,0] = 0
assert A != B
C[0,0] = 42
assert A != C
def test_matrix_numpy():
numpy = pytest.importorskip("numpy")
l = [[1, 2], [3, 4], [5, 6]]
a = numpy.array(l)
assert matrix(l) == matrix(a)
assert (numpy.array(matrix(l)) == numpy.array(matrix(l).tolist(),
dtype=object)).all()
if numpy.__version__ >= '2':
pytest.raises(ValueError, lambda: numpy.array(matrix(l), copy=False))
def test_interval_matrix_scalar_mult():
"""Multiplication of iv.matrix and any scalar type"""
a = mpi(-1, 1)
b = a + a * 2j
c = mpf(42)
d = c + c * 2j
e = 1.234
f = fp.convert(e)
g = e + e * 3j
h = fp.convert(g)
M = iv.ones(1)
for x in [a, b, c, d, e, f, g, h]:
assert x * M == iv.matrix([x])
assert M * x == iv.matrix([x])
@pytest.mark.xfail()
def test_interval_matrix_matrix_mult():
"""Multiplication of iv.matrix and other matrix types"""
A = ones(1)
B = fp.ones(1)
M = iv.ones(1)
for X in [A, B, M]:
assert X * M == iv.matrix(X)
assert X * M == X
assert M * X == iv.matrix(X)
assert M * X == X
def test_matrix_conversion_to_iv():
# Test that matrices with foreign datatypes are properly converted
for other_type_eye in [eye(3), fp.eye(3), iv.eye(3)]:
A = iv.matrix(other_type_eye)
B = iv.eye(3)
assert type(A[0,0]) == type(B[0,0])
assert A.tolist() == B.tolist()
def test_interval_matrix_mult_bug():
# regression test for interval matrix multiplication:
# result must be nonzero-width and contain the exact result
x = convert('1.00000000000001') # note: this is implicitly rounded to some near mpf float value
A = matrix([[x]])
B = iv.matrix(A)
C = iv.matrix([[x]])
assert B == C
B = B * B
C = C * C
assert B == C
assert B[0, 0].delta > 1e-16
assert B[0, 0].delta < 3e-16
assert C[0, 0].delta > 1e-16
assert C[0, 0].delta < 3e-16
assert mp.mpf('1.00000000000001998401444325291756783368705994138804689654') in B[0, 0]
assert mp.mpf('1.00000000000001998401444325291756783368705994138804689654') in C[0, 0]
# the following caused an error before the bug was fixed
assert iv.matrix(mp.eye(2)) * (iv.ones(2) + mpi(1, 2)) == iv.matrix([[mpi(2, 3), mpi(2, 3)], [mpi(2, 3), mpi(2, 3)]])
+18
View File
@@ -0,0 +1,18 @@
"""
Modules checks, in particular some hacks for Issue #657
"""
from pytest import raises
import mpmath
def test_erroneous_module_setting():
with raises(AttributeError):
mpmath.dps = 64
with raises(AttributeError):
mpmath.prec = 192
with raises(AttributeError):
mpmath.pretty = True
with raises(AttributeError):
mpmath.trap_complex = True
+7
View File
@@ -0,0 +1,7 @@
from mpmath import fp, iv, mp, mpc, mpf
def test_newstyle_classes():
for cls in [mp, fp, iv, mpf, mpc]:
for s in cls.__class__.__mro__:
assert isinstance(s, type)
+71
View File
@@ -0,0 +1,71 @@
#from mpmath.calculus import ODE_step_euler, ODE_step_rk4, odeint, arange
from mpmath import cos, mpf, odefun, sin, sinc
'''
solvers = [ODE_step_euler, ODE_step_rk4]
def test_ode1():
"""
Let's solve:
x'' + w**2 * x = 0
i.e. x1 = x, x2 = x1':
x1' = x2
x2' = -x1
"""
def derivs((x1, x2), t):
return x2, -x1
for solver in solvers:
t = arange(0, 3.1415926, 0.005)
sol = odeint(derivs, (0., 1.), t, solver)
x1 = [a[0] for a in sol]
x2 = [a[1] for a in sol]
# the result is x1 = sin(t), x2 = cos(t)
# let's just check the end points for t = pi
assert abs(x1[-1]) < 1e-2
assert abs(x2[-1] - (-1)) < 1e-2
def test_ode2():
"""
Let's solve:
x' - x = 0
i.e. x = exp(x)
"""
def derivs((x), t):
return x
for solver in solvers:
t = arange(0, 1, 1e-3)
sol = odeint(derivs, (1.,), t, solver)
x = [a[0] for a in sol]
# the result is x = exp(t)
# let's just check the end point for t = 1, i.e. x = e
assert abs(x[-1] - 2.718281828) < 1e-2
'''
def test_odefun_rational():
# A rational function
f = lambda t: 1/(1+mpf(t)**2)
g = odefun(lambda x, y: [-2*x*y[0]**2], 0, [f(0)])
assert f(2).ae(g(2)[0])
def test_odefun_sinc_large():
# Sinc function; test for large x
f = sinc
g = odefun(lambda x, y: [(cos(x)-y[0])/x], 1, [f(1)], tol=0.01, degree=5)
assert abs(f(100) - g(100)[0])/f(100) < 0.01
def test_odefun_harmonic():
# Harmonic oscillator
f = odefun(lambda x, y: [-y[1], y[0]], 0, [1, 0])
for x in [0, 1, 2.5, 8, 3.7]: # we go back to 3.7 to check caching
c, s = f(x)
assert c.ae(cos(x))
assert s.ae(sin(x))
+12
View File
@@ -0,0 +1,12 @@
import pickle
import pytest
from mpmath import matrix, mpc, mpf, mpi, sin
@pytest.mark.parametrize('protocol', range(pickle.HIGHEST_PROTOCOL + 1))
@pytest.mark.parametrize('obj', [mpf('0.5'), mpc('0.5','0.2'), mpi(10, 30),
matrix([1, sin(1)]), matrix([[1, 2], [3, 4]])])
def test_pickle(obj, protocol):
assert obj == pickle.loads(pickle.dumps(obj, protocol))
+155
View File
@@ -0,0 +1,155 @@
import random
from mpmath import make_mpf, mp, mpf
from mpmath.libmp import (from_int, mpf_pow, mpf_pow_int, round_ceiling,
round_down, round_floor, round_up, to_int)
def test_fractional_pow():
assert mpf(16) ** 2.5 == 1024
assert mpf(64) ** 0.5 == 8
assert mpf(64) ** -0.5 == 0.125
assert mpf(16) ** -2.5 == 0.0009765625
assert (mpf(10) ** 0.5).ae(3.1622776601683791)
assert (mpf(10) ** 2.5).ae(316.2277660168379)
assert (mpf(10) ** -0.5).ae(0.31622776601683794)
assert (mpf(10) ** -2.5).ae(0.0031622776601683794)
assert (mpf(10) ** 0.3).ae(1.9952623149688795)
assert (mpf(10) ** -0.3).ae(0.50118723362727224)
def test_pow_integer_direction():
"""
Test that inexact integer powers are rounded in the right
direction.
"""
random.seed(1234)
for prec in [10, 53, 200]:
for i in range(50):
a = random.randint(1<<(prec-1), 1<<prec)
b = random.randint(2, 100)
ab = a**b
# note: could actually be exact, but that's very unlikely!
assert to_int(mpf_pow(from_int(a), from_int(b), prec, round_down)) < ab
assert to_int(mpf_pow(from_int(a), from_int(b), prec, round_up)) > ab
def test_pow_epsilon_rounding():
"""
Stress test directed rounding for powers with integer exponents.
Basically, we look at the following cases:
>>> 1.0001 ** -5
0.999500149965007
>>> 0.9999 ** -5
1.000500150035007
>>> (-1.0001) ** -5
-0.999500149965007
>>> (-0.9999) ** -5
-1.000500150035007
>>> 1.0001 ** -6
0.9994002099440127
>>> 0.9999 ** -6
1.0006002100560125
>>> (-1.0001) ** -6
0.9994002099440127
>>> (-0.9999) ** -6
1.0006002100560125
etc.
We run the tests with values a very small epsilon away from 1:
small enough that the result is indistinguishable from 1 when
rounded to nearest at the output precision. We check that the
result is not erroneously rounded to 1 in cases where the
rounding should be done strictly away from 1.
"""
def powr(x, n, r):
return make_mpf(mpf_pow_int(x._mpf_, n, mp.prec, r))
for (inprec, outprec) in [(100, 20), (5000, 3000)]:
mp.prec = inprec
pos10001 = mpf(1) + mpf(2)**(-inprec+5)
pos09999 = mpf(1) - mpf(2)**(-inprec+5)
neg10001 = -pos10001
neg09999 = -pos09999
mp.prec = outprec
r = round_up
assert powr(pos10001, 5, r) > 1
assert powr(pos09999, 5, r) == 1
assert powr(neg10001, 5, r) < -1
assert powr(neg09999, 5, r) == -1
assert powr(pos10001, 6, r) > 1
assert powr(pos09999, 6, r) == 1
assert powr(neg10001, 6, r) > 1
assert powr(neg09999, 6, r) == 1
assert powr(pos10001, -5, r) == 1
assert powr(pos09999, -5, r) > 1
assert powr(neg10001, -5, r) == -1
assert powr(neg09999, -5, r) < -1
assert powr(pos10001, -6, r) == 1
assert powr(pos09999, -6, r) > 1
assert powr(neg10001, -6, r) == 1
assert powr(neg09999, -6, r) > 1
r = round_down
assert powr(pos10001, 5, r) == 1
assert powr(pos09999, 5, r) < 1
assert powr(neg10001, 5, r) == -1
assert powr(neg09999, 5, r) > -1
assert powr(pos10001, 6, r) == 1
assert powr(pos09999, 6, r) < 1
assert powr(neg10001, 6, r) == 1
assert powr(neg09999, 6, r) < 1
assert powr(pos10001, -5, r) < 1
assert powr(pos09999, -5, r) == 1
assert powr(neg10001, -5, r) > -1
assert powr(neg09999, -5, r) == -1
assert powr(pos10001, -6, r) < 1
assert powr(pos09999, -6, r) == 1
assert powr(neg10001, -6, r) < 1
assert powr(neg09999, -6, r) == 1
r = round_ceiling
assert powr(pos10001, 5, r) > 1
assert powr(pos09999, 5, r) == 1
assert powr(neg10001, 5, r) == -1
assert powr(neg09999, 5, r) > -1
assert powr(pos10001, 6, r) > 1
assert powr(pos09999, 6, r) == 1
assert powr(neg10001, 6, r) > 1
assert powr(neg09999, 6, r) == 1
assert powr(pos10001, -5, r) == 1
assert powr(pos09999, -5, r) > 1
assert powr(neg10001, -5, r) > -1
assert powr(neg09999, -5, r) == -1
assert powr(pos10001, -6, r) == 1
assert powr(pos09999, -6, r) > 1
assert powr(neg10001, -6, r) == 1
assert powr(neg09999, -6, r) > 1
r = round_floor
assert powr(pos10001, 5, r) == 1
assert powr(pos09999, 5, r) < 1
assert powr(neg10001, 5, r) < -1
assert powr(neg09999, 5, r) == -1
assert powr(pos10001, 6, r) == 1
assert powr(pos09999, 6, r) < 1
assert powr(neg10001, 6, r) == 1
assert powr(neg09999, 6, r) < 1
assert powr(pos10001, -5, r) < 1
assert powr(pos09999, -5, r) == 1
assert powr(neg10001, -5, r) == -1
assert powr(neg09999, -5, r) < -1
assert powr(pos10001, -6, r) < 1
assert powr(pos09999, -6, r) == 1
assert powr(neg10001, -6, r) < 1
assert powr(neg09999, -6, r) == 1
+98
View File
@@ -0,0 +1,98 @@
import pytest
from mpmath import (airyai, airyaizero, atan, cos, cosh, e, euler, exp, inf, j,
log, mp, pi, quad, quadgl, quadosc, quadts, sign, sin,
sinh, sqrt, tan)
def ae(a, b):
return abs(a-b) < 10**(-mp.dps+5)
def test_basic_integrals():
for prec in [15, 30, 100]:
mp.dps = prec
assert ae(quadts(lambda x: x**3 - 3*x**2, [-2, 4]), -12)
assert ae(quadgl(lambda x: x**3 - 3*x**2, [-2, 4]), -12)
assert ae(quadts(sin, [0, pi]), 2)
assert ae(quadts(sin, [0, 2*pi]), 0)
assert ae(quadts(exp, [-inf, -1]), 1/e)
assert ae(quadts(lambda x: exp(-x), [0, inf]), 1)
assert ae(quadts(lambda x: exp(-x*x), [-inf, inf]), sqrt(pi))
assert ae(quadts(lambda x: 1/(1+x*x), [-1, 1]), pi/2)
assert ae(quadts(lambda x: 1/(1+x*x), [-inf, inf]), pi)
assert ae(quadts(lambda x: 2*sqrt(1-x*x), [-1, 1]), pi)
def test_multiple_intervals():
y,err = quad(lambda x: sign(x), [-0.5, 0.9, 1], maxdegree=2, error=True)
assert abs(y-0.5) < 2*err
def test_quad_symmetry():
assert quadts(sin, [-1, 1]) == 0
assert quadgl(sin, [-1, 1]) == 0
def test_quad_infinite_mirror():
# Check mirrored infinite interval
assert ae(quad(lambda x: exp(-x*x), [inf,-inf]), -sqrt(pi))
assert ae(quad(lambda x: exp(x), [0,-inf]), -1)
def test_quadgl_linear():
assert quadgl(lambda x: x, [0, 1], maxdegree=1).ae(0.5)
def test_complex_integration():
assert quadts(lambda x: x, [0, 1+j]).ae(j)
def test_quadosc():
assert quadosc(lambda x: sin(x)/x, [0, inf], period=2*pi).ae(pi/2)
# issue #652
assert ae(quadosc(airyai, [-inf, 0], zeros=lambda n: -airyaizero(-n)), 2/3)
# Double integrals
def test_double_trivial():
assert ae(quadts(lambda x, y: x, [0, 1], [0, 1]), 0.5)
assert ae(quadts(lambda x, y: x, [-1, 1], [-1, 1]), 0.0)
def test_double_1():
assert ae(quadts(lambda x, y: cos(x+y/2), [-pi/2, pi/2], [0, pi]), 4)
def test_double_2():
assert ae(quadts(lambda x, y: (x-1)/((1-x*y)*log(x*y)), [0, 1], [0, 1]), euler)
def test_double_3():
assert ae(quadts(lambda x, y: 1/sqrt(1+x*x+y*y), [-1, 1], [-1, 1]), 4*log(2+sqrt(3))-2*pi/3)
def test_double_4():
assert ae(quadts(lambda x, y: 1/(1-x*x * y*y), [0, 1], [0, 1]), pi**2 / 8)
def test_double_5():
assert ae(quadts(lambda x, y: 1/(1-x*y), [0, 1], [0, 1]), pi**2 / 6)
def test_double_6():
assert ae(quadts(lambda x, y: exp(-(x+y)), [0, inf], [0, inf]), 1)
def test_double_7():
assert ae(quadts(lambda x, y: exp(-x*x-y*y), [-inf, inf], [-inf, inf]), pi)
# Test integrals from "Experimentation in Mathematics" by Borwein,
# Bailey & Girgensohn
def test_expmath_integrals():
for prec in [15, 30, 50]:
mp.dps = prec
assert ae(quadts(lambda x: x/sinh(x), [0, inf]), pi**2 / 4)
assert ae(quadts(lambda x: log(x)**2 / (1+x**2), [0, inf]), pi**3 / 8)
assert ae(quadts(lambda x: (1+x**2)/(1+x**4), [0, inf]), pi/sqrt(2))
assert ae(quadts(lambda x: log(x)/cosh(x)**2, [0, inf]), log(pi)-2*log(2)-euler)
assert ae(quadts(lambda x: log(1+x**3)/(1-x+x**2), [0, inf]), 2*pi*log(3)/sqrt(3))
assert ae(quadts(lambda x: log(x)**2 / (x**2+x+1), [0, 1]), 8*pi**3 / (81*sqrt(3)))
assert ae(quadts(lambda x: log(cos(x))**2, [0, pi/2]), pi/2 * (log(2)**2+pi**2/12))
assert ae(quadts(lambda x: x**2 / sin(x)**2, [0, pi/2]), pi*log(2))
assert ae(quadts(lambda x: x**2/sqrt(exp(x)-1), [0, inf]), 4*pi*(log(2)**2 + pi**2/12))
assert ae(quadts(lambda x: x*exp(-x)*sqrt(1-exp(-2*x)), [0, inf]), pi*(1+2*log(2))/8)
# Do not reach full accuracy
@pytest.mark.xfail
def test_expmath_fail():
assert ae(quadts(lambda x: sqrt(tan(x)), [0, pi/2]), pi*sqrt(2)/2)
assert ae(quadts(lambda x: atan(x)/(x*sqrt(1-x**2)), [0, 1]), pi*log(1+sqrt(2))/2)
assert ae(quadts(lambda x: log(1+x**2)/x**2, [0, 1]), pi/2-log(2))
assert ae(quadts(lambda x: x**2/((1+x**4)*sqrt(1-x**4)), [0, 1]), pi/8)
+176
View File
@@ -0,0 +1,176 @@
import pytest
from mpmath import (cos, eps, findroot, fp, inf, iv, jacobian, matrix, mnorm,
mp, mpc, mpf, multiplicity, norm, pi, polyval, sin, sqrt,
workprec)
from mpmath.calculus.optimization import (Anderson, ANewton, Bisection,
Illinois, MDNewton, MNewton, Muller,
Newton, Pegasus, Ridder, Secant, ModAB, Brent)
def test_findroot():
# old tests, assuming secant
assert findroot(lambda x: 4*x-3, mpf(5)).ae(0.75)
assert findroot(sin, mpf(3)).ae(pi)
assert findroot(sin, (mpf(3), mpf(3.14))).ae(pi)
assert findroot(lambda x: x*x+1, mpc(2+2j)).ae(1j)
# test all solvers with 1 starting point
f = lambda x: cos(x)
for solver in [Newton, Secant, MNewton, Muller, ANewton]:
x = findroot(f, 2., solver=solver)
assert abs(f(x)) < eps
# test all solvers with interval of 2 points
for solver in [Secant, Muller, Bisection, Illinois, Pegasus, Anderson,
Ridder, ModAB, Brent]:
x = findroot(f, (1., 2.), solver=solver)
assert abs(f(x)) < eps
# test types
f = lambda x: (x - 2)**2
assert isinstance(findroot(f, 1, tol=1e-10), mpf)
assert isinstance(iv.findroot(f, 1., tol=1e-10), iv.mpf)
assert isinstance(fp.findroot(f, 1, tol=1e-10), float)
assert isinstance(fp.findroot(f, 1+0j, tol=1e-10), complex)
# issue 401
with pytest.raises(ValueError):
with workprec(2):
findroot(lambda x: x**2 - 4456178*x + 60372201703370,
mpc(real='5.278e+13', imag='-5.278e+13'))
# issue 192
with pytest.raises(ValueError):
findroot(lambda x: -1, 0)
# issue 387
with pytest.raises(ValueError):
findroot(lambda p: (1 - p)**30 - 1, 0.9)
def test_bisection():
# issue 273
assert findroot(lambda x: x**2-1,(0,2),solver='bisect') == 1
with pytest.raises(ValueError):
findroot(lambda x: x**2-1, (4, 2), solver='bisect') == 1
# issue 285
mp.dps = 240
sol = -mp.ceil(mp.log(abs(findroot(lambda x: mp.sign(x - 3), (1, 4),
solver='bisect', verify=False,
tol=1e-200) - 3))/mp.log(10))
assert sol.ae(200)
# issue 339
mp.dps = 15
res = mpf('0.73908513321516064')
for dps in [100, 200, 300, 1000]:
with mp.workdps(dps):
sol = findroot(lambda x: cos(x) - x, [0, 1], solver='bisect')
assert (+sol).ae(res)
def test_mnewton():
f = lambda x: polyval([1, 3, 3, 1], x)
x = findroot(f, -0.9, solver='mnewton')
assert abs(f(x)) < eps
def test_anewton():
f = lambda x: (x - 2)**100
x = findroot(f, 1., solver=ANewton)
assert abs(f(x)) < eps
def test_muller():
f = lambda x: (2 + x)**3 + 2
x = findroot(f, 1., solver=Muller)
assert abs(f(x)) < eps
def test_ridder():
f = lambda x: cos(x)/x
x = findroot(f, (1, 2), solver='ridder')
assert abs(f(x)) < eps
def test_brent():
f = lambda x: cos(x)/x
x = findroot(f, (1, 2), solver='brent')
assert abs(f(x)) < eps
with pytest.raises(ValueError, match="expected interval of 2 points"):
findroot(lambda x: x**2 - 1, (0,), solver='brent')
with pytest.raises(ValueError, match="Function must have opposite signs"):
findroot(lambda x: x**2 - 1, (2, 4), solver='brent')
assert findroot(lambda x: x, (-1, 2), solver='brent') == 0.0
assert findroot(lambda x: x, (-1, 1), solver='brent') == 0.0
def test_modAB():
assert findroot(lambda x: x**2 - 1, (0, 2), solver='modAB') == 1
# test ordering
assert findroot(lambda x: x**2 - 1, (2, 0), solver='modAB') == 1
with pytest.raises(ValueError, match="expected interval of 2 points"):
findroot(lambda x: x**2 - 1, (0,), solver='modAB')
with pytest.raises(ValueError, match="Function must have opposite signs"):
findroot(lambda x: x**2 - 1, (2, 4), solver='modAB')
# test exact zero hit
assert findroot(lambda x: x, (-1, 1), solver='modAB') == 0.0
# test bisection to secant switch for a purely linear function
f_linear = lambda x: 2*x - 4
assert mp.almosteq(findroot(f_linear, (0, 5), solver='modAB'), 2.0)
f_convex = lambda x: x**10 - 1
assert mp.almosteq(findroot(f_convex, (0.1, 2.0), solver='modAB'), 1.0)
f_concave = lambda x: 1 - x**10
assert mp.almosteq(findroot(f_concave, (2.0, 0.1), solver='modAB'), 1.0)
f_cubic_inflection = lambda x: x**3 - 3*x + 3
root = findroot(f_cubic_inflection, (-3, 2), solver='modAB')
assert abs(f_cubic_inflection(root)) < eps
# test reset to Bisection if the interval width exceeds the threshold
f_step = lambda x: mp.sin(x) if x > 1 else x - 1
assert mp.almosteq(findroot(f_step, (0.4, 3.0), solver='modAB'), 1.0)
def test_multiplicity():
for i in range(1, 5):
assert multiplicity(lambda x: (x - 1)**i, 1) == i
assert multiplicity(lambda x: x**2, 1) == 0
def test_multidimensional(capsys):
def f(*x):
return [3*x[0]**2-2*x[1]**2-1, x[0]**2-2*x[0]+x[1]**2+2*x[1]-8]
assert mnorm(jacobian(f, (1,-2)) - matrix([[6,8],[0,-2]]),1) < 1.e-7
for x, error in MDNewton(mp, f, (1,-2), verbose=0,
norm=lambda x: norm(x, inf)):
pass
assert norm(f(*x), 2) < 1e-14
for x, error in MDNewton(mp, f, (1,-2), verbose=1,
norm=lambda x: norm(x, inf)):
pass
assert norm(f(*x), 2) < 1e-14
captured = capsys.readouterr()
assert captured.out.find("canceled, won't get more exact") >= 0
# The Chinese mathematician Zhu Shijie was the very first to solve this
# nonlinear system 700 years ago
f1 = lambda x, y: -x + 2*y
f2 = lambda x, y: (x**2 + x*(y**2 - 2) - 4*y) / (x + 4)
f3 = lambda x, y: sqrt(x**2 + y**2)
def f(x, y):
f1x = f1(x, y)
return (f2(x, y) - f1x, f3(x, y) - f1x)
x = findroot(f, (10, 10))
assert [round(i) for i in x] == [3, 4]
def test_trivial():
assert findroot(lambda x: 0, 1) == 1
assert findroot(lambda x: x, 0) == 0
#assert findroot(lambda x, y: x + y, (1, -1)) == (1, -1)
def test_issue_869():
f = [lambda x: sqrt(x) + 1]
pytest.raises(mp.ComplexResult, lambda: findroot(f, [-1]))
+115
View File
@@ -0,0 +1,115 @@
from mpmath import atan, exp, inf, isinf, isnan, log, mpf, nan, pi, sin, sqrt
def test_special():
assert inf == inf
assert inf != -inf
assert -inf == -inf
assert inf != nan
assert nan != nan
assert isnan(nan)
assert --inf == inf
assert abs(inf) == inf
assert abs(-inf) == inf
assert abs(nan) != abs(nan)
assert isnan(inf - inf)
assert isnan(inf + (-inf))
assert isnan(-inf - (-inf))
assert isnan(inf + nan)
assert isnan(-inf + nan)
assert mpf(2) + inf == inf
assert 2 + inf == inf
assert mpf(2) - inf == -inf
assert 2 - inf == -inf
assert inf > 3
assert 3 < inf
assert 3 > -inf
assert -inf < 3
assert inf > mpf(3)
assert mpf(3) < inf
assert mpf(3) > -inf
assert -inf < mpf(3)
assert not (nan < 3)
assert not (nan > 3)
assert isnan(inf * 0)
assert isnan(-inf * 0)
assert inf * 3 == inf
assert inf * -3 == -inf
assert -inf * 3 == -inf
assert -inf * -3 == inf
assert inf * inf == inf
assert -inf * -inf == inf
assert isnan(nan / 3)
assert inf / -3 == -inf
assert inf / 3 == inf
assert 3 / inf == 0
assert -3 / inf == 0
assert 0 / inf == 0
assert isnan(inf / inf)
assert isnan(inf / -inf)
assert isnan(inf / nan)
assert mpf('inf') == mpf('+inf') == inf
assert mpf('-inf') == -inf
assert isnan(mpf('nan'))
assert isinf(inf)
assert isinf(-inf)
assert not isinf(mpf(0))
assert not isinf(nan)
def test_special_powers():
assert inf**3 == inf
assert inf**0 == 1
assert inf**-3 == 0
assert (-inf)**2 == inf
assert (-inf)**3 == -inf
assert (-inf)**0 == 1
assert (-inf)**-2 == 0
assert (-inf)**-3 == 0
assert isnan(nan**5)
assert nan**0 == 1
assert 1**inf == 1
def test_functions_special():
assert exp(inf) == inf
assert exp(-inf) == 0
assert isnan(exp(nan))
assert log(inf) == inf
assert isnan(log(nan))
assert isnan(sin(inf))
assert isnan(sin(nan))
assert atan(inf).ae(pi/2)
assert atan(-inf).ae(-pi/2)
assert isnan(sqrt(nan))
assert sqrt(inf) == inf
def test_convert_special():
float_inf = 1e300 * 1e300
float_ninf = -float_inf
float_nan = float_inf/float_ninf
assert mpf(3) * float_inf == inf
assert mpf(3) * float_ninf == -inf
assert isnan(mpf(3) * float_nan)
assert not (mpf(3) < float_nan)
assert not (mpf(3) > float_nan)
assert not (mpf(3) <= float_nan)
assert not (mpf(3) >= float_nan)
assert float(mpf('1e1000')) == float_inf
assert float(mpf('-1e1000')) == float_ninf
assert float(mpf('1e100000000000000000')) == float_inf
assert float(mpf('-1e100000000000000000')) == float_ninf
assert float(mpf('1e-100000000000000000')) == 0.0
def test_div_bug():
assert isnan(nan/1)
assert isnan(nan/2)
assert inf/2 == inf
assert (-inf)/2 == -inf
+52
View File
@@ -0,0 +1,52 @@
from mpmath import inf, matrix, mpc, nstr
A1 = matrix([])
A2 = matrix([[]])
A3 = matrix(2)
A4 = matrix([1, 2, 3])
def test_nstr():
m = matrix([[0.75, 0.190940654, -0.0299195971],
[0.190940654, 0.65625, 0.205663228],
[-0.0299195971, 0.205663228, 0.64453125e-20]])
assert nstr(m, 4, min_fixed=-inf) == \
'''[ 0.75 0.1909 -0.02992]
[ 0.1909 0.6562 0.2057]
[-0.02992 0.2057 0.000000000000000000006445]'''
assert nstr(m, 4) == \
'''[ 0.75 0.1909 -0.02992]
[ 0.1909 0.6562 0.2057]
[-0.02992 0.2057 6.445e-21]'''
# Check that kwargs works properly for mpc
assert nstr(mpc(1.23e-4+4.56e-4j)) == '(0.000123 + 0.000456j)'
assert nstr(mpc(1.23e-4+4.56e-4j), min_fixed=-4) == '(1.23e-4 + 4.56e-4j)'
def test_matrix_repr():
assert repr(A1) == \
'''matrix(
[])'''
assert repr(A2) == \
'''matrix(
[[]])'''
assert repr(A3) == \
'''matrix(
[['0.0', '0.0'],
['0.0', '0.0']])'''
assert repr(A4) == \
'''matrix(
[['1.0'],
['2.0'],
['3.0']])'''
def test_matrix_str():
assert str(A1) == ''
assert str(A2) == '[]'
assert str(A3) == \
'''[0.0 0.0]
[0.0 0.0]'''
assert str(A4) == \
'''[1.0]
[2.0]
[3.0]'''
+50
View File
@@ -0,0 +1,50 @@
from mpmath import (e, exp, fac, factorial, fp, fprod, fsum, inf, isnan, iv, j,
log, mpi, nprod, nsum, pi, sumem)
def test_sumem():
assert sumem(lambda k: 1/k**2.5, [50, 100]).ae(0.0012524505324784962)
assert sumem(lambda k: k**4 + 3*k + 1, [10, 100]).ae(2050333103)
def test_nsum():
assert nsum(lambda x: x**2, [1, 3]) == 14
assert nsum(lambda k: 1/factorial(k), [0, inf]).ae(e)
assert nsum(lambda k: (-1)**(k+1) / k, [1, inf]).ae(log(2))
assert nsum(lambda k: (-1)**(k+1) / k**2, [1, inf]).ae(pi**2 / 12)
assert nsum(lambda k: (-1)**k / log(k), [2, inf]).ae(0.9242998972229388)
assert nsum(lambda k: 1/k**2, [1, inf]).ae(pi**2 / 6)
assert nsum(lambda k: 2**k/fac(k), [0, inf]).ae(exp(2))
assert nsum(lambda k: 1/k**2, [4, inf], method='e').ae(0.2838229557371153)
assert abs(fp.nsum(lambda k: 1/k**4, [1, fp.inf]) - 1.082323233711138) < 1e-5
assert abs(fp.nsum(lambda k: 1/k**4, [1, fp.inf], method='e') - 1.082323233711138) < 1e-4
def test_nprod():
assert nprod(lambda k: exp(1/k**2), [1,inf], method='r').ae(exp(pi**2/6))
assert nprod(lambda x: x**2, [1, 3]) == 36
def test_fsum():
assert fsum([]) == 0
assert fsum([-4]) == -4
assert fsum([2,3]) == 5
assert fsum([1e-100,1]) == 1
assert fsum([1,1e-100]) == 1
assert fsum([1e100,1]) == 1e100
assert fsum([1,1e100]) == 1e100
assert fsum([1e-100,0]) == 1e-100
assert fsum([1e-100,1e100,1e-100]) == 1e100
assert fsum([2,1+1j,1]) == 4+1j
assert fsum([2,inf,3]) == inf
assert fsum([2,-1], absolute=1) == 3
assert fsum([2,-1], squared=1) == 5
assert fsum([1,1+j], squared=1) == 1+2j
assert fsum([1,3+4j], absolute=1) == 6
assert fsum([1,2+3j], absolute=1, squared=1) == 14
assert isnan(fsum([inf,-inf]))
assert fsum([inf,-inf], absolute=1) == inf
assert fsum([inf,-inf], squared=1) == inf
assert fsum([inf,-inf], absolute=1, squared=1) == inf
assert iv.fsum([1,mpi(2,3)]) == mpi(3,4)
def test_fprod():
assert fprod([]) == 1
assert fprod([2,3]) == 6
+181
View File
@@ -0,0 +1,181 @@
"""
Torture tests for asymptotics and high precision evaluation of
special functions.
(Other torture tests may also be placed here.)
Running this file (gmpy recommended!) takes several CPU minutes.
The multiprocessing module is used automatically to run tests
in parallel if many cores are available. (A single test may take between
a second and several minutes; possibly more.)
The idea:
* We evaluate functions at positive, negative, imaginary, 45- and 135-degree
complex values with magnitudes between 10^-20 to 10^20, at precisions between
5 and 150 digits (we can go even higher for fast functions).
* Comparing the result from two different precision levels provides
a strong consistency check (particularly for functions that use
different algorithms at different precision levels).
* That the computation finishes at all (without failure), within reasonable
time, provides a check that evaluation works at all: that the code runs,
that it doesn't get stuck in an infinite loop, and that it doesn't use
some extremely slowly algorithm where it could use a faster one.
TODO:
* Speed up those functions that take long to finish!
* Generalize to test more cases; more options.
* Implement a timeout mechanism.
* Some functions are notably absent, including the following:
* inverse trigonometric functions (some become inaccurate for complex arguments)
* ci, si (not implemented properly for large complex arguments)
* zeta functions (need to modify test not to try too large imaginary values)
* and others...
"""
import pytest
from mpmath import (agm, airyai, airybi, apery, barnesg, bernfrac, bernoulli,
besseli, besselj, besselk, bessely, catalan, cbrt, chi, ci,
cos, cosh, coulombf, coulombg, e, e1, ei, ellipe, ellipk,
erf, erfc, erfi, euler, exp, expint, expm1, gamma,
gammainc, glaisher, hermite, hyp0f1, hyp1f1, hyp1f2,
hyp2f0, hyp2f1, hyp2f2, hyp2f3, hyperu, j, jtheta,
khinchin, lambertw, legendre, legenp, legenq, li, ln, ln2,
ln10, loggamma, mertens, mp, mpf, phi, pi, polylog, power,
root, shi, si, sin, sinh, sqrt, stieltjes, tan, tanh,
twinprime, workprec)
a1, a2, a3, a4, a5 = 1.5, -2.25, 3.125, 4, 2
@pytest.mark.parametrize('f,maxdps,huge_range',
[(lambda z: +pi, 10000, False),
(lambda z: +e, 10000, False),
(lambda z: +ln2, 10000, False),
(lambda z: +ln10, 10000, False),
(lambda z: +phi, 10000, False),
(lambda z: +catalan, 5000, False),
(lambda z: +euler, 5000, False),
(lambda z: +glaisher, 1000, False),
(lambda z: +khinchin, 1000, False),
(lambda z: +twinprime, 150, False),
(lambda z: stieltjes(2), 150, False),
(lambda z: +mertens, 150, False),
(lambda z: +apery, 5000, False),
(sqrt, 10000, True),
(cbrt, 5000, True),
(lambda z: root(z,4), 5000, True),
(lambda z: root(z,-5), 5000, True),
(exp, 5000, True),
(expm1, 1500, False),
(ln, 5000, True),
(cosh, 5000, False),
(sinh, 5000, False),
(tanh, 1500, False),
(sin, 5000, True),
(cos, 5000, True),
(tan, 1500, False),
(agm, 1500, True),
(ellipk, 1500, False),
(ellipe, 1500, False),
(lambertw, 150, True),
(lambda z: lambertw(z,-1), 150, False),
(lambda z: lambertw(z,1), 150, False),
(lambda z: lambertw(z,4), 150, False),
(gamma, 150, False),
(loggamma, 150, False), # True ?
(ei, 150, False),
(e1, 150, False),
(li, 150, True),
(ci, 150, False),
(si, 150, False),
(chi, 150, False),
(shi, 150, False),
(erf, 150, False),
(erfc, 150, False),
(erfi, 150, False),
(lambda z: besselj(2, z), 150, False),
(lambda z: bessely(2, z), 150, False),
(lambda z: besseli(2, z), 150, False),
(lambda z: besselk(2, z), 150, False),
(lambda z: besselj(-2.25, z), 150, False),
(lambda z: bessely(-2.25, z), 150, False),
(lambda z: besseli(-2.25, z), 150, False),
(lambda z: besselk(-2.25, z), 150, False),
(airyai, 150, False),
(airybi, 150, False),
(lambda z: hyp0f1(a1, z), 150, False),
(lambda z: hyp1f1(a1, a2, z), 150, False),
(lambda z: hyp1f2(a1, a2, a3, z), 150, False),
(lambda z: hyp2f0(a1, a2, z), 150, False),
(lambda z: hyperu(a1, a2, z), 150, False),
(lambda z: hyp2f1(a1, a2, a3, z), 150, False),
(lambda z: hyp2f2(a1, a2, a3, a4, z), 150, False),
(lambda z: hyp2f3(a1, a2, a3, a4, a5, z), 150, False),
(lambda z: coulombf(a1, a2, z), 150, False),
(lambda z: coulombg(a1, a2, z), 150, False),
(lambda z: polylog(2,z), 150, False),
(lambda z: polylog(3,z), 150, False),
(lambda z: polylog(-2,z), 150, False),
(lambda z: expint(4, z), 150, False),
(lambda z: expint(-4, z), 150, False),
(lambda z: expint(2.25, z), 150, False),
(lambda z: gammainc(2.5, z, 5), 150, False),
(lambda z: gammainc(2.5, 5, z), 150, False),
(lambda z: hermite(3, z), 150, False),
(lambda z: hermite(2.5, z), 150, False),
(lambda z: legendre(3, z), 150, False),
(lambda z: legendre(4, z), 150, False),
(lambda z: legendre(2.5, z), 150, False),
(lambda z: legenp(a1, a2, z), 150, False),
(lambda z: legenq(a1, a2, z), 90, False), # abnormally slow
(lambda z: jtheta(1, z, 0.5), 150, False),
(lambda z: jtheta(2, z, 0.5), 150, False),
(lambda z: jtheta(3, z, 0.5), 150, False),
(lambda z: jtheta(4, z, 0.5), 150, False),
(lambda z: jtheta(1, z, 0.5, 1), 150, False),
(lambda z: jtheta(2, z, 0.5, 1), 150, False),
(lambda z: jtheta(3, z, 0.5, 1), 150, False),
(lambda z: jtheta(4, z, 0.5, 1), 150, False),
(barnesg, 90, False)])
def test_asymp(f, maxdps, huge_range):
dps = [5,15,25,50,90,150,500,1500,5000,10000]
dps = [p for p in dps if p <= maxdps]
def check(x,y,p,inpt):
assert abs(x-y)/abs(y) < workprec(20)(power)(10, -p+1)
exponents = list(range(-20,20))
if huge_range:
exponents += [-1000, -100, -50, 50, 100, 1000]
for n in exponents:
mp.dps = 25
xpos = mpf(10)**n / 1.1287
xneg = -xpos
ximag = xpos*j
xcomplex1 = xpos*(1+j)
xcomplex2 = xpos*(-1+j)
for i in range(len(dps)):
mp.dps = dps[i]
new = f(xpos), f(xneg), f(ximag), f(xcomplex1), f(xcomplex2)
if i != 0:
p = dps[i-1]
check(prev[0], new[0], p, xpos)
check(prev[1], new[1], p, xneg)
check(prev[2], new[2], p, ximag)
check(prev[3], new[3], p, xcomplex1)
check(prev[4], new[4], p, xcomplex2)
prev = new
def test_bernoulli_huge():
p, q = bernfrac(9000)
assert p % 10**10 == 9636701091
assert q == 4091851784687571609141381951327092757255270
mp.dps = 15
assert str(bernoulli(10**100)) == '-2.58183325604736e+987675256497386331227838638980680030172857347883537824464410652557820800494271520411283004120790908623'
mp.dps = 50
assert str(bernoulli(10**100)) == '-2.5818332560473632073252488656039475548106223822913e+987675256497386331227838638980680030172857347883537824464410652557820800494271520411283004120790908623'
+131
View File
@@ -0,0 +1,131 @@
from mpmath import cos, ldexp, mp, mpf, pi, sin, tan
from mpmath.libmp import (round_ceiling, round_down, round_floor,
round_nearest, round_up)
def test_trig_misc_hard():
# Worst-case input for an IEEE double, from a paper by Kahan
x = ldexp(6381956970095103,797)
assert cos(x) == mpf('-4.6871659242546277e-19')
assert sin(x) == 1
mp.prec = 150
a = mpf(10**50)
mp.prec = 53
assert sin(a).ae(-0.7896724934293100827)
assert cos(a).ae(-0.6135286082336635622)
# Check relative accuracy close to x = zero
assert sin(1e-100) == 1e-100 # when rounding to nearest
assert sin(1e-6).ae(9.999999999998333e-007, rel_eps=2e-15, abs_eps=0)
assert sin(1e-6j).ae(1.0000000000001666e-006j, rel_eps=2e-15, abs_eps=0)
assert sin(-1e-6j).ae(-1.0000000000001666e-006j, rel_eps=2e-15, abs_eps=0)
assert cos(1e-100) == 1
assert cos(1e-6).ae(0.9999999999995)
assert cos(-1e-6j).ae(1.0000000000005)
assert tan(1e-100) == 1e-100
assert tan(1e-6).ae(1.0000000000003335e-006, rel_eps=2e-15, abs_eps=0)
assert tan(1e-6j).ae(9.9999999999966644e-007j, rel_eps=2e-15, abs_eps=0)
assert tan(-1e-6j).ae(-9.9999999999966644e-007j, rel_eps=2e-15, abs_eps=0)
def test_trig_near_zero():
for r in [round_nearest, round_down, round_up, round_floor, round_ceiling]:
assert sin(0, rounding=r) == 0
assert cos(0, rounding=r) == 1
a = mpf('1e-100')
b = mpf('-1e-100')
assert sin(a, rounding=round_nearest) == a
assert sin(a, rounding=round_down) < a
assert sin(a, rounding=round_floor) < a
assert sin(a, rounding=round_up) >= a
assert sin(a, rounding=round_ceiling) >= a
assert sin(b, rounding=round_nearest) == b
assert sin(b, rounding=round_down) > b
assert sin(b, rounding=round_floor) <= b
assert sin(b, rounding=round_up) <= b
assert sin(b, rounding=round_ceiling) > b
assert cos(a, rounding=round_nearest) == 1
assert cos(a, rounding=round_down) < 1
assert cos(a, rounding=round_floor) < 1
assert cos(a, rounding=round_up) == 1
assert cos(a, rounding=round_ceiling) == 1
assert cos(b, rounding=round_nearest) == 1
assert cos(b, rounding=round_down) < 1
assert cos(b, rounding=round_floor) < 1
assert cos(b, rounding=round_up) == 1
assert cos(b, rounding=round_ceiling) == 1
def test_trig_near_n_pi():
a = [n*pi for n in [1, 2, 6, 11, 100, 1001, 10000, 100001]]
mp.dps = 135
a.append(10**100 * pi)
mp.dps = 15
assert sin(a[0]) == mpf('1.2246467991473531772e-16')
assert sin(a[1]) == mpf('-2.4492935982947063545e-16')
assert sin(a[2]) == mpf('-7.3478807948841190634e-16')
assert sin(a[3]) == mpf('4.8998251578625894243e-15')
assert sin(a[4]) == mpf('1.9643867237284719452e-15')
assert sin(a[5]) == mpf('-8.8632615209684813458e-15')
assert sin(a[6]) == mpf('-4.8568235395684898392e-13')
assert sin(a[7]) == mpf('3.9087342299491231029e-11')
assert sin(a[8]) == mpf('-1.369235466754566993528e-36')
r = round_nearest
assert cos(a[0], rounding=r) == -1
assert cos(a[1], rounding=r) == 1
assert cos(a[2], rounding=r) == 1
assert cos(a[3], rounding=r) == -1
assert cos(a[4], rounding=r) == 1
assert cos(a[5], rounding=r) == -1
assert cos(a[6], rounding=r) == 1
assert cos(a[7], rounding=r) == -1
assert cos(a[8], rounding=r) == 1
r = round_up
assert cos(a[0], rounding=r) == -1
assert cos(a[1], rounding=r) == 1
assert cos(a[2], rounding=r) == 1
assert cos(a[3], rounding=r) == -1
assert cos(a[4], rounding=r) == 1
assert cos(a[5], rounding=r) == -1
assert cos(a[6], rounding=r) == 1
assert cos(a[7], rounding=r) == -1
assert cos(a[8], rounding=r) == 1
r = round_down
assert cos(a[0], rounding=r) > -1
assert cos(a[1], rounding=r) < 1
assert cos(a[2], rounding=r) < 1
assert cos(a[3], rounding=r) > -1
assert cos(a[4], rounding=r) < 1
assert cos(a[5], rounding=r) > -1
assert cos(a[6], rounding=r) < 1
assert cos(a[7], rounding=r) > -1
assert cos(a[8], rounding=r) < 1
r = round_floor
assert cos(a[0], rounding=r) == -1
assert cos(a[1], rounding=r) < 1
assert cos(a[2], rounding=r) < 1
assert cos(a[3], rounding=r) == -1
assert cos(a[4], rounding=r) < 1
assert cos(a[5], rounding=r) == -1
assert cos(a[6], rounding=r) < 1
assert cos(a[7], rounding=r) == -1
assert cos(a[8], rounding=r) < 1
r = round_ceiling
assert cos(a[0], rounding=r) > -1
assert cos(a[1], rounding=r) == 1
assert cos(a[2], rounding=r) == 1
assert cos(a[3], rounding=r) > -1
assert cos(a[4], rounding=r) == 1
assert cos(a[5], rounding=r) > -1
assert cos(a[6], rounding=r) == 1
assert cos(a[7], rounding=r) > -1
assert cos(a[8], rounding=r) == 1
+51
View File
@@ -0,0 +1,51 @@
#!/bin/bash
#
# Test that the version number is provided correctly in a frozen (bundled)
# executable (see #1044).
set -e
# Get the directory of the current repository
MPMATH_DIR="$(realpath "$(dirname "$0")/../../")"
echo "Repo mpmath directory: $MPMATH_DIR"
echo "Install requirements..."
python3 -m pip install build pyinstaller
echo "Building the source distribution from the local repo..."
python3 -m build --sdist
# Find and install the generated tarball
TARBALL=$(ls -t dist/*.tar.gz | head -1)
echo "Generated tarball: $TARBALL"
echo "Installing mpmath from tarball..."
pip install dist/"$(basename $TARBALL)"
TEMP_DIR=$(mktemp -d)
echo "Created temporary directory: $TEMP_DIR"
cd "$TEMP_DIR"
# Create version_script.py that prints the package version
cat << EOF > version_script.py
import mpmath
print(mpmath.__version__)
EOF
# Save local version for later comparison
DIRECT_VERSION="$(python3 -m mpmath --version)"
echo "Building version_script with PyInstaller..."
pyinstaller --onefile --clean version_script.py
echo "Run frozen executable and extract the version from the output..."
FROZEN_VERSION="$(./dist/version_script 2>&1)"
if [ "$DIRECT_VERSION" == "$FROZEN_VERSION" ]; then
echo "Test passed: Version matches in frozen (bundled) executable."
else
echo "Test failed: Version mismatch."
echo "Direct version: $DIRECT_VERSION"
echo "Frozen version: $FROZEN_VERSION"
exit 1
fi
+70
View File
@@ -0,0 +1,70 @@
"""
Limited tests of the visualization module. Right now it just makes
sure that passing custom Axes works.
"""
import pytest
from mpmath import fp, mp
def test_axes():
try:
import matplotlib
version = matplotlib.__version__.split("-")[0]
version = version.split(".")[:2]
if [int(_) for _ in version] < [0,99]:
raise ImportError
import pylab
except ImportError:
pytest.skip("\nSkipping test (pylab not available or too old version)\n")
fig = pylab.figure()
axes = fig.add_subplot(111)
for ctx in [mp, fp]:
ctx.plot(lambda x: x**2, [0, 3], axes=axes)
assert axes.get_xlabel() == 'x'
assert axes.get_ylabel() == 'f(x)'
fig = pylab.figure()
axes = fig.add_subplot(111)
for ctx in [mp, fp]:
ctx.cplot(lambda z: z, [-2, 2], [-10, 10], axes=axes)
assert axes.get_xlabel() == 'Re(z)'
assert axes.get_ylabel() == 'Im(z)'
def test_issue_1007():
# plot(), cplot() and splot() must not leave a stale figure open
# when the user-supplied function raises an unexpected exception;
# otherwise that blank figure lingers and is shown on the next call.
try:
import matplotlib
version = matplotlib.__version__.split("-")[0]
version = version.split(".")[:2]
if [int(_) for _ in version] < [0,99]:
raise ImportError
import pylab
except ImportError:
pytest.skip("\nSkipping test (pylab not available or too old version)\n")
class Boom(Exception):
pass
def bad(*args):
# An error that is not in plot_ignore, so it propagates out of
# plot()/cplot()/splot() instead of being silently skipped.
raise Boom
for ctx in [mp, fp]:
pylab.close("all")
pytest.raises(Boom, lambda: ctx.plot(bad, [0, 2]))
assert pylab.get_fignums() == []
pylab.close("all")
pytest.raises(Boom, lambda: ctx.cplot(bad, [-2, 2], [-2, 2]))
assert pylab.get_fignums() == []
pylab.close("all")
pytest.raises(Boom, lambda: ctx.splot(bad, [-1, 1], [-1, 1]))
assert pylab.get_fignums() == []