use super::{Float, Vector3};
#[inline(always)]
pub fn cast<T: Float>(x: f64) -> T {
num_traits::cast::<f64, T>(x).unwrap()
}
#[inline(always)]
pub fn norm2<T: Float>(a: T, b: T) -> T {
#[cfg(feature = "norm-sqrt")]
{
(a*a + b*b).sqrt()
}
#[cfg(not(feature = "norm-sqrt"))]
{
a.hypot(b)
}
}
#[inline(always)]
pub fn mul_add<T: Float>(s: T, a: T, b: T) -> T {
#[cfg(feature = "fma")]
{
s.mul_add(a, b)
}
#[cfg(not(feature = "fma"))]
{
(s * a) + b
}
}
#[inline]
pub fn sinc<T: Float>(x: T) -> T {
const COEF: [f64; 7] = [
1.579349121783874e-10, -2.5048466629256012e-8, 2.7557294426482064e-6, -0.00019841269754547076, 0.008333333333188874, -0.16666666666665766, 0.9999999999999999, ];
if x.abs() <= T::one() { let z = x * x;
let mut y = cast(COEF[0]);
for i in 1..(COEF.len() - 1) {
y = mul_add(y, z, cast(COEF[i]));
}
y = mul_add(y, z, cast::<T>(COEF[COEF.len()-1]) - T::one()); y + T::one()
} else {
x.sin() / x
}
}
#[inline]
pub fn max4<T: Float>(nums: [T; 4]) -> (usize, T) {
let mut i_max = 0;
for i in 1..nums.len() {
if nums[i_max] < nums[i] {
i_max = i;
}
}
(i_max, nums[i_max])
}
#[inline]
pub fn orthogonal_vector<T: Float>(a: Vector3<T>) -> Vector3<T> {
let mut b = a.map(|x| x.abs());
let mut i_min: usize = 0;
let mut i_max: usize = 1;
if b[0] > b[1] {
i_min = 1;
i_max = 0;
}
if b[i_max] < b[2] {
i_max = 2;
} else {
if b[i_min] > b[2] {
i_min = 2;
}
}
let i_med = 3 - (i_min + i_max);
let norm_inv = norm2(a[i_med], a[i_max]).recip();
b[i_min] = T::zero();
b[i_med] = -a[i_max] * norm_inv;
b[i_max] = a[i_med] * norm_inv;
b
}