#![cfg(feature = "deterministic")]
use amari::deterministic::ga2d::{DetRotor2, DetVector2};
use amari::deterministic::DetF32;
mod golden_vectors {
use super::*;
#[test]
fn test_scalar_arithmetic_golden() {
let a = DetF32::from_bits(0x3fc00000); let b = DetF32::from_bits(0x40200000); let result = a + b;
assert_eq!(
result.to_bits(),
0x40800000,
"Addition: 1.5 + 2.5 must equal exactly 4.0"
);
let c = DetF32::from_bits(0x40400000); let d = DetF32::from_bits(0x40800000); let result = c * d;
assert_eq!(
result.to_bits(),
0x41400000,
"Multiplication: 3.0 * 4.0 must equal exactly 12.0"
);
let e = DetF32::from_bits(0x41200000); let f = DetF32::from_bits(0x40400000); let result = e - f;
assert_eq!(
result.to_bits(),
0x40e00000,
"Subtraction: 10.0 - 3.0 must equal exactly 7.0"
);
let g = DetF32::from_bits(0x41000000); let h = DetF32::from_bits(0x40000000); let result = g / h;
assert_eq!(
result.to_bits(),
0x40800000,
"Division: 8.0 / 2.0 must equal exactly 4.0"
);
}
#[test]
fn test_sqrt_golden() {
let x = DetF32::from_bits(0x40800000); let result = x.sqrt();
assert_eq!(
result.to_bits(),
0x40000000,
"sqrt(4.0) must equal exactly 2.0"
);
let y = DetF32::from_bits(0x41100000); let result1 = y.sqrt();
let result2 = y.sqrt();
let result3 = y.sqrt();
assert_eq!(
result1.to_bits(),
result2.to_bits(),
"sqrt(9.0) must produce consistent bit pattern (run 1 vs 2)"
);
assert_eq!(
result2.to_bits(),
result3.to_bits(),
"sqrt(9.0) must produce consistent bit pattern (run 2 vs 3)"
);
let error = (result1 - DetF32::from_f32(3.0)).abs();
assert!(
error < DetF32::from_f32(1e-2),
"sqrt(9.0) must be accurate within 1e-2"
);
let z = DetF32::from_bits(0x41800000); let result1 = z.sqrt();
let result2 = z.sqrt();
let result3 = z.sqrt();
assert_eq!(
result1.to_bits(),
result2.to_bits(),
"sqrt(16.0) must produce consistent bit pattern (run 1 vs 2)"
);
assert_eq!(
result2.to_bits(),
result3.to_bits(),
"sqrt(16.0) must produce consistent bit pattern (run 2 vs 3)"
);
let error = (result1 - DetF32::from_f32(4.0)).abs();
assert!(
error < DetF32::from_f32(1e-2),
"sqrt(16.0) must be accurate within 1e-2"
);
}
#[test]
fn test_trig_golden() {
let angle = DetF32::ZERO;
let result = angle.sin();
assert_eq!(
result.to_bits(),
0x00000000,
"sin(0) must equal exactly 0.0"
);
let result = angle.cos();
assert_eq!(
result.to_bits(),
0x3f800000,
"cos(0) must equal exactly 1.0"
);
let pi_half = DetF32::PI * DetF32::HALF;
let result = pi_half.sin();
let expected = result.to_bits();
assert_eq!(
result.to_bits(),
expected,
"sin(π/2) must produce consistent bit pattern"
);
}
#[test]
fn test_vector_operations_golden() {
let v1 = DetVector2::new(DetF32::ONE, DetF32::ZERO);
let v2 = DetVector2::new(DetF32::ZERO, DetF32::ONE);
let result = v1 + v2;
assert_eq!(
result.x.to_bits(),
0x3f800000,
"Vector addition x-component must be exactly 1.0"
);
assert_eq!(
result.y.to_bits(),
0x3f800000,
"Vector addition y-component must be exactly 1.0"
);
let v3 = DetVector2::new(DetF32::TWO, DetF32::from_f32(3.0));
let v4 = DetVector2::new(DetF32::from_f32(4.0), DetF32::from_f32(5.0));
let result = v3.dot(v4);
assert_eq!(
result.to_bits(),
0x41b80000,
"Dot product must be exactly 23.0"
);
}
#[test]
fn test_rotor_golden() {
let v = DetVector2::new(DetF32::from_f32(3.0), DetF32::from_f32(4.0));
let r = DetRotor2::IDENTITY;
let result = r.transform(v);
assert_eq!(
result.x.to_bits(),
v.x.to_bits(),
"Identity rotor must preserve x-component exactly"
);
assert_eq!(
result.y.to_bits(),
v.y.to_bits(),
"Identity rotor must preserve y-component exactly"
);
let v = DetVector2::X_AXIS;
let r = DetRotor2::from_angle(DetF32::PI * DetF32::HALF);
let result = r.transform(v);
let x_pattern = result.x.to_bits();
let y_pattern = result.y.to_bits();
let result2 = r.transform(v);
assert_eq!(
result2.x.to_bits(),
x_pattern,
"90° rotation must produce consistent x-component"
);
assert_eq!(
result2.y.to_bits(),
y_pattern,
"90° rotation must produce consistent y-component"
);
}
}
mod replay_validation {
use super::*;
#[test]
fn test_physics_step_replay() {
let mut position = DetVector2::new(DetF32::ZERO, DetF32::ZERO);
let mut rotation = DetRotor2::IDENTITY;
let delta_angle = DetF32::PI * DetF32::from_f32(15.0 / 180.0);
rotation = rotation * DetRotor2::from_angle(delta_angle);
let forward = rotation.transform(DetVector2::X_AXIS);
let speed = DetF32::from_f32(2.5);
position = position + forward * speed;
let pos_x_bits = position.x.to_bits();
let pos_y_bits = position.y.to_bits();
let rot_s_bits = rotation.s.to_bits();
let rot_b_bits = rotation.b.to_bits();
let mut replay_position = DetVector2::new(DetF32::ZERO, DetF32::ZERO);
let mut replay_rotation = DetRotor2::IDENTITY;
replay_rotation = replay_rotation * DetRotor2::from_angle(delta_angle);
let replay_forward = replay_rotation.transform(DetVector2::X_AXIS);
replay_position = replay_position + replay_forward * speed;
assert_eq!(
replay_position.x.to_bits(),
pos_x_bits,
"Replay position.x must match exactly"
);
assert_eq!(
replay_position.y.to_bits(),
pos_y_bits,
"Replay position.y must match exactly"
);
assert_eq!(
replay_rotation.s.to_bits(),
rot_s_bits,
"Replay rotation.s must match exactly"
);
assert_eq!(
replay_rotation.b.to_bits(),
rot_b_bits,
"Replay rotation.b must match exactly"
);
}
#[test]
fn test_multi_frame_replay() {
let frames = 10;
let dt = DetF32::from_f32(1.0 / 60.0); let angular_velocity = DetF32::PI * DetF32::from_f32(0.5);
let mut rotation = DetRotor2::IDENTITY;
for _ in 0..frames {
let delta_angle = angular_velocity * dt;
rotation = rotation * DetRotor2::from_angle(delta_angle);
}
let final_s = rotation.s.to_bits();
let final_b = rotation.b.to_bits();
let mut replay_rotation = DetRotor2::IDENTITY;
for _ in 0..frames {
let delta_angle = angular_velocity * dt;
replay_rotation = replay_rotation * DetRotor2::from_angle(delta_angle);
}
assert_eq!(
replay_rotation.s.to_bits(),
final_s,
"Multi-frame replay rotation.s must match exactly"
);
assert_eq!(
replay_rotation.b.to_bits(),
final_b,
"Multi-frame replay rotation.b must match exactly"
);
}
#[test]
fn test_collision_response_replay() {
let velocity = DetVector2::new(DetF32::from_f32(5.0), DetF32::from_f32(-3.0));
let normal = DetVector2::new(DetF32::ZERO, DetF32::ONE); let restitution = DetF32::from_f32(0.8);
let dot_vn = velocity.dot(normal);
let factor = (DetF32::ONE + restitution) * dot_vn;
let impulse = normal * factor;
let new_velocity = velocity - impulse;
let v_x_bits = new_velocity.x.to_bits();
let v_y_bits = new_velocity.y.to_bits();
let dot_vn_replay = velocity.dot(normal);
let factor_replay = (DetF32::ONE + restitution) * dot_vn_replay;
let impulse_replay = normal * factor_replay;
let replay_velocity = velocity - impulse_replay;
assert_eq!(
replay_velocity.x.to_bits(),
v_x_bits,
"Collision response x-velocity must replay exactly"
);
assert_eq!(
replay_velocity.y.to_bits(),
v_y_bits,
"Collision response y-velocity must replay exactly"
);
}
}
mod consistency {
use super::*;
#[test]
fn test_repeated_sqrt() {
let x = DetF32::from_f32(12345.679);
let sqrt1 = x.sqrt();
let sqrt2 = x.sqrt();
let sqrt3 = x.sqrt();
assert_eq!(
sqrt1.to_bits(),
sqrt2.to_bits(),
"Repeated sqrt must produce identical bits (run 1 vs 2)"
);
assert_eq!(
sqrt2.to_bits(),
sqrt3.to_bits(),
"Repeated sqrt must produce identical bits (run 2 vs 3)"
);
}
#[test]
fn test_repeated_trig() {
let angle = DetF32::from_f32(1.23456);
let sin1 = angle.sin();
let sin2 = angle.sin();
let sin3 = angle.sin();
assert_eq!(
sin1.to_bits(),
sin2.to_bits(),
"Repeated sin must produce identical bits"
);
assert_eq!(
sin2.to_bits(),
sin3.to_bits(),
"Repeated sin must produce identical bits"
);
let cos1 = angle.cos();
let cos2 = angle.cos();
let cos3 = angle.cos();
assert_eq!(
cos1.to_bits(),
cos2.to_bits(),
"Repeated cos must produce identical bits"
);
assert_eq!(
cos2.to_bits(),
cos3.to_bits(),
"Repeated cos must produce identical bits"
);
}
#[test]
fn test_repeated_atan2() {
let y = DetF32::from_f32(3.0);
let x = DetF32::from_f32(4.0);
let angle1 = DetF32::atan2(y, x);
let angle2 = DetF32::atan2(y, x);
let angle3 = DetF32::atan2(y, x);
assert_eq!(
angle1.to_bits(),
angle2.to_bits(),
"Repeated atan2 must produce identical bits"
);
assert_eq!(
angle2.to_bits(),
angle3.to_bits(),
"Repeated atan2 must produce identical bits"
);
}
#[test]
fn test_repeated_rotor_composition() {
let r1 = DetRotor2::from_angle(DetF32::from_f32(0.5));
let r2 = DetRotor2::from_angle(DetF32::from_f32(0.3));
let composed1 = r1 * r2;
let composed2 = r1 * r2;
let composed3 = r1 * r2;
assert_eq!(
composed1.s.to_bits(),
composed2.s.to_bits(),
"Repeated rotor composition must produce identical s bits"
);
assert_eq!(
composed1.b.to_bits(),
composed2.b.to_bits(),
"Repeated rotor composition must produce identical b bits"
);
assert_eq!(
composed2.s.to_bits(),
composed3.s.to_bits(),
"Repeated rotor composition must produce identical s bits"
);
assert_eq!(
composed2.b.to_bits(),
composed3.b.to_bits(),
"Repeated rotor composition must produce identical b bits"
);
}
#[test]
fn test_repeated_vector_transform() {
let v = DetVector2::new(DetF32::from_f32(1.5), DetF32::from_f32(2.5));
let r = DetRotor2::from_angle(DetF32::from_f32(0.75));
let transformed1 = r.transform(v);
let transformed2 = r.transform(v);
let transformed3 = r.transform(v);
assert_eq!(
transformed1.x.to_bits(),
transformed2.x.to_bits(),
"Repeated vector transform must produce identical x bits"
);
assert_eq!(
transformed1.y.to_bits(),
transformed2.y.to_bits(),
"Repeated vector transform must produce identical y bits"
);
assert_eq!(
transformed2.x.to_bits(),
transformed3.x.to_bits(),
"Repeated vector transform must produce identical x bits"
);
assert_eq!(
transformed2.y.to_bits(),
transformed3.y.to_bits(),
"Repeated vector transform must produce identical y bits"
);
}
}
mod complex_scenarios {
use super::*;
#[test]
fn test_projectile_trajectory() {
let frames = 100;
let dt = DetF32::from_f32(1.0 / 60.0);
let gravity = DetVector2::new(DetF32::ZERO, DetF32::from_f32(-9.8));
let mut position = DetVector2::new(DetF32::ZERO, DetF32::from_f32(10.0));
let mut velocity = DetVector2::new(DetF32::from_f32(15.0), DetF32::from_f32(20.0));
for _ in 0..frames {
velocity = velocity + gravity * dt;
position = position + velocity * dt;
}
let final_x = position.x.to_bits();
let final_y = position.y.to_bits();
let mut replay_pos = DetVector2::new(DetF32::ZERO, DetF32::from_f32(10.0));
let mut replay_vel = DetVector2::new(DetF32::from_f32(15.0), DetF32::from_f32(20.0));
for _ in 0..frames {
replay_vel = replay_vel + gravity * dt;
replay_pos = replay_pos + replay_vel * dt;
}
assert_eq!(
replay_pos.x.to_bits(),
final_x,
"Projectile trajectory x must replay exactly"
);
assert_eq!(
replay_pos.y.to_bits(),
final_y,
"Projectile trajectory y must replay exactly"
);
}
#[test]
fn test_rotating_platform() {
let frames = 50;
let dt = DetF32::from_f32(1.0 / 60.0);
let angular_velocity = DetF32::PI * DetF32::from_f32(0.25);
let mut platform_rotation = DetRotor2::IDENTITY;
let local_position = DetVector2::new(DetF32::from_f32(5.0), DetF32::ZERO);
for _ in 0..frames {
let delta_angle = angular_velocity * dt;
platform_rotation = platform_rotation * DetRotor2::from_angle(delta_angle);
}
let world_position = platform_rotation.transform(local_position);
let final_x = world_position.x.to_bits();
let final_y = world_position.y.to_bits();
let mut replay_rotation = DetRotor2::IDENTITY;
for _ in 0..frames {
let delta_angle = angular_velocity * dt;
replay_rotation = replay_rotation * DetRotor2::from_angle(delta_angle);
}
let replay_world_pos = replay_rotation.transform(local_position);
assert_eq!(
replay_world_pos.x.to_bits(),
final_x,
"Rotating platform x position must replay exactly"
);
assert_eq!(
replay_world_pos.y.to_bits(),
final_y,
"Rotating platform y position must replay exactly"
);
}
#[test]
fn test_spring_damper_system() {
let frames = 100;
let dt = DetF32::from_f32(1.0 / 60.0);
let spring_constant = DetF32::from_f32(50.0);
let damping = DetF32::from_f32(5.0);
let mass = DetF32::from_f32(1.0);
let mut position = DetF32::from_f32(10.0); let mut velocity = DetF32::ZERO;
for _ in 0..frames {
let spring_force = -spring_constant * position;
let damping_force = -damping * velocity;
let total_force = spring_force + damping_force;
let acceleration = total_force / mass;
velocity = velocity + acceleration * dt;
position = position + velocity * dt;
}
let final_pos = position.to_bits();
let final_vel = velocity.to_bits();
let mut replay_pos = DetF32::from_f32(10.0);
let mut replay_vel = DetF32::ZERO;
for _ in 0..frames {
let spring_force = -spring_constant * replay_pos;
let damping_force = -damping * replay_vel;
let total_force = spring_force + damping_force;
let acceleration = total_force / mass;
replay_vel = replay_vel + acceleration * dt;
replay_pos = replay_pos + replay_vel * dt;
}
assert_eq!(
replay_pos.to_bits(),
final_pos,
"Spring-damper position must replay exactly"
);
assert_eq!(
replay_vel.to_bits(),
final_vel,
"Spring-damper velocity must replay exactly"
);
}
}