#[cfg(feature = "maxsim")]
use super::simd_dot_f32;
#[cfg(feature = "maxsim")]
#[inline]
pub fn maxsim_score(queries: &[f32], documents: &[f32], lq: usize, ld: usize, dim: usize) -> f32 {
debug_assert!(
queries.len() >= lq * dim,
"maxsim_score: queries buffer too small: need {lq}*{dim}={}, have {}",
lq * dim,
queries.len()
);
debug_assert!(
documents.len() >= ld * dim,
"maxsim_score: documents buffer too small: need {ld}*{dim}={}, have {}",
ld * dim,
documents.len()
);
if ld == 0 {
return 0.0;
}
let mut score = 0.0f32;
for i in 0..lq {
let q_row = &queries[i * dim..(i + 1) * dim];
let mut my_max = f32::NEG_INFINITY;
for j in 0..ld {
let d_row = &documents[j * dim..(j + 1) * dim];
let dot = simd_dot_f32(q_row, d_row, dim);
my_max = my_max.max(dot);
}
score += my_max;
}
score
}
#[cfg(feature = "maxsim")]
#[inline]
#[allow(clippy::too_many_arguments)]
pub fn maxsim_score_packed(
queries: &[f32],
query_offsets: &[usize],
documents: &[f32],
doc_offsets: &[usize],
pair_q_ids: &[usize],
pair_d_ids: &[usize],
dim: usize,
results: &mut [f32],
) {
let num_pairs = pair_q_ids.len();
debug_assert_eq!(pair_d_ids.len(), num_pairs);
debug_assert!(results.len() >= num_pairs, "results buffer too short");
let mut max_q_id = 0usize;
let mut max_d_id = 0usize;
for p in 0..num_pairs {
max_q_id = max_q_id.max(pair_q_ids[p]);
max_d_id = max_d_id.max(pair_d_ids[p]);
}
debug_assert!(query_offsets.len() >= max_q_id.saturating_add(2));
debug_assert!(doc_offsets.len() >= max_d_id.saturating_add(2));
for p in 0..num_pairs {
let q_id = pair_q_ids[p];
let d_id = pair_d_ids[p];
let q_start = query_offsets[q_id];
let q_end = query_offsets[q_id + 1];
let d_start = doc_offsets[d_id];
let d_end = doc_offsets[d_id + 1];
let q_data = &queries[q_start..q_end];
let d_data = &documents[d_start..d_end];
let lq = q_data.len() / dim;
let ld = d_data.len() / dim;
results[p] = maxsim_score(q_data, d_data, lq, ld, dim);
}
}