use crate::{_impl_geom_dim, is, whilst};
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_location!("geom/metric")]
#[must_use]
#[repr(transparent)]
#[doc(alias = "Size")]
pub struct Extent<T, const D: usize> {
pub dim: [T; D],
}
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_location!("geom/metric")]
#[doc(alias = "Size")]
pub type Extent1<T> = Extent<T, 1>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_location!("geom/metric")]
#[doc(alias = "Size")]
pub type Extent2<T> = Extent<T, 2>;
#[doc = crate::_tags!(geom)]
#[doc = crate::_doc_location!("geom/metric")]
#[doc(alias = "Size")]
pub type Extent3<T> = Extent<T, 3>;
_impl_geom_dim![common_methods: Extent];
_impl_geom_dim![common_traits: Extent];
macro_rules! impl_extent {
() => {
impl_extent![sint i8, i16, i32, i64, i128, isize];
impl_extent![uint u8, u16, u32, u64, u128, usize];
impl_extent![float f32, f64];
};
(int $($t:ty),+) => { $( impl_extent![@int $t]; )+ };
(@int $t:ty) => {
impl<const D: usize> Extent<$t, D> {
#[must_use]
pub const fn measure(self) -> $t {
let mut measure = 1;
whilst!(i in 0..D; measure *= self.dim[i]);
measure
}
#[must_use]
pub const fn boundary(self) -> $t {
let mut boundary = 0;
whilst!(i in 0..D; {
let mut face_measure = 1;
whilst!(j in 0..D; is![i != j, face_measure *= self.dim[j]]);
boundary += face_measure;
});
2 * boundary }
}
impl Extent2<$t> {
#[must_use]
pub const fn area(self) -> $t { self.dim[0] * self.dim[1] }
#[must_use]
pub const fn perimeter(self) -> $t { 2 * (self.dim[0] + self.dim[1]) }
}
impl Extent3<$t> {
#[must_use]
pub const fn volume(self) -> $t {
self.dim[0] * self.dim[1] * self.dim[2]
}
#[must_use]
pub const fn surface_area(self) -> $t {
2 * (self.dim[0] * self.dim[1]
+ self.dim[1] * self.dim[2]
+ self.dim[2] * self.dim[0])
}
}
};
(sint $($t:ty),+) => { $( impl_extent![@sint $t]; )+ };
(@sint $t:ty ) => {
impl_extent![int $t];
};
(uint $($t:ty),+) => { $( impl_extent![@uint $t]; )+ };
(@uint $t:ty ) => {
impl_extent![int $t];
};
(float $($f:ty),+) => { $( impl_extent![@float $f]; )+ };
(@float $f:ty) => {
impl<const D: usize> Extent<$f, D> {
#[must_use]
pub const fn measure(self) -> $f {
let mut measure = 1.0;
whilst!(i in 0..D; measure *= self.dim[i]);
measure
}
#[must_use]
pub const fn boundary(self) -> $f {
let mut boundary = 0.0;
whilst!(i in 0..D; {
let mut face_measure = 1.0;
whilst!(j in 0..D; is![i != j, face_measure *= self.dim[j]]);
boundary += face_measure;
});
2.0 * boundary }
}
impl Extent2<$f> {
#[must_use]
pub const fn area(self) -> $f { self.dim[0] * self.dim[1] }
#[must_use]
pub const fn perimeter(self) -> $f { 2.0 * (self.dim[0] + self.dim[1]) }
}
impl Extent3<$f> {
#[must_use]
pub const fn volume(self) -> $f {
self.dim[0] * self.dim[1] * self.dim[2]
}
#[must_use]
pub const fn surface_area(self) -> $f {
2.0 * (self.dim[0] * self.dim[1]
+ self.dim[1] * self.dim[2]
+ self.dim[2] * self.dim[0])
}
}
};
}
impl_extent![];
#[rustfmt::skip]
impl<T: Copy> Extent1<T> {
#[must_use]
pub const fn length(self) -> T { self.dim[0] }
pub const fn l(self) -> T { self.dim[0] }
}
#[rustfmt::skip]
impl<T: Copy> Extent2<T> {
#[must_use]
pub const fn width(self) -> T { self.dim[0] }
#[must_use]
pub const fn w(self) -> T { self.dim[0] }
#[must_use]
pub const fn height(self) -> T { self.dim[1] }
#[must_use]
pub const fn h(self) -> T { self.dim[1] }
#[must_use]
pub const fn length(self) -> T { self.dim[0] }
#[must_use]
pub const fn l(self) -> T { self.dim[0] }
#[must_use]
pub const fn breadth(self) -> T { self.dim[1] }
#[must_use]
pub const fn b(self) -> T { self.dim[1] }
}
#[rustfmt::skip]
impl<T: Copy> Extent3<T> {
#[must_use]
pub const fn width(self) -> T { self.dim[0] }
#[must_use]
pub const fn w(self) -> T { self.dim[0] }
#[must_use]
pub const fn height(self) -> T { self.dim[1] }
#[must_use]
pub const fn h(self) -> T { self.dim[1] }
#[must_use]
pub const fn depth(self) -> T { self.dim[2] }
#[must_use]
pub const fn d(self) -> T { self.dim[2] }
}