#![allow(clippy::float_cmp)]
use super::{
ALL_INSIDE, BodySaddles, Contours, INTERIOR, MAX_CONTOURS, MAX_INTERIOR_VERTICES, Pair,
Topology,
};
use crate::Sdf;
use crate::cube::{corner_offset, is_inside};
use crate::fields::ReferenceField;
use crate::marching_cubes::interior::SweptFaces;
struct Lcg(u64);
impl Lcg {
fn new(seed: u64) -> Self {
Self(seed)
}
fn signed(&mut self) -> f64 {
self.0 = self
.0
.wrapping_mul(6_364_136_223_846_793_005)
.wrapping_add(1_442_695_040_888_963_407);
let unit = (self.0 >> 11) as f64 / (1u64 << 53) as f64;
unit * 2.0 - 1.0
}
fn corners(&mut self) -> [f64; 8] {
let mut f = [0.0; 8];
for slot in &mut f {
*slot = self.signed();
}
f
}
}
fn trilinear(f: &[f64; 8], p: [f64; 3]) -> f64 {
let mut sum = 0.0;
for (i, &value) in f.iter().enumerate() {
let o = corner_offset(i as u8);
let mut weight = value;
for axis in 0..3 {
weight *= if o[axis] == 1 { p[axis] } else { 1.0 - p[axis] };
}
sum += weight;
}
sum
}
fn corner_groups(f: &[f64; 8], n: usize) -> usize {
let at = |i: usize, j: usize, k: usize| {
let p = [
i as f64 / (n - 1) as f64,
j as f64 / (n - 1) as f64,
k as f64 / (n - 1) as f64,
];
trilinear(f, p) < 0.0
};
let idx = |i: usize, j: usize, k: usize| (k * n + j) * n + i;
let mut label = alloc::vec![usize::MAX; n * n * n];
let mut next = 0usize;
let mut stack = alloc::vec::Vec::new();
for k in 0..n {
for j in 0..n {
for i in 0..n {
if !at(i, j, k) || label[idx(i, j, k)] != usize::MAX {
continue;
}
let id = next;
next += 1;
stack.push((i, j, k));
label[idx(i, j, k)] = id;
while let Some((x, y, z)) = stack.pop() {
let push = |a: usize,
b: usize,
c: usize,
st: &mut alloc::vec::Vec<_>,
lb: &mut alloc::vec::Vec<usize>| {
if at(a, b, c) && lb[idx(a, b, c)] == usize::MAX {
lb[idx(a, b, c)] = id;
st.push((a, b, c));
}
};
if x > 0 {
push(x - 1, y, z, &mut stack, &mut label);
}
if x + 1 < n {
push(x + 1, y, z, &mut stack, &mut label);
}
if y > 0 {
push(x, y - 1, z, &mut stack, &mut label);
}
if y + 1 < n {
push(x, y + 1, z, &mut stack, &mut label);
}
if z > 0 {
push(x, y, z - 1, &mut stack, &mut label);
}
if z + 1 < n {
push(x, y, z + 1, &mut stack, &mut label);
}
}
}
}
}
let mut seen = alloc::collections::BTreeSet::new();
for (c, &value) in f.iter().enumerate() {
if !is_inside(value) {
continue;
}
let g = |bit: usize| if (c >> bit) & 1 == 1 { n - 1 } else { 0 };
let l = label[idx(g(0), g(1), g(2))];
if l != usize::MAX {
seen.insert(l);
}
}
seen.len()
}
#[test]
fn grosso_corner_numbering_is_ours() {
let grosso: [[u32; 3]; 8] = [
[0, 0, 0],
[1, 0, 0],
[0, 1, 0],
[1, 1, 0],
[0, 0, 1],
[1, 0, 1],
[0, 1, 1],
[1, 1, 1],
];
for (i, expected) in grosso.iter().enumerate() {
assert_eq!(
corner_offset(i as u8),
*expected,
"corner {i} is not where Grosso puts it"
);
}
}
#[test]
fn the_coefficients_reproduce_the_face_hyperbola_difference() {
let mut rng = Lcg::new(0x0000_A002_D000_0001);
let mut worst: f64 = 0.0;
for _ in 0..20_000 {
let f = rng.corners();
let [a, b, c] = BodySaddles::coefficients(&f);
for step in 0..=8 {
let u = f64::from(step) / 8.0;
let s = 1.0 - u;
let g0 = f[0] * s + f[1] * u;
let g1 = f[2] * s + f[3] * u;
let h0 = f[4] * s + f[5] * u;
let h1 = f[6] * s + f[7] * u;
let direct = (-g0) * (h1 - h0) - (-h0) * (g1 - g0);
let expanded = (a * u + b) * u + c;
worst = worst.max((direct - expanded).abs());
}
}
assert!(worst < 1e-12, "coefficients disagree by up to {worst:e}");
std::println!("measured: worst coefficient disagreement {worst:e} over 20,000 cells");
}
#[test]
fn every_body_saddle_lies_on_the_level_set() {
let mut rng = Lcg::new(0x0000_A002_D000_0002);
let mut checked = 0usize;
let mut worst: f64 = 0.0;
for _ in 0..200_000 {
let f = rng.corners();
let saddles = BodySaddles::of(&f);
let Some(hexagon) = saddles.inner_hexagon() else {
continue;
};
for vertex in hexagon {
worst = worst.max(trilinear(&f, vertex).abs());
checked += 1;
}
}
assert!(
checked > 0,
"no cell in the sweep had six saddles, so this measured nothing"
);
assert!(
worst < 1e-9,
"a hexagon vertex is {worst:e} off the surface"
);
std::println!(
"measured: {checked} hexagon vertices, worst distance from the level set {worst:e}"
);
}
#[test]
fn the_body_saddle_heights_agree_with_the_swept_saddle_roots() {
let mut rng = Lcg::new(0x0000_A002_D000_0003);
let mut compared = 0usize;
let mut worst: f64 = 0.0;
for _ in 0..200_000 {
let f = rng.corners();
let saddles = BodySaddles::of(&f);
if !saddles.has_inner_hexagon() {
continue;
}
let Ok(swept) = SweptFaces::new([f[0], f[1], f[3], f[2]], [f[4], f[5], f[7], f[6]]) else {
continue;
};
let mut theirs = [0.0f64; 2];
let mut count = 0;
for t in swept.numerator_roots() {
if t > 0.0 && t < 1.0 && count < 2 {
theirs[count] = t;
count += 1;
}
}
if count != 2 {
continue;
}
let mut ours = saddles.axis(2);
if ours[0] > ours[1] {
ours.swap(0, 1);
}
if theirs[0] > theirs[1] {
theirs.swap(0, 1);
}
for k in 0..2 {
worst = worst.max((ours[k] - theirs[k]).abs());
}
compared += 1;
}
assert!(
compared > 100,
"only {compared} cells reached the comparison, which measures nothing"
);
assert!(
worst < 1e-9,
"the two constructions disagree by up to {worst:e}"
);
std::println!(
"measured: {compared} cells cross-checked against the swept saddle, worst gap {worst:e}"
);
}
#[test]
fn hexagon_edges_are_axis_parallel_and_close() {
let mut rng = Lcg::new(0x0000_A002_D000_0004);
let mut rings = 0usize;
for _ in 0..200_000 {
let f = rng.corners();
let Some(hexagon) = BodySaddles::of(&f).inner_hexagon() else {
continue;
};
let mut per_axis = [0usize; 3];
for k in 0..6 {
let a = hexagon[k];
let b = hexagon[(k + 1) % 6];
let mut differing = 0;
for (axis, count) in per_axis.iter_mut().enumerate() {
if a[axis] != b[axis] {
*count += 1;
differing += 1;
}
}
assert_eq!(
differing,
1,
"hexagon edge {k}→{} changes {differing} coordinates, not one",
(k + 1) % 6
);
}
for (axis, &used) in per_axis.iter().enumerate() {
assert_eq!(
used, 2,
"axis {axis} supplies {used} hexagon edges, not two"
);
}
rings += 1;
}
assert!(rings > 0, "no hexagon was built, so this measured nothing");
std::println!("measured: {rings} inner hexagons, all closed and axis-parallel");
}
#[test]
fn the_classification_is_invariant_under_axis_relabelling() {
const PERM: [usize; 3] = [2, 0, 1];
fn relabel(f: &[f64; 8]) -> [f64; 8] {
let mut out = [0.0; 8];
for (n, slot) in out.iter_mut().enumerate() {
let mut old = 0usize;
for (axis, &target) in PERM.iter().enumerate() {
old |= ((n >> axis) & 1) << target;
}
*slot = f[old];
}
out
}
let mut rng = Lcg::new(0x0000_A002_D000_0005);
let mut disagreements = 0usize;
let mut hexagons = 0usize;
let mut cells = 0usize;
for _ in 0..200_000 {
let f = rng.corners();
let g = relabel(&f);
let probe = [0.31, 0.57, 0.13];
let mut mapped = [0.0f64; 3];
for (axis, &target) in PERM.iter().enumerate() {
mapped[target] = probe[axis];
}
assert!((trilinear(&g, probe) - trilinear(&f, mapped)).abs() < 1e-12);
let a = BodySaddles::of(&f);
let b = BodySaddles::of(&g);
if a.inside_count() != b.inside_count() {
disagreements += 1;
}
if a.has_inner_hexagon() {
hexagons += 1;
}
cells += 1;
}
assert!(
hexagons > 0,
"no hexagon was reached, so this measured nothing"
);
assert_eq!(
disagreements, 0,
"{disagreements} of {cells} cells classified differently after relabelling"
);
std::println!(
"measured: {cells} cells relabelled, {hexagons} with six saddles, 0 disagreements"
);
}
#[test]
fn a_double_root_is_one_point_not_two() {
let f = [0.0f64, 1.5, 0.5, 4.0, 0.5, 1.0, 2.0, 2.5];
let [a, b, c] = BodySaddles::coefficients(&f);
assert_eq!([a, b, c], [1.0, -1.0, 0.25], "the fixture drifted");
let discriminant = b * b - 4.0 * a * c;
assert_eq!(
discriminant, 0.0,
"the fixture is not an exact tangency; it measures nothing"
);
let saddles = BodySaddles::of(&f);
assert!(
saddles.inside_mask() & 0b01 != 0,
"the tangency's own root was not reported at all"
);
assert!(
saddles.inside_mask() & 0b10 == 0,
"a tangency was reported as two distinct intersection points"
);
assert!(
!saddles.has_inner_hexagon(),
"a tangency was reported as a full hexagon"
);
std::println!(
"measured: exact tangency, double root {}, mask {:#08b}",
saddles.axis(0)[0],
saddles.inside_mask()
);
}
#[test]
fn a_linear_equation_keeps_its_root() {
let f = [0.25f64, -0.5, -0.75, -1.5, 0.5, 0.0, -2.0, -2.5];
let [a, b, c] = BodySaddles::coefficients(&f);
assert_eq!(a, 0.0, "the fixture does not have a vanishing leading term");
assert_ne!(b, 0.0, "the fixture is not linear, it is constant");
assert_eq!([b, c], [-1.375, 0.125], "the fixture drifted");
let saddles = BodySaddles::of(&f);
let root = saddles.axis(0)[0];
assert!(
(b * root + c).abs() < 1e-12,
"the linear root does not satisfy the equation"
);
let expected_inside = root > 0.0 && root < 1.0;
assert_eq!(
saddles.inside_mask() & 1 != 0,
expected_inside,
"the linear root's in-range bit does not match its value {root}"
);
std::println!("measured: linear case root {root:.12}, in range {expected_inside}");
}
#[test]
fn how_often_a_cell_has_six_body_saddles() {
let mut rng = Lcg::new(0x0000_A002_D000_0006);
let mut histogram = [0usize; 7];
const CELLS: usize = 200_000;
for _ in 0..CELLS {
let saddles = BodySaddles::of(&rng.corners());
histogram[saddles.inside_count() as usize] += 1;
}
assert_eq!(histogram.iter().sum::<usize>(), CELLS);
assert!(
histogram[6] > 0,
"no cell reached six saddles, so the census measured nothing"
);
std::println!("measured: saddle-count histogram over {CELLS} random cells: {histogram:?}");
}
#[test]
fn the_hexagon_predicate_is_the_full_mask() {
let mut rng = Lcg::new(0x0000_A002_D000_0007);
for _ in 0..50_000 {
let saddles = BodySaddles::of(&rng.corners());
assert_eq!(
saddles.has_inner_hexagon(),
saddles.inside_mask() == ALL_INSIDE
);
assert_eq!(
saddles.has_inner_hexagon(),
saddles.inside_count() == 6,
"count and mask disagree"
);
}
}
#[test]
fn the_classification_is_deterministic_in_both_widths() {
let mut rng = Lcg::new(0x0000_A002_D000_0008);
for _ in 0..20_000 {
let wide = rng.corners();
let mut narrow = [0.0f32; 8];
for (slot, &value) in narrow.iter_mut().zip(wide.iter()) {
*slot = value as f32;
}
let a = BodySaddles::of(&wide);
let b = BodySaddles::of(&wide);
assert_eq!(a.inside_mask(), b.inside_mask());
for axis in 0..3 {
assert_eq!(
a.axis(axis),
b.axis(axis),
"axis {axis} is not reproducible"
);
}
let n = BodySaddles::of(&narrow);
assert_eq!(n.inside_mask(), BodySaddles::of(&narrow).inside_mask());
}
}
#[test]
fn how_often_the_reference_fields_reach_six_body_saddles() {
let mut reached = 0u64;
let mut surface_total = 0u64;
crate::for_each_reference_field!(f64, |name, field| {
for samples in [17u32, 33, 65] {
let (lo, hi) = field.domain();
let h = (hi[0] - lo[0]) / f64::from(samples - 1);
let mut surface = 0u64;
let mut histogram = [0u64; 7];
for z in 0..samples - 1 {
for y in 0..samples - 1 {
for x in 0..samples - 1 {
let mut corner = [0.0f64; 8];
let mut case = 0u8;
for (c, slot) in corner.iter_mut().enumerate() {
let o = corner_offset(c as u8);
*slot = field.sample([
lo[0] + h * f64::from(x + o[0]),
lo[1] + h * f64::from(y + o[1]),
lo[2] + h * f64::from(z + o[2]),
]);
if is_inside(*slot) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
surface += 1;
histogram[BodySaddles::of(&corner).inside_count() as usize] += 1;
}
}
}
surface_total += surface;
reached += histogram[6];
std::println!(
"measured: {name} at {samples}^3 -> {surface} surface cells, \
saddle histogram {histogram:?}"
);
}
});
assert!(
surface_total > 0,
"the sweep visited no surface cell, so it measured nothing"
);
std::println!(
"measured: {reached} of {surface_total} reference-field surface cells have six body saddles"
);
}
#[test]
fn the_tunnel_field_actually_contains_tunnels() {
let field = crate::fields::noise_cavity::<f64>();
let (lo, hi) = field.domain();
let mut counts = alloc::vec::Vec::new();
for samples in [17u32, 25, 33] {
let h = (hi[0] - lo[0]) / f64::from(samples - 1);
let mut six = 0u64;
for z in 0..samples - 1 {
for y in 0..samples - 1 {
for x in 0..samples - 1 {
let mut corner = [0.0f64; 8];
let mut case = 0u8;
for (c, slot) in corner.iter_mut().enumerate() {
let o = corner_offset(c as u8);
*slot = field.sample([
lo[0] + h * f64::from(x + o[0]),
lo[1] + h * f64::from(y + o[1]),
lo[2] + h * f64::from(z + o[2]),
]);
if is_inside(*slot) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
if BodySaddles::of(&corner).inside_count() == 6 {
six += 1;
}
}
}
}
assert!(
six > 0,
"noise_cavity at {samples}^3 has no six-saddle cell, so every gate \
that rests on it measures nothing"
);
counts.push(six);
}
assert_eq!(
counts,
alloc::vec![3, 4, 4],
"the tunnel population moved; the field or the classifier changed"
);
std::println!("measured: noise_cavity six-saddle cells at 17/25/33 -> {counts:?}");
}
#[test]
fn every_cut_edge_lies_on_exactly_one_closed_ring() {
use crate::cube::{EDGE_CORNERS, corner_inside};
use crate::marching_cubes::table::segment_links;
let mut worst_rings = 0usize;
let mut worst_len = 0usize;
for case in 0..=255u8 {
for mask in 0..64u8 {
let contours = Contours::of(case, mask);
let mut cut = 0u16;
for (edge, [lo, hi]) in EDGE_CORNERS.into_iter().enumerate() {
if corner_inside(case, lo) != corner_inside(case, hi) {
cut |= 1 << edge;
}
}
let mut seen = 0u16;
let next = segment_links(case, mask);
for r in 0..contours.count() {
let ring = contours.ring(r);
assert!(
ring.len() >= 3,
"case {case:#010b} mask {mask:#08b}: ring of {}",
ring.len()
);
for (k, &e) in ring.iter().enumerate() {
assert_eq!(seen & (1 << e), 0, "edge {e} is on two rings");
seen |= 1 << e;
let follows = ring[(k + 1) % ring.len()];
assert_eq!(
next[e as usize], follows,
"case {case:#010b} mask {mask:#08b}: ring does not follow the links"
);
}
worst_len = worst_len.max(ring.len());
}
assert_eq!(
seen, cut,
"case {case:#010b} mask {mask:#08b}: rings do not cover the cut edges"
);
worst_rings = worst_rings.max(contours.count());
}
}
assert_eq!(worst_rings, MAX_CONTOURS);
assert_eq!(worst_len, 12);
std::println!(
"measured: 16,384 combinations, at most {worst_rings} rings, longest {worst_len}"
);
}
#[test]
fn ring_lengths_are_the_set_the_paper_lists() {
let mut seen = [false; 13];
for case in 0..=255u8 {
for mask in 0..64u8 {
let contours = Contours::of(case, mask);
for r in 0..contours.count() {
seen[contours.ring(r).len()] = true;
}
}
}
let produced: alloc::vec::Vec<usize> = (0..13).filter(|&k| seen[k]).collect();
assert_eq!(
produced,
alloc::vec![3, 4, 5, 6, 7, 8, 9, 12],
"the ring-length set moved"
);
std::println!("measured: ring lengths produced = {produced:?}");
}
#[test]
fn six_saddles_split_into_tunnels_and_twelve_vertex_contours() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let mut rng = Lcg::new(0x0000_A002_F000_0001);
let mut tunnels = 0usize;
let mut twelves = 0usize;
let mut disks = 0usize;
let mut separate = 0usize;
for _ in 0..400_000 {
let f = rng.corners();
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
let mask = joined_mask(&f, AMBIGUOUS_FACES[case as usize]);
let contours = Contours::of(case, mask);
match contours.topology(&BodySaddles::of(&f)) {
Topology::Disks => disks += 1,
Topology::Tunnel => tunnels += 1,
Topology::TwelveVertexContour => twelves += 1,
Topology::SeparateDisks => separate += 1,
}
}
assert!(
tunnels > 0,
"no tunnel was reached, so the branch is untested"
);
assert!(
twelves > 0,
"no twelve-vertex contour was reached, so that branch is untested"
);
assert_eq!(
separate, 0,
"uniform sampling reached a separate-disks cell, which no sweep has before"
);
std::println!(
"measured: {disks} disks, {tunnels} tunnels, {twelves} twelve-vertex contours, \
{separate} separate-disk cells"
);
}
#[test]
fn few_saddles_mean_short_rings() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let mut rng = Lcg::new(0x0000_A002_F000_0002);
let mut checked = 0usize;
let mut violations = 0usize;
let mut worst = 0usize;
for _ in 0..400_000 {
let f = rng.corners();
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
let saddles = BodySaddles::of(&f);
if saddles.inside_count() >= 2 {
continue;
}
let mask = joined_mask(&f, AMBIGUOUS_FACES[case as usize]);
let contours = Contours::of(case, mask);
let longest = contours.longest();
worst = worst.max(longest);
if longest > 6 {
violations += 1;
}
checked += 1;
}
assert!(checked > 1000, "only {checked} cells reached the corollary");
assert_eq!(
violations, 0,
"{violations} of {checked} cells with fewer than two saddles had a ring longer than six"
);
std::println!(
"measured: {checked} cells with fewer than two body saddles, longest ring {worst}"
);
}
#[test]
fn the_line_inventory_agrees_with_the_inner_hexagon() {
let mut rng = Lcg::new(0x0000_A002_6000_0001);
let mut checked = 0usize;
for _ in 0..200_000 {
let f = rng.corners();
let saddles = BodySaddles::of(&f);
let Some(hexagon) = saddles.inner_hexagon() else {
continue;
};
for pair in Pair::ALL {
assert_eq!(
saddles.line_count(pair),
2,
"a full hexagon must give every pair both lines"
);
}
for k in 0..6 {
let a = hexagon[k];
let b = hexagon[(k + 1) % 6];
let axis = (0..3)
.find(|&ax| a[ax] != b[ax])
.expect("a hexagon edge changes a coordinate");
let pair = Pair::ALL[axis];
let mut matched = 0;
for line in 0..2 {
let probe = saddles.point_on_line_for_test(pair, line, a[axis]);
if probe == a {
matched += 1;
}
}
assert_eq!(
matched, 1,
"hexagon edge {k} along axis {axis} matches {matched} of the \
pair's two lines, not exactly one — the pairing is wrong"
);
}
checked += 1;
}
assert!(checked > 100, "only {checked} hexagons reached the check");
std::println!("measured: {checked} hexagons agree with the line inventory");
}
#[test]
fn the_interior_vertex_lies_on_the_level_set() {
let mut rng = Lcg::new(0x0000_A002_6000_0002);
let mut checked = 0usize;
let mut worst: f64 = 0.0;
let mut by_total = [0usize; 5];
for _ in 0..400_000 {
let f = rng.corners();
let saddles = BodySaddles::of(&f);
if saddles.has_inner_hexagon() {
continue; }
let Some(p) = saddles.interior_vertex() else {
continue;
};
assert!(
p.iter().all(|c| c.is_finite()),
"interior vertex is not finite: {p:?}"
);
let lines: u32 = Pair::ALL.iter().map(|&q| saddles.line_count(q)).sum();
by_total[lines as usize] += 1;
worst = worst.max(trilinear(&f, p).abs());
checked += 1;
}
assert!(
checked > 1000,
"only {checked} interior vertices were built"
);
assert!(
worst < 1e-9,
"an interior vertex is {worst:e} off the level set — the branch selection is wrong"
);
assert!(
by_total[2] > 0 && by_total[3] > 0 && by_total[4] > 0,
"{by_total:?}"
);
std::println!(
"measured: {checked} interior vertices, worst distance from the level set {worst:e}, \
by line count {by_total:?}"
);
}
#[test]
fn the_disk_path_never_sees_five_or_six_lines() {
let mut rng = Lcg::new(0x0000_A002_6000_0003);
let mut seen_five_or_six = 0usize;
let mut checked = 0usize;
for _ in 0..400_000 {
let f = rng.corners();
let saddles = BodySaddles::of(&f);
if saddles.has_inner_hexagon() {
continue;
}
let lines: u32 = Pair::ALL.iter().map(|&q| saddles.line_count(q)).sum();
if lines >= 5 {
seen_five_or_six += 1;
}
checked += 1;
}
assert!(checked > 1000);
assert_eq!(
seen_five_or_six, 0,
"the disk path reached {seen_five_or_six} cells with five or six lines, \
which `interior_vertex` answers `None` to"
);
std::println!("measured: {checked} disk cells, none with five or six lines");
}
#[test]
fn the_fan_covers_each_ring_once_and_repeats_no_index() {
for case in 0..=255u8 {
for mask in 0..64u8 {
let contours = Contours::of(case, mask);
for interior in [false, true] {
let mut count = 0usize;
let mut used = [0u32; INTERIOR as usize + MAX_CONTOURS];
contours.fan(interior, |t| {
assert!(
t[0] != t[1] && t[1] != t[2] && t[0] != t[2],
"case {case:#010b} mask {mask:#08b}: degenerate triangle {t:?}"
);
for &c in &t {
used[c as usize] += 1;
}
count += 1;
});
assert_eq!(
count,
contours.triangle_count(interior),
"case {case:#010b} mask {mask:#08b}: triangle_count disagrees with fan"
);
for r in 0..contours.count() {
let ring = contours.ring(r);
for &e in ring {
assert!(used[e as usize] > 0, "edge {e} was never emitted");
}
let expected = if interior && ring.len() > 3 {
ring.len()
} else {
0
};
assert_eq!(
used[INTERIOR as usize + r] as usize,
expected,
"case {case:#010b} mask {mask:#08b}: ring {r} of {} used apex \
{} times, expected {expected}",
ring.len(),
used[INTERIOR as usize + r]
);
}
for slot in contours.count()..MAX_CONTOURS {
assert_eq!(
used[INTERIOR as usize + slot],
0,
"an apex was used for a ring that does not exist"
);
}
}
}
}
std::println!("measured: fan checked over 16,384 combinations, both interior modes");
}
#[test]
fn the_worst_case_triangle_count_is_pinned() {
let mut worst_plain = 0usize;
let mut worst_interior = 0usize;
for case in 0..=255u8 {
for mask in 0..64u8 {
let c = Contours::of(case, mask);
worst_plain = worst_plain.max(c.triangle_count(false));
worst_interior = worst_interior.max(c.triangle_count(true));
}
}
assert_eq!((worst_plain, worst_interior), (10, 12));
assert!(
worst_interior <= crate::marching_cubes::table::MAX_TRIANGLES,
"the fan exceeds MAX_TRIANGLES"
);
std::println!(
"measured: worst triangle count {worst_plain} without an interior vertex, \
{worst_interior} with one (MAX_TRIANGLES is {})",
crate::marching_cubes::table::MAX_TRIANGLES
);
}
fn tunnel_patch(f: &[f64; 8]) -> Option<(alloc::vec::Vec<[u8; 3]>, usize)> {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
return None;
}
let saddles = BodySaddles::of(f);
if !saddles.has_inner_hexagon() {
return None;
}
let contours = Contours::of(case, joined_mask(f, AMBIGUOUS_FACES[case as usize]));
let mut tris = alloc::vec::Vec::new();
let unresolved = contours.fan_tunnel(&saddles, f, |t| tris.push(t));
Some((tris, unresolved))
}
#[test]
fn the_tunnel_patch_is_manifold_inside_the_cell() {
let mut rng = Lcg::new(0x0000_A002_8000_0001);
let mut cells = 0usize;
let mut unresolved_total = 0usize;
let mut worst_tris = 0usize;
let mut worst_interior = 0usize;
for _ in 0..400_000 {
let f = rng.corners();
let Some((tris, unresolved)) = tunnel_patch(&f) else {
continue;
};
unresolved_total += unresolved;
worst_tris = worst_tris.max(tris.len());
let mut ring_edge = [[false; 20]; 20];
{
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
let contours = Contours::of(case, joined_mask(&f, AMBIGUOUS_FACES[case as usize]));
for r in 0..contours.count() {
let ring = contours.ring(r);
for k in 0..ring.len() {
let (a, b) = (ring[k] as usize, ring[(k + 1) % ring.len()] as usize);
ring_edge[a.min(b)][a.max(b)] = true;
}
}
}
let mut directed = [[0u32; 20]; 20];
let mut used = [[0u32; 20]; 20];
let mut interior_seen = [false; 20];
for t in &tris {
assert!(
t[0] != t[1] && t[1] != t[2] && t[0] != t[2],
"degenerate tunnel triangle {t:?}"
);
for &c in t {
if c >= INTERIOR {
interior_seen[c as usize] = true;
}
}
for k in 0..3 {
let (a, b) = (t[k] as usize, t[(k + 1) % 3] as usize);
directed[a][b] += 1;
used[a.min(b)][a.max(b)] += 1;
}
}
for (a, row) in directed.iter().enumerate() {
for (b, &count) in row.iter().enumerate() {
assert!(
count <= 1,
"directed edge ({a},{b}) traversed {count} times — the patch \
is not consistently wound"
);
}
}
worst_interior = worst_interior.max(interior_seen.iter().filter(|&&s| s).count());
for a in 0..20 {
for b in a..20 {
let n = used[a][b];
if n == 0 {
continue;
}
let want = if ring_edge[a][b] { 1 } else { 2 };
assert_eq!(
n, want,
"edge ({a},{b}) carries {n} faces, wanted {want} — the tunnel \
patch is not manifold inside the cell. corners {f:?}"
);
}
}
cells += 1;
}
assert!(cells > 500, "only {cells} tunnel cells were built");
assert_eq!(
unresolved_total, 0,
"{unresolved_total} ring edges spanned three hexagon steps, so the patches \
above were judged outside the construction's defined domain"
);
std::println!(
"measured: {cells} tunnel patches, all manifold inside the cell; \
worst {worst_tris} triangles and {worst_interior} interior vertices"
);
}
#[test]
fn tunnel_interior_vertices_are_hexagon_saddles() {
let mut rng = Lcg::new(0x0000_A002_8000_0002);
let mut checked = 0usize;
let mut worst: f64 = 0.0;
for _ in 0..200_000 {
let f = rng.corners();
let Some((tris, _)) = tunnel_patch(&f) else {
continue;
};
let hexagon = BodySaddles::of(&f)
.inner_hexagon()
.expect("a tunnel patch has a hexagon");
for t in &tris {
for &c in t {
if c >= INTERIOR {
let k = (c - INTERIOR) as usize;
assert!(k < MAX_INTERIOR_VERTICES, "interior code {c} out of range");
worst = worst.max(trilinear(&f, hexagon[k]).abs());
checked += 1;
}
}
}
}
assert!(checked > 1000);
assert!(
worst < 1e-9,
"a tunnel interior vertex is {worst:e} off the surface"
);
std::println!("measured: {checked} tunnel interior-vertex references, worst {worst:e} off");
}
#[test]
fn the_worst_case_tunnel_triangle_count_is_pinned() {
let mut rng = Lcg::new(0x0000_A002_8000_0003);
let mut worst_tris = 0usize;
let mut worst_interior = 0usize;
let mut cells = 0usize;
for _ in 0..400_000 {
let f = rng.corners();
let Some((tris, _)) = tunnel_patch(&f) else {
continue;
};
worst_tris = worst_tris.max(tris.len());
let mut seen = [false; 20];
for t in &tris {
for &c in t {
if c >= INTERIOR {
seen[c as usize] = true;
}
}
}
worst_interior = worst_interior.max(seen.iter().filter(|&&s| s).count());
cells += 1;
}
assert!(cells > 500);
assert_eq!(
(worst_tris, worst_interior),
(22, MAX_INTERIOR_VERTICES),
"the tunnel's worst case moved"
);
std::println!(
"measured: {cells} tunnels, worst {worst_tris} triangles and \
{worst_interior} interior vertices"
);
}
#[test]
fn how_often_a_face_is_singular() {
use crate::cube::{face_corners, is_inside as inside};
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let singular = |v: [f64; 4]| {
let corner = [v[0], v[1], v[2], v[3], v[0], v[1], v[2], v[3]];
super::singular_face_mask(&corner) & super::super::table::face_bit(2, 0) != 0
};
let mut ambiguous = 0u64;
let mut singular_count = 0u64;
crate::for_each_reference_field!(f64, |name, field| {
for samples in [17u32, 33, 65] {
let (lo, hi) = field.domain();
let h = (hi[0] - lo[0]) / f64::from(samples - 1);
let mut amb = 0u64;
let mut sing = 0u64;
for z in 0..samples - 1 {
for y in 0..samples - 1 {
for x in 0..samples - 1 {
let mut corner = [0.0f64; 8];
let mut case = 0u8;
for (c, slot) in corner.iter_mut().enumerate() {
let o = corner_offset(c as u8);
*slot = field.sample([
lo[0] + h * f64::from(x + o[0]),
lo[1] + h * f64::from(y + o[1]),
lo[2] + h * f64::from(z + o[2]),
]);
if inside(*slot) {
case |= 1 << c;
}
}
let mask = AMBIGUOUS_FACES[case as usize];
if mask == 0 {
continue;
}
for axis in 0..3usize {
for side in 0..2u8 {
let bit = 1u8 << (axis * 2 + side as usize);
if mask & bit == 0 {
continue;
}
let c = face_corners(axis, side);
let v = [
corner[c[0] as usize],
corner[c[1] as usize],
corner[c[2] as usize],
corner[c[3] as usize],
];
amb += 1;
if singular(v) {
sing += 1;
}
}
}
}
}
}
ambiguous += amb;
singular_count += sing;
if sing > 0 {
std::println!(" {name} at {samples}^3: {sing} singular of {amb} ambiguous faces");
}
}
});
std::println!(
"measured: {singular_count} singular of {ambiguous} ambiguous faces, fourteen fields"
);
let mut rng = Lcg::new(0x0000_A002_9000_0001);
let mut ramb = 0u64;
let mut rsing = 0u64;
for _ in 0..400_000 {
let f = rng.corners();
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
let mask = AMBIGUOUS_FACES[case as usize];
for axis in 0..3usize {
for side in 0..2u8 {
if mask & (1u8 << (axis * 2 + side as usize)) == 0 {
continue;
}
let c = face_corners(axis, side);
let v = [
f[c[0] as usize],
f[c[1] as usize],
f[c[2] as usize],
f[c[3] as usize],
];
ramb += 1;
if singular(v) {
rsing += 1;
}
}
}
}
std::println!("measured: {rsing} singular of {ramb} ambiguous faces, 400,000 random cells");
assert!(
ambiguous > 1000 && ramb > 100_000,
"the sweep reached {ambiguous} and {ramb} ambiguous faces, too few to mean anything"
);
assert_eq!(
(singular_count, rsing),
(72, 0),
"the singular-face census moved: R-187 pins 24 on graph_theta_g2 and 48 on \
graph_k4_g3 at 17^3, zero elsewhere, and zero on random cells"
);
}
#[test]
fn a_nine_and_three_cell_is_refused_before_triangulation() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let f = [-0.8f64, 0.8, 0.6, -0.8, 0.8, -0.8, -0.2, 0.7];
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
assert_eq!(case, 0b0110_1001, "the fixture is no longer case 13");
let saddles = BodySaddles::of(&f);
assert!(saddles.has_inner_hexagon());
let mask = joined_mask(&f, AMBIGUOUS_FACES[case as usize]);
let contours = Contours::of(case, mask);
let mut sizes: alloc::vec::Vec<usize> = (0..contours.count())
.map(|r| contours.ring(r).len())
.collect();
sizes.sort_unstable();
assert_eq!(
sizes,
alloc::vec![3, 9],
"the fixture no longer produces the nine-and-three shape Corollary 6 excludes"
);
assert_eq!(
contours.topology(&saddles),
Topology::SeparateDisks,
"the length bound no longer excludes the nine-and-three cell"
);
let mut tris = 0usize;
let unresolved = contours.fan_tunnel(&saddles, &f, |_| tris += 1);
assert_eq!(
unresolved, 2,
"the three-step count moved — the construction's gap has changed shape"
);
std::println!(
"measured: case 13 mask {mask:#08b} gives rings {sizes:?}; classified \
SeparateDisks. Under the old tunnel rule it would emit {tris} triangles and \
leave {unresolved} contour edges with no rule"
);
}
#[test]
fn a_nine_and_three_cell_is_not_one_connected_tunnel() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
for (label, f) in [
(
"[9,3] case 13",
[-0.8f64, 0.8, 0.6, -0.8, 0.8, -0.8, -0.2, 0.7],
),
(
"[9,3] case 13 b",
[-0.3, 0.2, 0.3, -0.4, 0.6, -0.5, -0.4, 1.0],
),
(
"[6,3] tunnel",
[-0.2, -0.9, 0.7, -0.3, 0.8, -0.4, -0.9, 0.6],
),
("[4,3] tunnel", [0.2, -0.6, 0.2, -0.2, 0.4, 0.1, -0.9, 1.0]),
] {
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
let saddles = BodySaddles::of(&f);
let contours = Contours::of(case, joined_mask(&f, AMBIGUOUS_FACES[case as usize]));
let sizes: alloc::vec::Vec<usize> = (0..contours.count())
.map(|r| contours.ring(r).len())
.collect();
let inside_count = f.iter().filter(|v| inside(**v)).count();
let parts = corner_groups(&f, 96);
let is_nine_and_three = sizes.contains(&9);
assert_eq!(
parts,
if is_nine_and_three { 2 } else { 1 },
"{label}: inside corners fall into {parts} components, which contradicts \
the classification this test exists to check"
);
assert_eq!(
contours.topology(&saddles),
if is_nine_and_three {
Topology::SeparateDisks
} else {
Topology::Tunnel
},
"{label}"
);
std::println!(
"measured: {label:<16} case {case:#010b} rings {sizes:?} | inside corners \
{inside_count} in {parts} component(s)"
);
}
}
#[test]
fn the_asymptote_side_predicate_is_corollary_1() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let mut rng = Lcg::new(0x0000_A020_F000_0001);
let mut same = 0usize;
let mut opposite = 0usize;
let mut disagreements = 0usize;
for _ in 0..400_000 {
let f = rng.corners();
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
let saddles = BodySaddles::of(&f);
if !saddles.has_inner_hexagon() {
continue;
}
let predicate = saddles.same_asymptote_side(&f);
let contours = Contours::of(case, joined_mask(&f, AMBIGUOUS_FACES[case as usize]));
if predicate == (contours.count() == 1) {
disagreements += 1;
}
if predicate {
same += 1;
} else {
opposite += 1;
}
}
assert_eq!(
disagreements, 0,
"the derived predicate and the contour count disagree, so one of them is wrong"
);
assert!(same > 0, "no same-side cell was reached");
assert!(opposite > 0, "no opposite-side cell was reached");
std::println!(
"measured: {same} same-side and {opposite} opposite-side six-saddle cells, \
0 disagreements with Corollary 1"
);
}
#[test]
fn corollary_6s_length_bound_agrees_with_the_flood_fill() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
const GRID: usize = 48;
const CELLS: usize = 150;
let mut rng = Lcg::new(0x0000_A020_F000_0002);
let mut tunnels = 0usize;
let mut seen = 0usize;
let mut disagreements = alloc::vec::Vec::new();
while seen < CELLS {
let f = rng.corners();
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
let saddles = BodySaddles::of(&f);
if !saddles.has_inner_hexagon() {
continue;
}
let contours = Contours::of(case, joined_mask(&f, AMBIGUOUS_FACES[case as usize]));
if contours.count() != 2 {
continue;
}
seen += 1;
let is_tunnel = contours.topology(&saddles) == Topology::Tunnel;
if is_tunnel {
tunnels += 1;
}
if is_tunnel != (corner_groups(&f, GRID) == 1) {
disagreements.push(f);
}
}
assert!(
disagreements.is_empty(),
"the classifier and the {GRID}^3 flood fill disagree on {} of {seen} two-contour \
six-saddle cells; first is {:?}",
disagreements.len(),
disagreements.first()
);
assert_eq!(
tunnels, seen,
"the random sweep is expected to reach only genuine tunnels here; the \
nine-and-three shape is found by search, not by sampling"
);
std::println!(
"measured: {seen} two-contour six-saddle cells, all classified tunnels, \
0 disagreements with the {GRID}^3 flood fill"
);
}
#[test]
fn the_tunnel_contour_shapes_are_pinned() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
let mut rng = Lcg::new(0x0000_A002_F000_0001);
let mut shapes: alloc::collections::BTreeMap<alloc::vec::Vec<usize>, usize> =
alloc::collections::BTreeMap::new();
for _ in 0..400_000 {
let f = rng.corners();
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
continue;
}
let saddles = BodySaddles::of(&f);
let contours = Contours::of(case, joined_mask(&f, AMBIGUOUS_FACES[case as usize]));
if contours.topology(&saddles) != Topology::Tunnel {
continue;
}
let mut sizes: alloc::vec::Vec<usize> = (0..contours.count())
.map(|r| contours.ring(r).len())
.collect();
sizes.sort_unstable();
*shapes.entry(sizes).or_insert(0) += 1;
}
for (sizes, n) in &shapes {
std::println!("measured: tunnel contours {sizes:?} x{n}");
assert!(
sizes.iter().all(|&s| s <= super::MAX_TUNNEL_CONTOUR),
"a tunnel with a contour past Corollary 6's bound reached the census"
);
}
assert!(
shapes.keys().any(|s| !s.contains(&3)),
"no tunnel without a three-vertex contour was reached, so the falsification \
of Corollary 6's second half is untested"
);
}
#[test]
fn every_separate_disks_cell_has_a_saddle_on_a_face() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::ambiguity::joined_mask;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
const ON_FACE: f64 = 1e-12;
const CELLS: usize = 500_000;
let classify = |f: &[f64; 8]| {
let mut case = 0u8;
for (c, &val) in f.iter().enumerate() {
if inside(val) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
return None;
}
let saddles = BodySaddles::of(f);
if !saddles.has_inner_hexagon() {
return None;
}
let contours = Contours::of(case, joined_mask(f, AMBIGUOUS_FACES[case as usize]));
Some((saddles, contours.topology(&saddles)))
};
let on_face = |saddles: &BodySaddles<f64>| {
(0..3).any(|axis| saddles.axis(axis).iter().any(|&x| x.min(1.0 - x) < ON_FACE))
};
let mut rng = Lcg::new(0x0000_A020_B000_0003);
let mut six = 0usize;
let mut separate = 0usize;
for _ in 0..CELLS {
let f = rng.corners();
if let Some((_, topology)) = classify(&f) {
six += 1;
if topology == Topology::SeparateDisks {
separate += 1;
}
}
}
assert!(
six > 1000,
"only {six} six-saddle cells, too few to mean anything"
);
assert_eq!(
separate, 0,
"a separate-disks cell appeared without quantisation — A-020b's premise is \
back in scope and the singular-face explanation is not the whole story"
);
std::println!(
"measured: {six} six-saddle cells from continuous values, {separate} separate-disks"
);
for (label, quantum) in [("0.1", 0.1f64), ("1/3", 1.0 / 3.0)] {
let mut rng = Lcg::new(0x0000_A020_B000_0003);
let mut found = 0usize;
let mut degenerate = 0usize;
for _ in 0..CELLS {
let mut f = rng.corners();
for x in &mut f {
*x = (*x / quantum).round() * quantum;
}
if let Some((saddles, topology)) = classify(&f)
&& topology == Topology::SeparateDisks
{
found += 1;
if on_face(&saddles) {
degenerate += 1;
}
}
}
assert!(
found > 0,
"quantum {label} produced no separate-disks cell, so this asserted nothing"
);
assert_eq!(
found,
degenerate,
"quantum {label}: {} of {found} separate-disks cells have no saddle on a face, \
so the singular-face explanation does not cover them",
found - degenerate
);
std::println!(
"measured: quantum {label} gives {found} separate-disks cells, all {degenerate} \
with a saddle on a cell face"
);
}
}
#[test]
fn a_singular_face_needs_quantised_data() {
use crate::cube::is_inside as inside;
use crate::marching_cubes::table::AMBIGUOUS_FACES;
const CELLS: usize = 400_000;
let ambiguous_singular = |f: &[f64; 8]| -> u32 {
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if inside(v) {
case |= 1 << c;
}
}
if case == 0 || case == 255 {
return 0;
}
(super::singular_face_mask(f) & AMBIGUOUS_FACES[case as usize]).count_ones()
};
let mut rng = Lcg::new(0x0000_A002_1000_0001);
let mut continuous = 0u32;
for _ in 0..CELLS {
continuous += ambiguous_singular(&rng.corners());
}
assert_eq!(
continuous, 0,
"a continuous f64 sweep produced {continuous} singular ambiguous faces — \
A-002i's premise that this needs quantisation has changed"
);
for (label, quantum) in [("0.1", 0.1f64), ("1/255 (u8 density)", 1.0 / 255.0)] {
let mut rng = Lcg::new(0x0000_A002_1000_0001);
let mut found = 0u32;
for _ in 0..CELLS {
let mut f = rng.corners();
for x in &mut f {
*x = (*x / quantum).round() * quantum;
}
found += ambiguous_singular(&f);
}
assert!(
found > 0,
"quantum {label} produced no singular ambiguous face, so this asserted nothing"
);
std::println!(
"measured: quantum {label} gives {found} singular ambiguous faces in {CELLS} cells"
);
}
std::println!("measured: continuous f64 gives {continuous} in {CELLS} cells");
}
#[test]
fn a_face_has_only_two_routings_so_a_singular_face_has_nowhere_to_go() {
use crate::marching_cubes::table::{AMBIGUOUS_FACES, NO_EDGE, face_bit, segment_links};
let mut checked = 0usize;
for case in 0..=255u8 {
let ambiguous = AMBIGUOUS_FACES[case as usize];
if ambiguous == 0 {
continue;
}
for axis in 0..3usize {
for side in 0..2u8 {
let bit = face_bit(axis, side);
if ambiguous & bit == 0 {
continue;
}
for joined in [0u8, bit] {
let next = segment_links(case, joined);
let mut seen = [0u8; 12];
for &to in next.iter() {
if to != NO_EDGE {
seen[to as usize] += 1;
}
}
assert!(
seen.iter().all(|&n| n <= 1),
"case {case:#010b} face ({axis},{side}) joined {joined:#08b}: an edge \
has more than one predecessor, so a junction is representable after all"
);
checked += 1;
}
}
}
}
assert_eq!(checked, 384, "the ambiguous-face inventory moved");
std::println!(
"measured: {checked} (case, ambiguous face, bit) routings, every one a permutation \
of cut edges — no face junction is representable"
);
}
#[test]
fn the_interpolant_is_zero_at_every_body_saddle() {
fn trilinear(f: &[f64; 8], p: [f64; 3]) -> f64 {
let (u, v, w) = (p[0], p[1], p[2]);
let (su, sv, sw) = (1.0 - u, 1.0 - v, 1.0 - w);
f[0] * su * sv * sw
+ f[1] * u * sv * sw
+ f[2] * su * v * sw
+ f[3] * u * v * sw
+ f[4] * su * sv * w
+ f[5] * u * sv * w
+ f[6] * su * v * w
+ f[7] * u * v * w
}
let mut rng = Lcg::new(0x0000_A023_D000_0001);
let mut worst: f64 = 0.0;
let mut checked = 0usize;
for _ in 0..200_000 {
let f = rng.corners();
let saddles = BodySaddles::of(&f);
if !saddles.has_inner_hexagon() {
continue;
}
let (u, v, w) = (saddles.axis(0), saddles.axis(1), saddles.axis(2));
for k in 0..2 {
worst = worst.max(trilinear(&f, [u[k], v[k], w[k]]).abs());
checked += 1;
}
}
assert!(
checked > 1000,
"only {checked} saddles reached the check, which measures nothing"
);
assert!(
worst < 1e-9,
"F is {worst:.3e} at a body saddle, so these are not points on the level \
set and P-24's premise would be recoverable after all"
);
}
#[test]
fn the_case_13_cell_that_overflowed_the_patch_array_is_pinned() {
let f = [
0.519_630_416_140_653_5,
-0.323_561_278_230_897_53,
-0.392_376_979_817_058_44,
0.397_562_315_679_148_46,
-1.235_061_219_941_051_6,
0.851_518_039_009_829_8,
1.191_076_954_409_544_5,
-1.212_636_051_833_211_8,
];
let mut case = 0u8;
for (c, &v) in f.iter().enumerate() {
if crate::cube::is_inside(v) {
case |= 1 << c;
}
}
assert_eq!(
case, 0x96,
"the fixture is the case-13 configuration it names"
);
let (tris, unresolved) = tunnel_patch(&f).expect("this cell has an inner hexagon");
assert_eq!(unresolved, 0, "the patch resolves");
assert!(
tris.len() > 24,
"the fixture no longer exceeds the old sampled bound of 24, so it no \
longer pins anything: it emitted {}",
tris.len()
);
assert_eq!(
tris.len(),
26,
"the overflow fixture's triangle count moved"
);
assert!(
tris.len() <= super::MAX_PATCH_TRIANGLES,
"the derived bound must cover the case that broke the sampled one"
);
}