fn sort(input: &mut [f64]) {
input.sort_by(|a, b| a.abs().partial_cmp(&b.abs()).unwrap())
}
pub fn kbk_sum_sort(input: &mut [f64]) -> f64 {
sort(input);
kbk_sum(input)
}
pub fn kbk_sum(input: &[f64]) -> f64 {
let mut sum = 0.0;
let mut cs = 0.0;
let mut ccs = 0.0;
for addend in input {
let addend = *addend;
let mut t = sum + addend;
let c =
if sum.abs() >= addend.abs() {
(sum - t) + addend
} else {
(addend - t) + sum
};
sum = t;
t = cs + c;
let cc =
if cs.abs() >= c.abs() {
(cs - t) + c
} else {
(c - t) + cs
};
cs = t;
ccs += cc;
}
sum + cs + ccs
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn run_tests() {
let limit = 16;
let mut inputs = Vec::<f64>::new();
for i in 0..=limit {
inputs.push(i as f64);
}
let result = kbk_sum(&inputs);
let expected = ((limit + 1) * limit) / 2;
assert!(result == expected as f64);
let result = kbk_sum_sort(&mut inputs);
assert!(result == expected as f64);
println!("vector sum 1: {}", result);
for i in 0..=limit {
inputs.push(-i as f64);
}
let result = kbk_sum(&inputs);
println!("vector sum 2: {}", result);
assert!(result == 0.0);
let result = kbk_sum_sort(&mut inputs);
assert!(result == 0.0);
let large = (10.0 as f64).powi(100);
inputs.clear();
inputs.push(1.0);
inputs.push(large);
inputs.push(1.0);
inputs.push(-large);
let result = kbk_sum(&inputs);
assert!(result == 2.0);
let result = kbk_sum_sort(&mut inputs);
println!("vector sum 3: {}", result);
assert!(result == 2.0);
}
}