FIX: Issues with trigonometric functions

* Right branch for ACOT for negative numbers
* correct error for ACOTH
* Correct approx for COTH for x > 20
This commit is contained in:
Nicolás Hatcher
2025-11-19 19:25:14 +01:00
committed by Nicolás Hatcher Andrés
parent 7676efca44
commit acb90fbb9d
2 changed files with 15 additions and 3 deletions

View File

@@ -1278,9 +1278,18 @@ impl Model {
Ok((f * PI).sqrt()) Ok((f * PI).sqrt())
}); });
single_number_fn!(fn_acot, |f| Ok(f64::atan(1.0 / f))); single_number_fn!(fn_acot, |f| {
let v = f64::atan(1.0 / f);
if f >= 0.0 {
Ok(v)
} else {
// To be compatible with Excel we need a different branch
// when f < 0
Ok(v + PI)
}
});
single_number_fn!(fn_acoth, |f: f64| if f.abs() == 1.0 { single_number_fn!(fn_acoth, |f: f64| if f.abs() == 1.0 {
Err(Error::DIV) Err(Error::NUM)
} else { } else {
Ok(0.5 * (f64::ln((f + 1.0) / (f - 1.0)))) Ok(0.5 * (f64::ln((f + 1.0) / (f - 1.0))))
}); });
@@ -1289,8 +1298,11 @@ impl Model {
} else { } else {
Ok(f64::cos(f) / f64::sin(f)) Ok(f64::cos(f) / f64::sin(f))
}); });
single_number_fn!(fn_coth, |f| if f == 0.0 { single_number_fn!(fn_coth, |f: f64| if f == 0.0 {
Err(Error::DIV) Err(Error::DIV)
} else if f.abs() > 20.0 {
// for values > 20.0 this is exact in f64
Ok(f.signum())
} else { } else {
Ok(f64::cosh(f) / f64::sinh(f)) Ok(f64::cosh(f) / f64::sinh(f))
}); });