use num_traits::Float;
#[inline]
pub(super) fn compute_sum<T: Float>(x: &[T]) -> T {
x.iter().copied().fold(T::zero(), |acc, xi| acc + xi)
}
#[inline]
pub(super) fn compute_product<T: Float>(x: &[T]) -> T {
x.iter().copied().fold(T::one(), |acc, xi| acc * xi)
}
pub(super) fn generate_simplex_points<T: Float>(m: usize, n_points: usize) -> Vec<Vec<T>> {
if m == 2 {
return (0..n_points)
.map(|i| {
let t = T::from(i).expect("usize to Float")
/ T::from(n_points - 1).expect("usize to Float");
vec![T::one() - t, t]
})
.collect();
}
let mut points = Vec::new();
generate_simplex_recursive(m, n_points, T::zero(), Vec::new(), &mut points);
points
}
pub(super) fn generate_simplex_recursive<T: Float>(
m: usize,
n_points: usize,
sum: T,
current: Vec<T>,
points: &mut Vec<Vec<T>>,
) {
if current.len() == m - 1 {
let mut point = current;
point.push(T::one() - sum);
points.push(point);
return;
}
let divisions = (n_points as f64).powf(1.0 / (m - 1) as f64).ceil() as usize;
for i in 0..=divisions {
let val = T::from(i).expect("usize to Float") / T::from(divisions).expect("usize to Float")
* (T::one() - sum);
if sum + val <= T::one() + T::epsilon() {
let mut next = current.clone();
next.push(val);
generate_simplex_recursive(m, n_points, sum + val, next, points);
}
}
}