statrs-dev / statrs

Statistical computation library for Rust
https://docs.rs/statrs/latest/statrs/
MIT License
599 stars 84 forks source link

Weibull has some misbehaving cases #310

Open FreezyLemon opened 3 hours ago

FreezyLemon commented 3 hours ago

Might be part of #102.

I believe this behaviour is unpredictable and unwanted, but I'm not sure for every single case listed here. And I might've missed something.

Are parameters set to f64::INFINITY degenerate for this distribution? If they are not, then they need special handling from what I can tell.

Dirty testing code to find some things:

#[test]
    fn test_infinities() {
        let test_distrs = [
            create_ok(f64::INFINITY, 0.5),
            create_ok(f64::INFINITY, 1.0),
            create_ok(f64::INFINITY, 1.5),
            create_ok(0.5, f64::INFINITY),
            create_ok(1.0, f64::INFINITY),
            create_ok(1.5, f64::INFINITY),
            create_ok(f64::INFINITY, f64::INFINITY),
        ];

        for dist in test_distrs {
            println!("scale {}", dist.scale());
            println!("shape {}", dist.shape());
            println!("scale.powf(-shape) {}", dist.scale_pow_shape_inv);
            println!();
            println!("cdf(-1): {}", dist.cdf(-1.0));
            println!("cdf(0): {}", dist.cdf(0.0));
            println!("cdf(0.75): {}", dist.cdf(0.75));
            println!();
            println!("sf(-1): {}", dist.sf(-1.0));
            println!("sf(0): {}", dist.sf(0.0));
            println!("sf(0.75): {}", dist.sf(0.75));
            println!();
            println!("inverse_cdf(0): {}", dist.inverse_cdf(0.0));
            println!("inverse_cdf(0.75): {}", dist.inverse_cdf(0.75));

            println!();
            println!();
        }
    }

[^1]: x.powf(shape) will become x.powf(+Inf) which is zero for any x in (0, 1). Then it's 0 * scale_pow_shape_inv which is 0 * Inf which is NaN