use crate::exponents::core_expf;
use crate::polyeval::f_polyeval6;
pub fn f_logisticf(x: f32) -> f32 {
let x_u = x.to_bits();
let x_abs = x_u & 0x7fff_ffffu32;
if x_abs >= 0x42b2_0000u32 || x_abs <= 0x3d00_0000u32 {
let exp = ((x_u >> 23) & 0xFF) as i32;
if exp <= 101i32 {
return (1. / (2. + -x as f64)) as f32;
}
if x_abs <= 0x3400_0000u32 {
#[cfg(any(
all(
any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "fma"
),
target_arch = "aarch64"
))]
{
use crate::common::f_fmlaf;
return f_fmlaf(0.25, x, 0.5);
}
#[cfg(not(any(
all(
any(target_arch = "x86", target_arch = "x86_64"),
target_feature = "fma"
),
target_arch = "aarch64"
)))]
{
use crate::common::f_fmla;
return f_fmla(0.25, x as f64, 0.5) as f32;
}
}
if x_u >= 0xc2cf_f1b5u32 {
if x.is_infinite() {
return 0.0;
}
if x.is_nan() {
return x;
}
return if x.is_sign_positive() {
f32::INFINITY
} else {
0.
};
}
if x.is_sign_positive() && x_u >= 0x42d0_0000u32 {
if x.is_nan() {
return f32::NAN;
}
return 1.;
}
if x.is_sign_negative() && x_u >= 0xc2cb_fe00u32 {
return 0.;
}
if x_abs <= 0x3d00_0000u32 {
let dx = x as f64;
let p = f_polyeval6(
dx,
f64::from_bits(0x3fe0000000000000),
f64::from_bits(0x3fcffffffffffcf5),
f64::from_bits(0x3cfbce9c01a4987c),
f64::from_bits(0xbf955555524c34a4),
f64::from_bits(0xbda6322b5fac64d4),
f64::from_bits(0x3f61104f3a0dedc3),
);
return p as f32;
}
}
let v_exp = core_expf(-x);
let logistic = 1. / (1. + v_exp);
logistic as f32
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_logisticf() {
assert_eq!(f_logisticf(-89.), 2.227364e-39);
assert_eq!(f_logisticf(-104.), 0.);
assert_eq!(f_logisticf(-103.), 0.);
assert_eq!(f_logisticf(-88.9), 2.461613e-39);
assert_eq!(f_logisticf(-88.), 6.054601e-39);
assert_eq!(f_logisticf(-80.), 1.8048513e-35);
assert_eq!(f_logisticf(-60.), 8.756511e-27);
assert_eq!(f_logisticf(-40.), 4.248354e-18);
assert_eq!(f_logisticf(-20.), 2.0611537e-9);
assert_eq!(f_logisticf(-1.591388e29), 0.);
assert_eq!(f_logisticf(-3.), 0.047425874);
assert_eq!(f_logisticf(3.), 0.95257413);
assert_eq!(f_logisticf(20.), 1.);
assert_eq!(f_logisticf(55.), 1.);
assert_eq!(f_logisticf(-104.), 0.);
assert_eq!(f_logisticf(-90.), 8.19401e-40);
assert_eq!(f_logisticf(0.00000000000524323), 0.5);
assert_eq!(f_logisticf(0.00000000524323), 0.5);
assert_eq!(f_logisticf(0.02), 0.5049998);
assert_eq!(f_logisticf(-0.02), 0.49500015);
assert_eq!(f_logisticf(90.), 1.);
assert_eq!(f_logisticf(105.), 1.);
assert_eq!(f_logisticf(150.), 1.);
assert_eq!(f_logisticf(f32::INFINITY), 1.0);
assert_eq!(f_logisticf(f32::NEG_INFINITY), 0.);
assert!(f_logisticf(f32::NAN).is_nan());
}
}