Skip to content

Commit

Permalink
Use .iter_mut().enumerate() directly rather than indices
Browse files Browse the repository at this point in the history
  • Loading branch information
inthar-raven committed Apr 24, 2024
1 parent 0f74dc9 commit 5bd9579
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 70 deletions.
17 changes: 8 additions & 9 deletions common/src/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ impl Cursor {
// in both the dodecahedron sharing the face unique to the new vertex and that sharing the
// face that the new vertex isn't incident to.
let (a, b, c) = (self.a, self.b, self.c);
let a_prime = NEIGHBORS()[a as usize][b as usize][c as usize].unwrap();
let b_prime = NEIGHBORS()[b as usize][a as usize][c as usize].unwrap();
let c_prime = NEIGHBORS()[c as usize][b as usize][a as usize].unwrap();
let a_prime = neighbors_static()[a as usize][b as usize][c as usize].unwrap();
let b_prime = neighbors_static()[b as usize][a as usize][c as usize].unwrap();
let c_prime = neighbors_static()[c as usize][b as usize][a as usize].unwrap();
use Dir::*;
let (sides, neighbor) = match dir {
Left => ((a, b, c_prime), c),
Expand Down Expand Up @@ -103,10 +103,9 @@ impl std::ops::Neg for Dir {
}

/// Maps every (A, B, C) sharing a vertex to A', the side that shares edges with B and C but not A
fn NEIGHBORS() -> &'static [[[Option<Side>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT] {
static NEIGHBORS: OnceLock<[[[Option<Side>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT]> =
OnceLock::new();
NEIGHBORS.get_or_init(|| {
fn neighbors_static() -> &'static [[[Option<Side>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT] {
static LOCK: OnceLock<[[[Option<Side>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let mut result = [[[None; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT];
for a in Side::iter() {
for b in Side::iter() {
Expand Down Expand Up @@ -141,8 +140,8 @@ mod tests {
for v in Vertex::iter() {
let [a, b, c] = v.canonical_sides();
assert_eq!(
NEIGHBORS()[a as usize][b as usize][c as usize],
NEIGHBORS()[a as usize][c as usize][b as usize]
neighbors_static()[a as usize][b as usize][c as usize],
neighbors_static()[a as usize][c as usize][b as usize]
);
}
}
Expand Down
126 changes: 65 additions & 61 deletions common/src/dodeca.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,31 +40,31 @@ impl Side {
/// `false` when `self == other`.
#[inline]
pub fn adjacent_to(self, other: Side) -> bool {
ADJACENT()[self as usize][other as usize]
adjacent_static()[self as usize][other as usize]
}

/// Outward normal vector of this side
#[inline]
pub fn normal(self) -> &'static na::Vector4<f32> {
&SIDE_NORMALS_F32()[self as usize]
&side_normals_f32_static()[self as usize]
}

/// Outward normal vector of this side
#[inline]
pub fn normal_f64(self) -> &'static na::Vector4<f64> {
&SIDE_NORMALS_F64()[self as usize]
&side_normals_f64_static()[self as usize]
}

/// Reflection across this side
#[inline]
pub fn reflection(self) -> &'static na::Matrix4<f32> {
&REFLECTIONS_F32()[self as usize]
&reflections_f32_static()[self as usize]
}

/// Reflection across this side
#[inline]
pub fn reflection_f64(self) -> &'static na::Matrix4<f64> {
&REFLECTIONS_F64()[self as usize]
&reflections_f64_static()[self as usize]
}

/// Whether `p` is opposite the dodecahedron across the plane containing `self`
Expand Down Expand Up @@ -111,19 +111,19 @@ impl Vertex {
/// Vertex shared by three sides, if any
#[inline]
pub fn from_sides(a: Side, b: Side, c: Side) -> Option<Self> {
SIDES_TO_VERTEX()[a as usize][b as usize][c as usize]
sides_to_vertex_static()[a as usize][b as usize][c as usize]
}

/// Sides incident to this vertex, in canonical order
#[inline]
pub fn canonical_sides(self) -> [Side; 3] {
VERTEX_SIDES()[self as usize]
vertex_sides_static()[self as usize]
}

/// Vertices adjacent to this vertex, opposite the sides in canonical order
#[inline]
pub fn adjacent_vertices(self) -> [Vertex; 3] {
ADJACENT_VERTICES()[self as usize]
adjacent_vertices_static()[self as usize]
}

/// For each vertex of the cube dual to this dodecahedral vertex, provides an iterator of at
Expand Down Expand Up @@ -171,55 +171,55 @@ impl Vertex {

/// Transform from cube-centric coordinates to dodeca-centric coordinates
pub fn dual_to_node(self) -> &'static na::Matrix4<f32> {
&DUAL_TO_NODE_F32()[self as usize]
&dual_to_node_f32_static()[self as usize]
}

/// Transform from cube-centric coordinates to dodeca-centric coordinates
pub fn dual_to_node_f64(self) -> &'static na::Matrix4<f64> {
&DUAL_TO_NODE_F64()[self as usize]
&dual_to_node_f64_static()[self as usize]
}

/// Transform from dodeca-centric coordinates to cube-centric coordinates
pub fn node_to_dual(self) -> &'static na::Matrix4<f32> {
&NODE_TO_DUAL_F32()[self as usize]
&node_to_dual_f32_static()[self as usize]
}

/// Transform from dodeca-centric coordinates to cube-centric coordinates
pub fn node_to_dual_f64(self) -> &'static na::Matrix4<f64> {
&NODE_TO_DUAL_F64()[self as usize]
&node_to_dual_f64_static()[self as usize]
}

/// Scale factor used in conversion from cube-centric coordinates to euclidean chunk coordinates.
/// Scaling the x, y, and z components of a vector in cube-centric coordinates by this value
/// and dividing them by the w coordinate will yield euclidean chunk coordinates.
pub fn dual_to_chunk_factor() -> f32 {
*DUAL_TO_CHUNK_FACTOR_F32()
*dual_to_chunk_factor_f32_static()
}

/// Scale factor used in conversion from cube-centric coordinates to euclidean chunk coordinates.
/// Scaling the x, y, and z components of a vector in cube-centric coordinates by this value
/// and dividing them by the w coordinate will yield euclidean chunk coordinates.
pub fn dual_to_chunk_factor_f64() -> f64 {
*DUAL_TO_CHUNK_FACTOR_F64()
*dual_to_chunk_factor_f64_static()
}

/// Scale factor used in conversion from euclidean chunk coordinates to cube-centric coordinates.
/// Scaling the x, y, and z components of a vector in homogeneous euclidean chunk coordinates by this value
/// and lorentz-normalizing the result will yield cube-centric coordinates.
pub fn chunk_to_dual_factor() -> f32 {
*CHUNK_TO_DUAL_FACTOR_F32()
*chunk_to_dual_factor_f32_static()
}

/// Scale factor used in conversion from euclidean chunk coordinates to cube-centric coordinates.
/// Scaling the x, y, and z components of a vector in homogeneous euclidean chunk coordinates by this value
/// and lorentz-normalizing the result will yield cube-centric coordinates.
pub fn chunk_to_dual_factor_f64() -> f64 {
*CHUNK_TO_DUAL_FACTOR_F64()
*chunk_to_dual_factor_f64_static()
}

/// Convenience method for `self.chunk_to_node().determinant() < 0`.
pub fn parity(self) -> bool {
CHUNK_TO_NODE_PARITY()[self as usize]
chunk_to_node_parity_static()[self as usize]
}
}

Expand All @@ -229,24 +229,25 @@ pub const BOUNDING_SPHERE_RADIUS_F64: f64 = 1.2264568712514068;
pub const BOUNDING_SPHERE_RADIUS: f32 = BOUNDING_SPHERE_RADIUS_F64 as f32;

/// Whether two sides share an edge
fn ADJACENT() -> &'static [[bool; SIDE_COUNT]; SIDE_COUNT] {
fn adjacent_static() -> &'static [[bool; SIDE_COUNT]; SIDE_COUNT] {
static LOCK: OnceLock<[[bool; SIDE_COUNT]; SIDE_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let mut result = [[false; SIDE_COUNT]; SIDE_COUNT];
for i in 0..SIDE_COUNT {
for j in 0..SIDE_COUNT {
let cosh_distance = (REFLECTIONS_F64()[i] * REFLECTIONS_F64()[j])[(3, 3)];
for (i, triple) in result.iter_mut().enumerate().take(SIDE_COUNT) {
for (j, is_adjacent) in triple.iter_mut().enumerate().take(SIDE_COUNT) {
let cosh_distance =
(reflections_f64_static()[i] * reflections_f64_static()[j])[(3, 3)];
// Possile cosh_distances: 1, 4.23606 = 2+sqrt(5), 9.47213 = 5+2*sqrt(5), 12.70820 = 6+3*sqrt(5);
// < 2.0 indicates identical faces; < 5.0 indicates adjacent faces; > 5.0 indicates non-adjacent faces
result[i][j] = (2.0..5.0).contains(&cosh_distance);
*is_adjacent = (2.0..5.0).contains(&cosh_distance);
}
}
result
})
}

/// Vector corresponding to the outer normal of each side
fn SIDE_NORMALS_F64() -> &'static [na::Vector4<f64>; SIDE_COUNT] {
fn side_normals_f64_static() -> &'static [na::Vector4<f64>; SIDE_COUNT] {
static LOCK: OnceLock<[na::Vector4<f64>; SIDE_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let phi = libm::sqrt(1.25) + 0.5; // golden ratio
Expand All @@ -270,13 +271,13 @@ fn SIDE_NORMALS_F64() -> &'static [na::Vector4<f64>; SIDE_COUNT] {
}

/// Transform that moves from a neighbor to a reference node, for each side
fn REFLECTIONS_F64() -> &'static [na::Matrix4<f64>; SIDE_COUNT] {
fn reflections_f64_static() -> &'static [na::Matrix4<f64>; SIDE_COUNT] {
static LOCK: OnceLock<[na::Matrix4<f64>; SIDE_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| SIDE_NORMALS_F64().map(|r| math::reflect(&r)))
LOCK.get_or_init(|| side_normals_f64_static().map(|r| math::reflect(&r)))
}

/// Sides incident to a vertex, in canonical order
fn VERTEX_SIDES() -> &'static [[Side; 3]; VERTEX_COUNT] {
fn vertex_sides_static() -> &'static [[Side; 3]; VERTEX_COUNT] {
static LOCK: OnceLock<[[Side; 3]; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let mut result = [[Side::A; 3]; VERTEX_COUNT];
Expand All @@ -285,7 +286,10 @@ fn VERTEX_SIDES() -> &'static [[Side; 3]; VERTEX_COUNT] {
for a in 0..SIDE_COUNT {
for b in (a + 1)..SIDE_COUNT {
for c in (b + 1)..SIDE_COUNT {
if !ADJACENT()[a][b] || !ADJACENT()[b][c] || !ADJACENT()[c][a] {
if !adjacent_static()[a][b]
|| !adjacent_static()[b][c]
|| !adjacent_static()[c][a]
{
continue;
}
result[vertex] = [
Expand All @@ -303,25 +307,25 @@ fn VERTEX_SIDES() -> &'static [[Side; 3]; VERTEX_COUNT] {
}

// Which vertices are adjacent to other vertices and opposite the canonical sides
fn ADJACENT_VERTICES() -> &'static [[Vertex; 3]; VERTEX_COUNT] {
fn adjacent_vertices_static() -> &'static [[Vertex; 3]; VERTEX_COUNT] {
static LOCK: OnceLock<[[Vertex; 3]; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let mut result = [[Vertex::A; 3]; VERTEX_COUNT];

for vertex in 0..VERTEX_COUNT {
for (i, triple) in result.iter_mut().enumerate().take(VERTEX_COUNT) {
for result_index in 0..3 {
let mut test_sides = VERTEX_SIDES()[vertex];
let mut test_sides = vertex_sides_static()[i];
// Keep modifying the result_index'th element of test_sides until its three elements are all
// adjacent to a single vertex. That vertex is the vertex we're looking for.
for side in Side::iter() {
if side == VERTEX_SIDES()[vertex][result_index] {
if side == vertex_sides_static()[i][result_index] {
continue;
}
test_sides[result_index] = side;
if let Some(adjacent_vertex) =
Vertex::from_sides(test_sides[0], test_sides[1], test_sides[2])
{
result[vertex][result_index] = adjacent_vertex;
triple[result_index] = adjacent_vertex;
}
}
}
Expand All @@ -331,18 +335,18 @@ fn ADJACENT_VERTICES() -> &'static [[Vertex; 3]; VERTEX_COUNT] {
}

/// Transform that converts from cube-centric coordinates to dodeca-centric coordinates
fn DUAL_TO_NODE_F64() -> &'static [na::Matrix4<f64>; VERTEX_COUNT] {
fn dual_to_node_f64_static() -> &'static [na::Matrix4<f64>; VERTEX_COUNT] {
static LOCK: OnceLock<[na::Matrix4<f64>; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let mip_origin_normal = math::mip(&math::origin(), &SIDE_NORMALS_F64()[0]); // This value is the same for every side
let mip_origin_normal = math::mip(&math::origin(), &side_normals_f64_static()[0]); // This value is the same for every side
let mut result = [na::zero(); VERTEX_COUNT];
for i in 0..VERTEX_COUNT {
let [a, b, c] = VERTEX_SIDES()[i];
for (i, item) in result.iter_mut().enumerate().take(VERTEX_COUNT) {
let [a, b, c] = vertex_sides_static()[i];
let vertex_position = math::lorentz_normalize(
&(math::origin()
- (a.normal_f64() + b.normal_f64() + c.normal_f64()) * mip_origin_normal),
);
result[i] = na::Matrix4::from_columns(&[
*item = na::Matrix4::from_columns(&[
-a.normal_f64(),
-b.normal_f64(),
-c.normal_f64(),
Expand All @@ -354,23 +358,23 @@ fn DUAL_TO_NODE_F64() -> &'static [na::Matrix4<f64>; VERTEX_COUNT] {
}

/// Transform that converts from dodeca-centric coordinates to cube-centric coordinates
fn NODE_TO_DUAL_F64() -> &'static [na::Matrix4<f64>; VERTEX_COUNT] {
fn node_to_dual_f64_static() -> &'static [na::Matrix4<f64>; VERTEX_COUNT] {
static LOCK: OnceLock<[na::Matrix4<f64>; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| DUAL_TO_NODE_F64().map(|m| math::mtranspose(&m)))
LOCK.get_or_init(|| dual_to_node_f64_static().map(|m| math::mtranspose(&m)))
}

fn DUAL_TO_CHUNK_FACTOR_F64() -> &'static f64 {
fn dual_to_chunk_factor_f64_static() -> &'static f64 {
static LOCK: OnceLock<f64> = OnceLock::new();
LOCK.get_or_init(|| (2.0 + 5.0f64.sqrt()).sqrt())
}

fn CHUNK_TO_DUAL_FACTOR_F64() -> &'static f64 {
fn chunk_to_dual_factor_f64_static() -> &'static f64 {
static LOCK: OnceLock<f64> = OnceLock::new();
LOCK.get_or_init(|| 1.0 / *DUAL_TO_CHUNK_FACTOR_F64())
LOCK.get_or_init(|| 1.0 / *dual_to_chunk_factor_f64_static())
}

/// Vertex shared by 3 sides
fn SIDES_TO_VERTEX() -> &'static [[[Option<Vertex>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT] {
fn sides_to_vertex_static() -> &'static [[[Option<Vertex>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT] {
static LOCK: OnceLock<[[[Option<Vertex>; SIDE_COUNT]; SIDE_COUNT]; SIDE_COUNT]> =
OnceLock::new();
LOCK.get_or_init(|| {
Expand Down Expand Up @@ -402,7 +406,7 @@ fn SIDES_TO_VERTEX() -> &'static [[[Option<Vertex>; SIDE_COUNT]; SIDE_COUNT]; SI
}

/// Whether the determinant of the cube-to-node transform is negative
fn CHUNK_TO_NODE_PARITY() -> &'static [bool; VERTEX_COUNT] {
fn chunk_to_node_parity_static() -> &'static [bool; VERTEX_COUNT] {
static LOCK: OnceLock<[bool; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| {
let mut result = [false; VERTEX_COUNT];
Expand All @@ -415,34 +419,34 @@ fn CHUNK_TO_NODE_PARITY() -> &'static [bool; VERTEX_COUNT] {
})
}

fn SIDE_NORMALS_F32() -> &'static [na::Vector4<f32>; SIDE_COUNT] {
fn side_normals_f32_static() -> &'static [na::Vector4<f32>; SIDE_COUNT] {
static LOCK: OnceLock<[na::Vector4<f32>; SIDE_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| SIDE_NORMALS_F64().map(|n| n.cast()))
LOCK.get_or_init(|| side_normals_f64_static().map(|n| n.cast()))
}

fn REFLECTIONS_F32() -> &'static [na::Matrix4<f32>; SIDE_COUNT] {
fn reflections_f32_static() -> &'static [na::Matrix4<f32>; SIDE_COUNT] {
static LOCK: OnceLock<[na::Matrix4<f32>; SIDE_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| REFLECTIONS_F64().map(|n| n.cast()))
LOCK.get_or_init(|| reflections_f64_static().map(|n| n.cast()))
}

fn DUAL_TO_NODE_F32() -> &'static [na::Matrix4<f32>; VERTEX_COUNT] {
fn dual_to_node_f32_static() -> &'static [na::Matrix4<f32>; VERTEX_COUNT] {
static LOCK: OnceLock<[na::Matrix4<f32>; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| DUAL_TO_NODE_F64().map(|n| n.cast()))
LOCK.get_or_init(|| dual_to_node_f64_static().map(|n| n.cast()))
}

fn NODE_TO_DUAL_F32() -> &'static [na::Matrix4<f32>; VERTEX_COUNT] {
fn node_to_dual_f32_static() -> &'static [na::Matrix4<f32>; VERTEX_COUNT] {
static LOCK: OnceLock<[na::Matrix4<f32>; VERTEX_COUNT]> = OnceLock::new();
LOCK.get_or_init(|| NODE_TO_DUAL_F64().map(|n| n.cast()))
LOCK.get_or_init(|| node_to_dual_f64_static().map(|n| n.cast()))
}

fn DUAL_TO_CHUNK_FACTOR_F32() -> &'static f32 {
fn dual_to_chunk_factor_f32_static() -> &'static f32 {
static LOCK: OnceLock<f32> = OnceLock::new();
LOCK.get_or_init(|| *DUAL_TO_CHUNK_FACTOR_F64() as f32)
LOCK.get_or_init(|| *dual_to_chunk_factor_f64_static() as f32)
}

fn CHUNK_TO_DUAL_FACTOR_F32() -> &'static f32 {
fn chunk_to_dual_factor_f32_static() -> &'static f32 {
static LOCK: OnceLock<f32> = OnceLock::new();
LOCK.get_or_init(|| *CHUNK_TO_DUAL_FACTOR_F64() as f32)
LOCK.get_or_init(|| *chunk_to_dual_factor_f64_static() as f32)
}

#[cfg(test)]
Expand All @@ -453,15 +457,15 @@ mod tests {
#[test]
fn vertex_sides() {
use std::collections::HashSet;
let triples = VERTEX_SIDES().iter().collect::<HashSet<_>>();
let triples = vertex_sides_static().iter().collect::<HashSet<_>>();
assert_eq!(triples.len(), VERTEX_COUNT);
for &triple in &*VERTEX_SIDES() {
for &triple in &*vertex_sides_static() {

Check failure on line 462 in common/src/dodeca.rs

View workflow job for this annotation

GitHub Actions / lint

deref on an immutable reference
let mut sorted = triple;
sorted.sort_unstable();
assert_eq!(triple, sorted);
assert!(ADJACENT()[triple[0] as usize][triple[1] as usize]);
assert!(ADJACENT()[triple[1] as usize][triple[2] as usize]);
assert!(ADJACENT()[triple[2] as usize][triple[0] as usize]);
assert!(adjacent_static()[triple[0] as usize][triple[1] as usize]);
assert!(adjacent_static()[triple[1] as usize][triple[2] as usize]);
assert!(adjacent_static()[triple[2] as usize][triple[0] as usize]);
}
}

Expand Down

0 comments on commit 5bd9579

Please sign in to comment.