argmin_math/ndarray_m/
mul.rs

1// Copyright 2018-2024 argmin developers
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::ArgminMul;
9use ndarray::{Array1, Array2};
10use num_complex::Complex;
11
12macro_rules! make_mul {
13    ($t:ty) => {
14        impl ArgminMul<$t, Array1<$t>> for Array1<$t> {
15            #[inline]
16            fn mul(&self, other: &$t) -> Array1<$t> {
17                cfg_if::cfg_if! {
18                    if #[cfg(feature = "ndarray_0_14")] {
19                        self.iter().map(|s| s * other).collect()
20                    } else if #[cfg(feature = "ndarray_0_13")]  {
21                        self.iter().map(|s| s * other).collect()
22                    } else {
23                        self * *other
24                    }
25                }
26            }
27        }
28
29        impl ArgminMul<Array1<$t>, Array1<$t>> for $t {
30            #[inline]
31            fn mul(&self, other: &Array1<$t>) -> Array1<$t> {
32                cfg_if::cfg_if! {
33                    if #[cfg(feature = "ndarray_0_14")] {
34                        other.iter().map(|o| o * *self).collect()
35                    } else if #[cfg(feature = "ndarray_0_13")]  {
36                        other.iter().map(|o| o * *self).collect()
37                    } else {
38                        *self * other
39                    }
40                }
41            }
42        }
43
44        impl ArgminMul<Array1<$t>, Array1<$t>> for Array1<$t> {
45            #[inline]
46            fn mul(&self, other: &Array1<$t>) -> Array1<$t> {
47                cfg_if::cfg_if! {
48                    if #[cfg(feature = "ndarray_0_14")] {
49                        // Need to assert that the shapes are the same here because the iterators
50                        // will silently truncate.
51                        assert_eq!(self.shape(), other.shape());
52                        self.iter().zip(other.iter()).map(|(s, o)| s * o).collect()
53                    } else if #[cfg(feature = "ndarray_0_13")]  {
54                        // Need to assert that the shapes are the same here because the iterators
55                        // will silently truncate.
56                        assert_eq!(self.shape(), other.shape());
57                        self.iter().zip(other.iter()).map(|(s, o)| s * o).collect()
58                    } else {
59                        self * other
60                    }
61                }
62            }
63        }
64
65        impl ArgminMul<Array2<$t>, Array2<$t>> for Array2<$t> {
66            #[inline]
67            fn mul(&self, other: &Array2<$t>) -> Array2<$t> {
68                self * other
69            }
70        }
71
72        impl ArgminMul<$t, Array2<$t>> for Array2<$t> {
73            #[inline]
74            fn mul(&self, other: &$t) -> Array2<$t> {
75                self * *other
76            }
77        }
78
79        impl ArgminMul<Array2<$t>, Array2<$t>> for $t {
80            #[inline]
81            fn mul(&self, other: &Array2<$t>) -> Array2<$t> {
82                other * *self
83            }
84        }
85    };
86}
87
88macro_rules! make_complex_mul {
89    ($t:ty) => {
90        impl ArgminMul<Complex<$t>, Array1<Complex<$t>>> for Array1<Complex<$t>> {
91            #[inline]
92            fn mul(&self, other: &Complex<$t>) -> Array1<Complex<$t>> {
93                self * *other
94            }
95        }
96
97        impl ArgminMul<$t, Array1<Complex<$t>>> for Array1<Complex<$t>> {
98            #[inline]
99            fn mul(&self, other: &$t) -> Array1<Complex<$t>> {
100                self * *other
101            }
102        }
103
104        impl ArgminMul<Array1<Complex<$t>>, Array1<Complex<$t>>> for Complex<$t> {
105            #[inline]
106            fn mul(&self, other: &Array1<Complex<$t>>) -> Array1<Complex<$t>> {
107                *self * other
108            }
109        }
110
111        impl ArgminMul<Array1<Complex<$t>>, Array1<Complex<$t>>> for $t {
112            #[inline]
113            fn mul(&self, other: &Array1<Complex<$t>>) -> Array1<Complex<$t>> {
114                Complex::new(*self, 0 as $t) * other
115            }
116        }
117
118        impl ArgminMul<Array1<Complex<$t>>, Array1<Complex<$t>>> for Array1<Complex<$t>> {
119            #[inline]
120            fn mul(&self, other: &Array1<Complex<$t>>) -> Array1<Complex<$t>> {
121                self * other
122            }
123        }
124
125        impl ArgminMul<Array2<Complex<$t>>, Array2<Complex<$t>>> for Array2<Complex<$t>> {
126            #[inline]
127            fn mul(&self, other: &Array2<Complex<$t>>) -> Array2<Complex<$t>> {
128                self * other
129            }
130        }
131
132        impl ArgminMul<Complex<$t>, Array2<Complex<$t>>> for Array2<Complex<$t>> {
133            #[inline]
134            fn mul(&self, other: &Complex<$t>) -> Array2<Complex<$t>> {
135                self * *other
136            }
137        }
138
139        impl ArgminMul<$t, Array2<Complex<$t>>> for Array2<Complex<$t>> {
140            #[inline]
141            fn mul(&self, other: &$t) -> Array2<Complex<$t>> {
142                self * *other
143            }
144        }
145
146        impl ArgminMul<Array2<Complex<$t>>, Array2<Complex<$t>>> for Complex<$t> {
147            #[inline]
148            fn mul(&self, other: &Array2<Complex<$t>>) -> Array2<Complex<$t>> {
149                *self * other
150            }
151        }
152
153        impl ArgminMul<Array2<Complex<$t>>, Array2<Complex<$t>>> for $t {
154            #[inline]
155            fn mul(&self, other: &Array2<Complex<$t>>) -> Array2<Complex<$t>> {
156                Complex::new(*self, 0 as $t) * other
157            }
158        }
159    };
160}
161
162macro_rules! make_complex_integer_mul {
163    ($t:ty) => {
164        impl ArgminMul<Complex<$t>, Array1<Complex<$t>>> for Array1<Complex<$t>> {
165            #[inline]
166            fn mul(&self, other: &Complex<$t>) -> Array1<Complex<$t>> {
167                self.iter().map(|s| s * *other).collect()
168            }
169        }
170
171        impl ArgminMul<$t, Array1<Complex<$t>>> for Array1<Complex<$t>> {
172            #[inline]
173            fn mul(&self, other: &$t) -> Array1<Complex<$t>> {
174                self.iter().map(|s| s * *other).collect()
175            }
176        }
177
178        impl ArgminMul<Array1<Complex<$t>>, Array1<Complex<$t>>> for Complex<$t> {
179            #[inline]
180            fn mul(&self, other: &Array1<Complex<$t>>) -> Array1<Complex<$t>> {
181                other.iter().map(|o| o * *self).collect()
182            }
183        }
184
185        impl ArgminMul<Array1<Complex<$t>>, Array1<Complex<$t>>> for $t {
186            #[inline]
187            fn mul(&self, other: &Array1<Complex<$t>>) -> Array1<Complex<$t>> {
188                let s = Complex::new(*self, 0 as $t);
189                other.iter().map(|o| o * s).collect()
190            }
191        }
192
193        impl ArgminMul<Array1<Complex<$t>>, Array1<Complex<$t>>> for Array1<Complex<$t>> {
194            #[inline]
195            fn mul(&self, other: &Array1<Complex<$t>>) -> Array1<Complex<$t>> {
196                self * other
197            }
198        }
199
200        impl ArgminMul<Array2<Complex<$t>>, Array2<Complex<$t>>> for Array2<Complex<$t>> {
201            #[inline]
202            fn mul(&self, other: &Array2<Complex<$t>>) -> Array2<Complex<$t>> {
203                self * other
204            }
205        }
206
207        impl ArgminMul<Complex<$t>, Array2<Complex<$t>>> for Array2<Complex<$t>> {
208            #[inline]
209            fn mul(&self, other: &Complex<$t>) -> Array2<Complex<$t>> {
210                Array2::from_shape_fn((self.nrows(), self.ncols()), |(i, j)| self[(i, j)] * *other)
211            }
212        }
213
214        impl ArgminMul<$t, Array2<Complex<$t>>> for Array2<Complex<$t>> {
215            #[inline]
216            fn mul(&self, other: &$t) -> Array2<Complex<$t>> {
217                self * *other
218            }
219        }
220
221        impl ArgminMul<Array2<Complex<$t>>, Array2<Complex<$t>>> for Complex<$t> {
222            #[inline]
223            fn mul(&self, other: &Array2<Complex<$t>>) -> Array2<Complex<$t>> {
224                Array2::from_shape_fn((other.nrows(), other.ncols()), |(i, j)| {
225                    other[(i, j)] * *self
226                })
227            }
228        }
229
230        impl ArgminMul<Array2<Complex<$t>>, Array2<Complex<$t>>> for $t {
231            #[inline]
232            fn mul(&self, other: &Array2<Complex<$t>>) -> Array2<Complex<$t>> {
233                Array2::from_shape_fn((other.nrows(), other.ncols()), |(i, j)| {
234                    other[(i, j)] * *self
235                })
236            }
237        }
238    };
239}
240
241make_mul!(i8);
242make_mul!(u8);
243make_mul!(i16);
244make_mul!(u16);
245make_mul!(i32);
246make_mul!(u32);
247make_mul!(i64);
248make_mul!(u64);
249make_mul!(f32);
250make_mul!(f64);
251make_complex_mul!(f32);
252make_complex_mul!(f64);
253make_complex_integer_mul!(i8);
254make_complex_integer_mul!(u8);
255make_complex_integer_mul!(i16);
256make_complex_integer_mul!(u16);
257make_complex_integer_mul!(i32);
258make_complex_integer_mul!(u32);
259make_complex_integer_mul!(i64);
260make_complex_integer_mul!(u64);
261
262// All code that does not depend on a linked ndarray-linalg backend can still be tested as normal.
263// To avoid dublicating tests and to allow convenient testing of functionality that does not need ndarray-linalg the tests are still included here.
264// The tests expect the name for the crate containing the tested functions to be argmin_math
265#[cfg(test)]
266use crate as argmin_math;
267include!(concat!(
268    env!("CARGO_MANIFEST_DIR"),
269    "/ndarray-tests-src/mul.rs"
270));