use versorc_math::prelude::*;
#[test]
fn test_cayley_klein_tau_metric_transitions() {
let x = [0.2f32, 0.1, 0.0];
let y = [0.4f32, -0.1, 0.2];
let space_hyp = CayleyKleinSpace::new(-1.0);
let d_hyp = space_hyp.geodesic_distance(&x, &y);
assert!(d_hyp > 0.0);
let space_euc = CayleyKleinSpace::new(0.0);
let d_euc = space_euc.geodesic_distance(&x, &y);
let expected_euc = ((0.2 - 0.4f32).powi(2) + (0.1 - (-0.1f32)).powi(2) + (0.0 - 0.2f32).powi(2)).sqrt();
assert!((d_euc - expected_euc).abs() < 1e-6);
let space_ell = CayleyKleinSpace::new(1.0);
let d_ell = space_ell.geodesic_distance(&x, &y);
assert!(d_ell > 0.0);
assert!(d_hyp > 0.0, "Hyperbolic distance must be positive");
assert!(d_euc > 0.0, "Euclidean distance must be positive");
assert!(d_ell > 0.0, "Elliptic distance must be positive");
assert!(
d_hyp > d_euc,
"Hyperbolic metric should expand distances compared to Euclidean: {} vs {}",
d_hyp,
d_euc
);
let proj = space_hyp.project_to_euclidean(&x);
assert_eq!(proj.len(), 3);
}
#[test]
fn test_eisenstein_a3_kissing_number_and_conversions() {
let neighbors = EisensteinA3Lattice::generate_12_neighbors();
assert_eq!(neighbors.len(), EISENSTEIN_KISSING_NUMBER);
for n in &neighbors {
let d_sq = EisensteinA3Lattice::distance_sq(n[0], n[1], n[2]);
assert_eq!(d_sq, 1, "Nearest neighbor {:?} must have distance squared == 1", n);
}
let origin_coords = EisensteinA3Lattice::to_euclidean(0, 0, 0);
assert_eq!(origin_coords, [0.0, 0.0, 0.0]);
let (u, v, w) = (2, -1, 3);
let pt3d = EisensteinA3Lattice::to_euclidean(u, v, w);
let rounded = EisensteinA3Lattice::from_euclidean(pt3d[0], pt3d[1], pt3d[2]);
assert_eq!(rounded, [u, v, w], "Eisenstein lattice roundtrip failed: {:?} vs {:?}", rounded, [u, v, w]);
let p3d = EisensteinA3Lattice::to_poincare(u, v, w, 0.1);
let norm_p3d = (p3d[0] * p3d[0] + p3d[1] * p3d[1] + p3d[2] * p3d[2]).sqrt();
assert!(norm_p3d < 1.0, "Eisenstein Poincaré projection must strictly reside inside unit ball: norm={}", norm_p3d);
}
#[test]
fn test_data_oriented_design_64byte_cache_alignment() {
assert_eq!(std::mem::size_of::<Universal64Accumulator>(), 64);
assert_eq!(std::mem::align_of::<Universal64Accumulator>(), 64);
assert_eq!(std::mem::size_of::<Universal64Chunk>(), 64);
assert_eq!(std::mem::align_of::<Universal64Chunk>(), 64);
assert_eq!(std::mem::size_of::<SoABatch16>(), 256);
assert_eq!(std::mem::align_of::<SoABatch16>(), 64);
let mut acc = Universal64Accumulator::zero();
for i in 0..16 {
acc.lanes[i] = (i + 1) as f32; }
assert_eq!(acc.horizontal_sum(), 136.0f32);
}
#[test]
fn test_soa_batch_cache_line_operations() {
let mut pts_a = [[0.0f32; 3]; 16];
let mut pts_b = [[0.0f32; 3]; 16];
for i in 0..16 {
pts_a[i] = [0.1 * (i as f32), 0.05 * (i as f32), -0.02 * (i as f32)];
pts_b[i] = [0.05 * (i as f32), -0.05 * (i as f32), 0.04 * (i as f32)];
}
let batch_a = SoABatch16::from_aos_3d(&pts_a);
let batch_b = SoABatch16::from_aos_3d(&pts_b);
let space_hyp = CayleyKleinSpace::new(-0.5);
let dist_accum = batch_a.batch_geodesic_distance(&batch_b, &space_hyp);
assert_eq!(std::mem::size_of_val(&dist_accum), 64);
for i in 1..16 {
assert!(dist_accum.lanes[i] > 0.0, "Geodesic distance lane {} must be positive", i);
}
let (u_arr, v_arr, w_arr) = batch_a.batch_to_eisenstein_a3();
assert_eq!(u_arr.len(), 16);
assert_eq!(v_arr.len(), 16);
assert_eq!(w_arr.len(), 16);
let mut batch_rot = batch_a;
let cos_45 = 0.70710678f32;
let sin_45 = 0.70710678f32;
batch_rot.batch_planar_spinor_rotate(cos_45, sin_45);
let norm_before = (batch_a.x[1].powi(2) + batch_a.y[1].powi(2)).sqrt();
let norm_after = (batch_rot.x[1].powi(2) + batch_rot.y[1].powi(2)).sqrt();
assert!((norm_after - norm_before).abs() < 1e-6, "Planar spinor rotation in batch must preserve norm");
}