Skip to content

Half-Precision f16 & bf16 Numerics for Rust 🦀 #273

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jul 7, 2025
Merged

Conversation

ashvardanian
Copy link
Owner

@ashvardanian ashvardanian commented Jul 7, 2025

SimSIMD has historically been one of the largest collections of mixed-precision kernels, but f32 to/from f16 and bf16 conversion operators have never been exposed to bindings. This release is the first step in that direction. I look forward to everyone's suggestions on how to further improve the Rust API. Thanks 🤗


Here's an example:

use simsimd::{SpatialSimilarity, f16, bf16};

// Process embeddings at different precisions for speed vs accuracy trade-offs
let embeddings_f32 = vec![1.0, 2.0, 3.0, 4.0];
let query_f32 = vec![0.5, 1.5, 2.5, 3.5];

// Convert to f16 for memory efficiency (2x compression)
let embeddings_f16: Vec<f16> = embeddings_f32.iter()
    .map(|&x| f16::from_f32(x))
    .collect();
let query_f16: Vec<f16> = query_f32.iter()
    .map(|&x| f16::from_f32(x))
    .collect();

// Convert to bf16 for ML workloads (better range than f16)
let embeddings_bf16: Vec<bf16> = embeddings_f32.iter()
    .map(|&x| bf16::from_f32(x))
    .collect();
let query_bf16: Vec<bf16> = query_f32.iter()
    .map(|&x| bf16::from_f32(x))
    .collect();

// Hardware-accelerated similarity at different precisions
let similarity_f32 = f32::cosine(&embeddings_f32, &query_f32).unwrap();
let similarity_f16 = f16::cosine(&embeddings_f16, &query_f16).unwrap();
let similarity_bf16 = bf16::cosine(&embeddings_bf16, &query_bf16).unwrap();

println!("Cosine similarities:");
println!("f32:  {:.6}", similarity_f32);   // Full precision
println!("f16:  {:.6}", similarity_f16);   // 2x memory savings
println!("bf16: {:.6}", similarity_bf16);  // ML-optimized range

// Natural arithmetic operations work seamlessly
let scaled_f16 = embeddings_f16.iter()
    .map(|&x| x * f16::from_f32(2.0) + f16::ONE)
    .collect::<Vec<_>>();

// Direct bit manipulation when needed
let raw_bits = embeddings_f16[0].0; // Access underlying u16
let reconstructed = f16(raw_bits);

@ashvardanian ashvardanian merged commit 570041c into main Jul 7, 2025
66 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant