pub fn approx_eq(a: f64, b: f64, eps: f64) -> bool {
(a - b).abs() <= eps
}
pub fn signum_zero<T>(value: T) -> i8
where
T: PartialOrd + From<i8>,
{
if value > T::from(0) {
1
} else if value < T::from(0) {
-1
} else {
0
}
}
pub fn sum_i64_saturating(values: &[i64]) -> i64 {
values.iter().fold(0i64, |acc, &x| acc.saturating_add(x))
}
pub fn gcd_u64(mut a: u64, mut b: u64) -> u64 {
while b != 0 {
let t = b;
b = a % b;
a = t;
}
a
}
pub fn lcm_u64(a: u64, b: u64) -> u64 {
if a == 0 || b == 0 {
0
} else {
a / gcd_u64(a, b) * b
}
}
pub fn lerp(a: f64, b: f64, t: f64) -> f64 {
a + (b - a) * t
}
pub fn map_range(x: f64, in_min: f64, in_max: f64, out_min: f64, out_max: f64) -> f64 {
if in_max == in_min {
return out_min;
}
(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
}
pub fn factorial(n: u32) -> u128 {
(1..=n as u128).product()
}
pub fn is_prime(n: u64) -> bool {
if n < 2 {
return false;
}
if n % 2 == 0 {
return n == 2;
}
let mut d = 3u64;
while d * d <= n {
if n % d == 0 {
return false;
}
d += 2;
}
true
}
pub fn next_prime(mut n: u64) -> u64 {
if n <= 2 {
return 2;
}
if n % 2 == 0 {
n += 1;
}
while !is_prime(n) {
n += 2;
}
n
}
pub fn prev_prime(mut n: u64) -> Option<u64> {
if n <= 2 {
return None;
}
if n % 2 == 0 {
n -= 1;
}
while n >= 2 && !is_prime(n) {
n = n.saturating_sub(2);
}
if n >= 2 {
Some(n)
} else {
None
}
}
pub fn fibonacci(n: u32) -> u128 {
let (mut a, mut b) = (0u128, 1u128);
for _ in 0..n {
let t = a + b;
a = b;
b = t;
}
a
}
pub fn is_even(n: i64) -> bool {
n % 2 == 0
}
pub fn is_odd(n: i64) -> bool {
n % 2 != 0
}
pub fn degrees_to_radians(deg: f64) -> f64 {
deg.to_radians()
}
pub fn radians_to_degrees(rad: f64) -> f64 {
rad.to_degrees()
}
pub fn sigmoid(x: f64) -> f64 {
1.0 / (1.0 + (-x).exp())
}
pub fn normalize(x: f64, min: f64, max: f64) -> f64 {
if max == min {
0.0
} else {
(x - min) / (max - min)
}
}
pub fn euclidean_distance(a: &[f64], b: &[f64]) -> f64 {
a.iter()
.zip(b)
.map(|(x, y)| (x - y).powi(2))
.sum::<f64>()
.sqrt()
}
pub fn manhattan_distance(a: &[f64], b: &[f64]) -> f64 {
a.iter().zip(b).map(|(x, y)| (x - y).abs()).sum()
}
pub fn dot_product(a: &[f64], b: &[f64]) -> f64 {
a.iter().zip(b).map(|(x, y)| x * y).sum()
}
pub fn cross_product(a: [f64; 3], b: [f64; 3]) -> [f64; 3] {
[
a[1] * b[2] - a[2] * b[1],
a[2] * b[0] - a[0] * b[2],
a[0] * b[1] - a[1] * b[0],
]
}