devela/num/geom/metric/
extent.rs1use crate::{_impl_metric, cfor, is};
7
8#[doc = crate::TAG_GEOM!()]
9#[must_use]
15#[repr(transparent)]
16pub struct Extent<T, const D: usize> {
17 pub dim: [T; D],
19}
20
21_impl_metric![common_methods: Extent];
22_impl_metric![common_traits: Extent];
23
24#[rustfmt::skip]
27impl<T> Extent<T, 2> {
28 #[must_use]
30 pub const fn x(self) -> T where T: Copy { self.dim[0] }
31 #[must_use]
33 pub const fn y(self) -> T where T: Copy { self.dim[1] }
34
35 #[must_use]
37 pub const fn x_ref(&self) -> &T { &self.dim[0] }
38 #[must_use]
40 pub const fn y_ref(&self) -> &T { &self.dim[1] }
41
42 #[must_use]
44 pub fn x_mut(&mut self) -> &mut T { &mut self.dim[0] }
45 #[must_use]
47 pub fn y_mut(&mut self) -> &mut T { &mut self.dim[1] }
48
49 #[must_use]
51 pub fn is_uniform(&self) -> bool where T: PartialEq {
52 self.dim[0] == self.dim[1]
53 }
54}
55
56#[rustfmt::skip]
57impl<T> Extent<T, 3> {
58 #[must_use]
60 pub const fn x(self) -> T where T: Copy { self.dim[0] }
61 #[must_use]
63 pub const fn y(self) -> T where T: Copy { self.dim[1] }
64 #[must_use]
66 pub const fn z(self) -> T where T: Copy { self.dim[2] }
67
68 #[must_use]
70 pub const fn x_ref(&self) -> &T { &self.dim[0] }
71 #[must_use]
73 pub const fn y_ref(&self) -> &T { &self.dim[1] }
74 #[must_use]
76 pub const fn z_ref(&self) -> &T { &self.dim[2] }
77
78 #[must_use]
80 pub fn x_mut(&mut self) -> &mut T { &mut self.dim[0] }
81 #[must_use]
83 pub fn y_mut(&mut self) -> &mut T { &mut self.dim[1] }
84 #[must_use]
86 pub fn z_mut(&mut self) -> &mut T { &mut self.dim[2] }
87
88 #[must_use]
90 pub fn is_uniform_3d(&self) -> bool where T: PartialEq {
91 self.dim[0] == self.dim[1] && self.dim[0] == self.dim[2]
92 }
93}
94
95macro_rules! impl_extent {
97 () => {
98 impl_extent![sint i8, i16, i32, i64, i128, isize];
99 impl_extent![uint u8, u16, u32, u64, u128, usize];
100 impl_extent![float f32, f64];
101 };
102 (int $($t:ty),+) => { $( impl_extent![@int $t]; )+ };
106 (@int $t:ty) => {
107 impl<const D: usize> Extent<$t, D> {
108 pub const fn c_measure(self) -> $t {
112 let mut measure = 1;
113 cfor!(i in 0..D => {
114 measure *= self.dim[i];
115 });
116 measure
117 }
118 pub const fn c_boundary(self) -> $t {
122 let mut boundary = 0;
123 cfor!(i in 0..D => {
124 let mut face_measure = 1;
125 cfor!(j in 0..D => {
126 is![i != j; face_measure *= self.dim[j]];
127 });
128 boundary += face_measure;
129 });
130 2 * boundary }
132 }
133
134 impl Extent<$t, 1> {
135 #[must_use]
137 pub const fn c_length(self) -> $t { self.dim[0] }
138 }
139 impl Extent<$t, 2> {
140 #[must_use]
142 pub const fn c_area(self) -> $t { self.dim[0] * self.dim[1] }
143
144 #[must_use]
146 pub const fn c_perimeter(self) -> $t { 2 * (self.dim[0] + self.dim[1]) }
147
148 }
149 impl Extent<$t, 3> {
150 #[must_use]
152 pub const fn c_volume(self) -> $t {
153 self.dim[0] * self.dim[1] * self.dim[2]
154 }
155
156 #[must_use]
158 pub const fn c_surface_area(self) -> $t {
159 2 * (self.dim[0] * self.dim[1]
160 + self.dim[1] * self.dim[2]
161 + self.dim[2] * self.dim[0])
162 }
163 }
164 };
165
166 (sint $($t:ty),+) => { $( impl_extent![@sint $t]; )+ };
167 (@sint $t:ty ) => {
168 impl_extent![int $t];
169 };
170 (uint $($t:ty),+) => { $( impl_extent![@uint $t]; )+ };
171 (@uint $t:ty ) => {
172 impl_extent![int $t];
173 };
174
175 (float $($f:ty),+) => { $( impl_extent![@float $f]; )+ };
177 (@float $f:ty) => {
178 impl<const D: usize> Extent<$f, D> {
179 #[must_use]
183 pub const fn measure(self) -> $f {
184 let mut measure = 1.0;
185 cfor!(i in 0..D => {
186 measure *= self.dim[i];
187 });
188 measure
189 }
190 #[must_use]
194 pub const fn boundary(self) -> $f {
195 let mut boundary = 0.0;
196 cfor!(i in 0..D => {
197 let mut face_measure = 1.0;
198 cfor!(j in 0..D => {
199 is![i != j; face_measure *= self.dim[j]];
200 });
201 boundary += face_measure;
202 });
203 2.0 * boundary }
205 }
206
207 impl Extent<$f, 1> {
208 #[must_use]
210 pub const fn length(self) -> $f { self.dim[0] }
211 }
212 impl Extent<$f, 2> {
213 #[must_use]
215 pub const fn area(self) -> $f { self.dim[0] * self.dim[1] }
216
217 #[must_use]
219 pub const fn perimeter(self) -> $f { 2.0 * (self.dim[0] + self.dim[1]) }
220
221 }
222 impl Extent<$f, 3> {
223 #[must_use]
225 pub const fn volume(self) -> $f {
226 self.dim[0] * self.dim[1] * self.dim[2]
227 }
228
229 #[must_use]
231 pub const fn surface_area(self) -> $f {
232 2.0 * (self.dim[0] * self.dim[1]
233 + self.dim[1] * self.dim[2]
234 + self.dim[2] * self.dim[0])
235 }
236 }
237 };
238}
239impl_extent![];