~raph/blurrr

ref: fa3bce5fbcf5640b1414c10ef93c57d4db41793e blurrr/src/math.rs -rw-r--r-- 1.3 KiB
fa3bce5fRaph Levien All parameters automatically tuned 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//! Various math functions.
//!
//! In general, these are designed to be approximations good enough for image
//! usage (error on the order of 1e-3), and suitable for SIMD and GPU acceleration.

// see https://people.maths.ox.ac.uk/gilesm/files/gems_erfinv.pdf
// Note: we just do the center because it's precise enough
pub fn approx_inv_erf(x: f64) -> f64 {
    let w = -((1.0 - x) * (1.0 + x)).ln() - 2.5;
    let mut p = 2.81022636e-08;
    p = 3.43273939e-07 + p * w;
    p = -3.5233877e-06 + p * w;
    p = -4.39150654e-06 + p * w;
    p = 0.00021858087 + p * w;
    p = -0.00125372503 + p * w;
    p = -0.00417768164 + p * w;
    p = 0.246640727 + p * w;
    p = 1.50140941 + p * w;
    p * x
}

// See https://raphlinus.github.io/audio/2018/09/05/sigmoid.html for a little
// explanation of this approximation to the erf function.
pub fn compute_erf7(x: f64) -> f64 {
    let x = x * std::f64::consts::FRAC_2_SQRT_PI;
    let xx = x * x;
    let x = x + (0.24295 + (0.03395 + 0.0104 * xx) * xx) * (x * xx);
    x / (1.0 + x * x).sqrt()
}

// Solve rounded rect for x given y. Assume center at origin.
pub fn solve_rr(w: f64, h: f64, r: f64, y: f64) -> f64 {
    let yy = y.abs() - 0.5 * h;
    if yy >= 0.0 {
        0.0
    } else if yy <= -r {
        0.5 * w
    } else {
        0.5 * w + (r * r - (yy + r).powi(2)).sqrt() - r
    }
}