pub fn sort(slice: &mut [f64]) {
if slice.len() <= 1 {
return;
}
let n = slice.len();
let mut buckets: Vec<Vec<f64>> = vec![Vec::new(); n];
for &num in slice.iter() {
let idx = get_bucket_index(num, n);
buckets[idx].push(num);
}
for bucket in buckets.iter_mut() {
insertion_sort(bucket);
}
let mut index = 0;
for bucket in buckets.iter() {
for &value in bucket {
slice[index] = value;
index += 1;
}
}
}
fn insertion_sort(bucket: &mut [f64]) {
for i in 1..bucket.len() {
let key = bucket[i];
let mut j = i;
while j > 0 && bucket[j - 1] > key {
bucket[j] = bucket[j - 1];
j -= 1;
}
bucket[j] = key;
}
}
fn get_bucket_index(value: f64, num_buckets: usize) -> usize {
let bucket_idx = (value * num_buckets as f64) as usize;
bucket_idx.min(num_buckets - 1)
}
#[cfg(test)]
mod tests {
use super::*;
use std::f64::EPSILON;
#[test]
fn test_empty_slice() {
let mut arr: Vec<f64> = vec![];
sort(&mut arr);
assert_eq!(arr, Vec::<f64>::new());
}
#[test]
fn test_single_element() {
let mut arr = vec![0.5];
sort(&mut arr);
assert_eq!(arr, vec![0.5]);
}
#[test]
fn test_sorted_array() {
let mut arr = vec![0.1, 0.2, 0.3, 0.4, 0.5];
let expected = arr.clone();
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_reverse_sorted() {
let mut arr = vec![0.9, 0.7, 0.5, 0.3, 0.1];
sort(&mut arr);
assert_eq!(arr, vec![0.1, 0.3, 0.5, 0.7, 0.9]);
}
#[test]
fn test_random_order() {
let mut arr = vec![0.3, 0.1, 0.4, 0.1, 0.5, 0.9, 0.2, 0.6, 0.5, 0.3, 0.5];
let mut expected = arr.clone();
expected.sort_by(|a, b| a.partial_cmp(b).unwrap());
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_duplicate_elements() {
let mut arr = vec![0.5, 0.5, 0.5, 0.5, 0.5];
sort(&mut arr);
assert_eq!(arr, vec![0.5, 0.5, 0.5, 0.5, 0.5]);
}
#[test]
fn test_large_array() {
let mut arr: Vec<f64> = (0..1000).map(|x| (x as f64) / 1000.0).rev().collect();
let mut expected = arr.clone();
expected.sort_by(|a, b| a.partial_cmp(b).unwrap());
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_stability() {
#[derive(Debug, Clone, PartialEq)]
struct Pair {
key: f64,
original_index: usize,
}
let pairs = vec![
Pair {
key: 0.5,
original_index: 0,
},
Pair {
key: 0.5,
original_index: 1,
},
Pair {
key: 0.7,
original_index: 2,
},
Pair {
key: 0.7,
original_index: 3,
},
];
let mut values: Vec<f64> = pairs.iter().map(|p| p.key).collect();
sort(&mut values);
for i in 0..pairs.len() - 1 {
for j in i + 1..pairs.len() {
if (pairs[i].key - pairs[j].key).abs() < EPSILON {
let pos_i = values
.iter()
.position(|&x| (x - pairs[i].key).abs() < EPSILON)
.unwrap();
let pos_j = values
.iter()
.rposition(|&x| (x - pairs[j].key).abs() < EPSILON)
.unwrap();
assert!(
pos_i < pos_j,
"Stability violated for equal elements at original positions {} and {}",
pairs[i].original_index,
pairs[j].original_index
);
}
}
}
}
#[test]
fn test_uniform_distribution() {
let mut arr = vec![0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
let expected = arr.clone();
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_clustered_values() {
let mut arr = vec![0.51, 0.52, 0.53, 0.54, 0.55];
let expected = arr.clone();
sort(&mut arr);
assert_eq!(arr, expected);
}
#[test]
fn test_edge_values() {
let mut arr = vec![0.001, 0.999, 0.002, 0.998];
sort(&mut arr);
assert_eq!(arr, vec![0.001, 0.002, 0.998, 0.999]);
}
#[test]
fn test_bucket_index() {
let num_buckets = 10;
assert_eq!(get_bucket_index(0.1, num_buckets), 1);
assert_eq!(get_bucket_index(0.5, num_buckets), 5);
assert_eq!(get_bucket_index(0.99, num_buckets), 9);
assert_eq!(get_bucket_index(0.0, num_buckets), 0);
}
#[test]
fn test_insertion_sort() {
let mut bucket = vec![0.5, 0.3, 0.4, 0.2, 0.1];
insertion_sort(&mut bucket);
assert_eq!(bucket, vec![0.1, 0.2, 0.3, 0.4, 0.5]);
}
#[test]
fn test_sparse_distribution() {
let mut arr = vec![0.1, 0.9, 0.2, 0.8, 0.3, 0.7];
sort(&mut arr);
assert_eq!(arr, vec![0.1, 0.2, 0.3, 0.7, 0.8, 0.9]);
}
#[test]
fn test_almost_sorted() {
let mut arr = vec![0.1, 0.2, 0.4, 0.3, 0.5];
sort(&mut arr);
assert_eq!(arr, vec![0.1, 0.2, 0.3, 0.4, 0.5]);
}
}