175 lines
3.5 KiB
Rust
175 lines
3.5 KiB
Rust
#[derive(Eq, PartialEq, PartialOrd, Ord, Debug, Hash, Clone, Copy)]
|
|
pub struct Dim<I: ?Sized>(pub I);
|
|
|
|
pub type Ix = i64;
|
|
|
|
macro_rules! impl_ix {
|
|
($($t:ident: $n:literal),+) => {
|
|
$(
|
|
pub type $t = Dim<[Ix; $n]>;
|
|
|
|
impl From<[Ix; $n]> for $t {
|
|
#[inline]
|
|
fn from(value: [Ix; $n]) -> Self {
|
|
Dim(value)
|
|
}
|
|
}
|
|
|
|
#[allow(non_snake_case)]
|
|
#[inline]
|
|
pub fn $t() -> Dim<[Ix; $n]> { Dim([0; $n]) }
|
|
)+
|
|
};
|
|
}
|
|
|
|
impl_ix!(
|
|
Ix2: 2,
|
|
Ix3: 3
|
|
);
|
|
|
|
impl Ix2 {
|
|
pub const ORIGIN: Ix2 = Dim([0, 0]);
|
|
pub const UP: Ix2 = Dim([0, 1]);
|
|
pub const DOWN: Ix2 = Dim([0, -1]);
|
|
pub const LEFT: Ix2 = Dim([-1, 0]);
|
|
pub const RIGHT: Ix2 = Dim([1, 0]);
|
|
|
|
#[inline]
|
|
pub fn x(&self) -> Ix {
|
|
self.0[0]
|
|
}
|
|
|
|
#[inline]
|
|
pub fn y(&self) -> Ix {
|
|
self.0[1]
|
|
}
|
|
|
|
#[inline]
|
|
pub fn clockwise(self) -> Self {
|
|
Dim([-self.y(), self.x()])
|
|
}
|
|
|
|
#[inline]
|
|
pub fn counter_clockwise(self) -> Self {
|
|
Dim([self.y(), -self.x()])
|
|
}
|
|
|
|
#[inline]
|
|
pub fn manhatten(&self, other: Ix2) -> i64 {
|
|
(self.x() - other.x()).abs() + (self.y() - other.y()).abs()
|
|
}
|
|
|
|
pub fn linearize(&self, width: usize, height: usize) -> usize {
|
|
self.y() as usize * height + (width - 1)
|
|
}
|
|
}
|
|
|
|
impl From<u8> for Ix2 {
|
|
#[inline]
|
|
fn from(value: u8) -> Self {
|
|
match value {
|
|
b'U' | b'^' => Ix2::UP,
|
|
b'D' | b'v' => Ix2::DOWN,
|
|
b'L' | b'<' => Ix2::LEFT,
|
|
b'R' | b'>' => Ix2::RIGHT,
|
|
_ => panic!(""),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::ops::Add for Ix2 {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
Dim([self.0[0] + rhs.0[0], self.0[1] + rhs.0[1]])
|
|
}
|
|
}
|
|
|
|
impl std::ops::AddAssign for Ix2 {
|
|
#[inline]
|
|
fn add_assign(&mut self, rhs: Self) {
|
|
self.0[0] += rhs.0[0];
|
|
self.0[1] += rhs.0[1];
|
|
}
|
|
}
|
|
|
|
impl std::ops::Sub for Ix2 {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
Dim([self.0[0] - rhs.0[0], self.0[1] - rhs.0[1]])
|
|
}
|
|
}
|
|
|
|
impl std::ops::SubAssign for Ix2 {
|
|
#[inline]
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
self.0[0] -= rhs.0[0];
|
|
self.0[1] -= rhs.0[1];
|
|
}
|
|
}
|
|
|
|
impl std::ops::Mul for Ix2 {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn mul(self, rhs: Self) -> Self::Output {
|
|
Dim([self.0[0] * rhs.0[0], self.0[1] * rhs.0[1]])
|
|
}
|
|
}
|
|
|
|
impl std::ops::Mul<i64> for Ix2 {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn mul(self, rhs: i64) -> Self::Output {
|
|
Dim([self.0[0] * rhs, self.0[1] * rhs])
|
|
}
|
|
}
|
|
|
|
impl std::ops::Add for Ix3 {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn add(self, rhs: Self) -> Self::Output {
|
|
Dim([
|
|
self.0[0] + rhs.0[0],
|
|
self.0[1] + rhs.0[1],
|
|
self.0[2] + rhs.0[2],
|
|
])
|
|
}
|
|
}
|
|
|
|
impl std::ops::AddAssign for Ix3 {
|
|
#[inline]
|
|
fn add_assign(&mut self, rhs: Self) {
|
|
self.0[0] += rhs.0[0];
|
|
self.0[1] += rhs.0[1];
|
|
self.0[2] += rhs.0[2];
|
|
}
|
|
}
|
|
|
|
impl std::ops::Sub for Ix3 {
|
|
type Output = Self;
|
|
|
|
#[inline]
|
|
fn sub(self, rhs: Self) -> Self::Output {
|
|
Dim([
|
|
self.0[0] - rhs.0[0],
|
|
self.0[1] - rhs.0[1],
|
|
self.0[2] - rhs.0[2],
|
|
])
|
|
}
|
|
}
|
|
|
|
impl std::ops::SubAssign for Ix3 {
|
|
#[inline]
|
|
fn sub_assign(&mut self, rhs: Self) {
|
|
self.0[0] -= rhs.0[0];
|
|
self.0[1] -= rhs.0[1];
|
|
self.0[2] -= rhs.0[2];
|
|
}
|
|
}
|