89 lines
2.0 KiB
Rust
89 lines
2.0 KiB
Rust
use std::f64::consts::PI;
|
|
|
|
const CS: [f64; 14] = [
|
|
0.00048204,
|
|
-0.00142906,
|
|
0.0013200243174,
|
|
0.0009461589032,
|
|
-0.0045563339802,
|
|
0.00556964649138,
|
|
0.00125993961762116,
|
|
-0.01621575378835404,
|
|
0.02629651521057465,
|
|
-0.001829764677455021,
|
|
2.0 * (1.0 - PI / 3.0),
|
|
(4.0 - PI) / 3.0,
|
|
1.0,
|
|
1.0,
|
|
];
|
|
|
|
const RS: [f64; 5] = [
|
|
1.2753666447299659525,
|
|
5.019049726784267463450,
|
|
6.1602098531096305441,
|
|
7.409740605964741794425,
|
|
2.9788656263939928886,
|
|
];
|
|
|
|
const QS: [f64; 6] = [
|
|
2.260528520767326969592,
|
|
9.3960340162350541504,
|
|
12.048951927855129036034,
|
|
17.081440747466004316,
|
|
9.608965327192787870698,
|
|
3.3690752069827527677,
|
|
];
|
|
|
|
/// Normal cumulative density function.
|
|
fn normcdf(x: f64) -> f64 {
|
|
// If X ~ N(0,1), returns P(X < x).
|
|
// erfc(-x / SQRT2) / 2.0
|
|
// https://docs.rs/statrs/0.12.0/statrs/function/erf/fn.erfc.html
|
|
todo!();
|
|
}
|
|
|
|
/// Compute the log of the normal cumulative density function.
|
|
pub fn logphi(z: f64) -> (f64, f64) {
|
|
// Adapted from the GPML function `logphi.m`.
|
|
let SQRT2: f64 = 2.0f64.sqrt();
|
|
let SQRT2PI: f64 = (2.0 * PI).sqrt();
|
|
|
|
if z * z < 0.0492 {
|
|
// First case: z close to zero.
|
|
let coef = -z / SQRT2PI;
|
|
let mut val = 0.0;
|
|
|
|
for c in &CS {
|
|
val = coef * (c + val);
|
|
}
|
|
|
|
let res = -2.0 * val - 2.0f64.ln();
|
|
let dres = (-(z * z) / 2.0 - res).exp() / SQRT2PI;
|
|
|
|
(res, dres)
|
|
} else if z < -11.3137 {
|
|
// Second case: z very small.
|
|
let mut num = 0.5641895835477550741;
|
|
|
|
for r in &RS {
|
|
num = -z * num / SQRT2 + r;
|
|
}
|
|
|
|
let mut den = 1.0;
|
|
|
|
for q in &QS {
|
|
den = -z * den / SQRT2 + q;
|
|
}
|
|
|
|
let res = (num / (2.0 * den)).ln() - (z * z) / 2.0;
|
|
let dres = (den / num).abs() * (2.0 / PI).sqrt();
|
|
|
|
(res, dres)
|
|
} else {
|
|
let res = normcdf(z).ln();
|
|
let dres = (-(z * z) / 2.0 - res).exp() / SQRT2PI;
|
|
|
|
(res, dres)
|
|
}
|
|
}
|