use super::*;
use std::collections::HashSet;
macro_rules! exhaustive_test {
($name:ident, $parent_resolution:literal, $child_resolution:literal) => {
#[test]
fn $name() {
let parent_resolution =
Resolution::try_from($parent_resolution).unwrap();
let child_resolution =
Resolution::try_from($parent_resolution).unwrap();
for index in CellIndex::base_cells()
.flat_map(|index| index.children(parent_resolution))
{
assert_iterator_properties(index, child_resolution);
}
}
};
}
exhaustive_test!(exhaustive_res0_to_0, 0, 0);
exhaustive_test!(exhaustive_res0_to_1, 0, 1);
exhaustive_test!(exhaustive_res0_to_2, 0, 2);
exhaustive_test!(exhaustive_res0_to_3, 0, 3);
exhaustive_test!(exhaustive_res0_to_4, 0, 4);
exhaustive_test!(exhaustive_res1_to_1, 1, 1);
exhaustive_test!(exhaustive_res1_to_2, 1, 2);
exhaustive_test!(exhaustive_res1_to_3, 1, 3);
exhaustive_test!(exhaustive_res1_to_4, 1, 4);
exhaustive_test!(exhaustive_res2_to_2, 2, 2);
exhaustive_test!(exhaustive_res2_to_3, 2, 3);
exhaustive_test!(exhaustive_res2_to_4, 2, 4);
exhaustive_test!(exhaustive_res3_to_3, 3, 3);
exhaustive_test!(exhaustive_res3_to_4, 3, 4);
exhaustive_test!(exhaustive_res4_to_4, 4, 4);
#[test]
fn finer_resolution() {
let cells = [
0x8508000ffffffff, 0x85080003fffffff, 0x8808000009fffff, 0x8808000001fffff, 0x8a0800000017fff, 0x8a0800000007fff, 0x8e754e64992d6c7, 0x8e0800000000007, 0x8f754e64992d6d8, 0x8f0800000000000, ]
.iter()
.copied()
.map(|value| CellIndex::try_from(value).unwrap())
.collect::<Vec<_>>();
for cell in cells {
let parent_resolution = u8::from(cell.resolution());
for gap in 0..=5 {
if let Ok(children_resolution) =
Resolution::try_from(parent_resolution + gap)
{
assert_iterator_properties(cell, children_resolution);
}
}
}
}
#[test]
fn child_smaller_than_parent() {
let cell = CellIndex::try_from(0x820887fffffffff).unwrap();
assert!(Gosper::new(cell, Resolution::One).next().is_none());
}
#[test]
fn hexagon_2_to_2() {
let cell = CellIndex::try_from(0x820887fffffffff).unwrap();
let expected = [
0x1320887fffffffff,
0x1120887fffffffff,
0x1520887fffffffff,
0x1420887fffffffff,
0x1620887fffffffff,
0x1220887fffffffff,
]
.iter()
.copied()
.map(|value| DirectedEdgeIndex::try_from(value).unwrap())
.collect::<Vec<_>>();
assert_edges(cell, Resolution::Two, &expected);
}
#[test]
fn pentagon_2_to_2() {
let cell = CellIndex::try_from(0x820807fffffffff).unwrap();
let expected = [
0x1320807fffffffff,
0x1520807fffffffff,
0x1420807fffffffff,
0x1620807fffffffff,
0x1220807fffffffff,
]
.iter()
.copied()
.map(|value| DirectedEdgeIndex::try_from(value).unwrap())
.collect::<Vec<_>>();
assert_edges(cell, Resolution::Two, &expected);
}
#[test]
fn hexagon_2_to_4() {
let cell = CellIndex::try_from(0x82c64ffffffffff).unwrap();
#[rustfmt::skip]
let expected = [
0x134c6497ffffffff, 0x114c6497ffffffff, 0x134c6493ffffffff,
0x114c6493ffffffff, 0x154c6493ffffffff, 0x114c649bffffffff,
0x154c649bffffffff, 0x144c649bffffffff, 0x154c6499ffffffff,
0x114c64d3ffffffff, 0x154c64d3ffffffff, 0x114c64dbffffffff,
0x154c64dbffffffff, 0x144c64dbffffffff, 0x154c64d9ffffffff,
0x144c64d9ffffffff, 0x164c64d9ffffffff, 0x144c64ddffffffff,
0x154c64cbffffffff, 0x144c64cbffffffff, 0x154c64c9ffffffff,
0x144c64c9ffffffff, 0x164c64c9ffffffff, 0x144c64cdffffffff,
0x164c64cdffffffff, 0x124c64cdffffffff, 0x164c64c5ffffffff,
0x144c64e9ffffffff, 0x164c64e9ffffffff, 0x144c64edffffffff,
0x164c64edffffffff, 0x124c64edffffffff, 0x164c64e5ffffffff,
0x124c64e5ffffffff, 0x134c64e5ffffffff, 0x124c64e7ffffffff,
0x164c64adffffffff, 0x124c64adffffffff, 0x164c64a5ffffffff,
0x124c64a5ffffffff, 0x134c64a5ffffffff, 0x124c64a7ffffffff,
0x134c64a7ffffffff, 0x114c64a7ffffffff, 0x134c64a3ffffffff,
0x124c64b5ffffffff, 0x134c64b5ffffffff, 0x124c64b7ffffffff,
0x134c64b7ffffffff, 0x114c64b7ffffffff, 0x134c64b3ffffffff,
0x114c64b3ffffffff, 0x154c64b3ffffffff, 0x114c64bbffffffff,
]
.iter()
.copied()
.map(|value| DirectedEdgeIndex::try_from(value).unwrap())
.collect::<HashSet<_>>();
let result = Gosper::new(cell, Resolution::Four).collect::<HashSet<_>>();
assert_eq!(result, expected);
}
#[test]
fn pentagon_2_to_4() {
let cell = CellIndex::try_from(0x820807fffffffff).unwrap();
#[rustfmt::skip]
let expected = [
0x11408053ffffffff, 0x15408053ffffffff, 0x1140805bffffffff,
0x1540805bffffffff, 0x1440805bffffffff, 0x15408059ffffffff,
0x14408059ffffffff, 0x16408059ffffffff, 0x1440805dffffffff,
0x1540804bffffffff, 0x1440804bffffffff, 0x15408049ffffffff,
0x14408049ffffffff, 0x16408049ffffffff, 0x1440804dffffffff,
0x1640804dffffffff, 0x1240804dffffffff, 0x16408045ffffffff,
0x14408069ffffffff, 0x16408069ffffffff, 0x1440806dffffffff,
0x1640806dffffffff, 0x1240806dffffffff, 0x16408065ffffffff,
0x12408065ffffffff, 0x13408065ffffffff, 0x12408067ffffffff,
0x1640802dffffffff, 0x1240802dffffffff, 0x16408025ffffffff,
0x12408025ffffffff, 0x13408025ffffffff, 0x12408027ffffffff,
0x13408027ffffffff, 0x11408027ffffffff, 0x13408023ffffffff,
0x12408035ffffffff, 0x13408035ffffffff, 0x12408037ffffffff,
0x13408037ffffffff, 0x11408037ffffffff, 0x13408033ffffffff,
0x11408033ffffffff, 0x15408033ffffffff, 0x1140803bffffffff,
]
.iter()
.copied()
.map(|value| DirectedEdgeIndex::try_from(value).unwrap())
.collect::<HashSet<_>>();
let result = Gosper::new(cell, Resolution::Four).collect::<HashSet<_>>();
assert_eq!(result, expected);
}
#[test]
fn hexagon_1_to_3() {
let cell = CellIndex::try_from(0x81c67ffffffffff).unwrap();
#[rustfmt::skip]
let expected = [
0x133c64afffffffff, 0x123c64bfffffffff, 0x133c64bfffffffff,
0x113c64bfffffffff, 0x133c649fffffffff, 0x113c649fffffffff,
0x153c649fffffffff, 0x113c64dfffffffff, 0x153c64dfffffffff,
0x113c66bfffffffff, 0x133c669fffffffff, 0x113c669fffffffff,
0x153c669fffffffff, 0x113c66dfffffffff, 0x153c66dfffffffff,
0x143c66dfffffffff, 0x153c66cfffffffff, 0x143c66cfffffffff,
0x153c661fffffffff, 0x113c665fffffffff, 0x153c665fffffffff,
0x143c665fffffffff, 0x153c664fffffffff, 0x143c664fffffffff,
0x163c664fffffffff, 0x143c666fffffffff, 0x163c666fffffffff,
0x143c675fffffffff, 0x153c674fffffffff, 0x143c674fffffffff,
0x163c674fffffffff, 0x143c676fffffffff, 0x163c676fffffffff,
0x123c676fffffffff, 0x163c672fffffffff, 0x123c672fffffffff,
0x163c654fffffffff, 0x143c656fffffffff, 0x163c656fffffffff,
0x123c656fffffffff, 0x163c652fffffffff, 0x123c652fffffffff,
0x133c652fffffffff, 0x123c653fffffffff, 0x133c653fffffffff,
0x123c65efffffffff, 0x163c65afffffffff, 0x123c65afffffffff,
0x133c65afffffffff, 0x123c65bfffffffff, 0x133c65bfffffffff,
0x113c65bfffffffff, 0x133c659fffffffff, 0x113c659fffffffff,
]
.iter()
.copied()
.map(|value| DirectedEdgeIndex::try_from(value).unwrap())
.collect::<HashSet<_>>();
let result = Gosper::new(cell, Resolution::Three).collect::<HashSet<_>>();
assert_eq!(result, expected);
}
#[test]
fn pentagon_1_to_3() {
let cell = CellIndex::try_from(0x81083ffffffffff).unwrap();
#[rustfmt::skip]
let expected = [
0x113082bfffffffff, 0x1330829fffffffff, 0x1130829fffffffff,
0x1530829fffffffff, 0x113082dfffffffff, 0x153082dfffffffff,
0x143082dfffffffff, 0x153082cfffffffff, 0x143082cfffffffff,
0x1530821fffffffff, 0x1130825fffffffff, 0x1530825fffffffff,
0x1430825fffffffff, 0x1530824fffffffff, 0x1430824fffffffff,
0x1630824fffffffff, 0x1430826fffffffff, 0x1630826fffffffff,
0x1430835fffffffff, 0x1530834fffffffff, 0x1430834fffffffff,
0x1630834fffffffff, 0x1430836fffffffff, 0x1630836fffffffff,
0x1230836fffffffff, 0x1630832fffffffff, 0x1230832fffffffff,
0x1630814fffffffff, 0x1430816fffffffff, 0x1630816fffffffff,
0x1230816fffffffff, 0x1630812fffffffff, 0x1230812fffffffff,
0x1330812fffffffff, 0x1230813fffffffff, 0x1330813fffffffff,
0x123081efffffffff, 0x163081afffffffff, 0x123081afffffffff,
0x133081afffffffff, 0x123081bfffffffff, 0x133081bfffffffff,
0x113081bfffffffff, 0x1330819fffffffff, 0x1130819fffffffff,
]
.iter()
.copied()
.map(|value| DirectedEdgeIndex::try_from(value).unwrap())
.collect::<HashSet<_>>();
let result = Gosper::new(cell, Resolution::Three).collect::<HashSet<_>>();
assert_eq!(result, expected);
}
fn assert_iterator_properties(index: CellIndex, child_resolution: Resolution) {
let parent_resolution = index.resolution();
let delta = u8::from(child_resolution) - u8::from(parent_resolution);
let nb_sides = if index.is_pentagon() { 5 } else { 6 };
let expected_count = nb_sides * 3_usize.pow(delta.into());
let mut iter = Gosper::new(index, child_resolution);
let mut edges = HashSet::with_capacity(expected_count);
let first = iter.clone().next().unwrap();
let mut prev = None;
for edge in &mut iter {
assert!(edges.insert(edge));
assert_eq!(edge.origin().resolution(), child_resolution);
let origin = edge.origin();
let destination = edge.destination();
let parent_origin = origin.parent(parent_resolution).unwrap();
let parent_destination = destination.parent(parent_resolution).unwrap();
assert_eq!(parent_origin, index, "origin *is* a child of parent cell");
assert_ne!(
parent_destination, index,
"destination *is not* a child of parent cell"
);
if let Some(prev) = prev {
assert_edge_connect(prev, edge);
}
prev = Some(edge);
}
assert_edge_connect(prev.unwrap(), first);
assert_eq!(edges.len(), expected_count, "incorrect number of edges");
for _ in 0..100 {
assert!(iter.next().is_none());
}
}
fn assert_edge_connect(edge_a: DirectedEdgeIndex, edge_b: DirectedEdgeIndex) {
let len_a = edge_a.length_rads();
let len_b = edge_b.length_rads();
let tolerance = len_a.min(len_b) / 1000.0;
let end_a = edge_a.boundary().last().copied().unwrap();
let start_b = edge_b.boundary().first().copied().unwrap();
let distance = end_a.distance_rads(start_b);
assert!(distance < tolerance);
}
fn assert_edges(
index: CellIndex,
resolution: Resolution,
expected: &[DirectedEdgeIndex],
) {
let mut result = Gosper::new(index, resolution).collect::<Vec<_>>();
assert_eq!(result.len(), expected.len(), "wrong number of edges");
let Some(first) = expected.first() else {
return;
};
let offset = result
.iter()
.position(|edge| edge == first)
.expect("first edge not found");
result.rotate_left(offset);
assert_eq!(result, expected, "edges mismatch");
}