erf_inv.qbk 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145
  1. [section:error_inv Error Function Inverses]
  2. [h4 Synopsis]
  3. ``
  4. #include <boost/math/special_functions/erf.hpp>
  5. ``
  6. namespace boost{ namespace math{
  7. template <class T>
  8. ``__sf_result`` erf_inv(T p);
  9. template <class T, class ``__Policy``>
  10. ``__sf_result`` erf_inv(T p, const ``__Policy``&);
  11. template <class T>
  12. ``__sf_result`` erfc_inv(T p);
  13. template <class T, class ``__Policy``>
  14. ``__sf_result`` erfc_inv(T p, const ``__Policy``&);
  15. }} // namespaces
  16. The return type of these functions is computed using the __arg_promotion_rules:
  17. the return type is `double` if T is an integer type, and T otherwise.
  18. [optional_policy]
  19. [h4 Description]
  20. template <class T>
  21. ``__sf_result`` erf_inv(T z);
  22. template <class T, class ``__Policy``>
  23. ``__sf_result`` erf_inv(T z, const ``__Policy``&);
  24. Returns the [@http://functions.wolfram.com/GammaBetaErf/InverseErf/ inverse error function]
  25. of z, that is a value x such that:
  26. [expression ['p = erf(x);]]
  27. [graph erf_inv]
  28. template <class T>
  29. ``__sf_result`` erfc_inv(T z);
  30. template <class T, class ``__Policy``>
  31. ``__sf_result`` erfc_inv(T z, const ``__Policy``&);
  32. Returns the inverse of the complement of the error function of z, that is a
  33. value x such that:
  34. [expression ['p = erfc(x);]]
  35. [graph erfc_inv]
  36. [h4 Accuracy]
  37. For types up to and including 80-bit long doubles the approximations used
  38. are accurate to less than ~ 2 epsilon. For higher precision types these
  39. functions have the same accuracy as the
  40. [link math_toolkit.sf_erf.error_function forward error functions].
  41. [table_erf_inv]
  42. [table_erfc_inv]
  43. The following error plot are based on an exhaustive search of the functions domain, MSVC-15.5 at `double` precision,
  44. and GCC-7.1/Ubuntu for `long double` and `__float128`.
  45. [graph erfc__double]
  46. [graph erfc__80_bit_long_double]
  47. [graph erfc____float128]
  48. [h4 Testing]
  49. There are two sets of tests:
  50. * Basic sanity checks attempt to "round-trip" from
  51. /x/ to /p/ and back again. These tests have quite
  52. generous tolerances: in general both the error functions and their
  53. inverses change so rapidly in some places that round tripping to more than a couple
  54. of significant digits isn't possible. This is especially true when
  55. /p/ is very near one: in this case there isn't enough
  56. "information content" in the input to the inverse function to get
  57. back where you started.
  58. * Accuracy checks using high-precision test values. These measure
  59. the accuracy of the result, given /exact/ input values.
  60. [h4 Implementation]
  61. These functions use a rational approximation [jm_rationals]
  62. to calculate an initial
  63. approximation to the result that is accurate to ~10[super -19],
  64. then only if that has insufficient accuracy compared to the epsilon for T,
  65. do we clean up the result using
  66. [@http://en.wikipedia.org/wiki/Simple_rational_approximation Halley iteration].
  67. Constructing rational approximations to the erf/erfc functions is actually
  68. surprisingly hard, especially at high precision. For this reason no attempt
  69. has been made to achieve 10[super -34 ] accuracy suitable for use with 128-bit
  70. reals.
  71. In the following discussion, /p/ is the value passed to erf_inv, and /q/ is
  72. the value passed to erfc_inv, so that /p = 1 - q/ and /q = 1 - p/ and in both
  73. cases we want to solve for the same result /x/.
  74. For /p < 0.5/ the inverse erf function is reasonably smooth and the approximation:
  75. [expression ['x = p(p + 10)(Y + R(p))]]
  76. Gives a good result for a constant Y, and R(p) optimised for low absolute error
  77. compared to |Y|.
  78. For q < 0.5 things get trickier, over the interval /0.5 > q > 0.25/
  79. the following approximation works well:
  80. [expression ['x = sqrt(-2log(q)) / (Y + R(q))]]
  81. While for q < 0.25, let
  82. [expression ['z = sqrt(-log(q))]]
  83. Then the result is given by:
  84. [expression ['x = z(Y + R(z - B))]]
  85. As before Y is a constant and the rational function R is optimised for low
  86. absolute error compared to |Y|. B is also a constant: it is the smallest value
  87. of /z/ for which each approximation is valid. There are several approximations
  88. of this form each of which reaches a little further into the tail of the erfc
  89. function (at `long double` precision the extended exponent range compared to
  90. `double` means that the tail goes on for a very long way indeed).
  91. [endsect] [/ :error_inv The Error Function Inverses]
  92. [/
  93. Copyright 2006 John Maddock and Paul A. Bristow.
  94. Distributed under the Boost Software License, Version 1.0.
  95. (See accompanying file LICENSE_1_0.txt or copy at
  96. http://www.boost.org/LICENSE_1_0.txt).
  97. ]