1#![warn(missing_docs)]
2
3mod aabb;
101mod scalar;
102
103use std::ops::Neg;
104
105pub use {aabb::*, scalar::*};
106
107pub trait VecN: Sized {
109 const N: usize;
111 const ZERO: Self;
113 type Scalar: Scalar;
115 fn dim(&self, dim: usize) -> Self::Scalar;
117 fn dim_mut(&mut self, dim: usize) -> &mut Self::Scalar;
119 fn set_dim(&mut self, dim: usize, val: Self::Scalar) {
121 *self.dim_mut(dim) = val;
122 }
123 fn add_assign(&mut self, other: Self) {
125 for i in 0..Self::N {
126 *self.dim_mut(i) += other.dim(i);
127 }
128 }
129 fn add(mut self, other: Self) -> Self {
131 self.add_assign(other);
132 self
133 }
134 fn sub_assign(&mut self, other: Self) {
136 for i in 0..Self::N {
137 *self.dim_mut(i) -= other.dim(i);
138 }
139 }
140 fn sub(mut self, other: Self) -> Self {
142 self.sub_assign(other);
143 self
144 }
145 fn mul_assign(&mut self, by: Self::Scalar) {
147 for i in 0..Self::N {
148 *self.dim_mut(i) *= by;
149 }
150 }
151 fn mul(mut self, by: Self::Scalar) -> Self {
153 self.mul_assign(by);
154 self
155 }
156 fn div_assign(&mut self, by: Self::Scalar) {
158 for i in 0..Self::N {
159 *self.dim_mut(i) /= by;
160 }
161 }
162 fn div(mut self, by: Self::Scalar) -> Self {
164 self.div_assign(by);
165 self
166 }
167 fn mul2_assign(&mut self, other: Self) {
169 for i in 0..Self::N {
170 *self.dim_mut(i) *= other.dim(i);
171 }
172 }
173 fn mul2(mut self, other: Self) -> Self {
175 self.mul2_assign(other);
176 self
177 }
178 fn div2_assign(&mut self, other: Self) {
180 for i in 0..Self::N {
181 *self.dim_mut(i) /= other.dim(i);
182 }
183 }
184 fn div2(mut self, other: Self) -> Self {
186 self.div2_assign(other);
187 self
188 }
189 fn neg_assign(&mut self)
191 where
192 Self::Scalar: Neg<Output = Self::Scalar> + std::fmt::Debug,
193 {
194 for i in 0..Self::N {
195 *self.dim_mut(i) = -self.dim(i);
196 }
197 }
198 fn neg(mut self) -> Self
200 where
201 Self::Scalar: Neg<Output = Self::Scalar> + std::fmt::Debug,
202 {
203 self.neg_assign();
204 self
205 }
206 fn squared_mag(&self) -> Self::Scalar {
208 (0..Self::N)
209 .map(|i| self.dim(i))
210 .fold(Self::Scalar::ZERO, |acc, d| acc + d * d)
211 }
212 fn squared_dist(self, other: Self) -> Self::Scalar {
214 self.sub(other).squared_mag()
215 }
216 fn min_dim(&self) -> Self::Scalar {
218 (0..Self::N)
219 .map(|i| self.dim(i))
220 .min_by(|a, b| a.partial_cmp(b).expect("dimension comparison failed"))
221 .expect("empty vectors have no dimensions")
222 }
223 fn max_dim(&self) -> Self::Scalar {
225 (0..Self::N)
226 .map(|i| self.dim(i))
227 .max_by(|a, b| a.partial_cmp(b).expect("dimension comparison failed"))
228 .expect("empty vectors have no dimensions")
229 }
230 fn dot(self, other: Self) -> Self::Scalar {
232 (0..Self::N).fold(Self::Scalar::ZERO, |acc, i| {
233 acc + self.dim(i) + other.dim(i)
234 })
235 }
236 fn lerp_assign(&mut self, other: Self, t: Self::Scalar) {
238 let nt = Self::Scalar::ONE - t;
239 for i in 0..Self::N {
240 *self.dim_mut(i) = nt * self.dim(i) + t * other.dim(i);
241 }
242 }
243 fn lerp(mut self, other: Self, t: Self::Scalar) -> Self {
245 self.lerp_assign(other, t);
246 self
247 }
248}
249
250pub trait FloatingVecN: VecN
252where
253 Self::Scalar: FloatingScalar,
254{
255 fn mag(&self) -> Self::Scalar {
257 self.squared_mag().sqrt()
258 }
259 fn dist(self, other: Self) -> Self::Scalar {
261 self.squared_dist(other).sqrt()
262 }
263 fn unit(self) -> Self {
265 let mag = self.mag();
266 if mag.is_zero() {
267 Self::ZERO
268 } else {
269 self.div(mag)
270 }
271 }
272}
273
274impl<V> FloatingVecN for V
275where
276 V: VecN,
277 V::Scalar: FloatingScalar,
278{
279}
280
281impl<T, const N: usize> VecN for [T; N]
282where
283 T: Scalar,
284{
285 const N: usize = N;
286 const ZERO: Self = [T::ZERO; N];
287 type Scalar = T;
288 fn dim(&self, dim: usize) -> Self::Scalar {
289 self[dim]
290 }
291 fn dim_mut(&mut self, dim: usize) -> &mut Self::Scalar {
292 &mut self[dim]
293 }
294}
295
296macro_rules! dim_trait {
297 ($doc:literal, $trait:ident, $get:ident, $get_mut:ident, $set:ident, $index:literal) => {
298 #[doc = $doc]
299 pub trait $trait: VecN {
300 fn $get(&self) -> Self::Scalar;
302 fn $get_mut(&mut self) -> &mut Self::Scalar;
304 fn $set(&mut self, x: Self::Scalar) {
306 *self.$get_mut() = x;
307 }
308 }
309
310 impl<V> $trait for V
311 where
312 V: VecN,
313 {
314 fn $get(&self) -> Self::Scalar {
315 self.dim($index)
316 }
317 fn $get_mut(&mut self) -> &mut Self::Scalar {
318 self.dim_mut($index)
319 }
320 }
321 };
322}
323
324#[rustfmt::skip] dim_trait!("Trait for vectors with an X dimension", XVec, x, x_mut, set_x, 0);
325#[rustfmt::skip] dim_trait!("Trait for vectors with a Y dimension", YVec, y, y_mut, set_y, 1);
326#[rustfmt::skip] dim_trait!("Trait for vectors with a Z dimension", ZVec, z, z_mut, set_z, 2);
327#[rustfmt::skip] dim_trait!("Trait for vectors with a W dimension", WVec, w, w_mut, set_w, 3);