use super::*;
fn e0() -> [f32; EMBEDDING_DIM] {
let mut s = [0.0f32; EMBEDDING_DIM];
s[0] = 1.0;
s
}
fn norm_sq_f64(e: &Embedding) -> f64 {
e.as_slice()
.iter()
.map(|&x| f64::from(x) * f64::from(x))
.sum()
}
#[test]
fn from_slice_normalizing_produces_unit_norm() {
let s: Vec<f32> = (0..EMBEDDING_DIM).map(|i| (i as f32) + 1.0).collect();
let e = Embedding::from_slice_normalizing(&s).unwrap();
let norm_sq: f32 = e.as_slice().iter().map(|x| x * x).sum();
assert!((norm_sq - 1.0).abs() <= NORM_BUDGET, "norm² = {norm_sq}");
}
#[test]
fn from_slice_normalizing_rejects_zero() {
let s = [0.0f32; EMBEDDING_DIM];
let err = Embedding::from_slice_normalizing(&s).unwrap_err();
assert!(matches!(err, Error::EmbeddingZero), "got {err:?}");
}
#[test]
fn from_slice_normalizing_rejects_nan() {
let mut s = e0();
s[7] = f32::NAN;
let err = Embedding::from_slice_normalizing(&s).unwrap_err();
assert!(matches!(err, Error::NonFiniteEmbedding(7)), "got {err:?}");
}
#[test]
fn from_slice_normalizing_rejects_inf() {
let mut s = e0();
s[3] = f32::INFINITY;
let err = Embedding::from_slice_normalizing(&s).unwrap_err();
assert!(matches!(err, Error::NonFiniteEmbedding(3)), "got {err:?}");
}
#[test]
fn check_finite_output_accepts_finite() {
let s: Vec<f32> = (0..EMBEDDING_DIM).map(|i| (i as f32) - 100.0).collect();
assert!(check_finite_output(&s).is_ok());
}
#[test]
fn check_finite_output_rejects_model_nan_as_output_not_embedding() {
let mut s = e0();
s[5] = f32::NAN;
let err = check_finite_output(&s).unwrap_err();
assert!(matches!(err, Error::NonFiniteOutput(5)), "got {err:?}");
}
#[test]
fn check_finite_output_rejects_inf() {
let mut s = e0();
s[9] = f32::NEG_INFINITY;
let err = check_finite_output(&s).unwrap_err();
assert!(matches!(err, Error::NonFiniteOutput(9)), "got {err:?}");
}
#[test]
fn from_slice_normalizing_handles_overflow_magnitude() {
let s = [f32::MAX; EMBEDDING_DIM];
let e = Embedding::from_slice_normalizing(&s).expect("f32::MAX normalizes via f64");
let norm_sq: f32 = e.as_slice().iter().map(|x| x * x).sum();
assert!((norm_sq - 1.0).abs() <= NORM_BUDGET, "norm² = {norm_sq}");
}
#[test]
fn from_slice_normalizing_handles_smallest_subnormal() {
let s = [f32::from_bits(1); EMBEDDING_DIM]; let e = Embedding::from_slice_normalizing(&s).expect("subnormal magnitude normalizes");
let norm_sq: f32 = e.as_slice().iter().map(|x| x * x).sum();
assert!((norm_sq - 1.0).abs() <= NORM_BUDGET, "norm² = {norm_sq}");
}
#[test]
fn from_slice_normalizing_wrong_len() {
let s = [0.0f32; EMBEDDING_DIM - 1];
let err = Embedding::from_slice_normalizing(&s).unwrap_err();
assert!(
matches!(
err,
Error::EmbeddingDimMismatch(ref d)
if d.expected() == EMBEDDING_DIM && d.got() == EMBEDDING_DIM - 1
),
"got {err:?}"
);
}
#[test]
fn try_from_unit_slice_accepts_at_budget_edge() {
let target_sq = 1.0 + 0.5 * NORM_BUDGET;
let mut s = [0.0f32; EMBEDDING_DIM];
s[0] = target_sq.sqrt();
let e = Embedding::try_from_unit_slice(&s).expect("within budget");
assert!(
(norm_sq_f64(&e) - 1.0).abs() <= 1e-6,
"accepted vector must be stored unit-norm (f64 norm² = {})",
norm_sq_f64(&e)
);
}
#[test]
fn restored_budget_edge_vector_is_renormalized() {
let mut s = [0.0f32; EMBEDDING_DIM];
s[0] = (1.0f32 + 0.522e-4).sqrt();
let e = Embedding::try_from_unit_slice(&s).expect("within budget");
assert!(
(norm_sq_f64(&e) - 1.0).abs() <= 1e-6,
"stored vector must be renormalized to unit norm (f64 norm² = {})",
norm_sq_f64(&e)
);
let self_cos = e.cosine(&e);
assert!(
(1.0 - 1e-5..=1.0 + 1e-5).contains(&self_cos),
"cos(x, x) must stay in [−1, 1] (got {self_cos})"
);
assert!(
1.0 - self_cos >= -1e-5,
"cosine distance must be non-negative (1 − cos = {})",
1.0 - self_cos
);
let mut neg_s = [0.0f32; EMBEDDING_DIM];
neg_s[0] = -s[0];
let neg = Embedding::try_from_unit_slice(&neg_s).expect("−s is also within budget");
let opp = e.cosine(&neg);
assert!(
(-1.0 - 1e-5..=-1.0 + 1e-5).contains(&opp),
"cos(x, −x) must stay in [−1, 1] (got {opp})"
);
}
#[test]
fn near_budget_vectors_restore_unit_norm_property() {
let devs = [-1.0f32, -0.75, -0.5, -0.25, 0.25, 0.5, 0.75, 0.95, 1.0];
let uniform = (1.0f32 / EMBEDDING_DIM as f32).sqrt();
for &d in &devs {
let scale = (1.0f32 + d * NORM_BUDGET).sqrt();
let shapes: [Vec<f32>; 3] = [
{
let mut v = vec![0.0f32; EMBEDDING_DIM];
v[0] = scale; v
},
(0..EMBEDDING_DIM).map(|_| uniform * scale).collect(), (0..EMBEDDING_DIM) .map(|i| {
if i % 2 == 0 {
uniform * scale
} else {
-uniform * scale
}
})
.collect(),
];
for s in &shapes {
let norm_sq: f32 = s.iter().map(|x| x * x).sum();
let expect_accept = (norm_sq - 1.0).abs() <= NORM_BUDGET;
match Embedding::try_from_unit_slice(s) {
Ok(e) => {
assert!(
expect_accept,
"accepted a vector the gate should reject (norm² = {norm_sq})"
);
assert!(
(norm_sq_f64(&e) - 1.0).abs() <= 1e-6,
"accepted vector not stored unit-norm (f64 norm² = {})",
norm_sq_f64(&e)
);
let c = e.cosine(&e);
assert!(
(1.0 - 1e-5..=1.0 + 1e-5).contains(&c),
"cos(x, x) escaped [−1, 1]: {c}"
);
assert!(1.0 - c >= -1e-5, "negative cosine distance: {}", 1.0 - c);
let neg: Vec<f32> = e.to_vec().iter().map(|v| -v).collect();
let neg_e =
Embedding::try_from_unit_slice(&neg).expect("a negated unit vector is unit-norm");
let o = e.cosine(&neg_e);
assert!(
(-1.0 - 1e-5..=-1.0 + 1e-5).contains(&o),
"cos(x, −x) escaped [−1, 1]: {o}"
);
}
Err(Error::EmbeddingNotUnitNorm(_)) => {
assert!(
!expect_accept,
"rejected a vector the gate should accept (norm² = {norm_sq})"
);
}
Err(other) => panic!("unexpected error: {other:?}"),
}
}
}
}
#[test]
fn try_from_unit_slice_is_idempotent_on_its_output() {
let uniform = (1.0f32 / EMBEDDING_DIM as f32).sqrt();
let scale = (1.0f32 + 0.5 * NORM_BUDGET).sqrt();
let s: Vec<f32> = (0..EMBEDDING_DIM).map(|_| uniform * scale).collect();
let first = Embedding::try_from_unit_slice(&s).expect("within budget");
let second =
Embedding::try_from_unit_slice(&first.to_vec()).expect("renormalized output re-accepts");
assert!(
second.is_close(&first, 1e-6),
"renormalizing an already-renormalized vector must be a no-op to ULP scale"
);
}
#[test]
fn try_from_unit_slice_rejects_beyond_budget() {
let mut s = [0.0f32; EMBEDDING_DIM];
s[0] = (1.0 + 2.0 * NORM_BUDGET).sqrt();
let err = Embedding::try_from_unit_slice(&s).unwrap_err();
assert!(matches!(err, Error::EmbeddingNotUnitNorm(_)), "got {err:?}");
}
#[test]
fn try_from_unit_slice_wrong_len() {
let s = [0.0f32; EMBEDDING_DIM + 1];
let err = Embedding::try_from_unit_slice(&s).unwrap_err();
assert!(
matches!(
err,
Error::EmbeddingDimMismatch(ref d)
if d.expected() == EMBEDDING_DIM && d.got() == EMBEDDING_DIM + 1
),
"got {err:?}"
);
}
#[test]
fn dot_and_cosine_agree_for_unit_vectors() {
let e = Embedding::from_slice_normalizing(&e0()).unwrap();
assert_eq!(e.dot(&e), e.cosine(&e));
assert!((e.cosine(&e) - 1.0).abs() <= 1e-6);
}
#[test]
fn orthogonal_unit_vectors_have_zero_cosine() {
let a = Embedding::from_slice_normalizing(&e0()).unwrap();
let mut y = [0.0f32; EMBEDDING_DIM];
y[1] = 1.0;
let b = Embedding::from_slice_normalizing(&y).unwrap();
assert!(a.cosine(&b).abs() <= 1e-6);
}
#[test]
fn is_close_self_at_zero_tolerance() {
let a = Embedding::from_slice_normalizing(&e0()).unwrap();
assert!(a.is_close(&a, 0.0));
assert!(a.is_close_cosine(&a, 0.0));
}
#[test]
fn is_close_cosine_separates_orthogonal() {
let a = Embedding::from_slice_normalizing(&e0()).unwrap();
let mut y = [0.0f32; EMBEDDING_DIM];
y[1] = 1.0;
let b = Embedding::from_slice_normalizing(&y).unwrap();
assert!(!a.is_close_cosine(&b, 1.0e-6));
assert!(!a.is_close(&b, 1.0e-6));
}
#[test]
fn deref_and_as_ref_expose_the_slice() {
let e = Embedding::from_slice_normalizing(&e0()).unwrap();
assert_eq!(e.len(), EMBEDDING_DIM); let r: &[f32] = e.as_ref();
assert_eq!(r.len(), EMBEDDING_DIM);
assert_eq!(e.dim(), EMBEDDING_DIM);
}
#[test]
fn to_vec_roundtrips_via_try_from_unit_slice() {
let e = Embedding::from_slice_normalizing(&e0()).unwrap();
let v = e.to_vec();
assert_eq!(v.len(), EMBEDDING_DIM);
let back = Embedding::try_from_unit_slice(&v).expect("unit vector round-trips");
assert!(back.is_close(&e, 0.0));
}