use crate::ffi;
pub fn logaddexp(x: f64, y: f64) -> f64 {
unsafe { ffi::math_logaddexp(x, y) }
}
#[doc(alias = "lse")]
pub fn logsumexp(x: &[f64]) -> f64 {
if x.is_empty() {
f64::NEG_INFINITY
} else {
unsafe { ffi::math_logsumexp(x.as_ptr(), x.len()) }
}
}
#[cfg(test)]
mod tests {
use super::*;
use core::f64::consts::LN_2;
const RTOL: f64 = 2e-15;
const LN_3: f64 = 1.098_612_288_668_109_8;
#[test]
fn test_logaddexp() {
assert_relative_eq!(logaddexp(0.0, 0.0), LN_2, epsilon = RTOL);
assert_relative_eq!(logaddexp(1.0, 1.0), LN_2 + 1.0, epsilon = RTOL);
assert_relative_eq!(logaddexp(-1.0, -1.0), LN_2 - 1.0, epsilon = RTOL);
assert_relative_eq!(logaddexp(100.0, 100.0), LN_2 + 100.0, epsilon = RTOL);
assert_relative_eq!(logaddexp(-100.0, -100.0), LN_2 - 100.0, epsilon = RTOL);
assert_relative_eq!(logaddexp(100.0, -100.0), 100.0, epsilon = RTOL);
assert_relative_eq!(logaddexp(-100.0, 100.0), 100.0, epsilon = RTOL);
}
#[test]
fn test_logsumexp_0() {
assert_eq!(logsumexp(&[]), f64::NEG_INFINITY);
}
#[test]
fn test_logsumexp_1() {
assert_relative_eq!(logsumexp(&[0.0]), 0.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[1.0]), 1.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-1.0]), -1.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[100.0]), 100.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-100.0]), -100.0, epsilon = RTOL);
}
#[test]
fn test_logsumexp_2() {
assert_relative_eq!(logsumexp(&[0.0, 0.0]), LN_2, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[1.0, 1.0]), LN_2 + 1.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-1.0, -1.0]), LN_2 - 1.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[100.0, 100.0]), LN_2 + 100.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-100.0, -100.0]), LN_2 - 100.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[100.0, -100.0]), 100.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-100.0, 100.0]), 100.0, epsilon = RTOL);
}
#[test]
fn test_logsumexp_3() {
assert_relative_eq!(logsumexp(&[0.0, 0.0, 0.0]), LN_3, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[1.0, 1.0, 1.0]), LN_3 + 1.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-1.0, -1.0, -1.0]), LN_3 - 1.0, epsilon = RTOL);
assert_relative_eq!(
logsumexp(&[100.0, 100.0, 100.0]),
LN_3 + 100.0,
epsilon = RTOL
);
assert_relative_eq!(
logsumexp(&[-100.0, -100.0, -100.0]),
LN_3 - 100.0,
epsilon = RTOL
);
assert_relative_eq!(logsumexp(&[100.0, -100.0, -100.0]), 100.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-100.0, 100.0, -100.0]), 100.0, epsilon = RTOL);
assert_relative_eq!(logsumexp(&[-100.0, -100.0, 100.0]), 100.0, epsilon = RTOL);
}
}