test_gammainc.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. def test_infinite_limits(self):
  32. # Test that large arguments converge to the hard-coded limits
  33. # at infinity.
  34. assert_allclose(
  35. sc.gammainc(1000, 100),
  36. sc.gammainc(np.inf, 100),
  37. atol=1e-200, # Use `atol` since the function converges to 0.
  38. rtol=0
  39. )
  40. assert sc.gammainc(100, 1000) == sc.gammainc(100, np.inf)
  41. def test_x_zero(self):
  42. a = np.arange(1, 10)
  43. assert_array_equal(sc.gammainc(a, 0), 0)
  44. def test_limit_check(self):
  45. result = sc.gammainc(1e-10, 1)
  46. limit = sc.gammainc(0, 1)
  47. assert np.isclose(result, limit)
  48. def gammainc_line(self, x):
  49. # The line a = x where a simpler asymptotic expansion (analog
  50. # of DLMF 8.12.15) is available.
  51. c = np.array([-1/3, -1/540, 25/6048, 101/155520,
  52. -3184811/3695155200, -2745493/8151736420])
  53. res = 0
  54. xfac = 1
  55. for ck in c:
  56. res -= ck*xfac
  57. xfac /= x
  58. res /= np.sqrt(2*np.pi*x)
  59. res += 0.5
  60. return res
  61. def test_line(self):
  62. x = np.logspace(np.log10(25), 300, 500)
  63. a = x
  64. dataset = np.vstack((a, x, self.gammainc_line(x))).T
  65. FuncData(sc.gammainc, dataset, (0, 1), 2, rtol=1e-11).check()
  66. def test_roundtrip(self):
  67. a = np.logspace(-5, 10, 100)
  68. x = np.logspace(-5, 10, 100)
  69. y = sc.gammaincinv(a, sc.gammainc(a, x))
  70. assert_allclose(x, y, rtol=1e-10)
  71. class TestGammaincc:
  72. @pytest.mark.parametrize('a, x', INVALID_POINTS)
  73. def test_domain(self, a, x):
  74. assert np.isnan(sc.gammaincc(a, x))
  75. def test_a_eq_0_x_gt_0(self):
  76. assert sc.gammaincc(0, 1) == 0
  77. @pytest.mark.parametrize('a, x, desired', [
  78. (np.inf, 1, 1),
  79. (np.inf, 0, 1),
  80. (np.inf, np.inf, np.nan),
  81. (1, np.inf, 0)
  82. ])
  83. def test_infinite_arguments(self, a, x, desired):
  84. result = sc.gammaincc(a, x)
  85. if np.isnan(desired):
  86. assert np.isnan(result)
  87. else:
  88. assert result == desired
  89. def test_infinite_limits(self):
  90. # Test that large arguments converge to the hard-coded limits
  91. # at infinity.
  92. assert sc.gammaincc(1000, 100) == sc.gammaincc(np.inf, 100)
  93. assert_allclose(
  94. sc.gammaincc(100, 1000),
  95. sc.gammaincc(100, np.inf),
  96. atol=1e-200, # Use `atol` since the function converges to 0.
  97. rtol=0
  98. )
  99. def test_limit_check(self):
  100. result = sc.gammaincc(1e-10,1)
  101. limit = sc.gammaincc(0,1)
  102. assert np.isclose(result, limit)
  103. def test_x_zero(self):
  104. a = np.arange(1, 10)
  105. assert_array_equal(sc.gammaincc(a, 0), 1)
  106. def test_roundtrip(self):
  107. a = np.logspace(-5, 10, 100)
  108. x = np.logspace(-5, 10, 100)
  109. y = sc.gammainccinv(a, sc.gammaincc(a, x))
  110. assert_allclose(x, y, rtol=1e-14)