#![cfg(feature = "scalar")]
use crate::scalar::*;
use gemath::*;
#[cfg(test)]
mod tests {
use super::*;
use std::f32::consts::{PI, TAU};
const EPSILON: f32 = 1e-6;
#[test]
fn test_to_radians() {
assert!((to_radians(180.0) - PI).abs() < EPSILON);
assert!((to_radians(90.0) - PI / 2.0).abs() < EPSILON);
assert!((to_radians(360.0) - TAU).abs() < EPSILON);
assert!((to_radians(0.0) - 0.0).abs() < EPSILON);
}
#[test]
fn test_to_degrees() {
assert!((to_degrees(PI) - 180.0).abs() < EPSILON);
assert!((to_degrees(PI / 2.0) - 90.0).abs() < EPSILON);
assert!((to_degrees(TAU) - 360.0).abs() < EPSILON);
assert!((to_degrees(0.0) - 0.0).abs() < EPSILON);
}
#[test]
fn test_angle_diff() {
assert!((angle_diff(0.0, 0.0) - 0.0).abs() < EPSILON);
assert!((angle_diff(PI / 4.0, PI / 2.0) - (PI / 4.0)).abs() < EPSILON);
let val_a = PI / 2.0;
let val_b = PI / 4.0;
let result = angle_diff(val_a, val_b);
let expected = -PI / 4.0;
assert!((result - expected).abs() < EPSILON);
assert!((angle_diff(TAU - PI / 4.0, PI / 4.0) - (PI / 2.0)).abs() < EPSILON);
assert!((angle_diff(PI / 4.0, TAU - PI / 4.0) - (-PI / 2.0)).abs() < EPSILON);
assert!((angle_diff(0.0, PI) - PI).abs() < EPSILON);
assert!((angle_diff(0.0, PI + EPSILON) - (PI + EPSILON - TAU)).abs() < EPSILON);
assert!((angle_diff(0.0, 3.0 * PI / 2.0) - (-PI / 2.0)).abs() < EPSILON);
assert!(
(angle_diff(PI, 0.0) - PI).abs() < EPSILON,
"Test PI to 0.0, C++ output was PI, Rust result should be PI"
);
}
#[test]
fn test_square() {
assert!((square(0.0f32) - 0.0).abs() < EPSILON);
assert!((square(2.0f32) - 4.0).abs() < EPSILON);
assert!((square(-3.0f32) - 9.0).abs() < EPSILON);
assert!((square(1.5f32) - 2.25).abs() < EPSILON);
}
#[test]
fn test_cube() {
assert!((cube(0.0f32) - 0.0).abs() < EPSILON);
assert!((cube(2.0f32) - 8.0).abs() < EPSILON);
assert!((cube(-3.0f32) - -27.0).abs() < EPSILON);
assert!((cube(1.5f32) - 3.375).abs() < EPSILON);
}
#[test]
fn test_remainder() {
assert!((remainder(5.0, 3.0) - (-1.0)).abs() < EPSILON); assert!((remainder(-5.0, 3.0) - 1.0).abs() < EPSILON); assert!((remainder(5.0, -3.0) - (-1.0)).abs() < EPSILON); assert!((remainder(-5.0, -3.0) - 1.0).abs() < EPSILON);
assert!((remainder(6.0, 3.0) - 0.0).abs() < EPSILON); assert!((remainder(1.0, 5.0) - 1.0).abs() < EPSILON);
assert!((remainder(7.5, 3.0) - (-1.5)).abs() < EPSILON);
assert!((remainder(8.5, 3.0) - (-0.5)).abs() < EPSILON);
assert!(remainder(5.0, 0.0).is_nan());
}
#[test]
fn test_modulo() {
assert!((modulo(5.0, 3.0) - 2.0).abs() < EPSILON);
assert!((modulo(-5.0, 3.0) - (-2.0)).abs() < EPSILON);
assert!((modulo(6.0, 3.0) - 3.0).abs() < EPSILON);
assert!((modulo(-6.0, 3.0) - (-3.0)).abs() < EPSILON);
assert!((modulo(0.0, 5.0) - 5.0).abs() < EPSILON);
assert!((modulo(0.0, -5.0) - 5.0).abs() < EPSILON);
assert!((modulo(-PI, TAU) - (-PI)).abs() < EPSILON);
assert!((modulo(TAU, TAU) - TAU).abs() < EPSILON);
assert!(modulo(5.0, 0.0).is_nan());
}
#[test]
fn test_quake_rsqrt() {
let r1 = quake_rsqrt(1.0);
let r2 = quake_rsqrt(4.0);
let r3 = quake_rsqrt(16.0);
let r4 = quake_rsqrt(2.0);
const QUAKE_EPSILON: f32 = 1e-3;
assert!(
(r1 - 1.0).abs() < QUAKE_EPSILON,
"quake_rsqrt(1.0) failed. val: {}",
r1
);
assert!(
(r2 - 0.5).abs() < QUAKE_EPSILON,
"quake_rsqrt(4.0) failed. val: {}",
r2
);
assert!(
(r3 - 0.25).abs() < QUAKE_EPSILON,
"quake_rsqrt(16.0) failed. val: {}",
r3
);
assert!(
(r4 - 0.70710678).abs() < QUAKE_EPSILON,
"quake_rsqrt(2.0) failed. val: {}",
r4
);
assert!((quake_rsqrt(10.0) - (1.0 / 10.0f32.sqrt())).abs() < QUAKE_EPSILON);
assert!((quake_rsqrt(0.1) - (1.0 / 0.1f32.sqrt())).abs() < QUAKE_EPSILON);
}
#[test]
fn test_lerp() {
assert!((lerp(0.0, 10.0, 0.0) - 0.0).abs() < EPSILON);
assert!((lerp(0.0, 10.0, 1.0) - 10.0).abs() < EPSILON);
assert!((lerp(0.0, 10.0, 0.5) - 5.0).abs() < EPSILON);
assert!((lerp(10.0, 0.0, 0.5) - 5.0).abs() < EPSILON);
assert!((lerp(-5.0, 5.0, 0.5) - 0.0).abs() < EPSILON);
assert!((lerp(0.0, 10.0, -0.5) - (-5.0)).abs() < EPSILON); assert!((lerp(0.0, 10.0, 1.5) - 15.0).abs() < EPSILON); }
#[test]
fn test_unlerp() {
assert!((unlerp(0.0, 0.0, 10.0) - 0.0).abs() < EPSILON);
assert!((unlerp(10.0, 0.0, 10.0) - 1.0).abs() < EPSILON);
assert!((unlerp(5.0, 0.0, 10.0) - 0.5).abs() < EPSILON);
assert!((unlerp(5.0, 10.0, 0.0) - 0.5).abs() < EPSILON); assert!((unlerp(0.0, -5.0, 5.0) - 0.5).abs() < EPSILON);
assert!((unlerp(-5.0, 0.0, 10.0) - (-0.5)).abs() < EPSILON); assert!((unlerp(15.0, 0.0, 10.0) - 1.5).abs() < EPSILON); assert!(
unlerp(5.0, 10.0, 10.0).is_infinite() && unlerp(5.0, 10.0, 10.0).is_sign_negative()
);
assert!(unlerp(10.0, 10.0, 10.0).is_nan()); assert!(
unlerp(15.0, 10.0, 10.0).is_infinite() && unlerp(15.0, 10.0, 10.0).is_sign_positive()
); }
#[test]
fn test_smooth_step() {
assert!((smooth_step(0.0, 1.0, 0.0) - 0.0).abs() < EPSILON);
assert!((smooth_step(0.0, 1.0, 1.0) - 1.0).abs() < EPSILON);
assert!((smooth_step(0.0, 1.0, 0.5) - 0.5).abs() < EPSILON); assert!((smooth_step(0.0, 10.0, 5.0) - 0.5).abs() < EPSILON);
assert!((smooth_step(0.0, 1.0, -0.5) - 0.0).abs() < EPSILON); assert!((smooth_step(0.0, 1.0, 1.5) - 1.0).abs() < EPSILON);
assert!((smooth_step(1.0, 0.0, 0.5) - 0.5).abs() < EPSILON); assert!((smooth_step(10.0, 0.0, 5.0) - 0.5).abs() < EPSILON);
}
#[test]
fn test_smoother_step() {
assert!((smoother_step(0.0, 1.0, 0.0) - 0.0).abs() < EPSILON);
assert!((smoother_step(0.0, 1.0, 1.0) - 1.0).abs() < EPSILON);
let x_half = 0.5;
let expected_half = x_half * x_half * x_half * (x_half * (x_half * 6.0 - 15.0) + 10.0); assert!((smoother_step(0.0, 1.0, 0.5) - expected_half).abs() < EPSILON);
assert!((smoother_step(0.0, 10.0, 5.0) - expected_half).abs() < EPSILON);
assert!((smoother_step(0.0, 1.0, -0.5) - 0.0).abs() < EPSILON); assert!((smoother_step(0.0, 1.0, 1.5) - 1.0).abs() < EPSILON);
assert!((smoother_step(1.0, 0.0, 0.5) - expected_half).abs() < EPSILON);
assert!((smoother_step(10.0, 0.0, 5.0) - expected_half).abs() < EPSILON);
}
#[test]
fn test_clamp() {
assert_eq!(clamp(5.0, 1.0, 10.0), 5.0);
assert_eq!(clamp(-5.0, 0.0, 1.0), 0.0);
assert_eq!(clamp(15.0, 0.0, 10.0), 10.0);
assert_eq!(clamp(0.0, 0.0, 0.0), 0.0);
}
#[test]
fn test_min() {
assert_eq!(min(1.0, 2.0), 1.0);
assert_eq!(min(-1.0, 1.0), -1.0);
assert_eq!(min(0.0, 0.0), 0.0);
}
#[test]
fn test_max() {
assert_eq!(max(1.0, 2.0), 2.0);
assert_eq!(max(-1.0, 1.0), 1.0);
assert_eq!(max(0.0, 0.0), 0.0);
}
#[test]
fn test_sign() {
assert_eq!(sign(5.0), 1.0);
assert_eq!(sign(-5.0), -1.0);
assert_eq!(sign(0.0), 0.0);
}
#[test]
fn test_abs() {
assert_eq!(abs(5.0), 5.0);
assert_eq!(abs(-5.0), 5.0);
assert_eq!(abs(0.0), 0.0);
}
#[test]
fn test_is_nan() {
assert!(is_nan(f32::NAN));
assert!(!is_nan(0.0));
assert!(!is_nan(1.0));
}
#[test]
fn test_is_finite() {
assert!(is_finite(0.0));
assert!(is_finite(1.0));
assert!(!is_finite(f32::INFINITY));
assert!(!is_finite(f32::NEG_INFINITY));
assert!(!is_finite(f32::NAN));
}
#[test]
fn test_approx_eq() {
assert!(approx_eq(1.0, 1.0 + EPSILON / 2.0, EPSILON));
assert!(!approx_eq(1.0, 1.0 + EPSILON * 2.0, EPSILON));
assert!(approx_eq(-1.0, -1.0 - EPSILON / 2.0, EPSILON));
assert!(approx_eq(0.0, EPSILON / 2.0, EPSILON));
assert!(!approx_eq(0.0, EPSILON * 2.0, EPSILON));
}
}
const _CONST_RAD_180: f32 = to_radians(180.0);
const _CONST_DEG_PI: f32 = to_degrees(core::f32::consts::PI);
const _CONST_LERP: f32 = lerp(0.0, 10.0, 0.5);
const _CONST_UNLERP: f32 = unlerp(5.0, 0.0, 10.0);
const _CONST_CLAMP: f32 = clamp(5.0, 1.0, 10.0);
const _CONST_CLAMP_LOW: f32 = clamp(-5.0, 0.0, 10.0);
const _CONST_CLAMP_HIGH: f32 = clamp(15.0, 0.0, 10.0);
const _CONST_MIN: f32 = min(1.0, 2.0);
const _CONST_MAX: f32 = max(1.0, 2.0);
const _CONST_SIGN_POS: f32 = sign(5.0);
const _CONST_SIGN_NEG: f32 = sign(-5.0);
const _CONST_SIGN_ZERO: f32 = sign(0.0);
const _CONST_ABS_POS: f32 = abs(5.0);
const _CONST_ABS_NEG: f32 = abs(-5.0);
const _: () = {
assert!((_CONST_RAD_180 - core::f32::consts::PI).abs() < 1e-6);
assert!((_CONST_DEG_PI - 180.0).abs() < 1e-6);
assert!((_CONST_LERP - 5.0).abs() < 1e-6);
assert!((_CONST_UNLERP - 0.5).abs() < 1e-6);
assert!(_CONST_CLAMP == 5.0);
assert!(_CONST_CLAMP_LOW == 0.0);
assert!(_CONST_CLAMP_HIGH == 10.0);
assert!(_CONST_MIN == 1.0);
assert!(_CONST_MAX == 2.0);
assert!(_CONST_SIGN_POS == 1.0);
assert!(_CONST_SIGN_NEG == -1.0);
assert!(_CONST_SIGN_ZERO == 0.0);
assert!(_CONST_ABS_POS == 5.0);
assert!(_CONST_ABS_NEG == 5.0);
};