# How to Handle Float64 Arrays in Turbovec: Casting to Float32

> Learn how to handle float64 arrays in Turbovec by casting to float32. Avoid errors and ensure smooth data processing with this essential guide.

- Repository: [Ryan Codrai/turbovec](https://github.com/RyanCodrai/turbovec)
- Tags: how-to-guide
- Published: 2026-07-27

---

**Turbovec's Python and Rust APIs strictly enforce `float32` inputs and will raise errors or panic if `float64` arrays are passed without an explicit cast to `float32` first.**

If your pipeline produces NumPy **float64** embeddings or Rust `Vec<f64>` vectors, you must explicitly cast them before indexing. **Turbovec** is optimized strictly for 32-bit floating-point storage and SIMD search, so learning how to handle float64 arrays in turbovec is essential for integrating standard double-precision outputs without runtime errors.

## Why Turbovec Requires Float32

Turbovec is engineered around **32-bit floating-point** vectors to minimize memory footprint and power its hand-written SIMD kernels. In [`turbovec/src/lib.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/lib.rs), the public Rust API—methods such as `TurboQuantIndex::add` and `TurboQuantIndex::search`—accepts slices of `f32` (`&[f32]`) and validates the input type, panicking when a different precision is supplied. The Python bindings mirror this contract, documenting in [`README.md`](https://github.com/RyanCodrai/turbovec/blob/main/README.md) lines 44-45 that vectors and queries must be 2-D **float32** arrays and that other dtypes are rejected rather than silently converted.

## How to Cast Float64 Arrays in Python

According to the [`README.md`](https://github.com/RyanCodrai/turbovec/blob/main/README.md), you must preemptively convert NumPy arrays with `np.asarray(x, dtype=np.float32)`. This cast is computationally cheap and preserves the algorithmic correctness of nearest-neighbor search, which depends on vector direction rather than absolute scalar magnitude.

```python
import numpy as np
from turbovec import TurboQuantIndex

# Suppose `vectors64` is a NumPy array with dtype=float64

vectors64 = np.random.rand(1000, 1536)          # float64 by default

queries64  = np.random.rand(10, 1536)

# Cast to float32 before creating the index

vectors32 = np.asarray(vectors64, dtype=np.float32)
queries32 = np.asarray(queries64, dtype=np.float32)

index = TurboQuantIndex(dim=1536, bit_width=4)
index.add(vectors32)                # OK

scores, ids = index.search(queries32, k=10)   # OK

```

## How to Cast Float64 Arrays in Rust

On the Rust side, [`turbovec/src/lib.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/lib.rs) lines 72-78 implement the type enforcement that restricts the public API to `&[f32]`. If your source data arrives as `f64`, iterate through the collection and cast each element to `f32` before flattening into a contiguous slice.

```rust
use turbovec::TurboQuantIndex;

// Example `f64` data (could come from any source)
let vectors_f64: Vec<Vec<f64>> = (0..1000)
    .map(|_| (0..1536).map(|_| rand::random::<f64>()).collect())
    .collect();

// Convert to `f32` – one-by-one or with an iterator
let vectors_f32: Vec<Vec<f32>> = vectors_f64
    .iter()
    .map(|row| row.iter().map(|&x| x as f32).collect())
    .collect();

// Flatten into a single slice if the API expects `&[f32]`
let flat_f32: Vec<f32> = vectors_f32.iter().flat_map(|r| r.iter()).cloned().collect();

let mut index = TurboQuantIndex::new(1536, 4).unwrap();
index.add(&flat_f32).unwrap();                // Works with f32 slices only

```

## Converting Float64 Data for Command-Line Usage

If you are feeding serialized arrays to a Turbovec binary via `.npy` files, convert the file offline with NumPy before loading it into the Rust process. The one-liner below performs the cast without loading the full array into an interactive session.

```bash

# Convert a .npy file from float64 to float32 using NumPy, then feed it to turbovec

python -c "import numpy as np, sys; a = np.load('vectors64.npy'); np.save('vectors32.npy', a.astype(np.float32))"

# Now the Rust binary can load `vectors32.npy` without error

```

## Internal Precision vs. Public API

While the public API remains locked to `f32` for storage efficiency, some internal routines temporarily promote to higher precision. For example, [`turbovec/src/rotation.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/rotation.rs) lines 19-46 performs rotation-matrix calculations using `f64` internally. This pattern is also echoed in the test suite: [`turbovec/tests/io_v4.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/tests/io_v4.rs) lines 58-59 demonstrate converting raw state through intermediate `f64` casts before landing on `f32`. The takeaway is that your application should handle the `float64` to `float32` reduction at the boundary, not inside the library.

## Summary

- **Turbovec's core is `f32`-only**: The Rust crate in [`turbovec/src/lib.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/lib.rs) and the Python bindings both reject non-float32 inputs at the API boundary.
- **Explicit casting is required**: Use `np.asarray(x, dtype=np.float32)` in Python or element-wise `as f32` in Rust before calling `TurboQuantIndex::add` or `TurboQuantIndex::search`.
- **File workflow**: Pre-convert serialized `.npy` files from `float64` to `float32` before loading them into Turbovec CLI tools.
- **Correctness is preserved**: The cast does not affect nearest-neighbor accuracy because quantization and search rely on vector direction, not absolute magnitude.

## Frequently Asked Questions

### Does Turbovec support float64 arrays natively?

No. As implemented in `RyanCodrai/turbovec`, the public API in [`turbovec/src/lib.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/lib.rs) accepts only `&[f32]` slices, and the Python bindings require 2-D `float32` NumPy arrays. Passing `float64` data results in an explicit error or panic rather than a silent conversion.

### What happens if I pass a float64 array without casting?

The library validates dtypes at the boundary. In Python, the binding returns an error; in Rust, [`turbovec/src/lib.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/lib.rs) enforces the `f32` contract and will panic if a different precision is supplied. This strict behavior prevents accidental memory misinterpretation.

### Is casting from float64 to float32 expensive?

No. The conversion is a cheap per-element reinterpretation that runs in linear time relative to the number of vector dimensions. Because Turbovec's quantization algorithms depend on vector direction rather than absolute scalar magnitude, the cast does not degrade search quality.

### Why does Turbovec use f64 in some internal files if the API is f32?

Internal calculations—such as those in [`turbovec/src/rotation.rs`](https://github.com/RyanCodrai/turbovec/blob/main/turbovec/src/rotation.rs)—may temporarily promote values to `f64` for numerical stability when building rotation matrices. However, the public surface stays `f32` to keep index memory low and to align with the hand-optimized SIMD kernels.