test_gammainc.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import pytest
  2. import numpy as np
  3. from numpy.testing import assert_allclose, assert_array_equal
  4. import scipy.special as sc
  5. from scipy.special._testutils import FuncData
  6. INVALID_POINTS = [
  7. (1, -1),
  8. (0, 0),
  9. (-1, 1),
  10. (np.nan, 1),
  11. (1, np.nan)
  12. ]
  13. class TestGammainc:
  14. @pytest.mark.parametrize('a, x', INVALID_POINTS)
  15. def test_domain(self, a, x):
  16. assert np.isnan(sc.gammainc(a, x))
  17. def test_a_eq_0_x_gt_0(self):
  18. assert sc.gammainc(0, 1) == 1
  19. @pytest.mark.parametrize('a, x, desired', [
  20. (np.inf, 1, 0),
  21. (np.inf, 0, 0),
  22. (np.inf, np.inf, np.nan),
  23. (1, np.inf, 1)
  24. ])
  25. def test_infinite_arguments(self, a, x, desired):
  26. result = sc.gammainc(a, x)
  27. if np.isnan(desired):
  28. assert np.isnan(result)
  29. else:
  30. assert result == desired
  31. @pytest.mark.parametrize("x", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  32. def test_a_nan(self, x):
  33. assert np.isnan(sc.gammainc(np.nan, x))
  34. @pytest.mark.parametrize("a", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  35. def test_x_nan(self, a):
  36. assert np.isnan(sc.gammainc(a, np.nan))
  37. def test_infinite_limits(self):
  38. # Test that large arguments converge to the hard-coded limits
  39. # at infinity.
  40. assert_allclose(
  41. sc.gammainc(1000, 100),
  42. sc.gammainc(np.inf, 100),
  43. atol=1e-200, # Use `atol` since the function converges to 0.
  44. rtol=0
  45. )
  46. assert sc.gammainc(100, 1000) == sc.gammainc(100, np.inf)
  47. def test_x_zero(self):
  48. a = np.arange(1, 10)
  49. assert_array_equal(sc.gammainc(a, 0), 0)
  50. def test_limit_check(self):
  51. result = sc.gammainc(1e-10, 1)
  52. limit = sc.gammainc(0, 1)
  53. assert np.isclose(result, limit)
  54. def gammainc_line(self, x):
  55. # The line a = x where a simpler asymptotic expansion (analog
  56. # of DLMF 8.12.15) is available.
  57. c = np.array([-1/3, -1/540, 25/6048, 101/155520,
  58. -3184811/3695155200, -2745493/8151736420])
  59. res = 0
  60. xfac = 1
  61. for ck in c:
  62. res -= ck*xfac
  63. xfac /= x
  64. res /= np.sqrt(2*np.pi*x)
  65. res += 0.5
  66. return res
  67. def test_line(self):
  68. x = np.logspace(np.log10(25), 300, 500)
  69. a = x
  70. dataset = np.vstack((a, x, self.gammainc_line(x))).T
  71. FuncData(sc.gammainc, dataset, (0, 1), 2, rtol=1e-11).check()
  72. def test_roundtrip(self):
  73. a = np.logspace(-5, 10, 100)
  74. x = np.logspace(-5, 10, 100)
  75. y = sc.gammaincinv(a, sc.gammainc(a, x))
  76. assert_allclose(x, y, rtol=1e-10)
  77. class TestGammaincc:
  78. @pytest.mark.parametrize('a, x', INVALID_POINTS)
  79. def test_domain(self, a, x):
  80. assert np.isnan(sc.gammaincc(a, x))
  81. def test_a_eq_0_x_gt_0(self):
  82. assert sc.gammaincc(0, 1) == 0
  83. @pytest.mark.parametrize('a, x, desired', [
  84. (np.inf, 1, 1),
  85. (np.inf, 0, 1),
  86. (np.inf, np.inf, np.nan),
  87. (1, np.inf, 0)
  88. ])
  89. def test_infinite_arguments(self, a, x, desired):
  90. result = sc.gammaincc(a, x)
  91. if np.isnan(desired):
  92. assert np.isnan(result)
  93. else:
  94. assert result == desired
  95. @pytest.mark.parametrize("x", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  96. def test_a_nan(self, x):
  97. assert np.isnan(sc.gammaincc(np.nan, x))
  98. @pytest.mark.parametrize("a", [-np.inf, -1.0, -0.0, 0.0, np.inf, np.nan])
  99. def test_x_nan(self, a):
  100. assert np.isnan(sc.gammaincc(a, np.nan))
  101. def test_infinite_limits(self):
  102. # Test that large arguments converge to the hard-coded limits
  103. # at infinity.
  104. assert sc.gammaincc(1000, 100) == sc.gammaincc(np.inf, 100)
  105. assert_allclose(
  106. sc.gammaincc(100, 1000),
  107. sc.gammaincc(100, np.inf),
  108. atol=1e-200, # Use `atol` since the function converges to 0.
  109. rtol=0
  110. )
  111. def test_limit_check(self):
  112. result = sc.gammaincc(1e-10,1)
  113. limit = sc.gammaincc(0,1)
  114. assert np.isclose(result, limit)
  115. def test_x_zero(self):
  116. a = np.arange(1, 10)
  117. assert_array_equal(sc.gammaincc(a, 0), 1)
  118. def test_roundtrip(self):
  119. a = np.logspace(-5, 10, 100)
  120. x = np.logspace(-5, 10, 100)
  121. y = sc.gammainccinv(a, sc.gammaincc(a, x))
  122. assert_allclose(x, y, rtol=1e-14)