90 lines
3.0 KiB
Python
90 lines
3.0 KiB
Python
import numpy as np
|
|
from numpy.testing import assert_allclose, assert_equal
|
|
import pytest
|
|
|
|
import scipy.special as sc
|
|
|
|
|
|
class TestInverseErrorFunction:
|
|
def test_compliment(self):
|
|
# Test erfcinv(1 - x) == erfinv(x)
|
|
x = np.linspace(-1, 1, 101)
|
|
assert_allclose(sc.erfcinv(1 - x), sc.erfinv(x), rtol=0, atol=1e-15)
|
|
|
|
def test_literal_values(self):
|
|
# The expected values were calculated with mpmath:
|
|
#
|
|
# import mpmath
|
|
# mpmath.mp.dps = 200
|
|
# for y in [0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9]:
|
|
# x = mpmath.erfinv(y)
|
|
# print(x)
|
|
#
|
|
y = np.array([0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
|
|
actual = sc.erfinv(y)
|
|
expected = [
|
|
0.0,
|
|
0.08885599049425769,
|
|
0.1791434546212917,
|
|
0.2724627147267543,
|
|
0.37080715859355795,
|
|
0.4769362762044699,
|
|
0.5951160814499948,
|
|
0.7328690779592167,
|
|
0.9061938024368233,
|
|
1.1630871536766743,
|
|
]
|
|
assert_allclose(actual, expected, rtol=0, atol=1e-15)
|
|
|
|
@pytest.mark.parametrize(
|
|
'f, x, y',
|
|
[
|
|
(sc.erfinv, -1, -np.inf),
|
|
(sc.erfinv, 0, 0),
|
|
(sc.erfinv, 1, np.inf),
|
|
(sc.erfinv, -100, np.nan),
|
|
(sc.erfinv, 100, np.nan),
|
|
(sc.erfcinv, 0, np.inf),
|
|
(sc.erfcinv, 1, -0.0),
|
|
(sc.erfcinv, 2, -np.inf),
|
|
(sc.erfcinv, -100, np.nan),
|
|
(sc.erfcinv, 100, np.nan),
|
|
],
|
|
ids=[
|
|
'erfinv at lower bound',
|
|
'erfinv at midpoint',
|
|
'erfinv at upper bound',
|
|
'erfinv below lower bound',
|
|
'erfinv above upper bound',
|
|
'erfcinv at lower bound',
|
|
'erfcinv at midpoint',
|
|
'erfcinv at upper bound',
|
|
'erfcinv below lower bound',
|
|
'erfcinv above upper bound',
|
|
]
|
|
)
|
|
def test_domain_bounds(self, f, x, y):
|
|
assert_equal(f(x), y)
|
|
|
|
def test_erfinv_asympt(self):
|
|
# regression test for gh-12758: erfinv(x) loses precision at small x
|
|
# expected values precomputed with mpmath:
|
|
# >>> mpmath.mp.dps = 100
|
|
# >>> expected = [float(mpmath.erfinv(t)) for t in x]
|
|
x = np.array([1e-20, 1e-15, 1e-14, 1e-10, 1e-8, 0.9e-7, 1.1e-7, 1e-6])
|
|
expected = np.array([8.86226925452758e-21,
|
|
8.862269254527581e-16,
|
|
8.86226925452758e-15,
|
|
8.862269254527581e-11,
|
|
8.86226925452758e-09,
|
|
7.97604232907484e-08,
|
|
9.74849617998037e-08,
|
|
8.8622692545299e-07])
|
|
assert_allclose(sc.erfinv(x), expected,
|
|
rtol=1e-15)
|
|
|
|
# also test the roundtrip consistency
|
|
assert_allclose(sc.erf(sc.erfinv(x)),
|
|
x,
|
|
rtol=5e-15)
|