use super::Board; use num::Integer; use static_assertions::const_assert; /// PERF! having `Coord` be of type `u8` (instead of usize) increases /// performance by about 1-2% overall pub type CoordAxis = u8; /// using u8 for this results in a ~3-6% perf increase pub type CoordPairInner = u8; const_assert!(CoordPairInner::MAX as usize >= Board::AREA.0 as usize); #[derive(PartialEq, Eq, Copy, Clone, Hash)] pub struct CoordPair(pub CoordPairInner); impl CoordPair { /// Convert a row and column to an index in the board pub const fn from_axes(row: CoordAxis, col: CoordAxis) -> Self { Self(row * Board::SIZE + col) } #[allow(clippy::wrong_self_convention)] fn into_indexes(&self) -> (CoordAxis, CoordAxis) { self.0.div_mod_floor(&Board::SIZE) } pub const fn area(pos: CoordAxis) -> Self { Self(pos.pow(2) as CoordPairInner) } } impl std::fmt::Display for CoordPair { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { let (i, j) = (*self).into(); write!(f, "({}, {})", i, j) } } impl std::fmt::Debug for CoordPair { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}", self) } } impl From for (CoordAxis, CoordAxis) { fn from(val: CoordPair) -> Self { val.into_indexes() } } impl From<(CoordAxis, CoordAxis)> for CoordPair { fn from(value: (CoordAxis, CoordAxis)) -> Self { Self::from_axes(value.0, value.1) } } #[cfg(test)] mod tests { use super::*; #[test] fn into_out_of() { let a: CoordPair = (1, 3).into(); let back: (CoordAxis, CoordAxis) = a.into(); assert_eq!(back, (1, 3)); } }