#![cfg(feature = "alloc")]
use alloc::{
collections::{BTreeMap, BTreeSet},
vec::Vec,
};
use super::builder_utils::build_symmetric;
use crate::impls::{CSR2D, SymmetricCSR2D};
const CORNER_OFFSETS: [(i64, i64, i64); 6] =
[(2, -1, -1), (1, 1, -2), (-1, 2, -1), (-2, 1, 1), (-1, -1, 2), (1, -2, 1)];
#[must_use]
pub fn hexagonal_lattice_graph(
rows: usize,
cols: usize,
) -> SymmetricCSR2D<CSR2D<usize, usize, usize>> {
if rows == 0 || cols == 0 {
return build_symmetric(0, Vec::new());
}
let mut vertex_ids = BTreeMap::new();
let mut edges = BTreeSet::new();
let mut next_id = 0;
for row in 0..rows {
for col in 0..cols {
let x = i64::try_from(col).expect("hexagonal_lattice_graph columns exceed i64");
let z = i64::try_from(row).expect("hexagonal_lattice_graph rows exceed i64");
let y = -x - z;
let mut corners = [0; 6];
for (index, (dx, dy, dz)) in CORNER_OFFSETS.into_iter().enumerate() {
let corner = (3 * x + dx, 3 * y + dy, 3 * z + dz);
let vertex = *vertex_ids.entry(corner).or_insert_with(|| {
let vertex = next_id;
next_id += 1;
vertex
});
corners[index] = vertex;
}
for index in 0..6 {
let left = corners[index];
let right = corners[(index + 1) % 6];
edges.insert(if left < right { (left, right) } else { (right, left) });
}
}
}
build_symmetric(next_id, edges.into_iter().collect())
}