Skip to main content

Overview

The distance module provides optimized implementations of common distance and similarity metrics for vector operations. All functions are inlined for maximum performance.

Main Dispatch Function

compute

Main dispatch function called by HNSW for all distance computations.
pub fn compute(a: &[f32], b: &[f32], metric: DistanceMetric) -> f32
a
&[f32]
required
First vector.
b
&[f32]
required
Second vector (must have same dimension as a).
metric
DistanceMetric
required
Distance metric to use: Cosine, Euclidean, or DotProduct.
f32
f32
Returns the computed distance/similarity value.
Example:
use solvec_core::distance;
use solvec_core::types::DistanceMetric;

let a = vec![1.0, 0.0, 0.0];
let b = vec![0.9, 0.1, 0.0];

let score = distance::compute(&a, &b, DistanceMetric::Cosine);
println!("Cosine similarity: {:.4}", score);

Similarity Metrics

cosine_similarity

Cosine similarity — returns value in [-1, 1], higher = more similar. This is the DEFAULT metric (same as Pinecone default).
pub fn cosine_similarity(a: &[f32], b: &[f32]) -> f32
a
&[f32]
required
First vector.
b
&[f32]
required
Second vector.
f32
f32
Cosine similarity in range [-1, 1]:
  • 1.0: Identical direction
  • 0.0: Orthogonal (perpendicular)
  • -1.0: Opposite direction
Formula:
cosine_similarity(a, b) = (a · b) / (||a|| * ||b||)
Example:
use solvec_core::distance::cosine_similarity;

// Identical vectors
let a = vec![1.0, 0.0, 0.0];
let b = vec![1.0, 0.0, 0.0];
assert!((cosine_similarity(&a, &b) - 1.0).abs() < 1e-6);

// Orthogonal vectors
let a = vec![1.0, 0.0, 0.0];
let b = vec![0.0, 1.0, 0.0];
assert!(cosine_similarity(&a, &b).abs() < 1e-6);

// Opposite vectors
let a = vec![1.0, 0.0, 0.0];
let b = vec![-1.0, 0.0, 0.0];
assert!((cosine_similarity(&a, &b) + 1.0).abs() < 1e-6);

dot_product

Dot product similarity — returns scalar, higher = more similar. Best for normalized vectors (OpenAI embeddings are already normalized).
pub fn dot_product(a: &[f32], b: &[f32]) -> f32
a
&[f32]
required
First vector.
b
&[f32]
required
Second vector.
f32
f32
Dot product value. For normalized vectors, equivalent to cosine similarity but faster.
Formula:
dot_product(a, b) = Σ(a[i] * b[i])
Example:
use solvec_core::distance::dot_product;

let a = vec![1.0, 2.0, 3.0];
let b = vec![4.0, 5.0, 6.0];
let result = dot_product(&a, &b);
assert_eq!(result, 32.0); // 1*4 + 2*5 + 3*6

Distance Metrics

euclidean_distance

Euclidean distance — returns value in [0, ∞), lower = more similar.
pub fn euclidean_distance(a: &[f32], b: &[f32]) -> f32
a
&[f32]
required
First vector.
b
&[f32]
required
Second vector.
f32
f32
Euclidean (L2) distance between vectors. Zero means identical vectors.
Formula:
euclidean_distance(a, b) = sqrt(Σ(a[i] - b[i])²)
Example:
use solvec_core::distance::euclidean_distance;

// Same point
let a = vec![1.0, 2.0, 3.0];
let b = vec![1.0, 2.0, 3.0];
assert!(euclidean_distance(&a, &b).abs() < 1e-6);

// Different points
let a = vec![0.0, 0.0];
let b = vec![3.0, 4.0];
assert_eq!(euclidean_distance(&a, &b), 5.0); // 3-4-5 triangle

euclidean_distance_squared

Squared euclidean distance — avoids sqrt, used internally for comparisons.
pub fn euclidean_distance_squared(a: &[f32], b: &[f32]) -> f32
a
&[f32]
required
First vector.
b
&[f32]
required
Second vector.
f32
f32
Squared Euclidean distance. Faster than euclidean_distance when only comparing relative distances.
Formula:
euclidean_distance_squared(a, b) = Σ(a[i] - b[i])²
Example:
use solvec_core::distance::euclidean_distance_squared;

let a = vec![0.0, 0.0];
let b = vec![3.0, 4.0];
assert_eq!(euclidean_distance_squared(&a, &b), 25.0); // 3² + 4²

Utility Functions

normalize

Normalize a vector to unit length (for cosine optimization). Pre-normalizing vectors allows using dot_product instead of cosine (faster).
pub fn normalize(v: &[f32]) -> Vec<f32>
v
&[f32]
required
Vector to normalize.
Vec<f32>
Vec<f32>
Normalized vector with unit length (magnitude = 1.0).
Example:
use solvec_core::distance::normalize;

let v = vec![3.0, 4.0];
let norm = normalize(&v);
let magnitude: f32 = norm.iter().map(|x| x * x).sum::<f32>().sqrt();
assert!((magnitude - 1.0).abs() < 1e-6); // Unit vector

assert_eq!(norm, vec![0.6, 0.8]); // 3/5, 4/5

to_similarity_score

Convert distance to similarity score for consistent API output. All metrics return higher = more similar after this conversion.
pub fn to_similarity_score(distance: f32, metric: DistanceMetric) -> f32
distance
f32
required
Raw distance value from a metric function.
metric
DistanceMetric
required
The metric that produced the distance value.
f32
f32
Similarity score where higher = more similar. For Euclidean, converts to 1.0 / (1.0 + distance).
Example:
use solvec_core::distance::{euclidean_distance, to_similarity_score};
use solvec_core::types::DistanceMetric;

let a = vec![0.0, 0.0];
let b = vec![1.0, 0.0];

let dist = euclidean_distance(&a, &b);
let score = to_similarity_score(dist, DistanceMetric::Euclidean);

assert_eq!(score, 0.5); // 1.0 / (1.0 + 1.0)

Metric Comparison

Cosine

Best for text embeddings. Range: [-1, 1]. Ignores magnitude.

Euclidean

Best for spatial data. Range: [0, ∞). Considers magnitude.

Dot Product

Fastest for normalized vectors. Equivalent to cosine when vectors are unit length.

Complete Example

use solvec_core::distance::*;
use solvec_core::types::DistanceMetric;

fn main() {
    let a = vec![1.0, 2.0, 3.0];
    let b = vec![4.0, 5.0, 6.0];

    // Test all metrics
    let cosine = cosine_similarity(&a, &b);
    println!("Cosine similarity: {:.4}", cosine);

    let euclidean = euclidean_distance(&a, &b);
    println!("Euclidean distance: {:.4}", euclidean);

    let dot = dot_product(&a, &b);
    println!("Dot product: {:.4}", dot);

    // Normalize vectors
    let a_norm = normalize(&a);
    let b_norm = normalize(&b);

    // For normalized vectors, dot product ≈ cosine
    let dot_norm = dot_product(&a_norm, &b_norm);
    let cos_norm = cosine_similarity(&a, &b);
    assert!((dot_norm - cos_norm).abs() < 1e-6);

    // Use compute dispatch
    let result = compute(&a, &b, DistanceMetric::Cosine);
    println!("Via compute(): {:.4}", result);
}

Performance Notes

  • All functions are #[inline] for zero-cost abstraction
  • compute() is #[inline(always)] for optimal dispatch
  • Use dot_product instead of cosine_similarity for pre-normalized vectors
  • Use euclidean_distance_squared for comparisons to avoid sqrt

When to Use Each Metric

Cosine Similarity (Default):
  • Text embeddings (e.g., OpenAI, Cohere)
  • Semantic similarity
  • When direction matters more than magnitude
Euclidean Distance:
  • Image embeddings
  • Spatial coordinates
  • When absolute distance matters
Dot Product:
  • Pre-normalized embeddings (OpenAI ada-002)
  • Maximum performance on unit vectors
  • When you’ve already normalized inputs

See Also

Build docs developers (and LLMs) love