static_math/
vector5.rs

1//-------------------------------------------------------------------------
2// @file vector5.rs
3//
4// @date 06/02/20 20:49:59
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 num::{Float, Zero, Num, Signed};
33use core::ops::{Deref, DerefMut};
34
35use core::ops::{Add, Sub, Div, Mul, SubAssign, AddAssign, Neg};
36
37use crate::slices_methods::{norm_inf, norm_l};
38use crate::errors::VectorErrors;
39use crate::matrix5x5::M55;
40//-------------------------------------------------------------------------
41//                        code
42//-------------------------------------------------------------------------
43#[derive(Copy, Clone, Debug, PartialEq)]
44pub struct V5<T>([T; 5]);
45
46impl<T> V5<T> {
47    /// create a new V5 from a static array
48    pub const fn new(input: [T; 5]) -> Self {
49        Self(input)
50    }
51
52    /// create a new V5 from raw numbers
53    pub const fn new_from(num1: T, num2: T, num3: T, num4: T, num5: T) -> Self {
54        Self::new([num1, num2, num3, num4, num5])
55    }
56}
57
58impl<T: Num + Copy> V5<T> {
59    /// create a V5 with all elements zeros
60    pub fn zeros() -> Self {
61        <V5<T> as Zero>::zero()
62    }
63
64    /// create a V5 with all elements one
65    pub fn ones() -> Self {
66        let one = T::one();
67        Self::new([one, one, one, one, one])
68    }
69}
70
71impl<T: Num + Copy + core::cmp::PartialOrd> V5<T> {
72    pub fn norm_inf(&self) -> T {
73        norm_inf(&**self)
74    }
75}
76
77impl<T: Num + Copy + Signed + core::iter::Sum> V5<T> {
78    pub fn norm_l(&self) -> T {
79        norm_l(&**self)
80    }
81}
82
83impl<T: Num + Copy + Signed> Neg for V5<T> {
84    type Output = Self;
85
86    #[inline]
87    fn neg(self) -> Self {
88        Self::new_from(-self[0], -self[1], -self[2], -self[3], -self[4])
89    }
90}
91
92impl<T: Float> V5<T> {
93    /// calculate the euclidean norm of the V5
94    #[inline]
95    pub fn norm2(&self) -> T {
96        T::sqrt(self[0] * self[0] + self[1] * self[1] + self[2] * self[2] + self[3] * self[3] + self[4] * self[4])
97    }
98
99    /// normalize the current V5 and return a new one
100    pub fn normalize(&mut self) -> Result<Self, VectorErrors> {
101        let n = self.norm2();
102        if n != T::zero() {
103            // this method return a new fresh and clean vector :)
104            let mut result = Self::zeros();
105            for i in 0..self.len() {
106                result[i] = self[i] / n;
107            }
108            Ok(result)
109        } else {
110            Err(VectorErrors::Norm2IsZero)
111        }
112    }
113}
114
115// V5 * V5(dot product)
116impl<T: Num + Copy> Mul for V5<T> {
117    type Output = T;
118
119    #[inline]
120    fn mul(self, rhs: Self) -> T {
121        self[0] * rhs[0] + self[1] * rhs[1] + self[2] * rhs[2] + self[3] * rhs[3] + self[4] * rhs[4]
122    }
123}
124
125// V5 * constant
126impl<T: Num + Copy> Mul<T> for V5<T> {
127    type Output = V5<T>;
128
129    #[inline]
130    fn mul(self, rhs: T) -> V5<T> {
131        Self::new_from(self[0] * rhs, self[1] * rhs, self[2] * rhs, self[3] * rhs, self[4] * rhs)
132    }
133}
134
135// V5 / const
136impl<T: Num + Copy> Div<T> for V5<T> {
137    type Output = Self;
138
139    fn div(self, rhs: T) -> Self::Output {
140        Self::new_from(self[0] / rhs, self[1] / rhs, self[2] / rhs, self[3] / rhs, self[4] / rhs)
141    }
142}
143// f32 * V5<f32>
144impl Mul<V5<f32>> for f32 {
145    type Output = V5<f32>;
146
147    #[inline]
148    fn mul(self, rhs: V5<f32>) -> V5<f32> {
149        V5::new_from(self * rhs[0], self * rhs[1], self * rhs[2], self * rhs[3], self * rhs[4])
150    }
151}
152
153// V5 * M55
154impl<T: Num + Copy> Mul<M55<T>> for V5<T> {
155    type Output = V5<T>;
156
157    #[inline]
158    fn mul(self, rhs: M55<T>) -> V5<T> {
159        Self::new_from(
160            rhs[(0, 0)] * self[0] + rhs[(1, 0)] * self[1] + rhs[(2, 0)] * self[2] + rhs[(3, 0)] * self[3] + rhs[(4, 0)] * self[4],
161            rhs[(0, 1)] * self[0] + rhs[(1, 1)] * self[1] + rhs[(2, 1)] * self[2] + rhs[(3, 1)] * self[3] + rhs[(4, 1)] * self[4],
162            rhs[(0, 2)] * self[0] + rhs[(1, 2)] * self[1] + rhs[(2, 2)] * self[2] + rhs[(3, 2)] * self[3] + rhs[(4, 2)] * self[4],
163            rhs[(0, 3)] * self[0] + rhs[(1, 3)] * self[1] + rhs[(2, 3)] * self[2] + rhs[(3, 3)] * self[3] + rhs[(4, 3)] * self[4],
164            rhs[(0, 4)] * self[0] + rhs[(1, 4)] * self[1] + rhs[(2, 4)] * self[2] + rhs[(3, 4)] * self[3] + rhs[(4, 4)] * self[4],
165        )
166    }
167}
168
169// V5 - V5
170impl<T: Num + Copy> Sub for V5<T> {
171    type Output = Self;
172
173    #[inline]
174    fn sub(self, rhs: Self) -> Self {
175        Self::new_from(self[0] - rhs[0], self[1] - rhs[1], self[2] - rhs[2], self[3] - rhs[3], self[4] - rhs[4])
176    }
177}
178
179// V5 -= V5
180impl<T: Num + Copy> SubAssign for V5<T> {
181    #[inline]
182    fn sub_assign(&mut self, other: Self) {
183        *self = *self - other
184    }
185}
186
187// V5 + V5
188impl<T: Num + Copy> Add for V5<T> {
189    type Output = Self;
190    #[inline]
191    fn add(self, rhs: Self) -> Self {
192        Self::new_from(self[0] + rhs[0], self[1] + rhs[1], self[2] + rhs[2], self[3] + rhs[3], self[4] + rhs[4])
193    }
194}
195
196// V5 += V5
197impl<T: Num + Copy> AddAssign for V5<T> {
198    #[inline]
199    fn add_assign(&mut self, other: Self) {
200        *self = *self + other
201    }
202}
203
204impl<T: Num + Copy> Zero for V5<T> {
205    fn zero() -> V5<T> {
206        Self::new([T::zero(); 5])
207    }
208
209    fn is_zero(&self) -> bool {
210        *self == V5::zero()
211    }
212}
213
214impl<T> Deref for V5<T> {
215    type Target = [T; 5];
216    #[inline]
217    fn deref(&self) -> &Self::Target {
218        &self.0
219    }
220}
221
222impl<T> DerefMut for V5<T> {
223    #[inline]
224    fn deref_mut(&mut self) -> &mut Self::Target {
225        &mut self.0
226    }
227}
228
229impl<T> From<[T; 5]> for V5<T> {
230    fn from(data: [T; 5]) -> V5<T> {
231        V5(data)
232    }
233}
234
235//-------------------------------------------------------------------------
236//                        Display impl
237//-------------------------------------------------------------------------
238impl<T: Num + fmt::Display> fmt::Display for V5<T> {
239    fn fmt(&self, dest: &mut fmt::Formatter) -> fmt::Result {
240        writeln!(dest, "[{0:^3.2} {1:^3.2} {2:^3.2} {3:^3.2} {4:^3.2}]", self[0], self[1], self[2], self[3], self[4])
241    }
242}
243
244//-------------------------------------------------------------------------
245//                        tests
246//-------------------------------------------------------------------------
247#[cfg(test)]
248mod vector5_test {
249
250    use crate::matrix5x5::M55;
251    use crate::vector5::V5;
252
253    #[test]
254    fn vector5_creation_test() {
255        let v = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
256        assert_eq!(v[0], 1.0);
257        assert_eq!(v[1], 2.0);
258        assert_eq!(v[2], 3.0);
259        assert_eq!(v[3], 4.0);
260        assert_eq!(v[4], 5.0);
261    }
262
263    #[test]
264    fn vector5_zeros_test() {
265        let result: V5<f32> = V5::zeros();
266        let expected = V5::new([0.0, 0.0, 0.0, 0.0, 0.0]);
267        assert_eq!(
268            &result[..],
269            &expected[..],
270            "\nExpected\n{:?}\nfound\n{:?}",
271            &result[..],
272            &expected[..]
273        );
274    }
275
276    #[test]
277    fn vector5_add_test() {
278        let v1 = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
279        let v2 = V5::new([6.0, 7.0, 8.0, 9.0, 10.0]);
280        let result = v1 + v2;
281        let expected = V5::new([7.0, 9.0, 11.0, 13.0, 15.0]);
282        assert_eq!(
283            &result[..],
284            &expected[..],
285            "\nExpected\n{:?}\nfound\n{:?}",
286            &result[..],
287            &expected[..]
288        );
289    }
290
291    #[test]
292    fn sub_test() {
293        let v1 = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
294        let v2 = V5::new([6.0, 7.0, 8.0, 9.0, 10.0]);
295        let result = v1 - v2;
296        let expected = V5::new([-5.0, -5.0, -5.0, -5.0, -5.0]);
297        assert_eq!(
298            &result[..],
299            &expected[..],
300            "\nExpected\n{:?}\nfound\n{:?}",
301            &result[..],
302            &expected[..]
303        );
304    }
305
306    #[test]
307    fn vector5_mul_test() {
308        let v1 = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
309        let v2 = V5::new([6.0, 7.0, 8.0, 9.0, 10.0]);
310        let result = v1 * v2;
311        let expected = 130.0;
312        assert_eq!(result, expected);
313    }
314
315    #[test]
316    fn vector5_norm_test() {
317        let v1 = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
318        let result = v1.norm2();
319        let expected = 7.416198487095663;
320        assert_eq!(result, expected);
321    }
322
323    #[test]
324    fn mul_const_rhs() {
325        let v = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
326        let result = 2.0 * v;
327        let expected = V5::new([2.0, 4.0, 6.0, 8.0, 10.0]);
328        assert_eq!(
329            &result[..],
330            &expected[..],
331            "\nExpected\n{:?}\nfound\n{:?}",
332            &result[..],
333            &expected[..]
334        );
335    }
336
337    #[test]
338    fn mul_const() {
339        let v = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
340        let result = v * 2.0;
341        let expected = V5::new([2.0, 4.0, 6.0, 8.0, 10.0]);
342        assert_eq!(
343            &result[..],
344            &expected[..],
345            "\nExpected\n{:?}\nfound\n{:?}",
346            &result[..],
347            &expected[..]
348        );
349    }
350
351    #[test]
352    fn vector5_mul_matrix5x5_test() {
353        let v1 = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
354        let m = M55::new([
355            [10.0, 1.0, 7.0, 1.0, 5.0],
356            [2.0, 4.0, 8.0, 3.0, 2.0],
357            [5.0, 1.0, 2.0, 9.0, 10.0],
358            [6.0, 9.0, 9.0, 7.0, 3.0],
359            [1.0, 8.0, 8.0, 10.0, 5.0],
360        ]);
361        let result = v1 * m;
362        let expected = V5::new([58.0, 88.0, 105.0, 112.0, 76.0]);
363        assert_eq!(
364            &result[..],
365            &expected[..],
366            "\nExpected\n{:?}\nfound\n{:?}",
367            &result[..],
368            &expected[..]
369        );
370    }
371
372    #[test]
373    fn normalize_test() {
374        let result = V5::new([1.0, 1.0, 1.0, 1.0, 1.0]).normalize().unwrap();
375        let expected = V5::new([0.4472135954999579, 0.4472135954999579, 0.4472135954999579, 0.4472135954999579, 0.4472135954999579]);
376        assert_eq!(
377            &result[..],
378            &expected[..],
379            "\nExpected\n{:?}\nfound\n{:?}",
380            &result[..],
381            &expected[..]
382        );
383    }
384
385    #[test]
386    fn sub_assigment_test() {
387        let mut result = V5::new([1.0, 2.0, 3.0, 4.0, 5.0]);
388        let v = V5::new([0.0, 1.0, 2.0, 3.0, 4.0]);
389        let expected = V5::new([1.0, 1.0, 1.0, 1.0, 1.0]);
390        result -= v;
391        assert_eq!(
392            &result[..],
393            &expected[..],
394            "\nExpected\n{:?}\nfound\n{:?}",
395            &result[..],
396            &expected[..]
397        );
398    }
399
400    #[test]
401    fn add_assigment_test() {
402        let mut result = V5::new_from(1.0, 2.0, 3.0, 4.0, 5.0);
403        let v = V5::new_from(0.0, 1.0, 2.0, 3.0, 4.0);
404        let expected = V5::new_from(1.0, 3.0, 5.0, 7.0, 9.0);
405        result += v;
406        assert_eq!(
407            &result[..],
408            &expected[..],
409            "\nExpected\n{:?}\nfound\n{:?}",
410            &result[..],
411            &expected[..]
412        );
413    }
414
415    #[test]
416    fn norm_inf_test() {
417        let v = V5::new_from(1, 2, 30, 91, 10);
418        let result = v.norm_inf();
419        let expected = 91;
420        assert_eq!(result, expected);
421    }
422
423    #[test]
424    fn norm_l_test() {
425        let v = V5::new_from(-1, 1, -1, 1, -1);
426        let result = v.norm_l();
427        let expected = 5;
428        assert_eq!(result, expected);
429    }
430}
431