#![allow(clippy::approx_constant)]
use inari::*;
fn exp2_point_reduced(x: f64) -> Interval {
let x = interval!(x, x).unwrap();
assert!(x.subset(const_interval!(-0.5, 0.5)));
const N: usize = 14;
const C: [Interval; N] = [
const_interval!(1.0, 1.0),
const_interval!(0.6931471805599453, 0.6931471805599454),
const_interval!(0.2402265069591007, 0.24022650695910072),
const_interval!(5.5504108664821576e-2, 5.550410866482158e-2),
const_interval!(9.618129107628477e-3, 9.618129107628479e-3),
const_interval!(1.3333558146428443e-3, 1.3333558146428445e-3),
const_interval!(1.540353039338161e-4, 1.5403530393381611e-4),
const_interval!(1.525273380405984e-5, 1.5252733804059841e-5),
const_interval!(1.3215486790144307e-6, 1.321548679014431e-6),
const_interval!(1.0178086009239699e-7, 1.01780860092397e-7),
const_interval!(7.0549116208011225e-9, 7.054911620801123e-9),
const_interval!(4.445538271870811e-10, 4.4455382718708116e-10),
const_interval!(2.5678435993488202e-11, 2.5678435993488206e-11),
const_interval!(1.3691488853904128e-12, 1.369148885390413e-12),
];
let mut y = const_interval!(4.7932833733029885e-14, 9.586566746605978e-14);
for n in (0..N).rev() {
y = y.mul_add(x, C[n]);
}
y
}
fn exp2_point(x: f64) -> Interval {
assert!(x.is_finite());
let mut a = x.floor();
let mut b = x - a;
if b > 0.5 {
a += 1.0;
b -= 1.0;
}
let exp2_a = if a < -1074.0 {
const_interval!(0.0, 5e-324)
} else if a > 1023.0 {
const_interval!(f64::MAX, f64::INFINITY)
} else {
let exp2_a = libm::ldexp(1.0, a as i32);
interval!(exp2_a, exp2_a).unwrap()
};
let exp2_b = exp2_point_reduced(b);
exp2_a * exp2_b
}
fn exp2(x: Interval) -> Interval {
if x.is_empty() {
return x;
}
let inf = if x.inf() == f64::NEG_INFINITY {
0.0
} else {
exp2_point(x.inf()).inf()
};
let sup = if x.sup() == f64::INFINITY {
f64::INFINITY
} else {
exp2_point(x.sup()).sup()
};
interval!(inf, sup).unwrap()
}
fn exp(x: Interval) -> Interval {
exp2(Interval::LOG2_E * x)
}
fn exp10(x: Interval) -> Interval {
exp2(Interval::LOG2_10 * x)
}
fn main() {
let x = interval!("[1.234567]").unwrap();
println!("2^x ⊆ {:.15e}", exp2(x));
println!("2^x ⊆ {:.15e} (MPFR)", x.exp2());
assert!(x.exp2().subset(exp2(x)));
println!("e^x ⊆ {:.15e}", exp(x));
println!("e^x ⊆ {:.15e} (MPFR)", x.exp());
assert!(x.exp().subset(exp(x)));
println!("10^x ⊆ {:.15e}", x.exp10());
println!("10^x ⊆ {:.15e} (MPFR)", exp10(x));
assert!(x.exp10().subset(exp10(x)));
}