erfinv.c
Go to the documentation of this file.
1 /*
2  * mconf configures NANS, INFINITYs etc. for cephes and includes some standard
3  * headers. Although erfinv and erfcinv are not defined in cephes, erf and erfc
4  * are. We want to keep the behaviour consistent for the inverse functions and
5  * so need to include mconf.
6  */
7 #include "mconf.h"
8 
9 /*
10  * Inverse of the error function.
11  *
12  * Computes the inverse of the error function on the restricted domain
13  * -1 < y < 1. This restriction ensures the existence of a unique result
14  * such that erf(erfinv(y)) = y.
15  */
16 double erfinv(double y) {
17  const double domain_lb = -1;
18  const double domain_ub = 1;
19 
20  const double thresh = 1e-7;
21 
22  /*
23  * For small arguments, use the Taylor expansion
24  * erf(y) = 2/\sqrt{\pi} (y - y^3 / 3 + O(y^5)), y\to 0
25  * where we only retain the linear term.
26  * Otherwise, y + 1 loses precision for |y| << 1.
27  */
28  if ((-thresh < y) && (y < thresh)){
29  return y / M_2_SQRTPI;
30  }
31  if ((domain_lb < y) && (y < domain_ub)) {
32  return ndtri(0.5 * (y+1)) * M_SQRT1_2;
33  }
34  else if (y == domain_lb) {
35  return -INFINITY;
36  }
37  else if (y == domain_ub) {
38  return INFINITY;
39  }
40  else if (cephes_isnan(y)) {
41  sf_error("erfinv", SF_ERROR_DOMAIN, NULL);
42  return y;
43  }
44  else {
45  sf_error("erfinv", SF_ERROR_DOMAIN, NULL);
46  return NAN;
47  }
48 }
49 
50 /*
51  * Inverse of the complementary error function.
52  *
53  * Computes the inverse of the complimentary error function on the restricted
54  * domain 0 < y < 2. This restriction ensures the existence of a unique result
55  * such that erfc(erfcinv(y)) = y.
56  */
57 double erfcinv(double y) {
58  const double domain_lb = 0;
59  const double domain_ub = 2;
60 
61  if ((domain_lb < y) && (y < domain_ub)) {
62  return -ndtri(0.5 * y) * M_SQRT1_2;
63  }
64  else if (y == domain_lb) {
65  return INFINITY;
66  }
67  else if (y == domain_ub) {
68  return -INFINITY;
69  }
70  else if (cephes_isnan(y)) {
71  sf_error("erfcinv", SF_ERROR_DOMAIN, NULL);
72  return y;
73  }
74  else {
75  sf_error("erfcinv", SF_ERROR_DOMAIN, NULL);
76  return NAN;
77  }
78 }
e
Array< double, 1, 3 > e(1./3., 0.5, 2.)
cephes_isnan
#define cephes_isnan(x)
Definition: mconf.h:99
erfinv
double erfinv(double y)
Definition: erfinv.c:16
M_SQRT1_2
#define M_SQRT1_2
Definition: mconf.h:124
y
Scalar * y
Definition: level1_cplx_impl.h:124
mconf.h
erfcinv
double erfcinv(double y)
Definition: erfinv.c:57
M_2_SQRTPI
#define M_2_SQRTPI
Definition: mconf.h:122
sf_error
void sf_error(const char *func_name, sf_error_t code, const char *fmt,...)
Definition: sf_error.c:41
ndtri
double ndtri(double y0)
Definition: ndtri.c:134
NULL
#define NULL
Definition: ccolamd.c:609
SF_ERROR_DOMAIN
@ SF_ERROR_DOMAIN
Definition: sf_error.h:16


gtsam
Author(s):
autogenerated on Thu Jun 13 2024 03:02:18