argmin_math/vec/
transpose.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
8// Note: This is not really the preferred way I think. Maybe this should also be implemented for
9// ArrayViews, which would probably make it more efficient.
10
11use crate::ArgminTranspose;
12use num_complex::Complex;
13
14macro_rules! make_transpose {
15    ($t:ty) => {
16        impl ArgminTranspose<Vec<Vec<$t>>> for Vec<Vec<$t>> {
17            fn t(self) -> Self {
18                let n1 = self.len();
19                let n2 = self[0].len();
20                let v = vec![<$t>::default(); n1];
21                let mut out = vec![v; n2];
22                for i in 0..n1 {
23                    for j in 0..n2 {
24                        out[j][i] = self[i][j];
25                    }
26                }
27                out
28            }
29        }
30    };
31}
32
33make_transpose!(i8);
34make_transpose!(u8);
35make_transpose!(i16);
36make_transpose!(u16);
37make_transpose!(i32);
38make_transpose!(u32);
39make_transpose!(i64);
40make_transpose!(u64);
41make_transpose!(f32);
42make_transpose!(f64);
43make_transpose!(Complex<i8>);
44make_transpose!(Complex<u8>);
45make_transpose!(Complex<i16>);
46make_transpose!(Complex<u16>);
47make_transpose!(Complex<i32>);
48make_transpose!(Complex<u32>);
49make_transpose!(Complex<i64>);
50make_transpose!(Complex<u64>);
51make_transpose!(Complex<f32>);
52make_transpose!(Complex<f64>);
53
54#[cfg(test)]
55mod tests {
56    use super::*;
57    use approx::assert_relative_eq;
58    use paste::item;
59
60    macro_rules! make_test {
61        ($t:ty) => {
62            item! {
63                #[test]
64                fn [<test_transpose_2d_1_ $t>]() {
65                    let a = vec![
66                        vec![1 as $t, 4 as $t],
67                        vec![8 as $t, 7 as $t]
68                    ];
69                    let target = vec![
70                        vec![1 as $t, 8 as $t],
71                        vec![4 as $t, 7 as $t]
72                    ];
73                    let res = a.t();
74                    for i in 0..2 {
75                        for j in 0..2 {
76                            assert_relative_eq!(target[i][j] as f64, res[i][j] as f64, epsilon = f64::EPSILON);
77                        }
78                    }
79                }
80            }
81
82            item! {
83                #[test]
84                fn [<test_transpose_2d_2_ $t>]() {
85                    let a = vec![
86                        vec![1 as $t, 4 as $t],
87                        vec![8 as $t, 7 as $t],
88                        vec![3 as $t, 6 as $t]
89                    ];
90                    let target = vec![
91                        vec![1 as $t, 8 as $t, 3 as $t],
92                        vec![4 as $t, 7 as $t, 6 as $t]
93                    ];
94                    let res = a.t();
95                    for i in 0..2 {
96                        for j in 0..3 {
97                            assert_relative_eq!(target[i][j] as f64, res[i][j] as f64, epsilon = f64::EPSILON);
98                        }
99                    }
100                }
101            }
102        };
103    }
104
105    make_test!(i8);
106    make_test!(u8);
107    make_test!(i16);
108    make_test!(u16);
109    make_test!(i32);
110    make_test!(u32);
111    make_test!(i64);
112    make_test!(u64);
113    make_test!(f32);
114    make_test!(f64);
115}