1use std::ops::Sub;
9
10use crate::{Allocator, ArgminSub};
11
12use crate::ClosedSub;
13use nalgebra::{
14 base::{dimension::Dim, storage::Storage, Scalar},
15 DefaultAllocator, Matrix, OMatrix,
16};
17
18impl<N, R, C, S> ArgminSub<N, OMatrix<N, R, C>> for Matrix<N, R, C, S>
19where
20 N: Scalar + Copy + Sub<Output = N>,
21 R: Dim,
22 C: Dim,
23 S: Storage<N, R, C>,
24 DefaultAllocator: Allocator<N, R, C>,
25{
26 #[inline]
27 fn sub(&self, other: &N) -> OMatrix<N, R, C> {
28 self.map(|entry| entry - *other)
29 }
30}
31
32impl<N, R, C, S> ArgminSub<Matrix<N, R, C, S>, OMatrix<N, R, C>> for N
33where
34 N: Scalar + Copy + Sub<Output = N>,
35 R: Dim,
36 C: Dim,
37 S: Storage<N, R, C>,
38 DefaultAllocator: Allocator<N, R, C>,
39{
40 #[inline]
41 fn sub(&self, other: &Matrix<N, R, C, S>) -> OMatrix<N, R, C> {
42 other.map(|entry| *self - entry)
43 }
44}
45
46impl<N, R, C, S> ArgminSub<Matrix<N, R, C, S>, OMatrix<N, R, C>> for Matrix<N, R, C, S>
47where
48 N: Scalar + ClosedSub,
49 R: Dim,
50 C: Dim,
51 S: Storage<N, R, C>,
52 DefaultAllocator: Allocator<N, R, C>,
53{
54 #[inline]
55 fn sub(&self, other: &Matrix<N, R, C, S>) -> OMatrix<N, R, C> {
56 self - other
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::*;
63 use approx::assert_relative_eq;
64 use nalgebra::{Matrix2x3, Vector3};
65 use paste::item;
66
67 macro_rules! make_test {
68 ($t:ty) => {
69 item! {
70 #[test]
71 fn [<test_sub_vec_scalar_ $t>]() {
72 let a = Vector3::new(36 as $t, 39 as $t, 43 as $t);
73 let b = 1 as $t;
74 let target = Vector3::new(35 as $t, 38 as $t, 42 as $t);
75 let res = <Vector3<$t> as ArgminSub<$t, Vector3<$t>>>::sub(&a, &b);
76 for i in 0..3 {
77 assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
78 }
79 }
80 }
81
82 item! {
83 #[test]
84 fn [<test_sub_scalar_vec_ $t>]() {
85 let a = Vector3::new(1 as $t, 4 as $t, 8 as $t);
86 let b = 34 as $t;
87 let target = Vector3::new(33 as $t, 30 as $t, 26 as $t);
88 let res = <$t as ArgminSub<Vector3<$t>, Vector3<$t>>>::sub(&b, &a);
89 for i in 0..3 {
90 assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
91 }
92 }
93 }
94
95 item! {
96 #[test]
97 fn [<test_sub_vec_vec_ $t>]() {
98 let a = Vector3::new(41 as $t, 38 as $t, 34 as $t);
99 let b = Vector3::new(1 as $t, 4 as $t, 8 as $t);
100 let target =Vector3::new(40 as $t, 34 as $t, 26 as $t);
101 let res = <Vector3<$t> as ArgminSub<Vector3<$t>, Vector3<$t>>>::sub(&a, &b);
102 for i in 0..3 {
103 assert_relative_eq!(target[i] as f64, res[i] as f64, epsilon = f64::EPSILON);
104 }
105 }
106 }
107
108 item! {
109 #[test]
110 fn [<test_sub_mat_mat_ $t>]() {
111 let a = Matrix2x3::new(
112 43 as $t, 46 as $t, 50 as $t,
113 44 as $t, 47 as $t, 51 as $t
114 );
115 let b = Matrix2x3::new(
116 1 as $t, 4 as $t, 8 as $t,
117 2 as $t, 5 as $t, 9 as $t
118 );
119 let target = Matrix2x3::new(
120 42 as $t, 42 as $t, 42 as $t,
121 42 as $t, 42 as $t, 42 as $t
122 );
123 let res = <Matrix2x3<$t> as ArgminSub<Matrix2x3<$t>, Matrix2x3<$t>>>::sub(&a, &b);
124 for i in 0..3 {
125 for j in 0..2 {
126 assert_relative_eq!(target[(j, i)] as f64, res[(j, i)] as f64, epsilon = f64::EPSILON);
127 }
128 }
129 }
130 }
131
132 item! {
133 #[test]
134 fn [<test_sub_mat_scalar_ $t>]() {
135 let a = Matrix2x3::new(
136 43 as $t, 46 as $t, 50 as $t,
137 44 as $t, 47 as $t, 51 as $t
138 );
139 let b = 2 as $t;
140 let target = Matrix2x3::new(
141 41 as $t, 44 as $t, 48 as $t,
142 42 as $t, 45 as $t, 49 as $t
143 );
144 let res = <Matrix2x3<$t> as ArgminSub<$t, Matrix2x3<$t>>>::sub(&a, &b);
145 for i in 0..3 {
146 for j in 0..2 {
147 assert_relative_eq!(target[(j, i)] as f64, res[(j, i)] as f64, epsilon = f64::EPSILON);
148 }
149 }
150 }
151 }
152 };
153 }
154
155 make_test!(i8);
156 make_test!(u8);
157 make_test!(i16);
158 make_test!(u16);
159 make_test!(i32);
160 make_test!(u32);
161 make_test!(i64);
162 make_test!(u64);
163 make_test!(f32);
164 make_test!(f64);
165}