use crate::SumF64;
#[cfg(kani_slow)]
fn any_finite() -> f64 {
let x: f64 = kani::any();
kani::assume(x.is_finite());
x
}
#[cfg(kani_slow)]
#[kani::proof]
fn add_commutes() {
let x = any_finite();
let y = any_finite();
let mut a = SumF64::new();
a.add(x);
a.add(y);
let mut b = SumF64::new();
b.add(y);
b.add(x);
assert_eq!(a, b);
}
#[cfg(kani_slow)]
#[kani::proof]
fn cancellation_is_exact() {
let x = any_finite();
let mut a = SumF64::new();
a.add(x);
a.add(-x);
let mut empty = SumF64::new();
empty.add(0.0);
empty.add(0.0);
assert_eq!(a, empty);
}
#[kani::proof]
fn merge_commutes() {
let bytes_a: [u8; SumF64::BYTES] = kani::any();
let bytes_b: [u8; SumF64::BYTES] = kani::any();
let (Some(a0), Some(b0)) = (SumF64::from_bytes(&bytes_a), SumF64::from_bytes(&bytes_b)) else {
return; };
let mut ab = a0.clone();
ab.merge(&b0);
let mut ba = b0;
ba.merge(&a0);
assert_eq!(ab, ba);
}
#[kani::proof]
fn merge_associates() {
let bytes_a: [u8; SumF64::BYTES] = kani::any();
let bytes_b: [u8; SumF64::BYTES] = kani::any();
let bytes_c: [u8; SumF64::BYTES] = kani::any();
let (Some(a), Some(b), Some(c)) = (
SumF64::from_bytes(&bytes_a),
SumF64::from_bytes(&bytes_b),
SumF64::from_bytes(&bytes_c),
) else {
return;
};
let mut left = a.clone();
left.merge(&b);
left.merge(&c);
let mut right_inner = b;
right_inner.merge(&c);
let mut right = a;
right.merge(&right_inner);
assert_eq!(left, right);
}
#[cfg(kani_slow)]
#[kani::proof]
fn add_placement_is_irrelevant() {
let x = any_finite();
let bytes_a: [u8; SumF64::BYTES] = kani::any();
let bytes_b: [u8; SumF64::BYTES] = kani::any();
let (Some(a0), Some(b0)) = (SumF64::from_bytes(&bytes_a), SumF64::from_bytes(&bytes_b)) else {
return;
};
let mut a1 = a0.clone();
a1.add(x);
let mut left = a1;
left.merge(&b0);
let mut b1 = b0;
b1.add(x);
let mut right = a0;
right.merge(&b1);
assert_eq!(left, right);
}
#[kani::proof]
fn bytes_roundtrip() {
let bytes: [u8; SumF64::BYTES] = kani::any();
if let Some(acc) = SumF64::from_bytes(&bytes) {
assert_eq!(acc.to_bytes(), bytes);
}
}
#[kani::proof]
fn extrema_merge_commutes() {
let ba: [u8; crate::ExtremaF64::BYTES] = kani::any();
let bb: [u8; crate::ExtremaF64::BYTES] = kani::any();
let (Some(a0), Some(b0)) = (
crate::ExtremaF64::from_bytes(&ba),
crate::ExtremaF64::from_bytes(&bb),
) else {
return;
};
let mut ab = a0.clone();
crate::Mergeable::merge(&mut ab, &b0);
let mut ba2 = b0;
crate::Mergeable::merge(&mut ba2, &a0);
assert_eq!(ab.to_bytes(), ba2.to_bytes());
}
#[kani::proof]
fn extrema_merge_associates() {
let ba: [u8; crate::ExtremaF64::BYTES] = kani::any();
let bb: [u8; crate::ExtremaF64::BYTES] = kani::any();
let bc: [u8; crate::ExtremaF64::BYTES] = kani::any();
let (Some(a), Some(b), Some(c)) = (
crate::ExtremaF64::from_bytes(&ba),
crate::ExtremaF64::from_bytes(&bb),
crate::ExtremaF64::from_bytes(&bc),
) else {
return;
};
let mut left = a.clone();
crate::Mergeable::merge(&mut left, &b);
crate::Mergeable::merge(&mut left, &c);
let mut right_inner = b;
crate::Mergeable::merge(&mut right_inner, &c);
let mut right = a;
crate::Mergeable::merge(&mut right, &right_inner);
assert_eq!(left.to_bytes(), right.to_bytes());
}
#[kani::proof]
fn extrema_bytes_roundtrip() {
let bytes: [u8; crate::ExtremaF64::BYTES] = kani::any();
if let Some(e) = crate::ExtremaF64::from_bytes(&bytes) {
assert_eq!(e.to_bytes(), bytes);
}
}