#![allow(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss,
clippy::float_cmp
)]
use super::dispatch::{
batch_hamming_native, batch_jaccard_native, hamming_distance_native, jaccard_similarity_native,
DistanceEngine,
};
use super::scalar;
const JACCARD_EPS: f32 = 1e-4;
fn make_pattern_vector(dim: usize, modulus: usize) -> Vec<f32> {
(0..dim)
.map(|i| if i % modulus == 0 { 1.0 } else { 0.0 })
.collect()
}
fn assert_hamming_matches_scalar(dim: usize) {
let a = make_pattern_vector(dim, 3);
let b = make_pattern_vector(dim, 2);
let native = hamming_distance_native(&a, &b);
let reference = scalar::hamming_scalar(&a, &b);
assert_eq!(
native, reference,
"hamming mismatch at dim={dim}: native={native}, scalar={reference}"
);
}
fn assert_jaccard_matches_scalar(dim: usize) {
let a = make_pattern_vector(dim, 3);
let b = make_pattern_vector(dim, 2);
let native = jaccard_similarity_native(&a, &b);
let reference = scalar::jaccard_scalar(&a, &b);
assert!(
(native - reference).abs() < JACCARD_EPS,
"jaccard mismatch at dim={dim}: native={native}, scalar={reference}"
);
}
const THRESHOLD_DIMS: &[usize] = &[
1, 3, 4, 7, 8, 15, 16, 31, 32, 63, 64, 127, 128, 255, 256, 511, 512, 768, 1023, 1024, 1025,
1536, 2048,
];
#[test]
fn test_hamming_native_matches_scalar_all_thresholds() {
for &dim in THRESHOLD_DIMS {
assert_hamming_matches_scalar(dim);
}
}
#[test]
fn test_jaccard_native_matches_scalar_all_thresholds() {
for &dim in THRESHOLD_DIMS {
assert_jaccard_matches_scalar(dim);
}
}
#[test]
fn test_hamming_identical_vectors() {
for dim in [1, 8, 16, 64, 128, 512] {
let a: Vec<f32> = (0..dim)
.map(|i| if i % 2 == 0 { 1.0 } else { 0.0 })
.collect();
let result = hamming_distance_native(&a, &a);
assert_eq!(
result, 0.0,
"identical vectors at dim={dim} should have hamming=0"
);
}
}
#[test]
fn test_jaccard_identical_vectors() {
for dim in [1, 8, 16, 64, 128, 512] {
let a: Vec<f32> = (0..dim)
.map(|i| if i % 2 == 0 { 1.0 } else { 0.0 })
.collect();
let result = jaccard_similarity_native(&a, &a);
assert!(
(result - 1.0).abs() < JACCARD_EPS,
"identical vectors at dim={dim} should have jaccard=1.0, got {result}"
);
}
}
#[test]
fn test_hamming_all_different() {
for dim in [1, 8, 16, 64, 128, 512] {
let a = vec![1.0_f32; dim];
let b = vec![0.0_f32; dim];
let result = hamming_distance_native(&a, &b);
assert_eq!(
result, dim as f32,
"all-different at dim={dim}: expected {dim}, got {result}"
);
}
}
#[test]
fn test_jaccard_all_different() {
for dim in [1, 8, 16, 64, 128, 512] {
let a = vec![1.0_f32; dim];
let b = vec![0.0_f32; dim];
let result = jaccard_similarity_native(&a, &b);
assert!(
result.abs() < JACCARD_EPS,
"all-different at dim={dim}: jaccard should be 0.0, got {result}"
);
}
}
#[test]
fn test_hamming_all_zero_vectors() {
for dim in [1, 8, 16, 64, 128, 512] {
let a = vec![0.0_f32; dim];
let b = vec![0.0_f32; dim];
let result = hamming_distance_native(&a, &b);
assert_eq!(result, 0.0, "all-zero at dim={dim}: hamming should be 0.0");
}
}
#[test]
fn test_jaccard_all_zero_vectors() {
for dim in [1, 8, 16, 64, 128, 512] {
let a = vec![0.0_f32; dim];
let b = vec![0.0_f32; dim];
let result = jaccard_similarity_native(&a, &b);
assert!(
(result - 1.0).abs() < JACCARD_EPS,
"all-zero at dim={dim}: jaccard should be 1.0 (div-by-zero guard), got {result}"
);
}
}
#[test]
fn test_hamming_odd_lengths() {
for dim in [1, 3, 5, 7, 9, 13, 15, 17, 33] {
assert_hamming_matches_scalar(dim);
}
}
#[test]
fn test_jaccard_odd_lengths() {
for dim in [1, 3, 5, 7, 9, 13, 15, 17, 33] {
assert_jaccard_matches_scalar(dim);
}
}
#[test]
fn test_hamming_single_element() {
assert_eq!(hamming_distance_native(&[1.0], &[1.0]), 0.0);
assert_eq!(hamming_distance_native(&[1.0], &[0.0]), 1.0);
assert_eq!(hamming_distance_native(&[0.0], &[0.0]), 0.0);
}
#[test]
fn test_jaccard_single_element() {
let j_same = jaccard_similarity_native(&[1.0], &[1.0]);
assert!((j_same - 1.0).abs() < JACCARD_EPS);
let j_diff = jaccard_similarity_native(&[1.0], &[0.0]);
assert!(j_diff.abs() < JACCARD_EPS);
let j_zero = jaccard_similarity_native(&[0.0], &[0.0]);
assert!((j_zero - 1.0).abs() < JACCARD_EPS);
}
const ENGINE_DIMS: &[usize] = &[512, 768, 1024, 1536];
#[test]
fn test_engine_hamming_matches_native_large_dims() {
for &dim in ENGINE_DIMS {
let engine = DistanceEngine::new(dim);
let a = make_pattern_vector(dim, 3);
let b = make_pattern_vector(dim, 2);
let cached = engine.hamming(&a, &b);
let native = hamming_distance_native(&a, &b);
assert_eq!(
cached, native,
"engine hamming mismatch at dim={dim}: cached={cached}, native={native}"
);
}
}
#[test]
fn test_engine_jaccard_matches_native_large_dims() {
for &dim in ENGINE_DIMS {
let engine = DistanceEngine::new(dim);
let a = make_pattern_vector(dim, 3);
let b = make_pattern_vector(dim, 2);
let cached = engine.jaccard(&a, &b);
let native = jaccard_similarity_native(&a, &b);
assert!(
(cached - native).abs() < JACCARD_EPS,
"engine jaccard mismatch at dim={dim}: cached={cached}, native={native}"
);
}
}
fn build_candidates(dim: usize, count: usize) -> Vec<Vec<f32>> {
(0..count)
.map(|seed| {
(0..dim)
.map(|i| if (i + seed) % 3 == 0 { 1.0 } else { 0.0 })
.collect()
})
.collect()
}
fn assert_batch_hamming_matches_individual(dim: usize, count: usize) {
let owned = build_candidates(dim, count);
let candidates: Vec<&[f32]> = owned.iter().map(Vec::as_slice).collect();
let query = make_pattern_vector(dim, 2);
let batch = batch_hamming_native(&candidates, &query);
assert_eq!(batch.len(), count);
for (i, &batch_val) in batch.iter().enumerate() {
let individual = hamming_distance_native(candidates[i], &query);
assert_eq!(
batch_val, individual,
"batch hamming mismatch at index {i}, dim={dim}"
);
}
}
fn assert_batch_jaccard_matches_individual(dim: usize, count: usize) {
let owned = build_candidates(dim, count);
let candidates: Vec<&[f32]> = owned.iter().map(Vec::as_slice).collect();
let query = make_pattern_vector(dim, 2);
let batch = batch_jaccard_native(&candidates, &query);
assert_eq!(batch.len(), count);
for (i, &batch_val) in batch.iter().enumerate() {
let individual = jaccard_similarity_native(candidates[i], &query);
assert!(
(batch_val - individual).abs() < JACCARD_EPS,
"batch jaccard mismatch at index {i}, dim={dim}: batch={batch_val}, individual={individual}"
);
}
}
#[test]
fn test_batch_hamming_matches_individual_calls() {
assert_batch_hamming_matches_individual(384, 100);
}
#[test]
fn test_batch_jaccard_matches_individual_calls() {
assert_batch_jaccard_matches_individual(384, 100);
}
#[test]
fn test_batch_hamming_empty_candidates() {
let candidates: Vec<&[f32]> = vec![];
let query = vec![1.0_f32; 16];
let result = batch_hamming_native(&candidates, &query);
assert!(result.is_empty());
}
#[test]
fn test_batch_jaccard_empty_candidates() {
let candidates: Vec<&[f32]> = vec![];
let query = vec![1.0_f32; 16];
let result = batch_jaccard_native(&candidates, &query);
assert!(result.is_empty());
}
#[test]
fn test_batch_hamming_single_candidate() {
let candidate = vec![1.0_f32; 64];
let query = vec![0.0_f32; 64];
let candidates: Vec<&[f32]> = vec![&candidate];
let batch = batch_hamming_native(&candidates, &query);
assert_eq!(batch.len(), 1);
assert_eq!(batch[0], hamming_distance_native(&candidate, &query));
}
#[test]
fn test_batch_jaccard_single_candidate() {
let candidate = vec![1.0_f32; 64];
let query = vec![0.0_f32; 64];
let candidates: Vec<&[f32]> = vec![&candidate];
let batch = batch_jaccard_native(&candidates, &query);
assert_eq!(batch.len(), 1);
let expected = jaccard_similarity_native(&candidate, &query);
assert!((batch[0] - expected).abs() < JACCARD_EPS);
}
#[test]
fn test_hamming_exact_count_large_dim() {
let dim = 10_000;
let a = make_pattern_vector(dim, 3);
let b = make_pattern_vector(dim, 2);
let expected: usize = (0..dim).filter(|&i| (i % 3 == 0) != (i % 2 == 0)).count();
let result = hamming_distance_native(&a, &b);
assert_eq!(
result, expected as f32,
"hamming at dim={dim}: expected exact count {expected}, got {result}"
);
}
#[test]
fn test_hamming_exact_count_all_set() {
let dim = 10_000;
let a = vec![1.0_f32; dim];
let b = vec![0.0_f32; dim];
let result = hamming_distance_native(&a, &b);
assert_eq!(
result, dim as f32,
"hamming at dim={dim}: expected {dim}, got {result}"
);
}
#[test]
fn test_hamming_exact_count_none_set() {
let dim = 10_000;
let a = vec![0.0_f32; dim];
let b = vec![0.0_f32; dim];
let result = hamming_distance_native(&a, &b);
assert_eq!(
result, 0.0,
"hamming at dim={dim}: expected 0, got {result}"
);
}