finance_solution/derivatives/
norm.rs1#[inline]
5pub fn norm_pdf(x: f64) -> f64 {
6 const INV_SQRT_2PI: f64 = 0.398_942_280_401_432_7;
7 INV_SQRT_2PI * (-0.5 * x * x).exp()
8}
9
10#[inline]
12pub fn norm_cdf(x: f64) -> f64 {
13 if x.is_nan() {
14 return f64::NAN;
15 }
16 if x > 8.0 {
17 return 1.0;
18 }
19 if x < -8.0 {
20 return 0.0;
21 }
22 const B0: f64 = 0.231_641_9;
24 const B1: f64 = 0.319_381_530;
25 const B2: f64 = -0.356_563_782;
26 const B3: f64 = 1.781_477_937;
27 const B4: f64 = -1.821_255_978;
28 const B5: f64 = 1.330_274_429;
29
30 let t = 1.0 / (1.0 + B0 * x.abs());
31 let poly = ((((B5 * t + B4) * t + B3) * t + B2) * t + B1) * t;
32 let pdf = norm_pdf(x.abs());
33 let tail = pdf * poly;
34 if x >= 0.0 {
35 1.0 - tail
36 } else {
37 tail
38 }
39}
40
41#[cfg(test)]
42mod tests {
43 use super::*;
44
45 #[test]
46 fn pdf_at_zero() {
47 let p = norm_pdf(0.0);
48 assert!((p - 0.398_942_280_4).abs() < 1e-9);
49 }
50
51 #[test]
52 fn cdf_symmetry() {
53 assert!((norm_cdf(0.0) - 0.5).abs() < 1e-7);
54 assert!((norm_cdf(1.0) + norm_cdf(-1.0) - 1.0).abs() < 1e-6);
55 assert!((norm_cdf(1.96) - 0.975).abs() < 5e-4);
57 }
58}