surrealdb_core/idx/trees/
vector.rs

1use crate::err::Error;
2use crate::fnc::util::math::ToFloat;
3use crate::idx::VersionedStore;
4use crate::sql::index::{Distance, VectorType};
5use crate::sql::{Number, Value};
6use ahash::AHasher;
7use ahash::HashSet;
8use linfa_linalg::norm::Norm;
9use ndarray::{Array1, LinalgScalar, Zip};
10use ndarray_stats::DeviationExt;
11use num_traits::Zero;
12use revision::revisioned;
13use rust_decimal::prelude::FromPrimitive;
14use serde::{Deserialize, Deserializer, Serialize, Serializer};
15use std::cmp::PartialEq;
16use std::hash::{Hash, Hasher};
17use std::ops::{Add, Deref, Div, Sub};
18use std::sync::Arc;
19
20/// In the context of a Symmetric MTree index, the term object refers to a vector, representing the indexed item.
21#[derive(Debug, Clone, PartialEq)]
22#[non_exhaustive]
23pub enum Vector {
24	F64(Array1<f64>),
25	F32(Array1<f32>),
26	I64(Array1<i64>),
27	I32(Array1<i32>),
28	I16(Array1<i16>),
29}
30
31#[revisioned(revision = 1)]
32#[derive(Debug, PartialEq, Serialize, Deserialize)]
33#[non_exhaustive]
34pub enum SerializedVector {
35	F64(Vec<f64>),
36	F32(Vec<f32>),
37	I64(Vec<i64>),
38	I32(Vec<i32>),
39	I16(Vec<i16>),
40}
41
42impl VersionedStore for SerializedVector {}
43
44impl From<&Vector> for SerializedVector {
45	fn from(value: &Vector) -> Self {
46		match value {
47			Vector::F64(v) => Self::F64(v.to_vec()),
48			Vector::F32(v) => Self::F32(v.to_vec()),
49			Vector::I64(v) => Self::I64(v.to_vec()),
50			Vector::I32(v) => Self::I32(v.to_vec()),
51			Vector::I16(v) => Self::I16(v.to_vec()),
52		}
53	}
54}
55
56impl From<SerializedVector> for Vector {
57	fn from(value: SerializedVector) -> Self {
58		match value {
59			SerializedVector::F64(v) => Self::F64(Array1::from_vec(v)),
60			SerializedVector::F32(v) => Self::F32(Array1::from_vec(v)),
61			SerializedVector::I64(v) => Self::I64(Array1::from_vec(v)),
62			SerializedVector::I32(v) => Self::I32(Array1::from_vec(v)),
63			SerializedVector::I16(v) => Self::I16(Array1::from_vec(v)),
64		}
65	}
66}
67
68impl Vector {
69	#[inline]
70	fn chebyshev<T>(a: &Array1<T>, b: &Array1<T>) -> f64
71	where
72		T: ToFloat,
73	{
74		a.iter()
75			.zip(b.iter())
76			.map(|(a, b)| (a.to_float() - b.to_float()).abs())
77			.fold(0.0_f64, f64::max)
78	}
79
80	fn chebyshev_distance(&self, other: &Self) -> f64 {
81		match (self, other) {
82			(Self::F64(a), Self::F64(b)) => a.linf_dist(b).unwrap_or(f64::INFINITY),
83			(Self::F32(a), Self::F32(b)) => {
84				a.linf_dist(b).map(|r| r as f64).unwrap_or(f64::INFINITY)
85			}
86			(Self::I64(a), Self::I64(b)) => {
87				a.linf_dist(b).map(|r| r as f64).unwrap_or(f64::INFINITY)
88			}
89			(Self::I32(a), Self::I32(b)) => {
90				a.linf_dist(b).map(|r| r as f64).unwrap_or(f64::INFINITY)
91			}
92			(Self::I16(a), Self::I16(b)) => Self::chebyshev(a, b),
93			_ => f64::NAN,
94		}
95	}
96
97	#[inline]
98	fn cosine_distance_f64(a: &Array1<f64>, b: &Array1<f64>) -> f64 {
99		let dot_product = a.dot(b);
100		let norm_a = a.norm_l2();
101		let norm_b = b.norm_l2();
102		1.0 - dot_product / (norm_a * norm_b)
103	}
104
105	#[inline]
106	fn cosine_distance_f32(a: &Array1<f32>, b: &Array1<f32>) -> f64 {
107		let dot_product = a.dot(b) as f64;
108		let norm_a = a.norm_l2() as f64;
109		let norm_b = b.norm_l2() as f64;
110		1.0 - dot_product / (norm_a * norm_b)
111	}
112
113	#[inline]
114	fn cosine_dist<T>(a: &Array1<T>, b: &Array1<T>) -> f64
115	where
116		T: ToFloat + LinalgScalar,
117	{
118		let dot_product = a.dot(b).to_float();
119		let norm_a = a.mapv(|x| x.to_float() * x.to_float()).sum().sqrt();
120		let norm_b = b.mapv(|x| x.to_float() * x.to_float()).sum().sqrt();
121		1.0 - dot_product / (norm_a * norm_b)
122	}
123
124	fn cosine_distance(&self, other: &Self) -> f64 {
125		match (self, other) {
126			(Self::F64(a), Self::F64(b)) => Self::cosine_distance_f64(a, b),
127			(Self::F32(a), Self::F32(b)) => Self::cosine_distance_f32(a, b),
128			(Self::I64(a), Self::I64(b)) => Self::cosine_dist(a, b),
129			(Self::I32(a), Self::I32(b)) => Self::cosine_dist(a, b),
130			(Self::I16(a), Self::I16(b)) => Self::cosine_dist(a, b),
131			_ => f64::INFINITY,
132		}
133	}
134
135	#[inline]
136	fn euclidean<T>(a: &Array1<T>, b: &Array1<T>) -> f64
137	where
138		T: ToFloat,
139	{
140		Zip::from(a).and(b).map_collect(|x, y| (x.to_float() - y.to_float()).powi(2)).sum().sqrt()
141	}
142	fn euclidean_distance(&self, other: &Self) -> f64 {
143		match (self, other) {
144			(Self::F64(a), Self::F64(b)) => a.l2_dist(b).unwrap_or(f64::INFINITY),
145			(Self::F32(a), Self::F32(b)) => a.l2_dist(b).unwrap_or(f64::INFINITY),
146			(Self::I64(a), Self::I64(b)) => a.l2_dist(b).unwrap_or(f64::INFINITY),
147			(Self::I32(a), Self::I32(b)) => a.l2_dist(b).unwrap_or(f64::INFINITY),
148			(Self::I16(a), Self::I16(b)) => Self::euclidean(a, b),
149			_ => f64::INFINITY,
150		}
151	}
152
153	#[inline]
154	fn hamming<T>(a: &Array1<T>, b: &Array1<T>) -> f64
155	where
156		T: PartialEq,
157	{
158		Zip::from(a).and(b).fold(0, |acc, a, b| {
159			if a != b {
160				acc + 1
161			} else {
162				acc
163			}
164		}) as f64
165	}
166
167	fn hamming_distance(&self, other: &Self) -> f64 {
168		match (self, other) {
169			(Self::F64(a), Self::F64(b)) => Self::hamming(a, b),
170			(Self::F32(a), Self::F32(b)) => Self::hamming(a, b),
171			(Self::I64(a), Self::I64(b)) => Self::hamming(a, b),
172			(Self::I32(a), Self::I32(b)) => Self::hamming(a, b),
173			(Self::I16(a), Self::I16(b)) => Self::hamming(a, b),
174			_ => f64::INFINITY,
175		}
176	}
177
178	#[inline]
179	fn jaccard_f64(a: &Array1<f64>, b: &Array1<f64>) -> f64 {
180		let mut union: HashSet<u64> = a.iter().map(|f| f.to_bits()).collect();
181		let intersection_size = b.iter().fold(0, |acc, n| {
182			if !union.insert(n.to_bits()) {
183				acc + 1
184			} else {
185				acc
186			}
187		}) as f64;
188		1.0 - intersection_size / union.len() as f64
189	}
190
191	#[inline]
192	fn jaccard_f32(a: &Array1<f32>, b: &Array1<f32>) -> f64 {
193		let mut union: HashSet<u32> = a.iter().map(|f| f.to_bits()).collect();
194		let intersection_size = b.iter().fold(0, |acc, n| {
195			if !union.insert(n.to_bits()) {
196				acc + 1
197			} else {
198				acc
199			}
200		}) as f64;
201		intersection_size / union.len() as f64
202	}
203
204	#[inline]
205	fn jaccard_integers<T>(a: &Array1<T>, b: &Array1<T>) -> f64
206	where
207		T: Eq + Hash + Clone,
208	{
209		let mut union: HashSet<T> = a.iter().cloned().collect();
210		let intersection_size = b.iter().cloned().fold(0, |acc, n| {
211			if !union.insert(n) {
212				acc + 1
213			} else {
214				acc
215			}
216		}) as f64;
217		intersection_size / union.len() as f64
218	}
219
220	pub(super) fn jaccard_similarity(&self, other: &Self) -> f64 {
221		match (self, other) {
222			(Self::F64(a), Self::F64(b)) => Self::jaccard_f64(a, b),
223			(Self::F32(a), Self::F32(b)) => Self::jaccard_f32(a, b),
224			(Self::I64(a), Self::I64(b)) => Self::jaccard_integers(a, b),
225			(Self::I32(a), Self::I32(b)) => Self::jaccard_integers(a, b),
226			(Self::I16(a), Self::I16(b)) => Self::jaccard_integers(a, b),
227			_ => f64::NAN,
228		}
229	}
230
231	#[inline]
232	fn manhattan<T>(a: &Array1<T>, b: &Array1<T>) -> f64
233	where
234		T: Sub<Output = T> + ToFloat + Copy,
235	{
236		a.iter().zip(b.iter()).map(|(&a, &b)| (a - b).to_float().abs()).sum()
237	}
238
239	pub(super) fn manhattan_distance(&self, other: &Self) -> f64 {
240		match (self, other) {
241			(Self::F64(a), Self::F64(b)) => a.l1_dist(b).unwrap_or(f64::INFINITY),
242			(Self::F32(a), Self::F32(b)) => a.l1_dist(b).map(|r| r as f64).unwrap_or(f64::INFINITY),
243			(Self::I64(a), Self::I64(b)) => a.l1_dist(b).map(|r| r as f64).unwrap_or(f64::INFINITY),
244			(Self::I32(a), Self::I32(b)) => a.l1_dist(b).map(|r| r as f64).unwrap_or(f64::INFINITY),
245			(Self::I16(a), Self::I16(b)) => Self::manhattan(a, b),
246			_ => f64::NAN,
247		}
248	}
249
250	#[inline]
251	fn minkowski<T>(a: &Array1<T>, b: &Array1<T>, order: f64) -> f64
252	where
253		T: ToFloat,
254	{
255		let dist: f64 = a
256			.iter()
257			.zip(b.iter())
258			.map(|(a, b)| (a.to_float() - b.to_float()).abs().powf(order))
259			.sum();
260		dist.powf(1.0 / order)
261	}
262
263	pub(super) fn minkowski_distance(&self, other: &Self, order: f64) -> f64 {
264		match (self, other) {
265			(Self::F64(a), Self::F64(b)) => Self::minkowski(a, b, order),
266			(Self::F32(a), Self::F32(b)) => Self::minkowski(a, b, order),
267			(Self::I64(a), Self::I64(b)) => Self::minkowski(a, b, order),
268			(Self::I32(a), Self::I32(b)) => Self::minkowski(a, b, order),
269			(Self::I16(a), Self::I16(b)) => Self::minkowski(a, b, order),
270			_ => f64::NAN,
271		}
272	}
273
274	#[inline]
275	fn pearson<T>(x: &Array1<T>, y: &Array1<T>) -> f64
276	where
277		T: ToFloat + Clone + FromPrimitive + Add<Output = T> + Div<Output = T> + Zero,
278	{
279		let mean_x = x.mean().unwrap().to_float();
280		let mean_y = y.mean().unwrap().to_float();
281
282		let mut sum_xy = 0.0;
283		let mut sum_x2 = 0.0;
284		let mut sum_y2 = 0.0;
285
286		for (xi, yi) in x.iter().zip(y.iter()) {
287			let diff_x = xi.to_float() - mean_x;
288			let diff_y = yi.to_float() - mean_y;
289			sum_xy += diff_x * diff_y;
290			sum_x2 += diff_x.powi(2);
291			sum_y2 += diff_y.powi(2);
292		}
293
294		let numerator = sum_xy;
295		let denominator = (sum_x2 * sum_y2).sqrt();
296
297		if denominator == 0.0 {
298			return 0.0; // Return 0 if the denominator is 0
299		}
300
301		numerator / denominator
302	}
303
304	fn pearson_similarity(&self, other: &Self) -> f64 {
305		match (self, other) {
306			(Self::F64(a), Self::F64(b)) => Self::pearson(a, b),
307			(Self::F32(a), Self::F32(b)) => Self::pearson(a, b),
308			(Self::I64(a), Self::I64(b)) => Self::pearson(a, b),
309			(Self::I32(a), Self::I32(b)) => Self::pearson(a, b),
310			(Self::I16(a), Self::I16(b)) => Self::pearson(a, b),
311			_ => f64::NAN,
312		}
313	}
314}
315
316/// For vectors, as we want to support very large vectors, we want to avoid copy or clone.
317/// So the requirement is multiple ownership but not thread safety.
318/// However, because we are running in an async context, and because we are using cache structures that use the Arc as a key,
319/// the cached objects has to be Sent, which then requires the use of Arc (rather than just Rc).
320/// As computing the hash for a large vector is costly, this structures also caches the hashcode to avoid recomputing it.
321#[derive(Debug, Clone)]
322pub struct SharedVector(Arc<Vector>, u64);
323impl From<Vector> for SharedVector {
324	fn from(v: Vector) -> Self {
325		let mut h = AHasher::default();
326		v.hash(&mut h);
327		Self(Arc::new(v), h.finish())
328	}
329}
330
331impl Deref for SharedVector {
332	type Target = Vector;
333
334	fn deref(&self) -> &Self::Target {
335		&self.0
336	}
337}
338
339impl Hash for SharedVector {
340	fn hash<H: Hasher>(&self, state: &mut H) {
341		state.write_u64(self.1);
342	}
343}
344
345impl PartialEq for SharedVector {
346	fn eq(&self, other: &Self) -> bool {
347		self.1 == other.1 && self.0 == other.0
348	}
349}
350impl Eq for SharedVector {}
351
352impl Serialize for SharedVector {
353	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
354	where
355		S: Serializer,
356	{
357		// We only serialize the vector part, not the u64
358		let ser: SerializedVector = self.0.as_ref().into();
359		ser.serialize(serializer)
360	}
361}
362
363impl<'de> Deserialize<'de> for SharedVector {
364	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
365	where
366		D: Deserializer<'de>,
367	{
368		// We deserialize into a vector and construct the struct
369		let v: Vector = SerializedVector::deserialize(deserializer)?.into();
370		Ok(v.into())
371	}
372}
373
374impl Hash for Vector {
375	fn hash<H: Hasher>(&self, state: &mut H) {
376		match self {
377			Vector::F64(v) => {
378				let h = v.iter().fold(0, |acc, &x| acc ^ x.to_bits());
379				state.write_u64(h);
380			}
381			Vector::F32(v) => {
382				let h = v.iter().fold(0, |acc, &x| acc ^ x.to_bits());
383				state.write_u32(h);
384			}
385			Vector::I64(v) => {
386				let h = v.iter().fold(0, |acc, &x| acc ^ x);
387				state.write_i64(h);
388			}
389			Vector::I32(v) => {
390				let h = v.iter().fold(0, |acc, &x| acc ^ x);
391				state.write_i32(h);
392			}
393			Vector::I16(v) => {
394				let h = v.iter().fold(0, |acc, &x| acc ^ x);
395				state.write_i16(h);
396			}
397		}
398	}
399}
400
401#[cfg(test)]
402impl SharedVector {
403	pub(crate) fn clone_vector(&self) -> Vector {
404		self.0.as_ref().clone()
405	}
406}
407
408#[cfg(test)]
409impl From<&Vector> for Value {
410	fn from(v: &Vector) -> Self {
411		let vec: Vec<Number> = match v {
412			Vector::F64(a) => a.iter().map(|i| Number::Float(*i)).collect(),
413			Vector::F32(a) => a.iter().map(|i| Number::Float(*i as f64)).collect(),
414			Vector::I64(a) => a.iter().map(|i| Number::Int(*i)).collect(),
415			Vector::I32(a) => a.iter().map(|i| Number::Int(*i as i64)).collect(),
416			Vector::I16(a) => a.iter().map(|i| Number::Int(*i as i64)).collect(),
417		};
418		Value::from(vec)
419	}
420}
421
422impl Vector {
423	pub(super) fn try_from_value(t: VectorType, d: usize, v: &Value) -> Result<Self, Error> {
424		let res = match t {
425			VectorType::F64 => {
426				let mut vec = Vec::with_capacity(d);
427				Self::check_vector_value(v, &mut vec)?;
428				Vector::F64(Array1::from_vec(vec))
429			}
430			VectorType::F32 => {
431				let mut vec = Vec::with_capacity(d);
432				Self::check_vector_value(v, &mut vec)?;
433				Vector::F32(Array1::from_vec(vec))
434			}
435			VectorType::I64 => {
436				let mut vec = Vec::with_capacity(d);
437				Self::check_vector_value(v, &mut vec)?;
438				Vector::I64(Array1::from_vec(vec))
439			}
440			VectorType::I32 => {
441				let mut vec = Vec::with_capacity(d);
442				Self::check_vector_value(v, &mut vec)?;
443				Vector::I32(Array1::from_vec(vec))
444			}
445			VectorType::I16 => {
446				let mut vec = Vec::with_capacity(d);
447				Self::check_vector_value(v, &mut vec)?;
448				Vector::I16(Array1::from_vec(vec))
449			}
450		};
451		Ok(res)
452	}
453
454	fn check_vector_value<T>(value: &Value, vec: &mut Vec<T>) -> Result<(), Error>
455	where
456		T: for<'a> TryFrom<&'a Number, Error = Error>,
457	{
458		match value {
459			Value::Array(a) => {
460				for v in a.0.iter() {
461					Self::check_vector_value(v, vec)?;
462				}
463				Ok(())
464			}
465			Value::Number(n) => {
466				vec.push(n.try_into()?);
467				Ok(())
468			}
469			_ => Err(Error::InvalidVectorValue(value.clone().to_raw_string())),
470		}
471	}
472
473	pub fn try_from_vector(t: VectorType, v: &[Number]) -> Result<Self, Error> {
474		let res = match t {
475			VectorType::F64 => {
476				let mut vec = Vec::with_capacity(v.len());
477				Self::check_vector_number(v, &mut vec)?;
478				Vector::F64(Array1::from_vec(vec))
479			}
480			VectorType::F32 => {
481				let mut vec = Vec::with_capacity(v.len());
482				Self::check_vector_number(v, &mut vec)?;
483				Vector::F32(Array1::from_vec(vec))
484			}
485			VectorType::I64 => {
486				let mut vec = Vec::with_capacity(v.len());
487				Self::check_vector_number(v, &mut vec)?;
488				Vector::I64(Array1::from_vec(vec))
489			}
490			VectorType::I32 => {
491				let mut vec = Vec::with_capacity(v.len());
492				Self::check_vector_number(v, &mut vec)?;
493				Vector::I32(Array1::from_vec(vec))
494			}
495			VectorType::I16 => {
496				let mut vec = Vec::with_capacity(v.len());
497				Self::check_vector_number(v, &mut vec)?;
498				Vector::I16(Array1::from_vec(vec))
499			}
500		};
501		Ok(res)
502	}
503
504	fn check_vector_number<T>(v: &[Number], vec: &mut Vec<T>) -> Result<(), Error>
505	where
506		T: for<'a> TryFrom<&'a Number, Error = Error>,
507	{
508		for n in v {
509			vec.push(n.try_into()?);
510		}
511		Ok(())
512	}
513
514	pub(super) fn len(&self) -> usize {
515		match self {
516			Self::F64(v) => v.len(),
517			Self::F32(v) => v.len(),
518			Self::I64(v) => v.len(),
519			Self::I32(v) => v.len(),
520			Self::I16(v) => v.len(),
521		}
522	}
523
524	pub(super) fn check_expected_dimension(current: usize, expected: usize) -> Result<(), Error> {
525		if current != expected {
526			Err(Error::InvalidVectorDimension {
527				current,
528				expected,
529			})
530		} else {
531			Ok(())
532		}
533	}
534
535	pub(super) fn check_dimension(&self, expected_dim: usize) -> Result<(), Error> {
536		Self::check_expected_dimension(self.len(), expected_dim)
537	}
538}
539
540impl Distance {
541	pub(super) fn calculate(&self, a: &Vector, b: &Vector) -> f64 {
542		match self {
543			Distance::Chebyshev => a.chebyshev_distance(b),
544			Distance::Cosine => a.cosine_distance(b),
545			Distance::Euclidean => a.euclidean_distance(b),
546			Distance::Hamming => a.hamming_distance(b),
547			Distance::Jaccard => a.jaccard_similarity(b),
548			Distance::Manhattan => a.manhattan_distance(b),
549			Distance::Minkowski(order) => a.minkowski_distance(b, order.to_float()),
550			Distance::Pearson => a.pearson_similarity(b),
551		}
552	}
553}
554
555#[cfg(test)]
556mod tests {
557	use crate::idx::trees::knn::tests::{get_seed_rnd, new_random_vec, RandomItemGenerator};
558	use crate::idx::trees::vector::{SharedVector, Vector};
559	use crate::sql::index::{Distance, VectorType};
560
561	fn test_distance(dist: Distance, a1: &[f64], a2: &[f64], res: f64) {
562		// Convert the arrays to Vec<Number>
563		let mut v1 = vec![];
564		a1.iter().for_each(|&n| v1.push(n.into()));
565		let mut v2 = vec![];
566		a2.iter().for_each(|&n| v2.push(n.into()));
567
568		// Check the generic distance implementation
569		assert_eq!(dist.compute(&v1, &v2).unwrap(), res.into());
570
571		// Check the "Vector" optimised implementations
572		let t = VectorType::F64;
573		let v1: SharedVector = Vector::try_from_vector(t, &v1).unwrap().into();
574		let v2: SharedVector = Vector::try_from_vector(t, &v2).unwrap().into();
575		assert_eq!(dist.calculate(&v1, &v2), res);
576	}
577
578	fn test_distance_collection(dist: Distance, size: usize, dim: usize) {
579		let mut rng = get_seed_rnd();
580		for vt in
581			[VectorType::F64, VectorType::F32, VectorType::I64, VectorType::I32, VectorType::I16]
582		{
583			let gen = RandomItemGenerator::new(&dist, dim);
584			let mut num_zero = 0;
585			for i in 0..size {
586				let v1 = new_random_vec(&mut rng, vt, dim, &gen);
587				let v2 = new_random_vec(&mut rng, vt, dim, &gen);
588				let d = dist.calculate(&v1, &v2);
589				assert!(
590					d.is_finite() && !d.is_nan(),
591					"i: {i} - vt: {vt} - v1: {v1:?} - v2: {v2:?}"
592				);
593				assert_ne!(d, f64::NAN, "i: {i} - vt: {vt} - v1: {v1:?} - v2: {v2:?}");
594				assert_ne!(d, f64::INFINITY, "i: {i} - vt: {vt} - v1: {v1:?} - v2: {v2:?}");
595				if d == 0.0 {
596					num_zero += 1;
597				}
598			}
599			let zero_rate = num_zero as f64 / size as f64;
600			assert!(zero_rate < 0.1, "vt: {vt} - zero_rate: {zero_rate}");
601		}
602	}
603
604	#[test]
605	fn test_distance_chebyshev() {
606		test_distance_collection(Distance::Chebyshev, 100, 1536);
607		test_distance(Distance::Chebyshev, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 1.0);
608	}
609
610	#[test]
611	fn test_distance_cosine() {
612		test_distance_collection(Distance::Cosine, 100, 1536);
613		test_distance(Distance::Cosine, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 0.007416666029069652);
614	}
615
616	#[test]
617	fn test_distance_euclidean() {
618		test_distance_collection(Distance::Euclidean, 100, 1536);
619		test_distance(Distance::Euclidean, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 1.7320508075688772);
620	}
621
622	#[test]
623	fn test_distance_hamming() {
624		test_distance_collection(Distance::Hamming, 100, 1536);
625		test_distance(Distance::Hamming, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 3.0);
626	}
627
628	#[test]
629	fn test_distance_jaccard() {
630		test_distance_collection(Distance::Jaccard, 100, 768);
631		test_distance(Distance::Jaccard, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 0.5);
632	}
633	#[test]
634	fn test_distance_manhattan() {
635		test_distance_collection(Distance::Manhattan, 100, 1536);
636		test_distance(Distance::Manhattan, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 3.0);
637	}
638	#[test]
639	fn test_distance_minkowski() {
640		test_distance_collection(Distance::Minkowski(3.into()), 100, 1536);
641		test_distance(
642			Distance::Minkowski(3.into()),
643			&[1.0, 2.0, 3.0],
644			&[2.0, 3.0, 4.0],
645			1.4422495703074083,
646		);
647	}
648
649	#[test]
650	fn test_distance_pearson() {
651		test_distance_collection(Distance::Pearson, 100, 1536);
652		test_distance(Distance::Pearson, &[1.0, 2.0, 3.0], &[2.0, 3.0, 4.0], 1.0);
653	}
654}