1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
//! Top-level dispatch over [`iqdb_types::DistanceMetric`].
//!
//! These functions are the runtime equivalent of the type-level
//! [`crate::Distance`] trait: the caller chooses the metric at runtime
//! through the enum tag, the dispatcher routes to the matching metric
//! type. They are the entry points used by the engine and query crates,
//! which do not know the metric at compile time.
use ;
use crate::;
/// Compute the distance for `metric` between `a` and `b`.
///
/// Mismatched or empty inputs surface as [`iqdb_types::IqdbError`].
///
/// [`DistanceMetric`] is `#[non_exhaustive]`. A metric this crate does not
/// implement yet surfaces as [`iqdb_types::IqdbError::InvalidMetric`] rather
/// than a panic, so a newer `iqdb-types` that adds a variant never breaks the
/// dispatcher at runtime.
///
/// # Examples
///
/// ```
/// use iqdb_distance::compute;
/// use iqdb_types::DistanceMetric;
///
/// let a = [0.0_f32, 0.0, 0.0];
/// let b = [3.0_f32, 4.0, 0.0];
/// let d = compute(DistanceMetric::Euclidean, &a, &b)
/// .expect("valid pair");
/// assert!((d - 5.0).abs() < 1e-6);
/// ```
/// Compute distances for `metric` between `query` and each entry in
/// `candidates`, writing into `out`.
///
/// `out.len()` MUST equal `candidates.len()`. The function is
/// allocation-free; the caller owns the output buffer.
///
/// As with [`compute`], a metric outside the implemented set surfaces as
/// [`iqdb_types::IqdbError::InvalidMetric`] (`DistanceMetric` is
/// `#[non_exhaustive]`).
///
/// # Examples
///
/// ```
/// use iqdb_distance::compute_batch;
/// use iqdb_types::DistanceMetric;
///
/// let q = [0.0_f32, 0.0];
/// let cs: [&[f32]; 2] = [&[1.0, 0.0], &[0.0, 2.0]];
/// let mut out = [0.0_f32; 2];
///
/// compute_batch(DistanceMetric::Manhattan, &q, &cs, &mut out)
/// .expect("matching lengths");
/// assert!((out[0] - 1.0).abs() < 1e-6);
/// assert!((out[1] - 2.0).abs() < 1e-6);
/// ```
/// Compute `metric` between `a` and `b` on the **scalar reference path**,
/// bypassing runtime dispatch — a per-call scalar oracle.
///
/// Unlike [`crate::force_scalar`], which is a sticky, process-wide override,
/// this computes scalar for a single call without touching global state, so a
/// caller can obtain SIMD and scalar results for the *same* input in the same
/// process. The equivalence fuzz target uses it to assert
/// `compute(metric, a, b) ≈ compute_scalar(metric, a, b)` per input.
///
/// Available only under `cfg(any(test, feature = "testing"))`. **Not part of
/// the stable public surface** — it exists for differential and fuzz testing
/// and may change without a major bump.
///
/// # Examples
///
/// ```
/// # #[cfg(feature = "testing")]
/// # {
/// use iqdb_distance::compute_scalar;
/// use iqdb_types::DistanceMetric;
///
/// let d = compute_scalar(DistanceMetric::Euclidean, &[0.0, 0.0], &[3.0, 4.0])
/// .expect("valid pair");
/// assert!((d - 5.0).abs() < 1e-6);
/// # }
/// ```