1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use crate::Float;
#[inline]
fn array_sub_generic<F, const N: usize>(x: [F; N], y: [F; N]) -> [F; N]
where
F: Float + std::fmt::Debug,
{
use std::convert::TryInto;
let d: Vec<_> = x.iter().zip(y.iter()).map(|(a, b)| *a - *b).collect();
d.try_into().unwrap()
}
#[inline]
fn array_add_generic<F, const N: usize>(x: [F; N], y: [F; N]) -> [F; N]
where
F: Float + std::fmt::Debug,
{
use std::convert::TryInto;
let d: Vec<_> = x.iter().zip(y.iter()).map(|(a, b)| *a + *b).collect();
d.try_into().unwrap()
}
pub trait ArrayMathExt<F: Float> {
fn array_add(self, other: Self) -> Self;
fn array_sub(self, other: Self) -> Self;
fn array_scale(self, value: F) -> Self;
}
impl<F, const N: usize> ArrayMathExt<F> for [F; N]
where
F: Float + std::fmt::Debug,
{
fn array_add(self, other: Self) -> Self {
array_add_generic(self, other)
}
fn array_sub(self, other: Self) -> Self {
array_sub_generic(self, other)
}
fn array_scale(self, value: F) -> Self {
self.map(|x| x * value)
}
}
#[test]
fn test_array_sub_add() {
use crate::approx::*;
let p1 = [1.0, 2.0, 3.0];
let p2 = [1.1, 2.2, 3.3];
let p3 = p2.array_sub(p1);
let p4 = p2.array_add(p1);
assert_relative_eq!(p3[0], 0.1, epsilon = 1e-4);
assert_relative_eq!(p3[1], 0.2, epsilon = 1e-4);
assert_relative_eq!(p3[2], 0.3, epsilon = 1e-4);
assert_relative_eq!(p4[0], 2.1, epsilon = 1e-4);
assert_relative_eq!(p4[1], 4.2, epsilon = 1e-4);
assert_relative_eq!(p4[2], 6.3, epsilon = 1e-4);
let p5 = p1.array_scale(2.0);
assert_eq!(p5[0], 2.0);
assert_eq!(p5[1], 4.0);
assert_eq!(p5[2], 6.0);
}