#![cfg(feature = "vec4")]
use gemath::{vec4::*, vec3::Vec3f32};
#[cfg(test)]
mod tests {
use super::*;
const EPSILON: f32 = if cfg!(feature = "libm") { 1e-5 } else { 1e-7 };
#[test]
fn test_vec4_new() {
let v: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
assert!((v.x - 1.0).abs() < EPSILON);
assert!((v.y - 2.0).abs() < EPSILON);
assert!((v.z - 3.0).abs() < EPSILON);
assert!((v.w - 4.0).abs() < EPSILON);
}
#[test]
fn test_vec4_zero() {
let v: Vec4f32 = Vec4::ZERO;
assert!((v.x - 0.0).abs() < EPSILON);
assert!((v.y - 0.0).abs() < EPSILON);
assert!((v.z - 0.0).abs() < EPSILON);
assert!((v.w - 0.0).abs() < EPSILON);
}
#[test]
fn test_vec4_default() {
let v: Vec4 = Default::default();
assert!((v.x - 0.0).abs() < EPSILON);
assert!((v.y - 0.0).abs() < EPSILON);
assert!((v.z - 0.0).abs() < EPSILON);
assert!((v.w - 0.0).abs() < EPSILON);
}
#[test]
fn test_vec4_checked_div_scalar() {
let v: Vec4f32 = Vec4::new(2.0, 4.0, 6.0, 8.0);
assert_eq!(v.checked_div_scalar(2.0), Some(Vec4::new(1.0, 2.0, 3.0, 4.0)));
assert_eq!(v.checked_div_scalar(0.0), None);
assert_eq!(v.checked_div_scalar(-0.0), None);
assert_eq!(v.checked_div_scalar(f32::NAN), None);
assert_eq!(v.checked_div_scalar(f32::INFINITY), None);
}
#[test]
fn test_vec4_eq() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let v2: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let v3: Vec4f32 = Vec4::new(4.0, 3.0, 2.0, 1.0);
assert_eq!(v1, v2);
assert_ne!(v1, v3);
}
#[test]
fn test_vec4_add() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let v2: Vec4f32 = Vec4::new(5.0, 6.0, 7.0, 8.0);
let result = v1 + v2;
assert!((result.x - 6.0).abs() < EPSILON);
assert!((result.y - 8.0).abs() < EPSILON);
assert!((result.z - 10.0).abs() < EPSILON);
assert!((result.w - 12.0).abs() < EPSILON);
let mut v3 = v1;
v3 += v2;
assert!((v3.x - 6.0).abs() < EPSILON);
assert!((v3.y - 8.0).abs() < EPSILON);
assert!((v3.z - 10.0).abs() < EPSILON);
assert!((v3.w - 12.0).abs() < EPSILON);
}
#[test]
fn test_vec4_sub() {
let v1: Vec4f32 = Vec4::new(5.0, 6.0, 7.0, 8.0);
let v2: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let result = v1 - v2;
assert!((result.x - 4.0).abs() < EPSILON);
assert!((result.y - 4.0).abs() < EPSILON);
assert!((result.z - 4.0).abs() < EPSILON);
assert!((result.w - 4.0).abs() < EPSILON);
let mut v3 = v1;
v3 -= v2;
assert!((v3.x - 4.0).abs() < EPSILON);
assert!((v3.y - 4.0).abs() < EPSILON);
assert!((v3.z - 4.0).abs() < EPSILON);
assert!((v3.w - 4.0).abs() < EPSILON);
}
#[test]
fn test_vec4_mul_scalar() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let scalar = 3.0;
let result1 = v1 * scalar;
assert!((result1.x - 3.0).abs() < EPSILON);
assert!((result1.y - 6.0).abs() < EPSILON);
assert!((result1.z - 9.0).abs() < EPSILON);
assert!((result1.w - 12.0).abs() < EPSILON);
let result2 = scalar * v1;
assert!((result2.x - 3.0).abs() < EPSILON);
assert!((result2.y - 6.0).abs() < EPSILON);
assert!((result2.z - 9.0).abs() < EPSILON);
assert!((result2.w - 12.0).abs() < EPSILON);
let mut v2 = v1;
v2 *= scalar;
assert!((v2.x - 3.0).abs() < EPSILON);
assert!((v2.y - 6.0).abs() < EPSILON);
assert!((v2.z - 9.0).abs() < EPSILON);
assert!((v2.w - 12.0).abs() < EPSILON);
}
#[test]
fn test_vec4_div_scalar() {
let v1: Vec4f32 = Vec4::new(3.0, 6.0, 9.0, 12.0);
let scalar = 3.0;
let result = v1 / scalar;
assert!((result.x - 1.0).abs() < EPSILON);
assert!((result.y - 2.0).abs() < EPSILON);
assert!((result.z - 3.0).abs() < EPSILON);
assert!((result.w - 4.0).abs() < EPSILON);
let mut v2 = v1;
v2 /= scalar;
assert!((v2.x - 1.0).abs() < EPSILON);
assert!((v2.y - 2.0).abs() < EPSILON);
assert!((v2.z - 3.0).abs() < EPSILON);
assert!((v2.w - 4.0).abs() < EPSILON);
}
#[test]
fn test_vec4_mul_hadamard() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let v2: Vec4f32 = Vec4::new(5.0, 6.0, 7.0, 8.0);
let result = v1 * v2;
assert!((result.x - 5.0).abs() < EPSILON);
assert!((result.y - 12.0).abs() < EPSILON);
assert!((result.z - 21.0).abs() < EPSILON);
assert!((result.w - 32.0).abs() < EPSILON);
let mut v3 = v1;
v3 *= v2;
assert!((v3.x - 5.0).abs() < EPSILON);
assert!((v3.y - 12.0).abs() < EPSILON);
assert!((v3.z - 21.0).abs() < EPSILON);
assert!((v3.w - 32.0).abs() < EPSILON);
}
#[test]
fn test_vec4_div_hadamard() {
let v1: Vec4f32 = Vec4::new(5.0, 12.0, 21.0, 32.0);
let v2: Vec4f32 = Vec4::new(5.0, 6.0, 7.0, 8.0);
let result = v1 / v2;
assert!((result.x - 1.0).abs() < EPSILON);
assert!((result.y - 2.0).abs() < EPSILON);
assert!((result.z - 3.0).abs() < EPSILON);
assert!((result.w - 4.0).abs() < EPSILON);
let mut v3 = v1;
v3 /= v2;
assert!((v3.x - 1.0).abs() < EPSILON);
assert!((v3.y - 2.0).abs() < EPSILON);
assert!((v3.z - 3.0).abs() < EPSILON);
assert!((v3.w - 4.0).abs() < EPSILON);
}
#[test]
fn test_vec4_neg() {
let v1: Vec4f32 = Vec4::new(1.0, -2.0, 3.0, -4.0);
let result = -v1;
assert_eq!(result, Vec4::new(-1.0, 2.0, -3.0, 4.0));
}
#[test]
fn test_vec4_dot() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let v2: Vec4f32 = Vec4::new(5.0, 6.0, 7.0, 8.0);
let result1 = v1.dot(v2);
assert!((result1 - 70.0).abs() < EPSILON);
let v3: Vec4f32 = Vec4::new(-1.0, 0.5, -0.2, 1.0);
let v4: Vec4f32 = Vec4::new(2.0, -4.0, 1.0, -0.5); let result2 = v3.dot(v4);
assert!((result2 - (-4.7)).abs() < EPSILON);
assert!((Vec4::ZERO.dot(v1) - 0.0).abs() < EPSILON);
assert!((v1.dot(Vec4::ZERO) - 0.0).abs() < EPSILON);
}
#[test]
fn test_vec4_div_assign_f32() {
let mut v: Vec4f32 = Vec4::new(2.0, 4.0, 6.0, 8.0);
v /= 2.0;
assert_eq!(v, Vec4::new(1.0, 2.0, 3.0, 4.0));
}
#[test]
fn test_vec4_length_squared() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 2.0, 4.0); assert!((v1.length_squared() - 25.0).abs() < EPSILON);
assert!((Vec4f32::ZERO.length_squared() - 0.0).abs() < EPSILON);
}
#[test]
fn test_vec4_length() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 2.0, 4.0);
assert!((v1.length() - 5.0).abs() < EPSILON);
assert!((Vec4f32::ZERO.length() - 0.0).abs() < EPSILON);
let v2: Vec4f32 = Vec4::new(0.0, 0.0, 0.0, 1.0);
assert!((v2.length() - 1.0).abs() < EPSILON);
}
#[test]
fn test_vec4_normalize() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 2.0, 4.0); let norm_v1 = v1.normalize();
assert!((norm_v1.length() - 1.0).abs() < EPSILON);
assert!((norm_v1.x - 1.0 / 5.0).abs() < EPSILON);
assert!((norm_v1.y - 2.0 / 5.0).abs() < EPSILON);
assert!((norm_v1.z - 2.0 / 5.0).abs() < EPSILON);
assert!((norm_v1.w - 4.0 / 5.0).abs() < EPSILON);
let v_zero = Vec4f32::ZERO;
assert_eq!(v_zero.normalize(), Vec4::ZERO);
}
#[test]
fn test_vec4_try_normalize() {
let v1: Vec4f32 = Vec4::new(1.0, 2.0, 2.0, 4.0);
let norm_v1_opt = v1.try_normalize();
assert!(norm_v1_opt.is_some());
let norm_v1 = norm_v1_opt.unwrap();
assert!((norm_v1.length() - 1.0).abs() < EPSILON);
assert!((norm_v1.x - 1.0 / 5.0).abs() < EPSILON);
assert!((norm_v1.y - 2.0 / 5.0).abs() < EPSILON);
assert!((norm_v1.z - 2.0 / 5.0).abs() < EPSILON);
assert!((norm_v1.w - 4.0 / 5.0).abs() < EPSILON);
let v_zero = Vec4f32::ZERO;
assert!(v_zero.try_normalize().is_none());
}
#[test]
fn test_vec4_xyz() {
let v4: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let v3 = v4.xyz();
assert_eq!(v3, Vec3f32::new(1.0, 2.0, 3.0));
}
#[test]
fn test_vec4_wzyx() {
let v: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let swapped = v.wzyx();
assert_eq!(swapped, Vec4::new(4.0, 3.0, 2.0, 1.0));
}
#[test]
fn test_vec4_reflect() {
let v: Vec4f32 = Vec4::new(1.0, 1.0, 1.0, 5.0); let n: Vec4f32 = Vec4::new(0.0, 0.0, -1.0, 0.0); let r = v.reflect(n);
assert_eq!(r, Vec4::new(1.0, 1.0, -1.0, 5.0));
}
#[test]
fn test_vec4_refract() {
let i: Vec4f32 = Vec4::new(1.0, 0.0, 0.0, 7.0);
let n: Vec4f32 = Vec4::new(0.0, 1.0, 0.0, 0.0);
let eta_tir = 1.5;
let r_tir = i.refract(n, eta_tir);
assert_eq!(r_tir, Vec4::new(0.0, 0.0, 0.0, 7.0));
let eta_no_tir = 0.5;
let r_no_tir = i.refract(n, eta_no_tir);
assert_eq!(r_no_tir, Vec4::new(0.5, 0.0, 0.0, 7.0)); }
#[test]
fn test_vec4_try_refract() {
let i: Vec4f32 = Vec4::new(1.0, 0.0, 0.0, 7.0);
let n: Vec4f32 = Vec4::new(0.0, 1.0, 0.0, 0.0);
let eta_tir = 1.5;
let r_tir_opt = i.try_refract(n, eta_tir);
assert!(r_tir_opt.is_none());
let eta_no_tir = 0.5;
let r_no_tir_opt = i.try_refract(n, eta_no_tir);
assert!(r_no_tir_opt.is_some());
if let Some(r_no_tir) = r_no_tir_opt {
assert_eq!(r_no_tir, Vec4::new(0.5, 0.0, 0.0, 7.0));
}
}
#[test]
fn test_vec4_lerp() {
let a: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
let b: Vec4f32 = Vec4::new(5.0, 6.0, 7.0, 8.0);
let r1 = a.lerp(b, 0.0); assert_eq!(r1, a);
let r2 = a.lerp(b, 1.0); assert_eq!(r2, b);
let r3 = a.lerp(b, 0.5); assert_eq!(r3, Vec4::new(3.0, 4.0, 5.0, 6.0));
let r4 = a.lerp(b, 0.25);
assert_eq!(r4, Vec4::new(2.0, 3.0, 4.0, 5.0));
}
#[test]
fn test_vec4_angle_between() {
let v1: Vec4f32 = Vec4::new(1.0, 0.0, 0.0, 0.0);
let v2: Vec4f32 = Vec4::new(0.0, 1.0, 0.0, 0.0);
assert!((v1.angle_between(v2) - std::f32::consts::FRAC_PI_2).abs() < EPSILON);
let v3: Vec4f32 = Vec4::new(1.0, 0.0, 0.0, 0.0);
let v4: Vec4f32 = Vec4::new(1.0, 0.0, 0.0, 0.0);
assert!((v3.angle_between(v4)).abs() < EPSILON);
}
#[test]
fn test_vec4_project_onto() {
let v: Vec4f32 = Vec4::new(2.0, 2.0, 0.0, 0.0);
let onto: Vec4f32 = Vec4::new(1.0, 0.0, 0.0, 0.0);
let proj = v.project_onto(onto);
assert!((proj.x - 2.0).abs() < EPSILON);
assert!((proj.y - 0.0).abs() < EPSILON);
assert!((proj.z - 0.0).abs() < EPSILON);
assert!((proj.w - 0.0).abs() < EPSILON);
}
#[test]
fn test_vec4_normalize_or_zero() {
let v: Vec4f32 = Vec4::new(1.0, 2.0, 2.0, 4.0);
let n = v.normalize_or_zero();
assert!((n.length() - 1.0).abs() < EPSILON);
let zero = Vec4f32::ZERO;
assert_eq!(zero.normalize_or_zero(), Vec4f32::ZERO);
}
#[test]
fn test_vec4_distance() {
let v1: Vec4f32 = Vec4::new(0.0, 0.0, 0.0, 0.0);
let v2: Vec4f32 = Vec4::new(1.0, 2.0, 2.0, 4.0);
assert!((v1.distance(v2) - 5.0).abs() < EPSILON);
}
#[test]
fn test_vec4_clamp() {
let v: Vec4f32 = Vec4::new(5.0, -2.0, 10.0, 7.0);
let min: Vec4f32 = Vec4::new(0.0, 0.0, 0.0, 0.0);
let max: Vec4f32 = Vec4::new(4.0, 4.0, 4.0, 4.0);
let clamped = v.clamp(min, max);
assert_eq!(clamped, Vec4::new(4.0, 0.0, 4.0, 4.0));
}
#[test]
fn test_vec4_min_max() {
let v1: Vec4f32 = Vec4::new(1.0, 5.0, 3.0, 7.0);
let v2: Vec4f32 = Vec4::new(3.0, 2.0, 4.0, 6.0);
assert_eq!(v1.min(v2), Vec4::new(1.0, 2.0, 3.0, 6.0));
assert_eq!(v1.max(v2), Vec4::new(3.0, 5.0, 4.0, 7.0));
}
#[test]
fn test_vec4_is_nan_is_finite() {
let v: Vec4f32 = Vec4::new(f32::NAN, 1.0, 2.0, 3.0);
assert!(v.is_nan());
let v2: Vec4f32 = Vec4::new(1.0, 2.0, 3.0, 4.0);
assert!(v2.is_finite());
let v3: Vec4f32 = Vec4::new(f32::INFINITY, 1.0, 2.0, 3.0);
assert!(!v3.is_finite());
}
}
const _CONST_V0: Vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0);
const _CONST_V1: Vec4 = Vec4::new(5.0, 6.0, 7.0, 8.0);
const _CONST_DOT: f32 = Vec4f32::new(1.0, 2.0, 3.0, 4.0).dot(Vec4f32::new(5.0, 6.0, 7.0, 8.0));
const _CONST_WZYX: Vec4 = Vec4::new(1.0, 2.0, 3.0, 4.0).wzyx();
const _CONST_LEN_SQ: f32 = Vec4f32::new(1.0, 2.0, 2.0, 4.0).length_squared();
const _CONST_MIN: Vec4 = Vec4::new(1.0, 5.0, 3.0, 7.0).min(Vec4::new(3.0, 2.0, 4.0, 6.0));
const _CONST_MAX: Vec4 = Vec4::new(1.0, 5.0, 3.0, 7.0).max(Vec4::new(3.0, 2.0, 4.0, 6.0));
const _CONST_CLAMP: Vec4 = Vec4::new(5.0, -2.0, 10.0, 7.0).clamp(Vec4::new(0.0, 0.0, 0.0, 0.0), Vec4::new(4.0, 4.0, 4.0, 4.0));
const _: () = {
assert!(_CONST_V0.x == 1.0 && _CONST_V0.y == 2.0 && _CONST_V0.z == 3.0 && _CONST_V0.w == 4.0);
assert!(_CONST_V1.x == 5.0 && _CONST_V1.y == 6.0 && _CONST_V1.z == 7.0 && _CONST_V1.w == 8.0);
assert!(_CONST_DOT == 70.0);
assert!(_CONST_WZYX.x == 4.0 && _CONST_WZYX.y == 3.0 && _CONST_WZYX.z == 2.0 && _CONST_WZYX.w == 1.0);
assert!(_CONST_LEN_SQ == 25.0);
assert!(_CONST_MIN.x == 1.0 && _CONST_MIN.y == 2.0 && _CONST_MIN.z == 3.0 && _CONST_MIN.w == 6.0);
assert!(_CONST_MAX.x == 3.0 && _CONST_MAX.y == 5.0 && _CONST_MAX.z == 4.0 && _CONST_MAX.w == 7.0);
assert!(_CONST_CLAMP.x == 4.0 && _CONST_CLAMP.y == 0.0 && _CONST_CLAMP.z == 4.0 && _CONST_CLAMP.w == 4.0);
};
const _CONST_METERS: Vec4Meters = Vec4Meters::new(1.0, 2.0, 3.0, 4.0);
const _CONST_PIXELS: Vec4Pixels = Vec4Pixels::new(10.0, 20.0, 30.0, 40.0);
const fn _make_vec4_meters() -> Vec4Meters {
Vec4Meters::new(3.0, 4.0, 5.0, 6.0)
}
const fn _make_vec4_pixels() -> Vec4Pixels {
Vec4Pixels::new(30.0, 40.0, 50.0, 60.0)
}
const _CONST_METERS2: Vec4Meters = _make_vec4_meters();
const _CONST_PIXELS2: Vec4Pixels = _make_vec4_pixels();
const _: () = {
assert!(_CONST_METERS.x == 1.0 && _CONST_METERS.y == 2.0 && _CONST_METERS.z == 3.0 && _CONST_METERS.w == 4.0);
assert!(_CONST_PIXELS.x == 10.0 && _CONST_PIXELS.y == 20.0 && _CONST_PIXELS.z == 30.0 && _CONST_PIXELS.w == 40.0);
assert!(_CONST_METERS2.x == 3.0 && _CONST_METERS2.y == 4.0 && _CONST_METERS2.z == 5.0 && _CONST_METERS2.w == 6.0);
assert!(_CONST_PIXELS2.x == 30.0 && _CONST_PIXELS2.y == 40.0 && _CONST_PIXELS2.z == 50.0 && _CONST_PIXELS2.w == 60.0);
};
#[test]
fn test_vec4_meters_to_pixels() {
let meters: Vec4<Meters, ()> = Vec4::new(2.0, 3.0, 4.0, 5.0);
let pixels = meters.to_pixels(100.0);
assert_eq!(pixels, Vec4::<Pixels, ()>::new(200.0, 300.0, 400.0, 500.0));
}
const _CONST_WORLD: Vec4<(), World> = Vec4::new(1.0, 2.0, 3.0, 4.0);
const _CONST_LOCAL: Vec4<(), Local> = Vec4::new(5.0, 6.0, 7.0, 8.0);
const _CONST_SCREEN: Vec4<(), Screen> = Vec4::new(9.0, 10.0, 11.0, 12.0);
const _: () = {
assert!(_CONST_WORLD.x == 1.0 && _CONST_WORLD.y == 2.0 && _CONST_WORLD.z == 3.0 && _CONST_WORLD.w == 4.0);
assert!(_CONST_LOCAL.x == 5.0 && _CONST_LOCAL.y == 6.0 && _CONST_LOCAL.z == 7.0 && _CONST_LOCAL.w == 8.0);
assert!(_CONST_SCREEN.x == 9.0 && _CONST_SCREEN.y == 10.0 && _CONST_SCREEN.z == 11.0 && _CONST_SCREEN.w == 12.0);
};