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