argmin/core/math/
transpose_vec.rs

1// Copyright 2018-2020 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::core::math::ArgminTranspose;
12use num_complex::Complex;
13
14macro_rules! make_transpose {
15    ($t:ty) => {
16        impl ArgminTranspose for Vec<Vec<$t>> {
17            fn t(self) -> Self {
18                let n1 = self.len();
19                let n2 = self[0].len();
20                // let mut out: Vec<Vec<$t>> = vec![vec![0; n1]; n2];
21                let mut v = Vec::with_capacity(n1);
22                unsafe {
23                    v.set_len(n1);
24                }
25                let mut out = vec![v; n2];
26                for i in 0..n1 {
27                    for j in 0..n2 {
28                        out[j][i] = self[i][j];
29                    }
30                }
31                out
32            }
33        }
34    };
35}
36
37make_transpose!(isize);
38make_transpose!(usize);
39make_transpose!(i8);
40make_transpose!(u8);
41make_transpose!(i16);
42make_transpose!(u16);
43make_transpose!(i32);
44make_transpose!(u32);
45make_transpose!(i64);
46make_transpose!(u64);
47make_transpose!(f32);
48make_transpose!(f64);
49make_transpose!(Complex<isize>);
50make_transpose!(Complex<usize>);
51make_transpose!(Complex<i8>);
52make_transpose!(Complex<u8>);
53make_transpose!(Complex<i16>);
54make_transpose!(Complex<u16>);
55make_transpose!(Complex<i32>);
56make_transpose!(Complex<u32>);
57make_transpose!(Complex<i64>);
58make_transpose!(Complex<u64>);
59make_transpose!(Complex<f32>);
60make_transpose!(Complex<f64>);
61
62#[cfg(test)]
63mod tests {
64    use super::*;
65    use paste::item;
66
67    macro_rules! make_test {
68        ($t:ty) => {
69            item! {
70                #[test]
71                fn [<test_transpose_2d_1_ $t>]() {
72                    let a = vec![
73                        vec![1 as $t, 4 as $t],
74                        vec![8 as $t, 7 as $t]
75                    ];
76                    let target = vec![
77                        vec![1 as $t, 8 as $t],
78                        vec![4 as $t, 7 as $t]
79                    ];
80                    let res = a.t();
81                    for i in 0..2 {
82                        for j in 0..2 {
83                            assert!(((target[i][j] - res[i][j]) as f64).abs() < std::f64::EPSILON);
84                        }
85                    }
86                }
87            }
88
89            item! {
90                #[test]
91                fn [<test_transpose_2d_2_ $t>]() {
92                    let a = vec![
93                        vec![1 as $t, 4 as $t],
94                        vec![8 as $t, 7 as $t],
95                        vec![3 as $t, 6 as $t]
96                    ];
97                    let target = vec![
98                        vec![1 as $t, 8 as $t, 3 as $t],
99                        vec![4 as $t, 7 as $t, 6 as $t]
100                    ];
101                    let res = a.t();
102                    for i in 0..2 {
103                        for j in 0..3 {
104                            assert!(((target[i][j] - res[i][j]) as f64).abs() < std::f64::EPSILON);
105                        }
106                    }
107                }
108            }
109        };
110    }
111
112    make_test!(isize);
113    make_test!(usize);
114    make_test!(i8);
115    make_test!(u8);
116    make_test!(i16);
117    make_test!(u16);
118    make_test!(i32);
119    make_test!(u32);
120    make_test!(i64);
121    make_test!(u64);
122    make_test!(f32);
123    make_test!(f64);
124}