Deprecate nGraph v0 ops and builders (#1856)
[platform/upstream/dldt.git] / ngraph / test / backend / concat.in.cpp
1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //     http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //*****************************************************************************
16
17 #include "gtest/gtest.h"
18 #include "ngraph/ngraph.hpp"
19 #include "ngraph/runtime/tensor.hpp"
20 #include "runtime/backend.hpp"
21 #include "util/all_close.hpp"
22 #include "util/all_close_f.hpp"
23 #include "util/ndarray.hpp"
24 #include "util/test_control.hpp"
25 #include "util/test_tools.hpp"
26
27 NGRAPH_SUPPRESS_DEPRECATED_START
28
29 using namespace std;
30 using namespace ngraph;
31
32 static string s_manifest = "${MANIFEST}";
33
34 NGRAPH_TEST(${BACKEND_NAME}, concat_negative_axis)
35 {
36     auto pshape_a = PartialShape::dynamic();
37     auto A = make_shared<op::Parameter>(element::f32, pshape_a);
38     auto pshape_b = PartialShape::dynamic();
39     auto B = make_shared<op::Parameter>(element::f32, pshape_b);
40     auto pshape_c = PartialShape::dynamic();
41     auto C = make_shared<op::Parameter>(element::f32, pshape_c);
42     auto pshape_r = PartialShape::dynamic();
43     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, -1),
44                                    ParameterVector{A, B, C});
45
46     auto backend = runtime::Backend::create("${BACKEND_NAME}", true);
47
48     // Create some tensors for input/output
49     auto a = backend->create_tensor(element::f32, Shape{2, 2});
50     copy_data(a, vector<float>{2, 4, 8, 16});
51     auto b = backend->create_tensor(element::f32, Shape{2, 3});
52     copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
53     auto c = backend->create_tensor(element::f32, Shape{2, 3});
54     copy_data(c, vector<float>{2, 3, 5, 7, 11, 13});
55     auto result = backend->create_dynamic_tensor(element::f32, PartialShape::dynamic());
56     auto handle = backend->compile(f);
57     handle->call_with_validate({result}, {a, b, c});
58     ASSERT_EQ(result->get_shape(), (Shape{2, 8}));
59     EXPECT_TRUE(
60         test::all_close_f((vector<float>{2, 4, 1, 2, 4, 2, 3, 5, 8, 16, 8, 16, 32, 7, 11, 13}),
61                           read_vector<float>(result)));
62 }
63 NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_colwise)
64 {
65     Shape shape_a{2, 2};
66     auto A = make_shared<op::Parameter>(element::f32, shape_a);
67     Shape shape_b{2, 3};
68     auto B = make_shared<op::Parameter>(element::f32, shape_b);
69     Shape shape_c{2, 3};
70     auto C = make_shared<op::Parameter>(element::f32, shape_c);
71     Shape shape_r{2, 8};
72     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 1),
73                                    ParameterVector{A, B, C});
74
75     auto backend = runtime::Backend::create("${BACKEND_NAME}");
76
77     // Create some tensors for input/output
78     auto a = backend->create_tensor(element::f32, shape_a);
79     copy_data(a, vector<float>{2, 4, 8, 16});
80     auto b = backend->create_tensor(element::f32, shape_b);
81     copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
82     auto c = backend->create_tensor(element::f32, shape_c);
83     copy_data(c, vector<float>{2, 3, 5, 7, 11, 13});
84     auto result = backend->create_tensor(element::f32, shape_r);
85
86     auto handle = backend->compile(f);
87     handle->call_with_validate({result}, {a, b, c});
88     EXPECT_TRUE(
89         test::all_close_f((vector<float>{2, 4, 1, 2, 4, 2, 3, 5, 8, 16, 8, 16, 32, 7, 11, 13}),
90                           read_vector<float>(result),
91                           MIN_FLOAT_TOLERANCE_BITS));
92 }
93
94 NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_rowwise)
95 {
96     Shape shape_a{2, 2};
97     auto A = make_shared<op::Parameter>(element::f32, shape_a);
98     Shape shape_b{3, 2};
99     auto B = make_shared<op::Parameter>(element::f32, shape_b);
100     Shape shape_c{3, 2};
101     auto C = make_shared<op::Parameter>(element::f32, shape_c);
102     Shape shape_r{8, 2};
103     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
104                                    ParameterVector{A, B, C});
105
106     auto backend = runtime::Backend::create("${BACKEND_NAME}");
107
108     // Create some tensors for input/output
109     auto a = backend->create_tensor(element::f32, shape_a);
110     copy_data(a, vector<float>{2, 4, 8, 16});
111     auto b = backend->create_tensor(element::f32, shape_b);
112     copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
113     auto c = backend->create_tensor(element::f32, shape_c);
114     copy_data(c, vector<float>{2, 3, 5, 7, 11, 13});
115     auto result = backend->create_tensor(element::f32, shape_r);
116
117     auto handle = backend->compile(f);
118     handle->call_with_validate({result}, {a, b, c});
119     EXPECT_TRUE(
120         test::all_close_f((vector<float>{2, 4, 8, 16, 1, 2, 4, 8, 16, 32, 2, 3, 5, 7, 11, 13}),
121                           read_vector<float>(result),
122                           MIN_FLOAT_TOLERANCE_BITS));
123 }
124
125 NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_int64)
126 {
127     Shape shape_a{2, 2};
128     auto A = make_shared<op::Parameter>(element::i64, shape_a);
129     Shape shape_b{3, 2};
130     auto B = make_shared<op::Parameter>(element::i64, shape_b);
131     Shape shape_c{3, 2};
132     auto C = make_shared<op::Parameter>(element::i64, shape_c);
133     Shape shape_r{8, 2};
134     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
135                                    ParameterVector{A, B, C});
136
137     auto backend = runtime::Backend::create("${BACKEND_NAME}");
138
139     // Create some tensors for input/output
140     auto a = backend->create_tensor(element::i64, shape_a);
141     copy_data(a, vector<int64_t>{2, 4, 8, 16});
142     auto b = backend->create_tensor(element::i64, shape_b);
143     copy_data(b, vector<int64_t>{1, 2, 4, 8, 16, 32});
144     auto c = backend->create_tensor(element::i64, shape_c);
145     copy_data(c, vector<int64_t>{2, 3, 5, 7, 11, 13});
146     auto result = backend->create_tensor(element::i64, shape_r);
147
148     auto handle = backend->compile(f);
149     handle->call_with_validate({result}, {a, b, c});
150     EXPECT_EQ((vector<int64_t>{2, 4, 8, 16, 1, 2, 4, 8, 16, 32, 2, 3, 5, 7, 11, 13}),
151               read_vector<int64_t>(result));
152 }
153
154 // Params to drive concat_vector_large testing variations
155 class concat_vector_params : public ::testing::TestWithParam<int>
156 {
157 protected:
158     concat_vector_params() { num_inputs = GetParam(); }
159     uint32_t num_inputs;
160 };
161
162 NGRAPH_TEST_P(${BACKEND_NAME}, concat_vector_params, concat_vector_large)
163 {
164     Shape shape_a{1};
165     NodeVector inputs;
166     ParameterVector inputs_param;
167     for (uint32_t i = 0; i < num_inputs; i++)
168     {
169         auto A = make_shared<op::Parameter>(element::f32, shape_a);
170         inputs_param.push_back(A);
171         inputs.push_back(A);
172     }
173     Shape shape_r{num_inputs};
174     auto f = make_shared<Function>(make_shared<op::Concat>(inputs, 0), inputs_param);
175
176     auto backend = runtime::Backend::create("${BACKEND_NAME}");
177
178     // Create some tensors for input/output
179     std::vector<std::shared_ptr<runtime::Tensor>> inputs_value;
180     std::vector<float> ref_result;
181     for (uint32_t i = 0; i < num_inputs; i++)
182     {
183         auto a = backend->create_tensor(element::f32, shape_a);
184         copy_data(a, vector<float>{static_cast<float>(i)});
185         ref_result.push_back(static_cast<float>(i));
186         inputs_value.push_back(a);
187     }
188     auto result = backend->create_tensor(element::f32, shape_r);
189
190     auto handle = backend->compile(f);
191     handle->call_with_validate({result}, inputs_value);
192     EXPECT_TRUE(
193         test::all_close_f(ref_result, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
194 }
195
196 // concat_vector_large case generation
197 // Add thhosw tests to cover paramter space overflow:
198 // cuda kernel parameter space have limit, if there is large number of parameters,
199 // there will be overflow for parameter space.
200 NGRAPH_INSTANTIATE_TEST_CASE_P(${BACKEND_NAME},
201                                input_sizes,
202                                concat_vector_params,
203                                testing::Values(100, 128, 999));
204
205 NGRAPH_TEST(${BACKEND_NAME}, concat_vector)
206 {
207     Shape shape_a{4};
208     auto A = make_shared<op::Parameter>(element::f32, shape_a);
209     Shape shape_b{6};
210     auto B = make_shared<op::Parameter>(element::f32, shape_b);
211     Shape shape_c{2};
212     auto C = make_shared<op::Parameter>(element::f32, shape_c);
213     Shape shape_r{12};
214     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
215                                    ParameterVector{A, B, C});
216
217     auto backend = runtime::Backend::create("${BACKEND_NAME}");
218
219     // Create some tensors for input/output
220     auto a = backend->create_tensor(element::f32, shape_a);
221     copy_data(a, vector<float>{2, 4, 8, 16});
222     auto b = backend->create_tensor(element::f32, shape_b);
223     copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
224     auto c = backend->create_tensor(element::f32, shape_c);
225     copy_data(c, vector<float>{18, 19});
226     auto result = backend->create_tensor(element::f32, shape_r);
227
228     auto handle = backend->compile(f);
229     handle->call_with_validate({result}, {a, b, c});
230     EXPECT_TRUE(test::all_close_f((vector<float>{2, 4, 8, 16, 1, 2, 4, 8, 16, 32, 18, 19}),
231                                   read_vector<float>(result),
232                                   MIN_FLOAT_TOLERANCE_BITS));
233 }
234
235 NGRAPH_TEST(${BACKEND_NAME}, concat_4d_tensor)
236 {
237     Shape shape{1, 1, 1, 1};
238     auto A = make_shared<op::Parameter>(element::f32, shape);
239     auto B = make_shared<op::Parameter>(element::f32, shape);
240     auto C = make_shared<op::Parameter>(element::f32, shape);
241     Shape shape_r{3, 1, 1, 1};
242     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
243                                    ParameterVector{A, B, C});
244
245     auto backend = runtime::Backend::create("${BACKEND_NAME}");
246
247     // Create some tensors for input/output
248     auto a = backend->create_tensor(element::f32, shape);
249     copy_data(a, vector<float>{1});
250     auto b = backend->create_tensor(element::f32, shape);
251     copy_data(b, vector<float>{2});
252     auto c = backend->create_tensor(element::f32, shape);
253     copy_data(c, vector<float>{3});
254     auto result = backend->create_tensor(element::f32, shape_r);
255
256     auto handle = backend->compile(f);
257     handle->call_with_validate({result}, {a, b, c});
258     EXPECT_TRUE(test::all_close_f(
259         (vector<float>{1, 2, 3}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
260 }
261
262 NGRAPH_TEST(${BACKEND_NAME}, concat_2d_tensor)
263 {
264     Shape shape{1, 1};
265     auto A = make_shared<op::Parameter>(element::f32, shape);
266     auto B = make_shared<op::Parameter>(element::f32, shape);
267     auto C = make_shared<op::Parameter>(element::f32, shape);
268     Shape shape_r{3, 1};
269     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
270                                    ParameterVector{A, B, C});
271
272     auto backend = runtime::Backend::create("${BACKEND_NAME}");
273
274     // Create some tensors for input/output
275     auto a = backend->create_tensor(element::f32, shape);
276     copy_data(a, vector<float>{1});
277     auto b = backend->create_tensor(element::f32, shape);
278     copy_data(b, vector<float>{2});
279     auto c = backend->create_tensor(element::f32, shape);
280     copy_data(c, vector<float>{3});
281     auto result = backend->create_tensor(element::f32, shape_r);
282
283     auto handle = backend->compile(f);
284     handle->call_with_validate({result}, {a, b, c});
285     EXPECT_TRUE(test::all_close_f(
286         (vector<float>{1, 2, 3}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
287 }
288
289 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_2d_tensor)
290 {
291     Shape shape{1, 1};
292     auto A = make_shared<op::Parameter>(element::f32, shape);
293     auto B = make_shared<op::Parameter>(element::f32, shape);
294     auto add1 = make_shared<op::Add>(A, B);
295     auto C = make_shared<op::Parameter>(element::f32, shape);
296     auto D = make_shared<op::Parameter>(element::f32, shape);
297     auto add2 = make_shared<op::Add>(C, D);
298     auto subtract = make_shared<op::Subtract>(C, A);
299     Shape shape_r{3, 1};
300     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{add1, add2, subtract}, 0),
301                                    ParameterVector{A, B, C, D});
302
303     auto backend = runtime::Backend::create("${BACKEND_NAME}");
304
305     // Create some tensors for input/output
306     auto a = backend->create_tensor(element::f32, shape);
307     copy_data(a, vector<float>{1});
308     auto b = backend->create_tensor(element::f32, shape);
309     copy_data(b, vector<float>{2});
310     auto c = backend->create_tensor(element::f32, shape);
311     copy_data(c, vector<float>{3});
312     auto d = backend->create_tensor(element::f32, shape);
313     copy_data(d, vector<float>{4});
314     auto result = backend->create_tensor(element::f32, shape_r);
315
316     auto handle = backend->compile(f);
317     handle->call_with_validate({result}, {a, b, c, d});
318     EXPECT_TRUE(test::all_close_f(
319         (vector<float>{3, 7, 2}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
320 }
321
322 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_propagate_2d_tensor)
323 {
324     Shape shape{1, 1};
325     auto A = make_shared<op::Parameter>(element::f32, shape);
326     auto B = make_shared<op::Parameter>(element::f32, shape);
327     auto add1 = make_shared<op::Add>(A, B);
328     auto C = make_shared<op::Parameter>(element::f32, shape);
329     auto D = make_shared<op::Parameter>(element::f32, shape);
330     auto add2 = make_shared<op::Add>(C, D);
331     auto concat1 = make_shared<op::Concat>(NodeVector{add1, add2}, 0);
332     auto subtract = make_shared<op::Subtract>(C, A);
333     Shape shape_r{3, 1};
334     auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{concat1, subtract}, 0),
335                                    ParameterVector{A, B, C, D});
336
337     auto backend = runtime::Backend::create("${BACKEND_NAME}");
338
339     // Create some tensors for input/output
340     auto a = backend->create_tensor(element::f32, shape);
341     copy_data(a, vector<float>{1});
342     auto b = backend->create_tensor(element::f32, shape);
343     copy_data(b, vector<float>{2});
344     auto c = backend->create_tensor(element::f32, shape);
345     copy_data(c, vector<float>{3});
346     auto d = backend->create_tensor(element::f32, shape);
347     copy_data(d, vector<float>{4});
348     auto result = backend->create_tensor(element::f32, shape_r);
349
350     auto handle = backend->compile(f);
351     handle->call_with_validate({result}, {a, b, c, d});
352     EXPECT_TRUE(test::all_close_f(
353         (vector<float>{3, 7, 2}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
354 }
355
356 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_tree_1)
357 {
358     Shape shape{1, 2, 2};
359     Shape shape_r{1, 4, 2};
360     auto A = make_shared<op::Parameter>(element::f32, shape);
361     auto B = make_shared<op::Parameter>(element::f32, shape);
362     auto add1 = make_shared<op::Add>(A, B);
363     auto add2 = make_shared<op::Add>(A, B);
364     auto concat = make_shared<op::Concat>(NodeVector{add1, add2}, 1);
365     auto f = make_shared<Function>(make_shared<op::Add>(concat, concat), ParameterVector{A, B});
366     auto backend = runtime::Backend::create("${BACKEND_NAME}");
367     // Create some tensors for input/output
368     auto a = backend->create_tensor(element::f32, shape);
369     copy_data(a, vector<float>{1, 1, 1, 1});
370     auto b = backend->create_tensor(element::f32, shape);
371     copy_data(b, vector<float>{1, 1, 1, 1});
372
373     auto result = backend->create_tensor(element::f32, shape_r);
374     auto handle = backend->compile(f);
375     handle->call_with_validate({result}, {a, b});
376     vector<float> expected;
377     expected.resize(8, 4);
378
379     EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
380 }
381
382 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_tree_2)
383 {
384     Shape shape{1, 2, 2};
385     Shape shape_r{1, 8, 2};
386     auto A = make_shared<op::Parameter>(element::f32, shape);
387     auto B = make_shared<op::Parameter>(element::f32, shape);
388     auto add1 = make_shared<op::Add>(A, B);
389     auto add2 = make_shared<op::Add>(A, B);
390     auto concat1 = make_shared<op::Concat>(NodeVector{add1, add2}, 1);
391     auto concat2 = make_shared<op::Concat>(NodeVector{add1, add2}, 1);
392     auto concat12 = make_shared<op::Concat>(NodeVector{concat1, concat2}, 1);
393     auto f = make_shared<Function>(make_shared<op::Add>(concat12, concat12), ParameterVector{A, B});
394     auto backend = runtime::Backend::create("${BACKEND_NAME}");
395
396     // Create some tensors for input/output
397     auto a = backend->create_tensor(element::f32, shape);
398     copy_data(a, vector<float>{1, 1, 1, 1});
399     auto b = backend->create_tensor(element::f32, shape);
400     copy_data(b, vector<float>{1, 1, 1, 1});
401     auto result = backend->create_tensor(element::f32, shape_r);
402     auto handle = backend->compile(f);
403     handle->call_with_validate({result}, {a, b});
404     vector<float> expected;
405     expected.resize(16, 4);
406
407     EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
408 }
409
410 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_tree_3)
411 {
412     Shape shape{1, 2, 2};
413     Shape shape_r{1, 16, 2};
414     auto A = make_shared<op::Parameter>(element::f32, shape);
415     auto B = make_shared<op::Parameter>(element::f32, shape);
416     auto concat1 = make_shared<op::Concat>(NodeVector{A, B}, 1);
417     auto concat2 = make_shared<op::Concat>(NodeVector{A, B}, 1);
418     auto concat3 = make_shared<op::Concat>(NodeVector{A, B}, 1);
419     auto concat4 = make_shared<op::Concat>(NodeVector{A, B}, 1);
420     auto concat12 = make_shared<op::Concat>(NodeVector{concat1, concat2}, 1);
421     auto concat34 = make_shared<op::Concat>(NodeVector{concat3, concat4}, 1);
422     auto concat14 = make_shared<op::Concat>(NodeVector{concat12, concat34}, 1);
423     auto f = make_shared<Function>(make_shared<op::Add>(concat14, concat14), ParameterVector{A, B});
424     auto backend = runtime::Backend::create("${BACKEND_NAME}");
425     // Create some tensors for input/output
426     auto a = backend->create_tensor(element::f32, shape);
427     copy_data(a, vector<float>{1, 1, 1, 1});
428     auto b = backend->create_tensor(element::f32, shape);
429     copy_data(b, vector<float>{1, 1, 1, 1});
430     auto result = backend->create_tensor(element::f32, shape_r);
431     auto handle = backend->compile(f);
432     handle->call_with_validate({result}, {a, b});
433     vector<float> expected;
434     expected.resize(32, 2);
435
436     EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
437 }
438
439 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_add_concat)
440 {
441     Shape shape{2, 2};
442     Shape shape_r{4, 2};
443     auto A = make_shared<op::Parameter>(element::f32, shape);
444     auto B = make_shared<op::Parameter>(element::f32, shape);
445     auto add1 = make_shared<op::Add>(A, B);
446     auto add2 = make_shared<op::Add>(add1, add1);
447     auto concat = make_shared<op::Concat>(NodeVector{add1, add2}, 0);
448     auto add3 = make_shared<op::Add>(concat, concat);
449     auto f = make_shared<Function>(add3, ParameterVector{A, B});
450     auto backend = runtime::Backend::create("${BACKEND_NAME}");
451
452     auto a = backend->create_tensor(element::f32, shape);
453     copy_data(a, vector<float>{1, 1, 1, 1});
454     auto b = backend->create_tensor(element::f32, shape);
455     copy_data(b, vector<float>{1, 1, 1, 1});
456     auto result = backend->create_tensor(element::f32, shape_r);
457     auto handle = backend->compile(f);
458     handle->call_with_validate({result}, {a, b});
459     vector<float> expected = {4, 4, 4, 4, 8, 8, 8, 8};
460     EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
461 }
462
463 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_add_concat_2)
464 {
465     Shape shape{1, 2, 2};
466     Shape shape_r{1, 6, 2};
467     auto A = make_shared<op::Parameter>(element::f32, shape);
468     auto B = make_shared<op::Parameter>(element::f32, shape);
469     auto add1 = make_shared<op::Add>(A, B);
470     auto add2 = make_shared<op::Add>(A, B);
471     auto add3 = make_shared<op::Add>(A, B);
472     auto add4 = make_shared<op::Add>(A, B);
473     auto add5 = make_shared<op::Add>(A, B);
474
475     auto concat1 = make_shared<op::Concat>(NodeVector{add1, add2, add3}, 1);
476
477     auto concat2 = make_shared<op::Concat>(NodeVector{add4, add2, add5}, 1);
478
479     auto add6 = make_shared<op::Add>(concat1, concat2);
480     auto f = make_shared<Function>(add6, ParameterVector{A, B});
481     auto backend = runtime::Backend::create("${BACKEND_NAME}");
482
483     auto a = backend->create_tensor(element::f32, shape);
484     copy_data(a, vector<float>{1, 1, 1, 1});
485     auto b = backend->create_tensor(element::f32, shape);
486     copy_data(b, vector<float>{1, 1, 1, 1});
487     auto result = backend->create_tensor(element::f32, shape_r);
488     auto handle = backend->compile(f);
489     handle->call_with_validate({result}, {a, b});
490     vector<float> expected = {4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4};
491     EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
492 }
493 // from numpy import *
494 // a=linspace(1,2*3*4*3*2,2*3*4*3*2)
495 // b=linspace(1000+1,1000+2*3*3*3*2,2*3*3*3*2)
496 // c=linspace(2000+1,2000+2*3*2*3*2,2*3*2*3*2)
497 // a.shape=(2,3,4,3,2)
498 // b.shape=(2,3,3,3,2)
499 // c.shape=(2,3,2,3,2)
500 // z=concatenate((a,b,c),axis=2)
501 // z.shape=(2*3*(4+3+2)*3*2)
502 // set_printoptions(suppress=True)
503 // print(z)
504 //
505 // [    1.     2.     3.     4.     5.     6.     7.     8.     9.    10.
506 //     11.    12.    13.    14.    15.    16.    17.    18.    19.    20.
507 //     21.    22.    23.    24.  1001.  1002.  1003.  1004.  1005.  1006.
508 //   1007.  1008.  1009.  1010.  1011.  1012.  1013.  1014.  1015.  1016.
509 //   1017.  1018.  2001.  2002.  2003.  2004.  2005.  2006.  2007.  2008.
510 //   2009.  2010.  2011.  2012.    25.    26.    27.    28.    29.    30.
511 //     31.    32.    33.    34.    35.    36.    37.    38.    39.    40.
512 //     41.    42.    43.    44.    45.    46.    47.    48.  1019.  1020.
513 //   1021.  1022.  1023.  1024.  1025.  1026.  1027.  1028.  1029.  1030.
514 //   1031.  1032.  1033.  1034.  1035.  1036.  2013.  2014.  2015.  2016.
515 //   2017.  2018.  2019.  2020.  2021.  2022.  2023.  2024.    49.    50.
516 //     51.    52.    53.    54.    55.    56.    57.    58.    59.    60.
517 //     61.    62.    63.    64.    65.    66.    67.    68.    69.    70.
518 //     71.    72.  1037.  1038.  1039.  1040.  1041.  1042.  1043.  1044.
519 //   1045.  1046.  1047.  1048.  1049.  1050.  1051.  1052.  1053.  1054.
520 //   2025.  2026.  2027.  2028.  2029.  2030.  2031.  2032.  2033.  2034.
521 //   2035.  2036.    73.    74.    75.    76.    77.    78.    79.    80.
522 //     81.    82.    83.    84.    85.    86.    87.    88.    89.    90.
523 //     91.    92.    93.    94.    95.    96.  1055.  1056.  1057.  1058.
524 //   1059.  1060.  1061.  1062.  1063.  1064.  1065.  1066.  1067.  1068.
525 //   1069.  1070.  1071.  1072.  2037.  2038.  2039.  2040.  2041.  2042.
526 //   2043.  2044.  2045.  2046.  2047.  2048.    97.    98.    99.   100.
527 //    101.   102.   103.   104.   105.   106.   107.   108.   109.   110.
528 //    111.   112.   113.   114.   115.   116.   117.   118.   119.   120.
529 //   1073.  1074.  1075.  1076.  1077.  1078.  1079.  1080.  1081.  1082.
530 //   1083.  1084.  1085.  1086.  1087.  1088.  1089.  1090.  2049.  2050.
531 //   2051.  2052.  2053.  2054.  2055.  2056.  2057.  2058.  2059.  2060.
532 //    121.   122.   123.   124.   125.   126.   127.   128.   129.   130.
533 //    131.   132.   133.   134.   135.   136.   137.   138.   139.   140.
534 //    141.   142.   143.   144.  1091.  1092.  1093.  1094.  1095.  1096.
535 //   1097.  1098.  1099.  1100.  1101.  1102.  1103.  1104.  1105.  1106.
536 //   1107.  1108.  2061.  2062.  2063.  2064.  2065.  2066.  2067.  2068.
537 //   2069.  2070.  2071.  2072.]
538 NGRAPH_TEST(${BACKEND_NAME}, concat_5d)
539 {
540     vector<float> a_data(2 * 3 * 4 * 3 * 2);
541     for (int i = 0; i < 2 * 3 * 4 * 3 * 2; i++)
542     {
543         a_data[i] = float(i + 1);
544     }
545
546     vector<float> b_data(2 * 3 * 3 * 3 * 2);
547     for (int i = 0; i < 2 * 3 * 3 * 3 * 2; i++)
548     {
549         b_data[i] = 1000 + float(i + 1);
550     }
551
552     vector<float> c_data(2 * 3 * 2 * 3 * 2);
553     for (int i = 0; i < 2 * 3 * 2 * 3 * 2; i++)
554     {
555         c_data[i] = 2000 + float(i + 1);
556     }
557
558     Shape shape_a{2, 3, 4, 3, 2};
559     auto A = make_shared<op::Parameter>(element::f32, shape_a);
560     Shape shape_b{2, 3, 3, 3, 2};
561     auto B = make_shared<op::Parameter>(element::f32, shape_b);
562     Shape shape_c{2, 3, 2, 3, 2};
563     auto C = make_shared<op::Parameter>(element::f32, shape_c);
564     Shape shape_r{2, 3, 9, 3, 2};
565
566     auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 2);
567     auto f = make_shared<Function>(r, ParameterVector{A, B, C});
568
569     auto backend = runtime::Backend::create("${BACKEND_NAME}");
570
571     // Create some tensors for input/output
572     auto a = backend->create_tensor(element::f32, shape_a);
573     copy_data(a, a_data);
574     auto b = backend->create_tensor(element::f32, shape_b);
575     copy_data(b, b_data);
576     auto c = backend->create_tensor(element::f32, shape_c);
577     copy_data(c, c_data);
578
579     auto result = backend->create_tensor(element::f32, shape_r);
580
581     auto handle = backend->compile(f);
582     handle->call_with_validate({result}, {a, b, c});
583     EXPECT_TRUE(test::all_close_f(
584         (vector<float>{
585             1.,    2.,    3.,    4.,    5.,    6.,    7.,    8.,    9.,    10.,   11.,   12.,
586             13.,   14.,   15.,   16.,   17.,   18.,   19.,   20.,   21.,   22.,   23.,   24.,
587             1001., 1002., 1003., 1004., 1005., 1006., 1007., 1008., 1009., 1010., 1011., 1012.,
588             1013., 1014., 1015., 1016., 1017., 1018., 2001., 2002., 2003., 2004., 2005., 2006.,
589             2007., 2008., 2009., 2010., 2011., 2012., 25.,   26.,   27.,   28.,   29.,   30.,
590             31.,   32.,   33.,   34.,   35.,   36.,   37.,   38.,   39.,   40.,   41.,   42.,
591             43.,   44.,   45.,   46.,   47.,   48.,   1019., 1020., 1021., 1022., 1023., 1024.,
592             1025., 1026., 1027., 1028., 1029., 1030., 1031., 1032., 1033., 1034., 1035., 1036.,
593             2013., 2014., 2015., 2016., 2017., 2018., 2019., 2020., 2021., 2022., 2023., 2024.,
594             49.,   50.,   51.,   52.,   53.,   54.,   55.,   56.,   57.,   58.,   59.,   60.,
595             61.,   62.,   63.,   64.,   65.,   66.,   67.,   68.,   69.,   70.,   71.,   72.,
596             1037., 1038., 1039., 1040., 1041., 1042., 1043., 1044., 1045., 1046., 1047., 1048.,
597             1049., 1050., 1051., 1052., 1053., 1054., 2025., 2026., 2027., 2028., 2029., 2030.,
598             2031., 2032., 2033., 2034., 2035., 2036., 73.,   74.,   75.,   76.,   77.,   78.,
599             79.,   80.,   81.,   82.,   83.,   84.,   85.,   86.,   87.,   88.,   89.,   90.,
600             91.,   92.,   93.,   94.,   95.,   96.,   1055., 1056., 1057., 1058., 1059., 1060.,
601             1061., 1062., 1063., 1064., 1065., 1066., 1067., 1068., 1069., 1070., 1071., 1072.,
602             2037., 2038., 2039., 2040., 2041., 2042., 2043., 2044., 2045., 2046., 2047., 2048.,
603             97.,   98.,   99.,   100.,  101.,  102.,  103.,  104.,  105.,  106.,  107.,  108.,
604             109.,  110.,  111.,  112.,  113.,  114.,  115.,  116.,  117.,  118.,  119.,  120.,
605             1073., 1074., 1075., 1076., 1077., 1078., 1079., 1080., 1081., 1082., 1083., 1084.,
606             1085., 1086., 1087., 1088., 1089., 1090., 2049., 2050., 2051., 2052., 2053., 2054.,
607             2055., 2056., 2057., 2058., 2059., 2060., 121.,  122.,  123.,  124.,  125.,  126.,
608             127.,  128.,  129.,  130.,  131.,  132.,  133.,  134.,  135.,  136.,  137.,  138.,
609             139.,  140.,  141.,  142.,  143.,  144.,  1091., 1092., 1093., 1094., 1095., 1096.,
610             1097., 1098., 1099., 1100., 1101., 1102., 1103., 1104., 1105., 1106., 1107., 1108.,
611             2061., 2062., 2063., 2064., 2065., 2066., 2067., 2068., 2069., 2070., 2071., 2072.}),
612         read_vector<float>(result),
613         MIN_FLOAT_TOLERANCE_BITS));
614 }
615
616 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_1d_last)
617 {
618     Shape shape_a{4};
619     auto A = make_shared<op::Parameter>(element::f32, shape_a);
620     Shape shape_b{0};
621     auto B = make_shared<op::Parameter>(element::f32, shape_b);
622     Shape shape_r{4};
623
624     auto r = make_shared<op::Concat>(NodeVector{A, B}, 0);
625     auto f = make_shared<Function>(r, ParameterVector{A, B});
626
627     auto backend = runtime::Backend::create("${BACKEND_NAME}");
628
629     // Create some tensors for input/output
630     vector<float> a_data{1, 2, 3, 4};
631     vector<float> b_data(0);
632
633     auto a = backend->create_tensor(element::f32, shape_a);
634     copy_data(a, a_data);
635     auto b = backend->create_tensor(element::f32, shape_b);
636     copy_data(b, b_data);
637
638     auto result = backend->create_tensor(element::f32, shape_r);
639
640     auto handle = backend->compile(f);
641     handle->call_with_validate({result}, {a, b});
642     EXPECT_TRUE(test::all_close_f(
643         (vector<float>{1, 2, 3, 4}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
644 }
645
646 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_1d_middle)
647 {
648     Shape shape_a{4};
649     auto A = make_shared<op::Parameter>(element::f32, shape_a);
650     Shape shape_b{0};
651     auto B = make_shared<op::Parameter>(element::f32, shape_b);
652     Shape shape_c{4};
653     auto C = make_shared<op::Parameter>(element::f32, shape_c);
654     Shape shape_r{8};
655
656     auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 0);
657     auto f = make_shared<Function>(r, ParameterVector{A, B, C});
658
659     auto backend = runtime::Backend::create("${BACKEND_NAME}");
660
661     // Create some tensors for input/output
662     vector<float> a_data{1, 2, 3, 4};
663     vector<float> b_data(0);
664     vector<float> c_data{5, 6, 7, 8};
665
666     auto a = backend->create_tensor(element::f32, shape_a);
667     copy_data(a, a_data);
668     auto b = backend->create_tensor(element::f32, shape_b);
669     copy_data(b, b_data);
670     auto c = backend->create_tensor(element::f32, shape_c);
671     copy_data(c, c_data);
672
673     auto result = backend->create_tensor(element::f32, shape_r);
674
675     auto handle = backend->compile(f);
676     handle->call_with_validate({result}, {a, b, c});
677     EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4, 5, 6, 7, 8}),
678                                   read_vector<float>(result),
679                                   MIN_FLOAT_TOLERANCE_BITS));
680 }
681
682 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_zero)
683 {
684     Shape shape{0};
685     auto constant_1 = op::Constant::create(element::f32, shape, {1});
686     auto concat_1 = make_shared<op::Concat>(NodeVector{constant_1, constant_1}, 0);
687
688     auto f = make_shared<Function>(concat_1, ParameterVector{});
689
690     auto backend = runtime::Backend::create("${BACKEND_NAME}");
691     auto result = backend->create_tensor(element::f32, shape);
692
693     auto handle = backend->compile(f);
694     handle->call_with_validate({result}, {});
695
696     EXPECT_TRUE(
697         test::all_close_f(vector<float>{}, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
698 }
699
700 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_4d_middle)
701 {
702     Shape shape_a{2, 2, 1, 1};
703     auto A = make_shared<op::Parameter>(element::f32, shape_a);
704     Shape shape_b{2, 2, 0, 1};
705     auto B = make_shared<op::Parameter>(element::f32, shape_b);
706     Shape shape_c{2, 2, 1, 1};
707     auto C = make_shared<op::Parameter>(element::f32, shape_c);
708     Shape shape_r{2, 2, 2, 1};
709
710     auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 2);
711     auto f = make_shared<Function>(r, ParameterVector{A, B, C});
712
713     auto backend = runtime::Backend::create("${BACKEND_NAME}");
714
715     // Create some tensors for input/output
716     vector<float> a_data{1, 2, 3, 4};
717     vector<float> b_data(0);
718     vector<float> c_data{5, 6, 7, 8};
719
720     auto a = backend->create_tensor(element::f32, shape_a);
721     copy_data(a, a_data);
722     auto b = backend->create_tensor(element::f32, shape_b);
723     copy_data(b, b_data);
724     auto c = backend->create_tensor(element::f32, shape_c);
725     copy_data(c, c_data);
726
727     auto result = backend->create_tensor(element::f32, shape_r);
728
729     auto handle = backend->compile(f);
730     handle->call_with_validate({result}, {a, b, c});
731     EXPECT_TRUE(test::all_close_f((vector<float>{1, 5, 2, 6, 3, 7, 4, 8}),
732                                   read_vector<float>(result),
733                                   MIN_FLOAT_TOLERANCE_BITS));
734 }