108 lines
3.5 KiB
Python
108 lines
3.5 KiB
Python
|
import pytest
|
||
|
import numpy as np
|
||
|
from numpy.testing import assert_allclose
|
||
|
from numpy.testing import assert_equal
|
||
|
|
||
|
import scipy.special as sc
|
||
|
|
||
|
|
||
|
class TestHyperu(object):
|
||
|
|
||
|
def test_negative_x(self):
|
||
|
a, b, x = np.meshgrid(
|
||
|
[-1, -0.5, 0, 0.5, 1],
|
||
|
[-1, -0.5, 0, 0.5, 1],
|
||
|
np.linspace(-100, -1, 10),
|
||
|
)
|
||
|
assert np.all(np.isnan(sc.hyperu(a, b, x)))
|
||
|
|
||
|
def test_special_cases(self):
|
||
|
assert sc.hyperu(0, 1, 1) == 1.0
|
||
|
|
||
|
@pytest.mark.parametrize('a', [0.5, 1, np.nan])
|
||
|
@pytest.mark.parametrize('b', [1, 2, np.nan])
|
||
|
@pytest.mark.parametrize('x', [0.25, 3, np.nan])
|
||
|
def test_nan_inputs(self, a, b, x):
|
||
|
assert np.isnan(sc.hyperu(a, b, x)) == np.any(np.isnan([a, b, x]))
|
||
|
|
||
|
class TestHyp1f1(object):
|
||
|
|
||
|
@pytest.mark.parametrize('a, b, x', [
|
||
|
(np.nan, 1, 1),
|
||
|
(1, np.nan, 1),
|
||
|
(1, 1, np.nan)
|
||
|
])
|
||
|
def test_nan_inputs(self, a, b, x):
|
||
|
assert np.isnan(sc.hyp1f1(a, b, x))
|
||
|
|
||
|
def test_poles(self):
|
||
|
assert_equal(sc.hyp1f1(1, [0, -1, -2, -3, -4], 0.5), np.infty)
|
||
|
|
||
|
@pytest.mark.parametrize('a, b, x, result', [
|
||
|
(-1, 1, 0.5, 0.5),
|
||
|
(1, 1, 0.5, 1.6487212707001281468),
|
||
|
(2, 1, 0.5, 2.4730819060501922203),
|
||
|
(1, 2, 0.5, 1.2974425414002562937),
|
||
|
(-10, 1, 0.5, -0.38937441413785204475)
|
||
|
])
|
||
|
def test_special_cases(self, a, b, x, result):
|
||
|
# Hit all the special case branches at the beginning of the
|
||
|
# function. Desired answers computed using Mpmath.
|
||
|
assert_allclose(sc.hyp1f1(a, b, x), result, atol=0, rtol=1e-15)
|
||
|
|
||
|
@pytest.mark.parametrize('a, b, x, result', [
|
||
|
(1, 1, 0.44, 1.5527072185113360455),
|
||
|
(-1, 1, 0.44, 0.55999999999999999778),
|
||
|
(100, 100, 0.89, 2.4351296512898745592),
|
||
|
(-100, 100, 0.89, 0.40739062490768104667),
|
||
|
(1.5, 100, 59.99, 3.8073513625965598107),
|
||
|
(-1.5, 100, 59.99, 0.25099240047125826943)
|
||
|
])
|
||
|
def test_geometric_convergence(self, a, b, x, result):
|
||
|
# Test the region where we are relying on the ratio of
|
||
|
#
|
||
|
# (|a| + 1) * |x| / |b|
|
||
|
#
|
||
|
# being small. Desired answers computed using Mpmath
|
||
|
assert_allclose(sc.hyp1f1(a, b, x), result, atol=0, rtol=1e-15)
|
||
|
|
||
|
@pytest.mark.parametrize('a, b, x, result', [
|
||
|
(-1, 1, 1.5, -0.5),
|
||
|
(-10, 1, 1.5, 0.41801777430943080357),
|
||
|
(-25, 1, 1.5, 0.25114491646037839809),
|
||
|
(-50, 1, 1.5, -0.25683643975194756115),
|
||
|
(-51, 1, 1.5, -0.19843162753845452972)
|
||
|
])
|
||
|
def test_a_negative_integer(self, a, b, x, result):
|
||
|
# Desired answers computed using Mpmath. After -51 the
|
||
|
# relative error becomes unsatisfactory and we start returning
|
||
|
# NaN.
|
||
|
assert_allclose(sc.hyp1f1(a, b, x), result, atol=0, rtol=1e-9)
|
||
|
|
||
|
def test_gh_3492(self):
|
||
|
desired = 0.99973683897677527773 # Computed using Mpmath
|
||
|
assert_allclose(
|
||
|
sc.hyp1f1(0.01, 150, -4),
|
||
|
desired,
|
||
|
atol=0,
|
||
|
rtol=1e-15
|
||
|
)
|
||
|
|
||
|
def test_gh_3593(self):
|
||
|
desired = 1.0020033381011970966 # Computed using Mpmath
|
||
|
assert_allclose(
|
||
|
sc.hyp1f1(1, 5, 0.01),
|
||
|
desired,
|
||
|
atol=0,
|
||
|
rtol=1e-15
|
||
|
)
|
||
|
|
||
|
@pytest.mark.parametrize('a, b, x, desired', [
|
||
|
(-1, -2, 2, 2),
|
||
|
(-1, -4, 10, 3.5),
|
||
|
(-2, -2, 1, 2.5)
|
||
|
])
|
||
|
def test_gh_11099(self, a, b, x, desired):
|
||
|
# All desired results computed using Mpmath
|
||
|
assert sc.hyp1f1(a, b, x) == desired
|