use super::edges::Case;
pub(super) const GRID: i64 = 16;
pub(super) fn grid_points(random: &mut SplitMix64, count: usize, scale: i32) -> Case {
let mut integer = || random.below(2 * GRID as u64 + 1) as i64 - GRID;
let mut p: Vec<[i64; 3]> = (0..count)
.map(|_| [integer(), integer(), integer()])
.collect();
if count >= 4 {
let (s, t) = (random.below(5) as i64 - 2, random.below(5) as i64 - 2);
let (a, b, c) = (p[0], p[1], p[2]);
p[count - 1] = std::array::from_fn(|i| a[i] + s * (b[i] - a[i]) + t * (c[i] - a[i]));
}
let unit = pow2(scale);
p.iter()
.map(|point| point.map(|n| n as f64 * unit))
.collect()
}
pub(super) const FINITE_KEYS: i128 = 0x7fef_ffff_ffff_ffff;
pub(super) fn key(x: f64) -> i128 {
let magnitude = i128::from(x.to_bits() & !(1 << 63));
if x.is_sign_negative() {
-magnitude
} else {
magnitude
}
}
pub(super) fn from_key(key: i128) -> f64 {
let magnitude = u64::try_from(key.unsigned_abs()).expect("a finite key");
let sign = if key < 0 { 1 << 63 } else { 0 };
f64::from_bits(sign | magnitude)
}
pub(super) fn exponent(x: f64) -> i32 {
i32::try_from(x.to_bits() >> 52).expect("11 bits") - 1023
}
pub(super) fn pow2(exponent: i32) -> f64 {
f64::from_bits(u64::try_from(exponent + 1023).expect("a normal power of two") << 52)
}
pub(super) struct SplitMix64(pub(super) u64);
impl SplitMix64 {
pub(super) fn next(&mut self) -> u64 {
self.0 = self.0.wrapping_add(0x9e37_79b9_7f4a_7c15);
let mut z = self.0;
z = (z ^ (z >> 30)).wrapping_mul(0xbf58_476d_1ce4_e5b9);
z = (z ^ (z >> 27)).wrapping_mul(0x94d0_49bb_1331_11eb);
z ^ (z >> 31)
}
pub(super) fn below(&mut self, n: u64) -> u64 {
self.next() % n
}
}