chore: import upstream snapshot with attribution
This commit is contained in:
@@ -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)
|
||||
@@ -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
|
||||
@@ -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))
|
||||
@@ -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.')
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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')
|
||||
@@ -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]))
|
||||
@@ -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
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
@@ -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)
|
||||
@@ -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
|
||||
@@ -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]
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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)]])
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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))
|
||||
@@ -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))
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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]))
|
||||
@@ -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
|
||||
@@ -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]'''
|
||||
@@ -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
|
||||
@@ -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'
|
||||
@@ -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
|
||||
Executable
+51
@@ -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
|
||||
@@ -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() == []
|
||||
Reference in New Issue
Block a user