1+ #include < cstdint>
2+ #include < iostream>
3+ #include < vector>
4+
5+ #include " gtest/gtest.h"
6+ #include " layers/Tensor.hpp"
7+ #include " layers/TransposeLayer.hpp"
8+
9+ using namespace it_lab_ai ;
10+
11+ TEST (TransposeLayerTest, EmptyTensor) {
12+ Tensor input = make_tensor<float >({}, {0 });
13+ TransposeLayer layer;
14+ Tensor output;
15+
16+ EXPECT_THROW (layer.run (input, output), std::runtime_error);
17+ }
18+
19+ TEST (TransposeLayerTest, IdentityTranspose) {
20+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
21+ TransposeLayer layer ({0 , 1 });
22+ Tensor output;
23+
24+ layer.run (input, output);
25+
26+ ASSERT_EQ (output.get_shape (), Shape ({2 , 2 }));
27+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 }), 1 .0f );
28+ EXPECT_FLOAT_EQ (output.get <float >({0 , 1 }), 2 .0f );
29+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 }), 3 .0f );
30+ EXPECT_FLOAT_EQ (output.get <float >({1 , 1 }), 4 .0f );
31+ }
32+
33+ TEST (TransposeLayerTest, VectorTranspose) {
34+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {4 });
35+ TransposeLayer layer ({0 });
36+ Tensor output;
37+
38+ layer.run (input, output);
39+
40+ ASSERT_EQ (output.get_shape (), Shape ({4 }));
41+ EXPECT_FLOAT_EQ (output.get <float >({0 }), 1 .0f );
42+ EXPECT_FLOAT_EQ (output.get <float >({1 }), 2 .0f );
43+ EXPECT_FLOAT_EQ (output.get <float >({2 }), 3 .0f );
44+ EXPECT_FLOAT_EQ (output.get <float >({3 }), 4 .0f );
45+ }
46+
47+ TEST (TransposeLayerTest, InvalidPermutationSize) {
48+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
49+ TransposeLayer layer ({0 });
50+ Tensor output;
51+
52+ EXPECT_THROW (layer.run (input, output), std::invalid_argument);
53+ }
54+
55+ TEST (TransposeLayerTest, DuplicateAxes) {
56+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
57+ TransposeLayer layer ({0 , 0 });
58+ Tensor output;
59+
60+ EXPECT_THROW (layer.run (input, output), std::invalid_argument);
61+ }
62+
63+ TEST (TransposeLayerTest, NegativeAxis) {
64+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
65+ TransposeLayer layer ({0 , -1 });
66+ Tensor output;
67+
68+ EXPECT_THROW (layer.run (input, output), std::invalid_argument);
69+ }
70+
71+ TEST (TransposeLayerTest, LargeAxis) {
72+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
73+ TransposeLayer layer ({0 , 2 });
74+ Tensor output;
75+
76+ EXPECT_THROW (layer.run (input, output), std::invalid_argument);
77+ }
78+
79+ TEST (TransposeLayerTest, 4DTensorTranspose) {
80+ std::vector<float > data (16 );
81+ std::iota (data.begin (), data.end (), 1 .0f );
82+ Tensor input = make_tensor<float >(data, {2 , 2 , 2 , 2 });
83+ TransposeLayer layer ({3 , 1 , 0 , 2 });
84+ Tensor output;
85+
86+ layer.run (input, output);
87+
88+ ASSERT_EQ (output.get_shape (), Shape ({2 , 2 , 2 , 2 }));
89+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 , 0 , 0 }), 1 .0f );
90+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 , 0 , 0 }), 2 .0f );
91+ EXPECT_FLOAT_EQ (output.get <float >({0 , 1 , 0 , 0 }), 5 .0f );
92+ EXPECT_FLOAT_EQ (output.get <float >({1 , 1 , 0 , 0 }), 6 .0f );
93+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 , 0 , 1 }), 3 .0f );
94+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 , 0 , 1 }), 4 .0f );
95+ EXPECT_FLOAT_EQ (output.get <float >({0 , 1 , 0 , 1 }), 7 .0f );
96+ EXPECT_FLOAT_EQ (output.get <float >({1 , 1 , 0 , 1 }), 8 .0f );
97+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 , 1 , 0 }), 9 .0f );
98+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 , 1 , 0 }), 10 .0f );
99+ EXPECT_FLOAT_EQ (output.get <float >({0 , 1 , 1 , 0 }), 13 .0f );
100+ EXPECT_FLOAT_EQ (output.get <float >({1 , 1 , 1 , 0 }), 14 .0f );
101+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 , 1 , 1 }), 11 .0f );
102+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 , 1 , 1 }), 12 .0f );
103+ EXPECT_FLOAT_EQ (output.get <float >({0 , 1 , 1 , 1 }), 15 .0f );
104+ EXPECT_FLOAT_EQ (output.get <float >({1 , 1 , 1 , 1 }), 16 .0f );
105+ }
106+
107+ TEST (TransposeLayerTest, MatrixTranspose) {
108+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
109+ TransposeLayer layer ({1 , 0 });
110+ Tensor output;
111+
112+ layer.run (input, output);
113+
114+ ASSERT_EQ (output.get_shape (), Shape ({2 , 2 }));
115+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 }), 1 .0f );
116+ EXPECT_FLOAT_EQ (output.get <float >({0 , 1 }), 3 .0f );
117+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 }), 2 .0f );
118+ EXPECT_FLOAT_EQ (output.get <float >({1 , 1 }), 4 .0f );
119+ }
120+
121+ TEST (TransposeLayerTest, 3DTensor) {
122+ std::vector<float > data (24 );
123+ std::iota (data.begin (), data.end (), 1 .0f );
124+ Tensor input = make_tensor<float >(data, {2 , 3 , 4 });
125+ TransposeLayer layer ({2 , 0 , 1 });
126+ Tensor output;
127+
128+ layer.run (input, output);
129+
130+ ASSERT_EQ (output.get_shape (), Shape ({4 , 2 , 3 }));
131+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 , 0 }), 1 .0f );
132+ EXPECT_FLOAT_EQ (output.get <float >({3 , 1 , 2 }), 24 .0f );
133+ }
134+
135+ TEST (TransposeLayerTest, IntTensor) {
136+ Tensor input = make_tensor<int >({1 , 2 , 3 , 4 }, {2 , 2 });
137+ TransposeLayer layer ({1 , 0 });
138+ Tensor output;
139+ layer.run (input, output);
140+ EXPECT_EQ (output.get <int >({0 , 0 }), 1 );
141+ EXPECT_EQ (output.get <int >({1 , 0 }), 2 );
142+ EXPECT_EQ (output.get <int >({0 , 1 }), 3 );
143+ EXPECT_EQ (output.get <int >({1 , 1 }), 4 );
144+ }
145+
146+ TEST (TransposeLayerTest, 1DDefaultPermutationIsNoOp) {
147+ Tensor input = make_tensor<float >({1 .0f , 2 .0f , 3 .0f , 4 .0f }, {4 });
148+
149+ TransposeLayer layer;
150+ Tensor output;
151+
152+ EXPECT_NO_THROW (layer.run (input, output));
153+
154+ EXPECT_EQ (output.get_shape (), Shape ({4 }));
155+ EXPECT_FLOAT_EQ (output.get <float >({0 }), 1 .0f );
156+ EXPECT_FLOAT_EQ (output.get <float >({1 }), 2 .0f );
157+ EXPECT_FLOAT_EQ (output.get <float >({2 }), 3 .0f );
158+ EXPECT_FLOAT_EQ (output.get <float >({3 }), 4 .0f );
159+ }
160+
161+ TEST (TransposeLayerTest, MultipleRunsWithDifferentRanks) {
162+ TransposeLayer layer ({1 , 0 });
163+
164+ {
165+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
166+ Tensor output;
167+ layer.run (input, output);
168+ EXPECT_EQ (output.get_shape (), Shape ({2 , 2 }));
169+ EXPECT_FLOAT_EQ (output.get <float >({0 , 0 }), 1 .0f );
170+ EXPECT_FLOAT_EQ (output.get <float >({1 , 0 }), 2 .0f );
171+ }
172+
173+ {
174+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 , 5 , 6 }, {3 , 2 });
175+ Tensor output;
176+ layer.run (input, output);
177+ EXPECT_EQ (output.get_shape (), Shape ({2 , 3 }));
178+ }
179+
180+ {
181+ Tensor input = make_tensor<float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }, {2 , 2 , 2 });
182+ Tensor output;
183+ EXPECT_THROW (layer.run (input, output), std::invalid_argument);
184+ }
185+ }
186+
187+ TEST (TransposeLayerTest, ExplicitPermutationWithDifferentRanks) {
188+ TransposeLayer layer ({1 , 0 });
189+
190+ Tensor input2D = make_tensor<float >({1 , 2 , 3 , 4 }, {2 , 2 });
191+ Tensor output2D;
192+ layer.run (input2D, output2D);
193+ EXPECT_EQ (output2D.get_shape (), Shape ({2 , 2 }));
194+ EXPECT_FLOAT_EQ (output2D.get <float >({1 , 0 }), 2 .0f );
195+
196+ Tensor input3D = make_tensor<float >({1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 }, {2 , 2 , 2 });
197+ Tensor output3D;
198+ EXPECT_THROW (layer.run (input3D, output3D), std::invalid_argument);
199+ }
0 commit comments