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 "util/all_close.hpp"
20 #include "util/all_close_f.hpp"
21 #include "util/known_element_types.hpp"
22 #include "util/ndarray.hpp"
23 #include "util/test_control.hpp"
24 #include "util/test_tools.hpp"
26 NGRAPH_SUPPRESS_DEPRECATED_START
29 using namespace ngraph;
31 static string s_manifest = "${MANIFEST}";
33 // Trivial case with no reduced axes.
34 NGRAPH_TEST(${BACKEND_NAME}, product_trivial)
37 auto A = make_shared<op::Parameter>(element::f32, shape);
38 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{}), ParameterVector{A});
40 auto backend = runtime::Backend::create("${BACKEND_NAME}");
42 // Create some tensors for input/output
43 auto a = backend->create_tensor(element::f32, shape);
44 copy_data(a, vector<float>{1, 2, 3, 4});
45 auto result = backend->create_tensor(element::f32, shape);
47 auto handle = backend->compile(f);
48 handle->call_with_validate({result}, {a});
49 EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4}), read_vector<float>(result)));
52 // Failure has been reported at 5D for some reason
53 NGRAPH_TEST(${BACKEND_NAME}, product_trivial_5d)
55 Shape shape{2, 2, 2, 2, 2};
56 auto A = make_shared<op::Parameter>(element::f32, shape);
57 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{}), ParameterVector{A});
59 auto backend = runtime::Backend::create("${BACKEND_NAME}");
61 // Create some tensors for input/output
62 auto a = backend->create_tensor(element::f32, shape);
63 copy_data(a, vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
64 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
65 auto result = backend->create_tensor(element::f32, shape);
67 auto handle = backend->compile(f);
68 handle->call_with_validate({result}, {a});
69 EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
70 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}),
71 read_vector<float>(result)));
74 NGRAPH_TEST(${BACKEND_NAME}, product_to_scalar)
77 auto A = make_shared<op::Parameter>(element::f32, shape);
78 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), ParameterVector{A});
80 auto backend = runtime::Backend::create("${BACKEND_NAME}");
82 // Create some tensors for input/output
83 auto a = backend->create_tensor(element::f32, shape);
84 copy_data(a, vector<float>{1, 2, 3, 4});
85 auto result = backend->create_tensor(element::f32, Shape{});
87 auto handle = backend->compile(f);
88 handle->call_with_validate({result}, {a});
89 EXPECT_TRUE(test::all_close_f((vector<float>{24}), read_vector<float>(result)));
91 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
92 // input tensors, so let's do this too.
93 EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4}), read_vector<float>(a)));
96 NGRAPH_TEST(${BACKEND_NAME}, product_matrix_columns)
99 auto A = make_shared<op::Parameter>(element::f32, shape_a);
101 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), ParameterVector{A});
103 auto backend = runtime::Backend::create("${BACKEND_NAME}");
105 // Create some tensors for input/output
106 auto a = backend->create_tensor(element::f32, shape_a);
107 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
108 auto result = backend->create_tensor(element::f32, shape_rt);
110 auto handle = backend->compile(f);
111 handle->call_with_validate({result}, {a});
112 EXPECT_TRUE(test::all_close_f((vector<float>{15, 48}), read_vector<float>(result)));
114 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
115 // input tensors, so let's do this too.
116 EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a)));
119 NGRAPH_TEST(${BACKEND_NAME}, product_matrix_rows)
122 auto A = make_shared<op::Parameter>(element::f32, shape_a);
124 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{1}), ParameterVector{A});
126 auto backend = runtime::Backend::create("${BACKEND_NAME}");
128 // Create some tensors for input/output
129 auto a = backend->create_tensor(element::f32, shape_a);
130 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
131 auto result = backend->create_tensor(element::f32, shape_rt);
133 auto handle = backend->compile(f);
134 handle->call_with_validate({result}, {a});
135 EXPECT_TRUE(test::all_close_f((vector<float>{2, 12, 30}), read_vector<float>(result)));
137 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
138 // input tensors, so let's do this too.
139 EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a)));
142 NGRAPH_TEST(${BACKEND_NAME}, product_matrix_rows_zero)
145 auto A = make_shared<op::Parameter>(element::f32, shape_a);
147 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{1}), ParameterVector{A});
149 auto backend = runtime::Backend::create("${BACKEND_NAME}");
151 // Create some tensors for input/output
152 auto a = backend->create_tensor(element::f32, shape_a);
153 copy_data(a, vector<float>{});
154 auto result = backend->create_tensor(element::f32, shape_rt);
155 copy_data(result, vector<float>({3, 3, 3}));
157 auto handle = backend->compile(f);
158 handle->call_with_validate({result}, {a});
159 EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1}), read_vector<float>(result)));
161 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
162 // input tensors, so let's do this too.
163 EXPECT_TRUE(test::all_close_f((vector<float>{}), read_vector<float>(a)));
166 NGRAPH_TEST(${BACKEND_NAME}, product_matrix_cols_zero)
168 // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
170 auto A = make_shared<op::Parameter>(element::f32, shape_a);
172 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), ParameterVector{A});
174 auto backend = runtime::Backend::create("${BACKEND_NAME}");
176 // Create some tensors for input/output
177 auto a = backend->create_tensor(element::f32, shape_a);
178 copy_data(a, vector<float>{});
179 auto result = backend->create_tensor(element::f32, shape_rt);
180 copy_data(result, vector<float>({3, 3}));
182 auto handle = backend->compile(f);
183 handle->call_with_validate({result}, {a});
184 EXPECT_TRUE(test::all_close_f((vector<float>{1, 1}), read_vector<float>(result)));
186 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
187 // input tensors, so let's do this too.
188 EXPECT_TRUE(test::all_close_f((vector<float>{}), read_vector<float>(a)));
191 NGRAPH_TEST(${BACKEND_NAME}, product_vector_zero)
194 auto A = make_shared<op::Parameter>(element::f32, shape_a);
196 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), ParameterVector{A});
198 auto backend = runtime::Backend::create("${BACKEND_NAME}");
200 // Create some tensors for input/output
201 auto a = backend->create_tensor(element::f32, shape_a);
202 copy_data(a, vector<float>{});
203 auto result = backend->create_tensor(element::f32, shape_rt);
204 copy_data(result, vector<float>({3}));
206 auto handle = backend->compile(f);
207 handle->call_with_validate({result}, {a});
208 EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
210 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
211 // input tensors, so let's do this too.
212 EXPECT_TRUE(test::all_close_f((vector<float>{}), read_vector<float>(a)));
215 NGRAPH_TEST(${BACKEND_NAME}, product_matrix_to_scalar_zero_by_zero)
218 auto A = make_shared<op::Parameter>(element::f32, shape_a);
220 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), ParameterVector{A});
222 auto backend = runtime::Backend::create("${BACKEND_NAME}");
224 // Create some tensors for input/output
225 auto a = backend->create_tensor(element::f32, shape_a);
226 copy_data(a, vector<float>{});
227 auto result = backend->create_tensor(element::f32, shape_rt);
228 copy_data(result, vector<float>({3}));
230 auto handle = backend->compile(f);
231 handle->call_with_validate({result}, {a});
232 EXPECT_TRUE(test::all_close_f((vector<float>{1}), read_vector<float>(result)));
234 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
235 // input tensors, so let's do this too.
236 EXPECT_TRUE(test::all_close_f((vector<float>{}), read_vector<float>(a)));
239 NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_matrix_most_sig)
241 Shape shape_a{3, 3, 3};
242 auto A = make_shared<op::Parameter>(element::f32, shape_a);
243 Shape shape_rt{3, 3};
244 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), ParameterVector{A});
246 auto backend = runtime::Backend::create("${BACKEND_NAME}");
248 // Create some tensors for input/output
249 auto a = backend->create_tensor(element::f32, shape_a);
250 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
251 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
252 auto result = backend->create_tensor(element::f32, shape_rt);
254 auto handle = backend->compile(f);
255 handle->call_with_validate({result}, {a});
256 EXPECT_TRUE(test::all_close_f((vector<float>{1 * 10 * 19,
265 read_vector<float>(result)));
268 NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_matrix_least_sig)
270 Shape shape_a{3, 3, 3};
271 auto A = make_shared<op::Parameter>(element::f32, shape_a);
272 Shape shape_rt{3, 3};
273 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{2}), ParameterVector{A});
275 auto backend = runtime::Backend::create("${BACKEND_NAME}");
277 // Create some tensors for input/output
278 auto a = backend->create_tensor(element::f32, shape_a);
279 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
280 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
281 auto result = backend->create_tensor(element::f32, shape_rt);
283 auto handle = backend->compile(f);
284 handle->call_with_validate({result}, {a});
285 EXPECT_TRUE(test::all_close_f((vector<float>{1 * 2 * 3,
294 read_vector<float>(result)));
297 NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_vector)
299 Shape shape_a{3, 3, 3};
300 auto A = make_shared<op::Parameter>(element::f32, shape_a);
302 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), ParameterVector{A});
304 auto backend = runtime::Backend::create("${BACKEND_NAME}");
306 // Create some tensors for input/output
307 auto a = backend->create_tensor(element::f32, shape_a);
308 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
309 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
310 auto result = backend->create_tensor(element::f32, shape_rt);
312 auto handle = backend->compile(f);
313 handle->call_with_validate({result}, {a});
314 EXPECT_TRUE(test::all_close_f(
315 (vector<float>{1.0f * 10.0f * 19.0f * 4.0f * 13.0f * 22.0f * 7.0f * 16.0f * 25.0f,
316 2.0f * 11.0f * 20.0f * 5.0f * 14.0f * 23.0f * 8.0f * 17.0f * 26.0f,
317 3.0f * 12.0f * 21.0f * 6.0f * 15.0f * 24.0f * 9.0f * 18.0f * 27.0f}),
318 read_vector<float>(result)));
321 NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_scalar)
323 Shape shape_a{3, 3, 3};
324 auto A = make_shared<op::Parameter>(element::f32, shape_a);
327 make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1, 2}), ParameterVector{A});
329 auto backend = runtime::Backend::create("${BACKEND_NAME}");
331 // Create some tensors for input/output
332 auto a = backend->create_tensor(element::f32, shape_a);
333 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
334 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1});
335 auto result = backend->create_tensor(element::f32, shape_rt);
337 auto handle = backend->compile(f);
338 handle->call_with_validate({result}, {a});
339 EXPECT_TRUE(test::all_close_f(vector<float>{1.0f * 10.0f * 9.0f * 4.0f * 13.0f * 6.0f * 7.0f *
340 12.0f * 3.0f * 2.0f * 11.0f * 8.0f * 5.0f * 14.0f *
341 5.0f * 8.0f * 11.0f * 2.0f * 3.0f * 12.0f * 7.0f *
342 6.0f * 13.0f * 4.0f * 9.0f * 10.0f * 1.0f},
343 read_vector<float>(result)));
346 NGRAPH_TEST(${BACKEND_NAME}, product_3d_eliminate_zero_dim)
348 Shape shape_a{3, 0, 2};
349 auto A = make_shared<op::Parameter>(element::f32, shape_a);
350 Shape shape_rt{3, 2};
351 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{1}), ParameterVector{A});
353 auto backend = runtime::Backend::create("${BACKEND_NAME}");
355 // Create some tensors for input/output
356 auto a = backend->create_tensor(element::f32, shape_a);
357 copy_data(a, vector<float>{});
358 auto result = backend->create_tensor(element::f32, shape_rt);
360 // Overwrite the initial result vector to make sure we're not just coincidentally getting the
362 copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
364 auto handle = backend->compile(f);
365 handle->call_with_validate({result}, {a});
366 EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1}), read_vector<float>(result)));
369 NGRAPH_TEST(${BACKEND_NAME}, product_2d_to_scalar_int32)
372 auto A = make_shared<op::Parameter>(element::i32, shape_a);
374 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), ParameterVector{A});
376 auto backend = runtime::Backend::create("${BACKEND_NAME}");
378 // Create some tensors for input/output
379 auto a = backend->create_tensor(element::i32, shape_a);
380 copy_data(a, vector<int32_t>{1, 2, 3, 4, 5, 6, 7, 8, 9});
381 auto result = backend->create_tensor(element::i32, shape_rt);
383 auto handle = backend->compile(f);
384 handle->call_with_validate({result}, {a});
385 EXPECT_EQ(vector<int32_t>{1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9}, read_vector<int32_t>(result));
388 NGRAPH_TEST(${BACKEND_NAME}, product_to_scalar_int32)
391 auto A = make_shared<op::Parameter>(element::i32, shape);
392 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), ParameterVector{A});
394 auto backend = runtime::Backend::create("${BACKEND_NAME}");
396 // Create some tensors for input/output
397 auto a = backend->create_tensor(element::i32, shape);
398 copy_data(a, vector<int32_t>{1, 2, 3, 4});
399 auto result = backend->create_tensor(element::i32, Shape{});
401 auto handle = backend->compile(f);
402 handle->call_with_validate({result}, {a});
403 EXPECT_EQ((vector<int32_t>{24}), read_vector<int32_t>(result));
405 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
406 // input tensors, so let's do this too.
407 EXPECT_EQ((vector<int32_t>{1, 2, 3, 4}), read_vector<int32_t>(a));
410 NGRAPH_TEST(${BACKEND_NAME}, product_to_scalar_int8)
413 auto A = make_shared<op::Parameter>(element::i8, shape);
414 auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), ParameterVector{A});
416 auto backend = runtime::Backend::create("${BACKEND_NAME}");
418 // Create some tensors for input/output
419 auto a = backend->create_tensor(element::i8, shape);
420 copy_data(a, vector<int8_t>{1, 2, 3, 4});
421 auto result = backend->create_tensor(element::i8, Shape{});
423 auto handle = backend->compile(f);
424 handle->call_with_validate({result}, {a});
425 EXPECT_EQ((vector<int8_t>{24}), read_vector<int8_t>(result));
427 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
428 // input tensors, so let's do this too.
429 EXPECT_EQ((vector<int8_t>{1, 2, 3, 4}), read_vector<int8_t>(a));