| Crates.io | eytzinger-interpolation |
| lib.rs | eytzinger-interpolation |
| version | 1.0.1 |
| created_at | 2025-10-18 01:49:52.332725+00 |
| updated_at | 2025-10-18 21:57:14.568095+00 |
| description | Eytzinger array layout with interpolative search support |
| homepage | |
| repository | https://github.com/sanity/eytzinger-interpolation |
| max_upload_size | |
| id | 1888689 |
| size | 62,007 |
This crate implements the "Eytzinger" (aka BFS) array layout with additional interpolative search support.
This is a fork of rust-eytzinger by main(), with additions by Andre Popovitch. The original crate provides excellent performance for binary search operations using the Eytzinger layout.
This fork was created to add the eytzinger_interpolative_search_by method and related functionality, which enables efficient interpolation between values in an Eytzinger-laid-out array. This is particularly useful for applications like isotonic regression where you need to find values that fall between data points.
The additions were needed for the pav.rs isotonic regression library to achieve optimal performance while maintaining the ability to publish to crates.io (which doesn't support git dependencies).
The Eytzinger layout is a cache-friendly array representation of a binary search tree. Instead of storing elements in sorted order, it arranges them by tree level (breadth-first), which significantly improves binary search performance by reducing cache misses.
For example, a sorted array [0, 1, 2, 3, 4, 5, 6] becomes [3, 1, 5, 0, 2, 4, 6] in Eytzinger layout.
See "Array layouts for comparison-based searching" by Khuong and Morin for detailed performance analysis.
All features from the original eytzinger crate, plus:
eytzinger_interpolative_search_by returns both the lower and upper bounds around a search value, perfect for interpolationAdd this to your Cargo.toml:
[dependencies]
eytzinger-interpolation = "1.0.0"
use eytzinger_interpolation::SliceExt;
let mut data = [0, 1, 2, 3, 4, 5, 6];
data.eytzingerize(&mut eytzinger_interpolation::permutation::InplacePermutator);
// Now the array is [3, 1, 5, 0, 2, 4, 6]
assert_eq!(data.eytzinger_search(&3), Some(0));
assert_eq!(data.eytzinger_search(&5), Some(2));
The interpolative search returns (Option<usize>, Option<usize>) representing the indices of values that bound your search target:
use eytzinger_interpolation::SliceExt;
let mut data = [0, 1, 2, 3, 4, 5, 6];
data.eytzingerize(&mut eytzinger_interpolation::permutation::InplacePermutator);
// Search for a value between data points
let (lower, upper) = data.eytzinger_interpolative_search_by(|x| x.cmp(&3));
assert_eq!((lower, upper), (Some(0), Some(5))); // Found 3 at index 0, next value at 5
// Interpolate between values
let (lower, upper) = data.eytzinger_interpolative_search_by(|x| (*x as f32).partial_cmp(&3.5).unwrap());
assert_eq!((lower, upper), (Some(0), Some(5))); // 3.5 is between indices 0 (value 3) and 5 (value 4)
// Below range
let (lower, upper) = data.eytzinger_interpolative_search_by(|x| x.cmp(&-1));
assert_eq!((lower, upper), (None, Some(3))); // Below minimum, next value at index 3
// Above range
let (lower, upper) = data.eytzinger_interpolative_search_by(|x| x.cmp(&7));
assert_eq!((lower, upper), (Some(6), None)); // Above maximum, previous value at index 6
This crate was created specifically to optimize pav.rs, which implements the Pool Adjacent Violators algorithm for isotonic regression. The interpolative search allows efficient lookup and interpolation between regression points.
The Eytzinger layout provides significant performance improvements for binary search:
See the original rust-eytzinger benchmarks for detailed numbers.
MIT (same as the original rust-eytzinger crate)
This fork is primarily maintained to support pav.rs. For general Eytzinger layout improvements, consider contributing to the upstream rust-eytzinger project.
If you need additional interpolative search features or find bugs in the interpolative search implementation, please open an issue or PR on this repository.