#![allow(
clippy::float_cmp,
clippy::incompatible_msrv,
clippy::unreadable_literal,
clippy::cast_possible_truncation,
clippy::cast_precision_loss,
clippy::cast_sign_loss,
clippy::cast_lossless,
clippy::unwrap_used
)]
mod support;
use support::{
Pred, SplitMix64, call, cocircular, collinear, config_span, coplanar, cospherical,
from_ordinal, oracle, ordinal,
};
const fn seed(number: u64) -> u64 {
0x2026_1010_D1D0_u64.wrapping_add(number)
}
fn power_of_two(exponent: i32) -> f64 {
assert!((-1022..=1023).contains(&exponent));
f64::from_bits(((exponent + 1023) as u64) << 52)
}
fn in_window_shifts(pred: Pred, config: &[f64]) -> (i32, i32) {
let (q_min, e_max) = pred.window();
let (highest, lowest) = config_span(config).expect("the fixtures are not all zero");
(q_min - lowest, e_max - highest)
}
fn scaled(config: &[f64], factor: f64) -> Vec<f64> {
assert_eq!(factor.to_bits() & 0x000F_FFFF_FFFF_FFFF, 0);
config.iter().map(|&c| c * factor).collect()
}
fn fixtures(pred: Pred, rng: &mut SplitMix64, cases: usize) -> Vec<Vec<f64>> {
let build = match pred {
Pred::Orient2d => collinear,
Pred::Incircle => cocircular,
Pred::Orient3d => coplanar,
Pred::Insphere => cospherical,
};
let mut out = Vec::new();
for _ in 0..cases {
let base = build(rng);
out.push(base.clone());
for _ in 0..3 {
let index = rng.index(base.len());
let step = if rng.coin() { 1 } else { -1 } * if rng.coin() { 1 } else { 2 };
let mut neighbor = base.clone();
neighbor[index] = from_ordinal(ordinal(base[index]) + i64::from(step));
out.push(neighbor);
}
}
out
}
fn assert_sign_is_scale_invariant(pred: Pred, cases: usize, number: u64) {
let mut rng = SplitMix64::new(seed(number));
let mut checked = 0_u32;
for config in fixtures(pred, &mut rng, cases) {
let want = oracle(pred, &config);
assert_eq!(call(pred, &config), want, "unscaled: {config:?}");
let (lowest, highest) = in_window_shifts(pred, &config);
let shifts = [
lowest,
highest,
i32::midpoint(lowest, highest),
lowest - 40,
highest + 40,
];
for shift in shifts {
if !(-1022..=1023).contains(&shift) || shift == 0 {
continue;
}
let moved = scaled(&config, power_of_two(shift));
for (original, scaled_value) in config.iter().zip(&moved) {
assert!(
scaled_value.is_finite() && (*scaled_value == 0.0) == (*original == 0.0),
"shift {shift} was not exact for {original:e}"
);
}
assert_eq!(
call(pred, &moved),
want,
"{}: shift {shift} changed the sign of {config:?}",
pred.name()
);
checked += 1;
}
}
assert!(checked > 0, "no scaling was checked");
}
#[test]
fn orient2d_sign_is_scale_invariant() {
assert_sign_is_scale_invariant(Pred::Orient2d, 300, 0);
}
#[test]
fn incircle_sign_is_scale_invariant() {
assert_sign_is_scale_invariant(Pred::Incircle, 120, 1);
}
#[test]
fn orient3d_sign_is_scale_invariant() {
assert_sign_is_scale_invariant(Pred::Orient3d, 120, 2);
}
#[test]
fn insphere_sign_is_scale_invariant() {
assert_sign_is_scale_invariant(Pred::Insphere, 40, 3);
}