|
""" |
|
Test cdflib functions versus mpmath, if available. |
|
|
|
The following functions still need tests: |
|
|
|
- ncfdtri |
|
- ncfdtridfn |
|
- ncfdtridfd |
|
- ncfdtrinc |
|
- nbdtrik |
|
- nbdtrin |
|
- pdtrik |
|
- nctdtrit |
|
- nctdtridf |
|
- nctdtrinc |
|
|
|
""" |
|
import itertools |
|
|
|
import numpy as np |
|
from numpy.testing import assert_equal, assert_allclose |
|
import pytest |
|
|
|
import scipy.special as sp |
|
from scipy.special._testutils import ( |
|
MissingModule, check_version, FuncData) |
|
from scipy.special._mptestutils import ( |
|
Arg, IntArg, get_args, mpf2float, assert_mpmath_equal) |
|
|
|
try: |
|
import mpmath |
|
except ImportError: |
|
mpmath = MissingModule('mpmath') |
|
|
|
|
|
class ProbArg: |
|
"""Generate a set of probabilities on [0, 1].""" |
|
|
|
def __init__(self): |
|
|
|
self.a = 0 |
|
self.b = 1 |
|
|
|
def values(self, n): |
|
"""Return an array containing approximately n numbers.""" |
|
m = max(1, n//3) |
|
v1 = np.logspace(-30, np.log10(0.3), m) |
|
v2 = np.linspace(0.3, 0.7, m + 1, endpoint=False)[1:] |
|
v3 = 1 - np.logspace(np.log10(0.3), -15, m) |
|
v = np.r_[v1, v2, v3] |
|
return np.unique(v) |
|
|
|
|
|
class EndpointFilter: |
|
def __init__(self, a, b, rtol, atol): |
|
self.a = a |
|
self.b = b |
|
self.rtol = rtol |
|
self.atol = atol |
|
|
|
def __call__(self, x): |
|
mask1 = np.abs(x - self.a) < self.rtol*np.abs(self.a) + self.atol |
|
mask2 = np.abs(x - self.b) < self.rtol*np.abs(self.b) + self.atol |
|
return np.where(mask1 | mask2, False, True) |
|
|
|
|
|
class _CDFData: |
|
def __init__(self, spfunc, mpfunc, index, argspec, spfunc_first=True, |
|
dps=20, n=5000, rtol=None, atol=None, |
|
endpt_rtol=None, endpt_atol=None): |
|
self.spfunc = spfunc |
|
self.mpfunc = mpfunc |
|
self.index = index |
|
self.argspec = argspec |
|
self.spfunc_first = spfunc_first |
|
self.dps = dps |
|
self.n = n |
|
self.rtol = rtol |
|
self.atol = atol |
|
|
|
if not isinstance(argspec, list): |
|
self.endpt_rtol = None |
|
self.endpt_atol = None |
|
elif endpt_rtol is not None or endpt_atol is not None: |
|
if isinstance(endpt_rtol, list): |
|
self.endpt_rtol = endpt_rtol |
|
else: |
|
self.endpt_rtol = [endpt_rtol]*len(self.argspec) |
|
if isinstance(endpt_atol, list): |
|
self.endpt_atol = endpt_atol |
|
else: |
|
self.endpt_atol = [endpt_atol]*len(self.argspec) |
|
else: |
|
self.endpt_rtol = None |
|
self.endpt_atol = None |
|
|
|
def idmap(self, *args): |
|
if self.spfunc_first: |
|
res = self.spfunc(*args) |
|
if np.isnan(res): |
|
return np.nan |
|
args = list(args) |
|
args[self.index] = res |
|
with mpmath.workdps(self.dps): |
|
res = self.mpfunc(*tuple(args)) |
|
|
|
res = mpf2float(res.real) |
|
else: |
|
with mpmath.workdps(self.dps): |
|
res = self.mpfunc(*args) |
|
res = mpf2float(res.real) |
|
args = list(args) |
|
args[self.index] = res |
|
res = self.spfunc(*tuple(args)) |
|
return res |
|
|
|
def get_param_filter(self): |
|
if self.endpt_rtol is None and self.endpt_atol is None: |
|
return None |
|
|
|
filters = [] |
|
for rtol, atol, spec in zip(self.endpt_rtol, self.endpt_atol, self.argspec): |
|
if rtol is None and atol is None: |
|
filters.append(None) |
|
continue |
|
elif rtol is None: |
|
rtol = 0.0 |
|
elif atol is None: |
|
atol = 0.0 |
|
|
|
filters.append(EndpointFilter(spec.a, spec.b, rtol, atol)) |
|
return filters |
|
|
|
def check(self): |
|
|
|
args = get_args(self.argspec, self.n) |
|
param_filter = self.get_param_filter() |
|
param_columns = tuple(range(args.shape[1])) |
|
result_columns = args.shape[1] |
|
args = np.hstack((args, args[:, self.index].reshape(args.shape[0], 1))) |
|
FuncData(self.idmap, args, |
|
param_columns=param_columns, result_columns=result_columns, |
|
rtol=self.rtol, atol=self.atol, vectorized=False, |
|
param_filter=param_filter).check() |
|
|
|
|
|
def _assert_inverts(*a, **kw): |
|
d = _CDFData(*a, **kw) |
|
d.check() |
|
|
|
|
|
def _binomial_cdf(k, n, p): |
|
k, n, p = mpmath.mpf(k), mpmath.mpf(n), mpmath.mpf(p) |
|
if k <= 0: |
|
return mpmath.mpf(0) |
|
elif k >= n: |
|
return mpmath.mpf(1) |
|
|
|
onemp = mpmath.fsub(1, p, exact=True) |
|
return mpmath.betainc(n - k, k + 1, x2=onemp, regularized=True) |
|
|
|
|
|
def _f_cdf(dfn, dfd, x): |
|
if x < 0: |
|
return mpmath.mpf(0) |
|
dfn, dfd, x = mpmath.mpf(dfn), mpmath.mpf(dfd), mpmath.mpf(x) |
|
ub = dfn*x/(dfn*x + dfd) |
|
res = mpmath.betainc(dfn/2, dfd/2, x2=ub, regularized=True) |
|
return res |
|
|
|
|
|
def _student_t_cdf(df, t, dps=None): |
|
if dps is None: |
|
dps = mpmath.mp.dps |
|
with mpmath.workdps(dps): |
|
df, t = mpmath.mpf(df), mpmath.mpf(t) |
|
fac = mpmath.hyp2f1(0.5, 0.5*(df + 1), 1.5, -t**2/df) |
|
fac *= t*mpmath.gamma(0.5*(df + 1)) |
|
fac /= mpmath.sqrt(mpmath.pi*df)*mpmath.gamma(0.5*df) |
|
return 0.5 + fac |
|
|
|
|
|
def _noncentral_chi_pdf(t, df, nc): |
|
res = mpmath.besseli(df/2 - 1, mpmath.sqrt(nc*t)) |
|
res *= mpmath.exp(-(t + nc)/2)*(t/nc)**(df/4 - 1/2)/2 |
|
return res |
|
|
|
|
|
def _noncentral_chi_cdf(x, df, nc, dps=None): |
|
if dps is None: |
|
dps = mpmath.mp.dps |
|
x, df, nc = mpmath.mpf(x), mpmath.mpf(df), mpmath.mpf(nc) |
|
with mpmath.workdps(dps): |
|
res = mpmath.quad(lambda t: _noncentral_chi_pdf(t, df, nc), [0, x]) |
|
return res |
|
|
|
|
|
def _tukey_lmbda_quantile(p, lmbda): |
|
|
|
return (p**lmbda - (1 - p)**lmbda)/lmbda |
|
|
|
|
|
@pytest.mark.slow |
|
@check_version(mpmath, '0.19') |
|
class TestCDFlib: |
|
|
|
@pytest.mark.xfail(run=False) |
|
def test_bdtrik(self): |
|
_assert_inverts( |
|
sp.bdtrik, |
|
_binomial_cdf, |
|
0, [ProbArg(), IntArg(1, 1000), ProbArg()], |
|
rtol=1e-4) |
|
|
|
def test_bdtrin(self): |
|
_assert_inverts( |
|
sp.bdtrin, |
|
_binomial_cdf, |
|
1, [IntArg(1, 1000), ProbArg(), ProbArg()], |
|
rtol=1e-4, endpt_atol=[None, None, 1e-6]) |
|
|
|
def test_btdtria(self): |
|
_assert_inverts( |
|
sp.btdtria, |
|
lambda a, b, x: mpmath.betainc(a, b, x2=x, regularized=True), |
|
0, [ProbArg(), Arg(0, 1e2, inclusive_a=False), |
|
Arg(0, 1, inclusive_a=False, inclusive_b=False)], |
|
rtol=1e-6) |
|
|
|
def test_btdtrib(self): |
|
|
|
_assert_inverts( |
|
sp.btdtrib, |
|
lambda a, b, x: mpmath.betainc(a, b, x2=x, regularized=True), |
|
1, |
|
[Arg(0, 1e2, inclusive_a=False), ProbArg(), |
|
Arg(0, 1, inclusive_a=False, inclusive_b=False)], |
|
rtol=1e-7, |
|
endpt_atol=[None, 1e-18, 1e-15]) |
|
|
|
@pytest.mark.xfail(run=False) |
|
def test_fdtridfd(self): |
|
_assert_inverts( |
|
sp.fdtridfd, |
|
_f_cdf, |
|
1, |
|
[IntArg(1, 100), ProbArg(), Arg(0, 100, inclusive_a=False)], |
|
rtol=1e-7) |
|
|
|
def test_gdtria(self): |
|
_assert_inverts( |
|
sp.gdtria, |
|
lambda a, b, x: mpmath.gammainc(b, b=a*x, regularized=True), |
|
0, |
|
[ProbArg(), Arg(0, 1e3, inclusive_a=False), |
|
Arg(0, 1e4, inclusive_a=False)], |
|
rtol=1e-7, |
|
endpt_atol=[None, 1e-7, 1e-10]) |
|
|
|
def test_gdtrib(self): |
|
|
|
_assert_inverts( |
|
sp.gdtrib, |
|
lambda a, b, x: mpmath.gammainc(b, b=a*x, regularized=True), |
|
1, |
|
[Arg(0, 1e2, inclusive_a=False), ProbArg(), |
|
Arg(0, 1e3, inclusive_a=False)], |
|
rtol=1e-5) |
|
|
|
def test_gdtrix(self): |
|
_assert_inverts( |
|
sp.gdtrix, |
|
lambda a, b, x: mpmath.gammainc(b, b=a*x, regularized=True), |
|
2, |
|
[Arg(0, 1e3, inclusive_a=False), Arg(0, 1e3, inclusive_a=False), |
|
ProbArg()], |
|
rtol=1e-7, |
|
endpt_atol=[None, 1e-7, 1e-10]) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def test_nrdtrimn(self): |
|
_assert_inverts( |
|
sp.nrdtrimn, |
|
lambda x, y, z: mpmath.ncdf(z, x, y), |
|
0, |
|
[ProbArg(), |
|
Arg(0.1, np.inf, inclusive_a=False, inclusive_b=False), |
|
Arg(-1e10, 1e10)], |
|
rtol=1e-5) |
|
|
|
def test_nrdtrisd(self): |
|
_assert_inverts( |
|
sp.nrdtrisd, |
|
lambda x, y, z: mpmath.ncdf(z, x, y), |
|
1, |
|
[Arg(-np.inf, 10, inclusive_a=False, inclusive_b=False), |
|
ProbArg(), |
|
Arg(10, 1e100)], |
|
rtol=1e-5) |
|
|
|
def test_stdtr(self): |
|
|
|
assert_mpmath_equal( |
|
sp.stdtr, |
|
_student_t_cdf, |
|
[IntArg(1, 100), Arg(1e-10, np.inf)], rtol=1e-7) |
|
|
|
@pytest.mark.xfail(run=False) |
|
def test_stdtridf(self): |
|
_assert_inverts( |
|
sp.stdtridf, |
|
_student_t_cdf, |
|
0, [ProbArg(), Arg()], rtol=1e-7) |
|
|
|
def test_stdtrit(self): |
|
_assert_inverts( |
|
sp.stdtrit, |
|
_student_t_cdf, |
|
1, [IntArg(1, 100), ProbArg()], rtol=1e-7, |
|
endpt_atol=[None, 1e-10]) |
|
|
|
def test_chdtriv(self): |
|
_assert_inverts( |
|
sp.chdtriv, |
|
lambda v, x: mpmath.gammainc(v/2, b=x/2, regularized=True), |
|
0, [ProbArg(), IntArg(1, 100)], rtol=1e-4) |
|
|
|
@pytest.mark.xfail(run=False) |
|
def test_chndtridf(self): |
|
|
|
_assert_inverts( |
|
sp.chndtridf, |
|
_noncentral_chi_cdf, |
|
1, [Arg(0, 100, inclusive_a=False), ProbArg(), |
|
Arg(0, 100, inclusive_a=False)], |
|
n=1000, rtol=1e-4, atol=1e-15) |
|
|
|
@pytest.mark.xfail(run=False) |
|
def test_chndtrinc(self): |
|
|
|
_assert_inverts( |
|
sp.chndtrinc, |
|
_noncentral_chi_cdf, |
|
2, [Arg(0, 100, inclusive_a=False), IntArg(1, 100), ProbArg()], |
|
n=1000, rtol=1e-4, atol=1e-15) |
|
|
|
def test_chndtrix(self): |
|
|
|
_assert_inverts( |
|
sp.chndtrix, |
|
_noncentral_chi_cdf, |
|
0, [ProbArg(), IntArg(1, 100), Arg(0, 100, inclusive_a=False)], |
|
n=1000, rtol=1e-4, atol=1e-15, |
|
endpt_atol=[1e-6, None, None]) |
|
|
|
def test_tklmbda_zero_shape(self): |
|
|
|
one = mpmath.mpf(1) |
|
assert_mpmath_equal( |
|
lambda x: sp.tklmbda(x, 0), |
|
lambda x: one/(mpmath.exp(-x) + one), |
|
[Arg()], rtol=1e-7) |
|
|
|
def test_tklmbda_neg_shape(self): |
|
_assert_inverts( |
|
sp.tklmbda, |
|
_tukey_lmbda_quantile, |
|
0, [ProbArg(), Arg(-25, 0, inclusive_b=False)], |
|
spfunc_first=False, rtol=1e-5, |
|
endpt_atol=[1e-9, 1e-5]) |
|
|
|
@pytest.mark.xfail(run=False) |
|
def test_tklmbda_pos_shape(self): |
|
_assert_inverts( |
|
sp.tklmbda, |
|
_tukey_lmbda_quantile, |
|
0, [ProbArg(), Arg(0, 100, inclusive_a=False)], |
|
spfunc_first=False, rtol=1e-5) |
|
|
|
|
|
@pytest.mark.parametrize('lmbda', [0.5, 1.0, 8.0]) |
|
def test_tklmbda_lmbda1(self, lmbda): |
|
bound = 1/lmbda |
|
assert_equal(sp.tklmbda([-bound, bound], lmbda), [0.0, 1.0]) |
|
|
|
|
|
funcs = [ |
|
("btdtria", 3), |
|
("btdtrib", 3), |
|
("bdtrik", 3), |
|
("bdtrin", 3), |
|
("chdtriv", 2), |
|
("chndtr", 3), |
|
("chndtrix", 3), |
|
("chndtridf", 3), |
|
("chndtrinc", 3), |
|
("fdtridfd", 3), |
|
("ncfdtr", 4), |
|
("ncfdtri", 4), |
|
("ncfdtridfn", 4), |
|
("ncfdtridfd", 4), |
|
("ncfdtrinc", 4), |
|
("gdtrix", 3), |
|
("gdtrib", 3), |
|
("gdtria", 3), |
|
("nbdtrik", 3), |
|
("nbdtrin", 3), |
|
("nrdtrimn", 3), |
|
("nrdtrisd", 3), |
|
("pdtrik", 2), |
|
("stdtr", 2), |
|
("stdtrit", 2), |
|
("stdtridf", 2), |
|
("nctdtr", 3), |
|
("nctdtrit", 3), |
|
("nctdtridf", 3), |
|
("nctdtrinc", 3), |
|
("tklmbda", 2), |
|
] |
|
|
|
|
|
@pytest.mark.parametrize('func,numargs', funcs, ids=[x[0] for x in funcs]) |
|
def test_nonfinite(func, numargs): |
|
|
|
rng = np.random.default_rng(1701299355559735) |
|
func = getattr(sp, func) |
|
args_choices = [(float(x), np.nan, np.inf, -np.inf) for x in rng.random(numargs)] |
|
|
|
for args in itertools.product(*args_choices): |
|
res = func(*args) |
|
|
|
if any(np.isnan(x) for x in args): |
|
|
|
assert_equal(res, np.nan) |
|
else: |
|
|
|
|
|
pass |
|
|
|
|
|
def test_chndtrix_gh2158(): |
|
|
|
res = sp.chndtrix(0.999999, 2, np.arange(20.)+1e-6) |
|
|
|
|
|
|
|
|
|
|
|
res_exp = [27.63103493142305, 35.25728589950540, 39.97396073236288, |
|
43.88033702110538, 47.35206403482798, 50.54112500166103, |
|
53.52720257322766, 56.35830042867810, 59.06600769498512, |
|
61.67243118946381, 64.19376191277179, 66.64228141346548, |
|
69.02756927200180, 71.35726934749408, 73.63759723904816, |
|
75.87368842650227, 78.06984431185720, 80.22971052389806, |
|
82.35640899964173, 84.45263768373256] |
|
assert_allclose(res, res_exp) |
|
|
|
|
|
def test_nctdtrinc_gh19896(): |
|
|
|
|
|
dfarr = [0.001, 0.98, 9.8, 98, 980, 10000, 98, 9.8, 0.98, 0.001] |
|
parr = [0.001, 0.1, 0.3, 0.8, 0.999, 0.001, 0.1, 0.3, 0.8, 0.999] |
|
tarr = [0.0015, 0.15, 1.5, 15, 300, 0.0015, 0.15, 1.5, 15, 300] |
|
desired = [3.090232306168629, 1.406141304556198, 2.014225177124157, |
|
13.727067118283456, 278.9765683871208, 3.090232306168629, |
|
1.4312427877936222, 2.014225177124157, 3.712743137978295, |
|
-3.086951096691082] |
|
actual = sp.nctdtrinc(dfarr, parr, tarr) |
|
assert_allclose(actual, desired, rtol=5e-12, atol=0.0) |
|
|
|
|
|
def test_stdtr_stdtrit_neg_inf(): |
|
|
|
assert np.all(np.isnan(sp.stdtr(-np.inf, [-np.inf, -1.0, 0.0, 1.0, np.inf]))) |
|
assert np.all(np.isnan(sp.stdtrit(-np.inf, [0.0, 0.25, 0.5, 0.75, 1.0]))) |
|
|
|
|
|
def test_bdtrik_nbdtrik_inf(): |
|
y = np.array( |
|
[np.nan,-np.inf,-10.0, -1.0, 0.0, .00001, .5, 0.9999, 1.0, 10.0, np.inf]) |
|
y = y[:,None] |
|
p = np.atleast_2d( |
|
[np.nan, -np.inf, -10.0, -1.0, 0.0, .00001, .5, 1.0, np.inf]) |
|
assert np.all(np.isnan(sp.bdtrik(y, np.inf, p))) |
|
assert np.all(np.isnan(sp.nbdtrik(y, np.inf, p))) |
|
|
|
|
|
@pytest.mark.parametrize( |
|
"dfn,dfd,nc,f,expected", |
|
[[100.0, 0.1, 0.1, 100.0, 0.29787396410092676], |
|
[100.0, 100.0, 0.01, 0.1, 4.4344737598690424e-26], |
|
[100.0, 0.01, 0.1, 0.01, 0.002848616633080384], |
|
[10.0, 0.01, 1.0, 0.1, 0.012339557729057956], |
|
[100.0, 100.0, 0.01, 0.01, 1.8926477420964936e-72], |
|
[1.0, 100.0, 100.0, 0.1, 1.7925940526821304e-22], |
|
[1.0, 0.01, 100.0, 10.0, 0.012334711965024968], |
|
[1.0, 0.01, 10.0, 0.01, 0.00021944525290299], |
|
[10.0, 1.0, 0.1, 100.0, 0.9219345555070705], |
|
[0.1, 0.1, 1.0, 1.0, 0.3136335813423239], |
|
[100.0, 100.0, 0.1, 10.0, 1.0], |
|
[1.0, 0.1, 100.0, 10.0, 0.02926064279680897]] |
|
) |
|
def test_ncfdtr(dfn, dfd, nc, f, expected): |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
assert_allclose(sp.ncfdtr(dfn, dfd, nc, f), expected, rtol=1e-13, atol=0) |
|
|
|
|
|
class TestNctdtr: |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.mark.parametrize("df, nc, x, expected", [ |
|
(0.98, -3.8, 0.0015, 0.9999279987514815), |
|
(0.98, -3.8, 0.15, 0.9999528361700505), |
|
(0.98, -3.8, 1.5, 0.9999908823016942), |
|
(0.98, -3.8, 15, 0.9999990264591945), |
|
(0.98, 0.38, 0.0015, 0.35241533122693), |
|
(0.98, 0.38, 0.15, 0.39749697267146983), |
|
(0.98, 0.38, 1.5, 0.716862963488558), |
|
(0.98, 0.38, 15, 0.9656246449257494), |
|
(0.98, 3.8, 0.0015, 7.26973354942293e-05), |
|
(0.98, 3.8, 0.15, 0.00012416481147589105), |
|
(0.98, 3.8, 1.5, 0.035388035775454095), |
|
(0.98, 3.8, 15, 0.7954826975430583), |
|
(0.98, 38, 0.0015, 3.02106943e-316), |
|
(0.98, 38, 0.15, 6.069970616996603e-309), |
|
(0.98, 38, 1.5, 2.591995360483094e-97), |
|
(0.98, 38, 15, 0.011927265886910935), |
|
(9.8, -3.8, 0.0015, 0.9999280776192786), |
|
(9.8, -3.8, 0.15, 0.9999599410685442), |
|
(9.8, -3.8, 1.5, 0.9999997432394788), |
|
(9.8, -3.8, 15, 0.9999999999999984), |
|
(9.8, 0.38, 0.0015, 0.3525155979107491), |
|
(9.8, 0.38, 0.15, 0.40763120140379194), |
|
(9.8, 0.38, 1.5, 0.8476794017024651), |
|
(9.8, 0.38, 15, 0.9999999297116268), |
|
(9.8, 3.8, 0.0015, 7.277620328149153e-05), |
|
(9.8, 3.8, 0.15, 0.00013024802220900652), |
|
(9.8, 3.8, 1.5, 0.013477432800072933), |
|
(9.8, 3.8, 15, 0.999850151230648), |
|
(9.8, 38, 0.0015, 3.05066095e-316), |
|
(9.8, 38, 0.15, 1.79065514676e-313), |
|
(9.8, 38, 1.5, 2.0935940165900746e-249), |
|
(9.8, 38, 15, 2.252076291604796e-09), |
|
(98, -3.8, 0.0015, 0.9999280875149109), |
|
(98, -3.8, 0.15, 0.9999608250170452), |
|
(98, -3.8, 1.5, 0.9999999304757682), |
|
(98, -3.8, 15, 1.0), |
|
(98, 0.38, 0.0015, 0.35252817848596313), |
|
(98, 0.38, 0.15, 0.40890253001794846), |
|
(98, 0.38, 1.5, 0.8664672830006552), |
|
(98, 0.38, 15, 1.0), |
|
(98, 3.8, 0.0015, 7.278609891281275e-05), |
|
(98, 3.8, 0.15, 0.0001310318674827004), |
|
(98, 3.8, 1.5, 0.010990879189991727), |
|
(98, 3.8, 15, 0.9999999999999989), |
|
(98, 38, 0.0015, 3.05437385e-316), |
|
(98, 38, 0.15, 9.1668336166e-314), |
|
(98, 38, 1.5, 1.8085884236563926e-288), |
|
(98, 38, 15, 2.7740532792035907e-50), |
|
(980, -3.8, 0.0015, 0.9999280885188965), |
|
(980, -3.8, 0.15, 0.9999609144559273), |
|
(980, -3.8, 1.5, 0.9999999410050979), |
|
(980, -3.8, 15, 1.0), |
|
(980, 0.38, 0.0015, 0.3525294548792812), |
|
(980, 0.38, 0.15, 0.4090315324657382), |
|
(980, 0.38, 1.5, 0.8684247068517293), |
|
(980, 0.38, 15, 1.0), |
|
(980, 3.8, 0.0015, 7.278710289828983e-05), |
|
(980, 3.8, 0.15, 0.00013111131667906573), |
|
(980, 3.8, 1.5, 0.010750678886113882), |
|
(980, 3.8, 15, 1.0), |
|
(980, 38, 0.0015, 3.0547506e-316), |
|
(980, 38, 0.15, 8.6191646313e-314), |
|
pytest.param(980, 38, 1.5, 1.1824454111413493e-291, |
|
marks=pytest.mark.xfail( |
|
reason="Bug in underlying Boost math implementation")), |
|
(980, 38, 15, 5.407535300713606e-105) |
|
]) |
|
def test_gh19896(self, df, nc, x, expected): |
|
|
|
|
|
|
|
|
|
result = sp.nctdtr(df, nc, x) |
|
assert_allclose(result, expected, rtol=1e-13, atol=1e-303) |
|
|
|
def test_nctdtr_gh8344(self): |
|
|
|
df, nc, x = 3000, 3, 0.1 |
|
expected = 0.0018657780826323328 |
|
assert_allclose(sp.nctdtr(df, nc, x), expected, rtol=1e-14) |
|
|
|
@pytest.mark.parametrize( |
|
"df, nc, x, expected, rtol", |
|
[[3., 5., -2., 1.5645373999149622e-09, 5e-9], |
|
[1000., 10., 1., 1.1493552133826623e-19, 1e-13], |
|
[1e-5, -6., 2., 0.9999999990135003, 1e-13], |
|
[10., 20., 0.15, 6.426530505957303e-88, 1e-13], |
|
[1., 1., np.inf, 1.0, 0.0], |
|
[1., 1., -np.inf, 0.0, 0.0] |
|
] |
|
) |
|
def test_accuracy(self, df, nc, x, expected, rtol): |
|
assert_allclose(sp.nctdtr(df, nc, x), expected, rtol=rtol) |
|
|