1 //*****************************************************************************
2 // Copyright 2017-2020 Intel Corporation
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
8 // http://www.apache.org/licenses/LICENSE-2.0
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 //*****************************************************************************
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"
27 NGRAPH_SUPPRESS_DEPRECATED_START
30 using namespace ngraph;
32 static string s_manifest = "${MANIFEST}";
34 NGRAPH_TEST(${BACKEND_NAME}, concat_negative_axis)
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});
46 auto backend = runtime::Backend::create("${BACKEND_NAME}", true);
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}));
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)));
63 NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_colwise)
66 auto A = make_shared<op::Parameter>(element::f32, shape_a);
68 auto B = make_shared<op::Parameter>(element::f32, shape_b);
70 auto C = make_shared<op::Parameter>(element::f32, shape_c);
72 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 1),
73 ParameterVector{A, B, C});
75 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
86 auto handle = backend->compile(f);
87 handle->call_with_validate({result}, {a, b, c});
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));
94 NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_rowwise)
97 auto A = make_shared<op::Parameter>(element::f32, shape_a);
99 auto B = make_shared<op::Parameter>(element::f32, shape_b);
101 auto C = make_shared<op::Parameter>(element::f32, shape_c);
103 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
104 ParameterVector{A, B, C});
106 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
117 auto handle = backend->compile(f);
118 handle->call_with_validate({result}, {a, b, c});
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));
125 NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_int64)
128 auto A = make_shared<op::Parameter>(element::i64, shape_a);
130 auto B = make_shared<op::Parameter>(element::i64, shape_b);
132 auto C = make_shared<op::Parameter>(element::i64, shape_c);
134 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
135 ParameterVector{A, B, C});
137 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
154 // Params to drive concat_vector_large testing variations
155 class concat_vector_params : public ::testing::TestWithParam<int>
158 concat_vector_params() { num_inputs = GetParam(); }
162 NGRAPH_TEST_P(${BACKEND_NAME}, concat_vector_params, concat_vector_large)
166 ParameterVector inputs_param;
167 for (uint32_t i = 0; i < num_inputs; i++)
169 auto A = make_shared<op::Parameter>(element::f32, shape_a);
170 inputs_param.push_back(A);
173 Shape shape_r{num_inputs};
174 auto f = make_shared<Function>(make_shared<op::Concat>(inputs, 0), inputs_param);
176 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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++)
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);
188 auto result = backend->create_tensor(element::f32, shape_r);
190 auto handle = backend->compile(f);
191 handle->call_with_validate({result}, inputs_value);
193 test::all_close_f(ref_result, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
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},
202 concat_vector_params,
203 testing::Values(100, 128, 999));
205 NGRAPH_TEST(${BACKEND_NAME}, concat_vector)
208 auto A = make_shared<op::Parameter>(element::f32, shape_a);
210 auto B = make_shared<op::Parameter>(element::f32, shape_b);
212 auto C = make_shared<op::Parameter>(element::f32, shape_c);
214 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
215 ParameterVector{A, B, C});
217 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
235 NGRAPH_TEST(${BACKEND_NAME}, concat_4d_tensor)
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});
245 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
262 NGRAPH_TEST(${BACKEND_NAME}, concat_2d_tensor)
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);
269 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
270 ParameterVector{A, B, C});
272 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
289 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_2d_tensor)
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);
300 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{add1, add2, subtract}, 0),
301 ParameterVector{A, B, C, D});
303 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
322 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_propagate_2d_tensor)
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);
334 auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{concat1, subtract}, 0),
335 ParameterVector{A, B, C, D});
337 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
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));
356 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_tree_1)
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});
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);
379 EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
382 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_tree_2)
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}");
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);
407 EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
410 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_tree_3)
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);
436 EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
439 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_add_concat)
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}");
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));
463 NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_add_concat_2)
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);
475 auto concat1 = make_shared<op::Concat>(NodeVector{add1, add2, add3}, 1);
477 auto concat2 = make_shared<op::Concat>(NodeVector{add4, add2, add5}, 1);
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}");
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));
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)
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)
540 vector<float> a_data(2 * 3 * 4 * 3 * 2);
541 for (int i = 0; i < 2 * 3 * 4 * 3 * 2; i++)
543 a_data[i] = float(i + 1);
546 vector<float> b_data(2 * 3 * 3 * 3 * 2);
547 for (int i = 0; i < 2 * 3 * 3 * 3 * 2; i++)
549 b_data[i] = 1000 + float(i + 1);
552 vector<float> c_data(2 * 3 * 2 * 3 * 2);
553 for (int i = 0; i < 2 * 3 * 2 * 3 * 2; i++)
555 c_data[i] = 2000 + float(i + 1);
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};
566 auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 2);
567 auto f = make_shared<Function>(r, ParameterVector{A, B, C});
569 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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);
579 auto result = backend->create_tensor(element::f32, shape_r);
581 auto handle = backend->compile(f);
582 handle->call_with_validate({result}, {a, b, c});
583 EXPECT_TRUE(test::all_close_f(
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));
616 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_1d_last)
619 auto A = make_shared<op::Parameter>(element::f32, shape_a);
621 auto B = make_shared<op::Parameter>(element::f32, shape_b);
624 auto r = make_shared<op::Concat>(NodeVector{A, B}, 0);
625 auto f = make_shared<Function>(r, ParameterVector{A, B});
627 auto backend = runtime::Backend::create("${BACKEND_NAME}");
629 // Create some tensors for input/output
630 vector<float> a_data{1, 2, 3, 4};
631 vector<float> b_data(0);
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);
638 auto result = backend->create_tensor(element::f32, shape_r);
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));
646 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_1d_middle)
649 auto A = make_shared<op::Parameter>(element::f32, shape_a);
651 auto B = make_shared<op::Parameter>(element::f32, shape_b);
653 auto C = make_shared<op::Parameter>(element::f32, shape_c);
656 auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 0);
657 auto f = make_shared<Function>(r, ParameterVector{A, B, C});
659 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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};
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);
673 auto result = backend->create_tensor(element::f32, shape_r);
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));
682 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_zero)
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);
688 auto f = make_shared<Function>(concat_1, ParameterVector{});
690 auto backend = runtime::Backend::create("${BACKEND_NAME}");
691 auto result = backend->create_tensor(element::f32, shape);
693 auto handle = backend->compile(f);
694 handle->call_with_validate({result}, {});
697 test::all_close_f(vector<float>{}, read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
700 NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_4d_middle)
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};
710 auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 2);
711 auto f = make_shared<Function>(r, ParameterVector{A, B, C});
713 auto backend = runtime::Backend::create("${BACKEND_NAME}");
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};
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);
727 auto result = backend->create_tensor(element::f32, shape_r);
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));