use super::quantile;
use num_traits::{Num, NumCast};
pub fn quartiles<T>(data: &mut [T]) -> (f64, f64, f64)
where
T: Num + NumCast + Copy + PartialOrd,
{
let n = data.len();
if n == 0 {
panic!("Input data slice must not be empty");
}
data.sort_by(|a, b| a.partial_cmp(b).unwrap());
let q1 = quantile(data, 0.25);
let q2 = quantile(data, 0.50);
let q3 = quantile(data, 0.75);
(q1, q2, q3)
}
#[cfg(test)]
mod tests {
use super::quartiles;
#[test]
#[should_panic(expected = "Input data slice must not be empty")]
fn calculate_quartiles_panics_on_empty_input() {
let mut data: Vec<i32> = vec![];
quartiles(&mut data);
}
#[test]
fn calculate_quartiles_works() {
let mut data = vec![7, 1, 3, 9, 5];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 3.0);
assert_eq!(q2, 5.0);
assert_eq!(q3, 7.0);
let mut data_odd = vec![17, 2, 5, 11, 14, 8, 20];
let (q1, q2, q3) = quartiles(&mut data_odd);
assert_eq!(q1, 6.5);
assert_eq!(q2, 11.0);
assert_eq!(q3, 15.5);
let mut data_even = vec![2, 14, 17, 20, 5, 8, 11, 23];
let (q1, q2, q3) = quartiles(&mut data_even);
assert_eq!(q1, 7.25);
assert_eq!(q2, 12.5);
assert_eq!(q3, 17.75);
}
#[test]
fn calculate_quartiles_single_element() {
let mut data = vec![42];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 42.0);
assert_eq!(q2, 42.0);
assert_eq!(q3, 42.0);
}
#[test]
fn calculate_quartiles_two_elements() {
let mut data = vec![10, 20];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 12.5);
assert_eq!(q2, 15.0);
assert_eq!(q3, 17.5);
}
#[test]
fn calculate_quartiles_three_elements() {
let mut data = vec![1, 2, 3];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 1.5);
assert_eq!(q2, 2.0);
assert_eq!(q3, 2.5);
}
#[test]
fn calculate_quartiles_four_elements() {
let mut data = vec![1, 2, 3, 4];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 1.75);
assert_eq!(q2, 2.5);
assert_eq!(q3, 3.25);
}
#[test]
fn calculate_quartiles_with_floats() {
let mut data = vec![1.5, 2.7, 3.2, 4.8, 5.1];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 2.7);
assert_eq!(q2, 3.2);
assert_eq!(q3, 4.8);
}
#[test]
fn calculate_quartiles_with_negative_values() {
let mut data = vec![-10, -5, 0, 5, 10];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, -5.0);
assert_eq!(q2, 0.0);
assert_eq!(q3, 5.0);
}
#[test]
fn calculate_quartiles_with_duplicates() {
let mut data = vec![1, 2, 2, 2, 3, 4, 5];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 2.0);
assert_eq!(q2, 2.0);
assert_eq!(q3, 3.5);
}
#[test]
fn calculate_quartiles_all_same_values() {
let mut data = vec![5, 5, 5, 5, 5];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 5.0);
assert_eq!(q2, 5.0);
assert_eq!(q3, 5.0);
}
#[test]
fn calculate_quartiles_unsorted_input() {
let mut data = vec![100, 1, 50, 25, 75];
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 25.0);
assert_eq!(q2, 50.0);
assert_eq!(q3, 75.0);
}
#[test]
fn calculate_quartiles_large_dataset() {
let mut data: Vec<i32> = (1..=100).collect();
let (q1, q2, q3) = quartiles(&mut data);
assert_eq!(q1, 25.75);
assert_eq!(q2, 50.5);
assert_eq!(q3, 75.25);
}
#[test]
fn calculate_quartiles_verifies_sorting() {
let mut data = vec![5, 2, 8, 1, 9, 3, 7];
let _ = quartiles(&mut data);
assert_eq!(data, vec![1, 2, 3, 5, 7, 8, 9]);
}
}