static_math/
vector3.rs

1//-------------------------------------------------------------------------
2// @file vector3.rs
3//
4// @date 06/02/20 18:50:41
5// @author Martin Noblia
6// @email mnoblia@disroot.org
7//
8// @brief
9//
10// @detail
11//
12// Licence MIT:
13// Copyright <2020> <Martin Noblia>
14//
15// Permission is hereby granted, free of charge, to any person obtaining a copy
16// of this software and associated documentation files (the "Software"), to deal
17// in the Software without restriction, including without limitation the rights
18// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
19// copies of the Software, and to permit persons to whom the Software is
20// furnished to do so, subject to the following conditions:
21//
22// The above copyright notice and this permission notice shall be included in
23// all copies or substantial portions of the Software.  THE SOFTWARE IS PROVIDED
24// "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
25// LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
26// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
27// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28// ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30//-------------------------------------------------------------------------
31use core::fmt;
32use core::ops::{Deref, DerefMut};
33use num::{Float, Num, Signed, Zero};
34
35use crate::slices_methods::{norm_inf, norm_l};
36use core::ops::{Add, AddAssign, Div, Mul, Neg, Sub, SubAssign};
37
38use crate::errors::VectorErrors;
39use crate::matrix3x3::M33;
40//-------------------------------------------------------------------------
41//                        code
42//-------------------------------------------------------------------------
43#[derive(Copy, Clone, Debug, PartialEq)]
44pub struct V3<T>([T; 3]);
45
46impl<T> V3<T> {
47    /// create a new V3 from a static array
48    pub const fn new(input: [T; 3]) -> Self {
49        Self(input)
50    }
51
52    /// create a new V3 from raw numbers
53    pub const fn new_from(a: T, b: T, c: T) -> Self {
54        Self::new([a, b, c])
55    }
56}
57
58impl<T: Num + Copy> V3<T> {
59    /// create a V3 with all elements zero
60    #[inline(always)]
61    pub fn zeros() -> Self {
62        <Self as Zero>::zero()
63    }
64
65    /// create a V3 with all elements one
66    pub fn ones() -> Self {
67        let one = T::one();
68        Self::new_from(one, one, one)
69    }
70
71    /// calculate the cross product
72    #[inline]
73    pub fn cross(&self, rhs: Self) -> Self {
74        Self::new_from(
75            self[1] * rhs[2] - self[2] * rhs[1],
76            self[2] * rhs[0] - self[0] * rhs[2],
77            self[0] * rhs[1] - self[1] * rhs[0],
78        )
79    }
80
81    /// create a unitary x axis vector
82    pub fn x_axis() -> Self {
83        let one = T::one();
84        let zero = T::zero();
85        Self::new_from(one, zero, zero)
86    }
87
88    /// create a unitary y axis vector
89    pub fn y_axis() -> Self {
90        let one = T::one();
91        let zero = T::zero();
92        Self::new_from(zero, one, zero)
93    }
94
95    /// create a unitary z axis vector
96    pub fn z_axis() -> Self {
97        let one = T::one();
98        let zero = T::zero();
99        Self::new_from(zero, zero, one)
100    }
101}
102
103impl<T: Num + Copy + core::cmp::PartialOrd> V3<T> {
104    pub fn norm_inf(&self) -> T {
105        norm_inf(&**self)
106    }
107}
108
109impl<T: Num + Copy + Signed + core::iter::Sum> V3<T> {
110    pub fn norm_l(&self) -> T {
111        norm_l(&**self)
112    }
113}
114
115impl<T: Num + Copy + Signed> Neg for V3<T> {
116    type Output = Self;
117
118    #[inline(always)]
119    fn neg(self) -> Self {
120        Self::new_from(-self[0], -self[1], -self[2])
121    }
122}
123
124impl<T: Float> V3<T> {
125    /// calculate the euclidean norm of the V3
126    #[inline(always)]
127    pub fn norm2(&self) -> T {
128        T::sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2])
129    }
130
131    /// normalize the current V3
132    pub fn normalize(&self) -> Result<Self, VectorErrors> {
133        let n = self.norm2();
134        if n != T::zero() {
135            // this method return a new fresh and clean vector :)
136            let mut result = Self::zeros();
137            for i in 0..self.len() {
138                result[i] = self[i] / n;
139            }
140            Ok(result)
141        } else {
142            Err(VectorErrors::Norm2IsZero)
143        }
144    }
145}
146
147//-------------------------------------------------------------------------
148//                        maths basic operations
149//-------------------------------------------------------------------------
150
151// V3 * const
152impl<T: Num + Copy> Mul<T> for V3<T> {
153    type Output = Self;
154
155    #[inline(always)]
156    fn mul(self, rhs: T) -> Self::Output {
157        Self::new_from(self[0] * rhs, self[1] * rhs, self[2] * rhs)
158    }
159}
160
161// V3 / const
162impl<T: Num + Copy> Div<T> for V3<T> {
163    type Output = Self;
164
165    #[inline(always)]
166    fn div(self, rhs: T) -> Self::Output {
167        Self::new_from(self[0] / rhs, self[1] / rhs, self[2] / rhs)
168    }
169}
170
171// FIXME(elsuizo:2020-06-19): this is a hack
172impl Mul<V3<f32>> for f32 {
173    type Output = V3<f32>;
174
175    #[inline(always)]
176    fn mul(self, rhs: V3<f32>) -> Self::Output {
177        V3::new_from(rhs[0] * self, rhs[1] * self, rhs[2] * self)
178    }
179}
180
181// f64 * V3<64>
182impl Mul<V3<f64>> for f64 {
183    type Output = V3<f64>;
184
185    #[inline(always)]
186    fn mul(self, rhs: V3<f64>) -> Self::Output {
187        V3::new_from(rhs[0] * self, rhs[1] * self, rhs[2] * self)
188    }
189}
190
191// V3 * V3
192impl<T: Num + Copy> Mul for V3<T> {
193    type Output = T;
194
195    #[inline(always)]
196    fn mul(self, rhs: Self) -> T {
197        self[0] * rhs[0] + self[1] * rhs[1] + self[2] * rhs[2]
198    }
199}
200
201// V3 * M33
202impl<T: Num + Copy> Mul<M33<T>> for V3<T> {
203    type Output = V3<T>;
204
205    #[inline]
206    fn mul(self, rhs: M33<T>) -> V3<T> {
207        Self::new_from(
208            rhs[(0, 0)] * self[0] + rhs[(0, 1)] * self[1] + rhs[(0, 2)] * self[2],
209            rhs[(1, 0)] * self[0] + rhs[(1, 1)] * self[1] + rhs[(1, 2)] * self[2],
210            rhs[(2, 0)] * self[0] + rhs[(2, 1)] * self[1] + rhs[(2, 2)] * self[2])
211    }
212}
213
214// V3 - V3
215impl<T: Num + Copy> Sub for V3<T> {
216    type Output = Self;
217
218    #[inline(always)]
219    fn sub(self, rhs: Self) -> Self {
220        Self::new_from(self[0] - rhs[0], self[1] - rhs[1], self[2] - rhs[2])
221    }
222}
223
224// V3 -= V3
225impl<T: Num + Copy> SubAssign for V3<T> {
226    #[inline(always)]
227    fn sub_assign(&mut self, other: Self) {
228        *self = *self - other
229    }
230}
231
232// V3 + V3
233impl<T: Num + Copy> Add for V3<T> {
234    type Output = Self;
235
236    #[inline(always)]
237    fn add(self, rhs: Self) -> Self {
238        Self::new_from(self[0] + rhs[0], self[1] + rhs[1], self[2] + rhs[2])
239    }
240}
241
242// V3 += V3
243impl<T: Num + Copy> AddAssign for V3<T> {
244    #[inline(always)]
245    fn add_assign(&mut self, other: Self) {
246        *self = *self + other
247    }
248}
249
250// impl the Zero trait
251impl<T: Num + Copy> Zero for V3<T> {
252    #[inline(always)]
253    fn zero() -> V3<T> {
254        Self::new_from(T::zero(), T::zero(), T::zero())
255    }
256
257    fn is_zero(&self) -> bool {
258        *self == V3::zero()
259    }
260}
261
262impl<T> Deref for V3<T> {
263    type Target = [T; 3];
264    #[inline]
265    fn deref(&self) -> &Self::Target {
266        &self.0
267    }
268}
269
270impl<T> DerefMut for V3<T> {
271    #[inline]
272    fn deref_mut(&mut self) -> &mut Self::Target {
273        &mut self.0
274    }
275}
276
277impl<T> From<[T; 3]> for V3<T> {
278    fn from(data: [T; 3]) -> V3<T> {
279        V3(data)
280    }
281}
282
283//-------------------------------------------------------------------------
284//                        Display impl
285//-------------------------------------------------------------------------
286impl<T: Num + fmt::Display> fmt::Display for V3<T> {
287    fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
288        writeln!(
289            dest,
290            "[{0:^3.2} {1:^3.2} {2:^3.2}]",
291            self[0], self[1], self[2]
292        )
293    }
294}
295
296//-------------------------------------------------------------------------
297//                        constants
298//-------------------------------------------------------------------------
299pub const X_AXIS: V3<f32> = V3::new_from(1.0, 0.0, 0.0);
300pub const Y_AXIS: V3<f32> = V3::new_from(0.0, 1.0, 0.0);
301pub const Z_AXIS: V3<f32> = V3::new_from(0.0, 0.0, 1.0);
302//-------------------------------------------------------------------------
303//                        tests
304//-------------------------------------------------------------------------
305#[cfg(test)]
306mod vector3_test {
307
308    use crate::vector3::V3;
309
310    #[test]
311    fn create_vector3_test() {
312        let v = V3::new([1.0, 1.0, 1.0]);
313        assert_eq!(v[0], 1.0);
314        assert_eq!(v[1], 1.0);
315        assert_eq!(v[2], 1.0);
316    }
317
318    #[test]
319    fn zero_vector3_test() {
320        let result: V3<f64> = V3::zeros();
321        let expected = V3::new([0.0, 0.0, 0.0]);
322        assert_eq!(
323            &result[..],
324            &expected[..],
325            "\nExpected\n{:?}\nfound\n{:?}",
326            &result[..],
327            &expected[..]
328        );
329    }
330
331    #[test]
332    fn product_test() {
333        let v1 = V3::new([1.0, 2.0, 3.0]);
334        let v2 = V3::new([4.0, 5.0, 6.0]);
335        let result = v1 * v2;
336        let expected = 32.0;
337        assert_eq!(result, expected);
338    }
339
340    #[test]
341    fn add_test() {
342        let v1 = V3::new([1.0, 2.0, 3.0]);
343        let v2 = V3::new([4.0, 5.0, 6.0]);
344        let result = v1 + v2;
345        let expected = V3::new([5.0, 7.0, 9.0]);
346        assert_eq!(
347            &result[..],
348            &expected[..],
349            "\nExpected\n{:?}\nfound\n{:?}",
350            &result[..],
351            &expected[..]
352        );
353    }
354
355    #[test]
356    fn norm2_test() {
357        let v1 = V3::new([1.0, 2.0, 3.0]);
358        let expected = 3.7416573867739413;
359        let result = v1.norm2();
360        assert_eq!(result, expected);
361    }
362
363    #[test]
364    fn mul_const_rhs() {
365        let v = V3::new([1.0, 2.0, 3.0]);
366        let result: V3<f64> = 2.0 * v;
367        let expected = V3::new([2.0, 4.0, 6.0]);
368        assert_eq!(
369            &result[..],
370            &expected[..],
371            "\nExpected\n{:?}\nfound\n{:?}",
372            &result[..],
373            &expected[..]
374        );
375    }
376
377    #[test]
378    fn mul_const() {
379        let v = V3::new([1.0, 2.0, 3.0]);
380        let result = v * 2.0;
381        let expected = V3::new([2.0, 4.0, 6.0]);
382        assert_eq!(
383            &result[..],
384            &expected[..],
385            "\nExpected\n{:?}\nfound\n{:?}",
386            &result[..],
387            &expected[..]
388        );
389    }
390
391    #[test]
392    fn sub_test() {
393        let v1 = V3::new([1.0, 1.0, 1.0]);
394        let v2 = V3::new([2.0, 3.0, 4.0]);
395        let result = v1 - v2;
396        let expected = V3::new([-1.0, -2.0, -3.0]);
397        assert_eq!(
398            &result[..],
399            &expected[..],
400            "\nExpected\n{:?}\nfound\n{:?}",
401            &result[..],
402            &expected[..]
403        );
404    }
405
406    #[test]
407    fn normalize_test() {
408        let result = V3::new([1.0, 1.0, 1.0]).normalize().unwrap();
409        let expected = V3::new([0.5773502691896258, 0.5773502691896258, 0.5773502691896258]);
410        assert_eq!(
411            &result[..],
412            &expected[..],
413            "\nExpected\n{:?}\nfound\n{:?}",
414            &result[..],
415            &expected[..]
416        );
417    }
418
419    #[test]
420    fn cross_test() {
421        let x = V3::new([1.0, 0.0, 0.0]);
422        let y = V3::new([0.0, 1.0, 0.0]);
423
424        let result = x.cross(y);
425        // z
426        let expected = V3::new([0.0, 0.0, 1.0]);
427        assert_eq!(
428            &result[..],
429            &expected[..],
430            "\nExpected\n{:?}\nfound\n{:?}",
431            &result[..],
432            &expected[..]
433        );
434    }
435
436    #[test]
437    fn sub_assigment_test() {
438        let mut result = V3::new([1.0, 2.0, 3.0]);
439        let v = V3::new([4.0, 5.0, 6.0]);
440        let expected = V3::new([-3.0, -3.0, -3.0]);
441        result -= v;
442        assert_eq!(
443            &result[..],
444            &expected[..],
445            "\nExpected\n{:?}\nfound\n{:?}",
446            &result[..],
447            &expected[..]
448        );
449    }
450
451    #[test]
452    fn add_assigment_test() {
453        let mut result = V3::new_from(1.0, 2.0, 3.0);
454        let v = V3::new_from(4.0, 5.0, 6.0);
455        let expected = V3::new_from(5.0, 7.0, 9.0);
456        result += v;
457        assert_eq!(
458            &result[..],
459            &expected[..],
460            "\nExpected\n{:?}\nfound\n{:?}",
461            &result[..],
462            &expected[..]
463        );
464    }
465
466    #[test]
467    fn norm_inf_test() {
468        let v = V3::new_from(1, -10, 73);
469        let result = v.norm_inf();
470        let expected = 73;
471        assert_eq!(result, expected);
472    }
473
474    #[test]
475    fn norm_l_test() {
476        let v = V3::new_from(1, -1, 1);
477        let result = v.norm_l();
478        let expected = 3;
479        assert_eq!(result, expected);
480    }
481}