#![allow(clippy::unwrap_used)]
use std::time::{Duration, Instant};
use iqdb_flat::{FlatConfig, FlatIndex};
use iqdb_index::{Index, IndexCore};
use iqdb_types::{DistanceMetric, SearchParams, VectorId};
use std::sync::Arc;
fn arc(v: &[f32]) -> Arc<[f32]> {
Arc::from(v)
}
const N: usize = 50_000;
const DIM: usize = 64;
const K: usize = 10;
const BUDGET: Duration = Duration::from_secs(30);
fn row(i: usize) -> Vec<f32> {
(0..DIM).map(|j| ((i * 17 + j * 31) as f32).sin()).collect()
}
#[test]
fn fifty_k_insert_delete_reinsert_search_within_budget() {
let start = Instant::now();
let mut idx = FlatIndex::new(DIM, DistanceMetric::Euclidean, FlatConfig).unwrap();
for i in 0..N {
idx.insert(VectorId::from(i as u64), arc(&row(i)), None)
.unwrap();
}
assert_eq!(idx.len(), N);
for i in (0..N).step_by(2) {
idx.delete(&VectorId::from(i as u64)).unwrap();
}
assert_eq!(idx.len(), N / 2);
for i in (0..N).step_by(2) {
let v: Vec<f32> = (0..DIM).map(|j| ((i + j) as f32).cos()).collect();
idx.insert(VectorId::from(i as u64), arc(&v), None).unwrap();
}
assert_eq!(idx.len(), N);
let query: Vec<f32> = (0..DIM).map(|j| (j as f32).cos()).collect();
let hits = idx
.search(&query, &SearchParams::new(K, DistanceMetric::Euclidean))
.unwrap();
assert_eq!(hits.len(), K);
let elapsed = start.elapsed();
assert!(
elapsed < BUDGET,
"50k insert+delete+reinsert+search took {elapsed:?}, budget {BUDGET:?} — \
C3 has likely regressed to O(n^2) behavior",
);
}