use sciforge::hub::prelude::maths::vector::Vec3;
pub fn lerp(a: f64, b: f64, t: f64) -> f64 {
a + (b - a) * t
}
pub fn clamp(val: f64, min: f64, max: f64) -> f64 {
val.max(min).min(max)
}
pub fn rk4_step<F>(y: f64, dy: f64, dt: f64, f: F) -> (f64, f64)
where
F: Fn(f64, f64) -> f64,
{
let k1 = f(y, dy);
let k2 = f(y + 0.5 * dt * dy, dy + 0.5 * dt * k1);
let k3 = f(y + 0.5 * dt * (dy + 0.5 * dt * k1), dy + 0.5 * dt * k2);
let k4 = f(y + dt * (dy + 0.5 * dt * k2), dy + dt * k3);
let new_dy = dy + dt / 6.0 * (k1 + 2.0 * k2 + 2.0 * k3 + k4);
let new_y = y + dt * dy + dt * dt / 6.0 * (k1 + k2 + k3);
(new_y, new_dy)
}
pub fn simpson_integrate<F>(f: F, a: f64, b: f64, n: usize) -> f64
where
F: Fn(f64) -> f64,
{
sciforge::hub::prelude::maths::integration::composite_simpson(f, a, b, n)
}
pub fn log_range(start: f64, end: f64, n: usize) -> Vec<f64> {
let log_start = start.ln();
let log_end = end.ln();
(0..n)
.map(|i| (log_start + (log_end - log_start) * i as f64 / (n - 1).max(1) as f64).exp())
.collect()
}
pub fn spherical_to_cartesian(r: f64, theta: f64, phi: f64) -> Vec3 {
Vec3::new(
r * theta.sin() * phi.cos(),
r * theta.sin() * phi.sin(),
r * theta.cos(),
)
}
pub fn cartesian_to_spherical(v: &Vec3) -> (f64, f64, f64) {
let r = v.magnitude();
let theta = if r > 0.0 { (v.z / r).acos() } else { 0.0 };
let phi = v.y.atan2(v.x);
(r, theta, phi)
}