pub fn bools_to_signs(flags: &[bool]) -> Vec<f64> {
flags
.iter()
.map(|flag| if *flag { 1.0 } else { -1.0 })
.collect()
}
pub fn add(a: &[f64], b: &[f64]) -> Vec<f64> {
assert_eq!(a.len(), b.len(), "length mismatch");
a.iter().zip(b).map(|(x, y)| x + y).collect()
}
pub fn subtract(a: &[f64], b: &[f64]) -> Vec<f64> {
assert_eq!(a.len(), b.len(), "length mismatch");
a.iter().zip(b).map(|(x, y)| x - y).collect()
}
pub fn align_right<'a>(a: &'a [f64], b: &'a [f64]) -> (&'a [f64], &'a [f64]) {
let n = a.len().min(b.len());
(&a[a.len() - n..], &b[b.len() - n..])
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn bools_to_signs_true_is_positive_one() {
assert_eq!(bools_to_signs(&[true]), vec![1.0]);
}
#[test]
fn bools_to_signs_false_is_negative_one() {
assert_eq!(bools_to_signs(&[false]), vec![-1.0]);
}
#[test]
fn bools_to_signs_mixed_sequence_preserves_order() {
assert_eq!(bools_to_signs(&[true, false, true, false]), vec![1.0, -1.0, 1.0, -1.0]);
}
#[test]
fn bools_to_signs_empty_input_is_empty() {
assert!(bools_to_signs(&[]).is_empty());
}
#[test]
fn bools_to_signs_all_true() {
assert_eq!(bools_to_signs(&[true, true, true]), vec![1.0, 1.0, 1.0]);
}
#[test]
fn bools_to_signs_all_false() {
assert_eq!(bools_to_signs(&[false, false, false]), vec![-1.0, -1.0, -1.0]);
}
#[test]
fn add_basic() {
assert_eq!(add(&[1.0, 2.0, 3.0], &[10.0, 20.0, 30.0]), vec![11.0, 22.0, 33.0]);
}
#[test]
fn add_empty() {
assert!(add(&[], &[]).is_empty());
}
#[test]
#[should_panic(expected = "length mismatch")]
fn add_length_mismatch_panics() {
let _ = add(&[1.0, 2.0], &[1.0]);
}
#[test]
#[should_panic(expected = "length mismatch")]
fn add_length_mismatch_when_second_input_is_longer_panics() {
let _ = add(&[1.0], &[1.0, 2.0]);
}
#[test]
fn add_overflow_to_infinity() {
assert_eq!(add(&[f64::MAX], &[f64::MAX]), vec![f64::INFINITY]);
}
#[test]
fn add_infinity_and_nan_propagates() {
assert!(add(&[f64::INFINITY], &[f64::NEG_INFINITY])[0].is_nan());
assert!(add(&[f64::NAN], &[1.0])[0].is_nan());
}
#[test]
fn add_preserves_negative_zero_from_ieee_addition() {
let zeros = [-0.0];
assert_eq!(add(&zeros, &zeros)[0].to_bits(), (-0.0_f64).to_bits());
}
#[test]
fn subtract_basic() {
assert_eq!(subtract(&[10.0, 20.0], &[1.0, 2.0]), vec![9.0, 18.0]);
}
#[test]
fn subtract_empty() {
assert!(subtract(&[], &[]).is_empty());
}
#[test]
#[should_panic(expected = "length mismatch")]
fn subtract_length_mismatch_panics() {
let _ = subtract(&[1.0], &[1.0, 2.0]);
}
#[test]
#[should_panic(expected = "length mismatch")]
fn subtract_length_mismatch_when_first_input_is_longer_panics() {
let _ = subtract(&[1.0, 2.0], &[1.0]);
}
#[test]
fn subtract_overflow_to_neg_infinity() {
assert_eq!(subtract(&[-f64::MAX], &[f64::MAX]), vec![f64::NEG_INFINITY]);
}
#[test]
fn subtract_infinity_yields_nan() {
assert!(subtract(&[f64::INFINITY], &[f64::INFINITY])[0].is_nan());
}
#[test]
fn subtract_propagates_nan_and_preserves_signed_zero() {
let values = [f64::NAN, -0.0];
let zeros = [1.0, 0.0];
let result = subtract(&values, &zeros);
assert!(result[0].is_nan());
assert_eq!(result[1].to_bits(), (-0.0_f64).to_bits());
}
#[test]
fn align_right_equal_lengths() {
let (a, b) = align_right(&[1.0, 2.0, 3.0], &[4.0, 5.0, 6.0]);
assert_eq!(a, &[1.0, 2.0, 3.0]);
assert_eq!(b, &[4.0, 5.0, 6.0]);
}
#[test]
fn align_right_first_longer_trims_front() {
let (a, b) = align_right(&[1.0, 2.0, 3.0, 4.0], &[5.0, 6.0]);
assert_eq!(a, &[3.0, 4.0]);
assert_eq!(b, &[5.0, 6.0]);
}
#[test]
fn align_right_second_longer_trims_front() {
let (a, b) = align_right(&[1.0, 2.0], &[3.0, 4.0, 5.0, 6.0]);
assert_eq!(a, &[1.0, 2.0]);
assert_eq!(b, &[5.0, 6.0]);
}
#[test]
fn align_right_both_empty() {
let (a, b) = align_right(&[], &[]);
assert!(a.is_empty());
assert!(b.is_empty());
}
#[test]
fn align_right_one_empty_clamps_to_zero_length() {
let (a, b) = align_right(&[1.0, 2.0, 3.0], &[]);
assert!(a.is_empty());
assert!(b.is_empty());
let (a, b) = align_right(&[], &[1.0, 2.0, 3.0]);
assert!(a.is_empty());
assert!(b.is_empty());
}
#[test]
fn align_right_single_element_each() {
let (a, b) = align_right(&[1.0], &[9.0]);
assert_eq!(a, &[1.0]);
assert_eq!(b, &[9.0]);
}
}