pub struct MathUtils;
impl MathUtils {
#[must_use]
pub fn lerp(start: f64, stop: f64, amount: f64) -> f64 {
(1.0 - amount).mul_add(start, amount * stop)
}
#[must_use]
pub const fn sanitize_degrees_int(degrees: i32) -> i32 {
let mut degrees = degrees % 360;
if degrees < 0 {
degrees += 360;
}
degrees
}
#[must_use]
pub fn sanitize_degrees_double(degrees: f64) -> f64 {
let mut degrees = degrees % 360.0;
if degrees < 0.0 {
degrees += 360.0;
}
degrees
}
#[must_use]
pub fn rotation_direction(from: f64, to: f64) -> f64 {
let increasing_difference = Self::sanitize_degrees_double(to - from);
if increasing_difference <= 180.0 {
1.0
} else {
-1.0
}
}
#[must_use]
pub fn difference_degrees(a: f64, b: f64) -> f64 {
180.0 - ((a - b).abs() - 180.0).abs()
}
#[must_use]
pub fn matrix_multiply(row: [f64; 3], matrix: [[f64; 3]; 3]) -> [f64; 3] {
let a = row[2].mul_add(
matrix[0][2],
row[0].mul_add(matrix[0][0], row[1] * matrix[0][1]),
);
let b = row[2].mul_add(
matrix[1][2],
row[0].mul_add(matrix[1][0], row[1] * matrix[1][1]),
);
let c = row[2].mul_add(
matrix[2][2],
row[0].mul_add(matrix[2][0], row[1] * matrix[2][1]),
);
[a, b, c]
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::float_cmp)]
use super::*;
#[test]
fn test_lerp() {
assert_eq!(MathUtils::lerp(0.0, 10.0, 0.0), 0.0);
assert_eq!(MathUtils::lerp(0.0, 10.0, 1.0), 10.0);
assert_eq!(MathUtils::lerp(0.0, 10.0, 0.5), 5.0);
assert_eq!(MathUtils::lerp(10.0, 20.0, 0.25), 12.5);
}
#[test]
fn test_sanitize_degrees_int() {
assert_eq!(MathUtils::sanitize_degrees_int(0), 0);
assert_eq!(MathUtils::sanitize_degrees_int(360), 0);
assert_eq!(MathUtils::sanitize_degrees_int(720), 0);
assert_eq!(MathUtils::sanitize_degrees_int(180), 180);
assert_eq!(MathUtils::sanitize_degrees_int(-90), 270);
assert_eq!(MathUtils::sanitize_degrees_int(-450), 270);
}
#[test]
fn test_sanitize_degrees_double() {
assert_eq!(MathUtils::sanitize_degrees_double(0.0), 0.0);
assert_eq!(MathUtils::sanitize_degrees_double(360.0), 0.0);
assert_eq!(MathUtils::sanitize_degrees_double(180.0), 180.0);
assert_eq!(MathUtils::sanitize_degrees_double(-90.0), 270.0);
assert_eq!(MathUtils::sanitize_degrees_double(-450.0), 270.0);
}
#[test]
fn test_rotation_direction() {
assert_eq!(MathUtils::rotation_direction(0.0, 10.0), 1.0);
assert_eq!(MathUtils::rotation_direction(10.0, 0.0), -1.0);
assert_eq!(MathUtils::rotation_direction(0.0, 180.0), 1.0);
assert_eq!(MathUtils::rotation_direction(0.0, 190.0), -1.0);
assert_eq!(MathUtils::rotation_direction(190.0, 0.0), 1.0);
}
#[test]
fn test_difference_degrees() {
assert_eq!(MathUtils::difference_degrees(0.0, 10.0), 10.0);
assert_eq!(MathUtils::difference_degrees(10.0, 0.0), 10.0);
assert_eq!(MathUtils::difference_degrees(0.0, 180.0), 180.0);
assert_eq!(MathUtils::difference_degrees(0.0, 190.0), 170.0);
assert_eq!(MathUtils::difference_degrees(190.0, 0.0), 170.0);
assert_eq!(MathUtils::difference_degrees(350.0, 10.0), 20.0);
}
#[test]
fn test_matrix_multiply() {
let row = [1.0, 2.0, 3.0];
let matrix = [[1.0, 0.0, 0.0], [0.1, 1.0, 0.0], [0.0, 0.0, 1.0]];
let result = MathUtils::matrix_multiply(row, matrix);
assert_eq!(result, [1.0, 2.1, 3.0]);
}
}