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/known_element_types.hpp"
24 #include "util/ndarray.hpp"
25 #include "util/test_control.hpp"
26 #include "util/test_tools.hpp"
28 NGRAPH_SUPPRESS_DEPRECATED_START
31 using namespace ngraph;
33 static string s_manifest = "${MANIFEST}";
35 // Trivial case with no reduced axes.
36 NGRAPH_TEST(${BACKEND_NAME}, min_trivial)
39 auto A = make_shared<op::Parameter>(element::f32, shape);
40 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{}), ParameterVector{A});
42 auto backend = runtime::Backend::create("${BACKEND_NAME}");
44 // Create some tensors for input/output
45 auto a = backend->create_tensor(element::f32, shape);
46 copy_data(a, vector<float>{1, 2, 3, 4});
47 auto result = backend->create_tensor(element::f32, shape);
49 auto handle = backend->compile(f);
50 handle->call_with_validate({result}, {a});
51 EXPECT_TRUE(test::all_close_f(
52 (vector<float>{1, 2, 3, 4}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
55 // Failure has been reported at 5D for some reason
56 NGRAPH_TEST(${BACKEND_NAME}, min_trivial_5d)
58 Shape shape{2, 2, 2, 2, 2};
59 auto A = make_shared<op::Parameter>(element::f32, shape);
60 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{}), ParameterVector{A});
62 auto backend = runtime::Backend::create("${BACKEND_NAME}");
64 // Create some tensors for input/output
65 auto a = backend->create_tensor(element::f32, shape);
66 copy_data(a, vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
67 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
68 auto result = backend->create_tensor(element::f32, shape);
70 auto handle = backend->compile(f);
71 handle->call_with_validate({result}, {a});
72 EXPECT_TRUE(test::all_close_f((vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
73 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}),
74 read_vector<float>(result),
75 MIN_FLOAT_TOLERANCE_BITS));
78 NGRAPH_TEST(${BACKEND_NAME}, min_trivial_5d_int32)
80 Shape shape{2, 2, 2, 2, 2};
81 auto A = make_shared<op::Parameter>(element::i32, shape);
82 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{}), ParameterVector{A});
84 auto backend = runtime::Backend::create("${BACKEND_NAME}");
86 // Create some tensors for input/output
87 auto a = backend->create_tensor(element::i32, shape);
88 copy_data(a, vector<int32_t>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
89 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
90 auto result = backend->create_tensor(element::i32, shape);
92 auto handle = backend->compile(f);
93 handle->call_with_validate({result}, {a});
94 EXPECT_EQ((vector<int32_t>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
95 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}),
96 read_vector<int32_t>(result));
99 NGRAPH_TEST(${BACKEND_NAME}, min_to_scalar)
102 auto A = make_shared<op::Parameter>(element::f32, shape);
103 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), ParameterVector{A});
105 auto backend = runtime::Backend::create("${BACKEND_NAME}");
107 // Create some tensors for input/output
108 auto a = backend->create_tensor(element::f32, shape);
109 copy_data(a, vector<float>{1, 2, 3, 4});
110 auto result = backend->create_tensor(element::f32, Shape{});
112 auto handle = backend->compile(f);
113 handle->call_with_validate({result}, {a});
114 EXPECT_TRUE(test::all_close_f(
115 (vector<float>{1}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
117 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
118 // input tensors, so let's do this too.
119 EXPECT_TRUE(test::all_close_f(
120 (vector<float>{1, 2, 3, 4}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
123 NGRAPH_TEST(${BACKEND_NAME}, min_to_scalar_int8)
126 auto A = make_shared<op::Parameter>(element::i8, shape);
127 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), ParameterVector{A});
129 auto backend = runtime::Backend::create("${BACKEND_NAME}");
131 // Create some tensors for input/output
132 auto a = backend->create_tensor(element::i8, shape);
133 copy_data(a, vector<int8_t>{1, 2, 3, 4});
134 auto result = backend->create_tensor(element::i8, Shape{});
136 auto handle = backend->compile(f);
137 handle->call_with_validate({result}, {a});
138 EXPECT_EQ((vector<int8_t>{1}), read_vector<int8_t>(result));
140 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
141 // input tensors, so let's do this too.
142 EXPECT_EQ((vector<int8_t>{1, 2, 3, 4}), read_vector<int8_t>(a));
145 NGRAPH_TEST(${BACKEND_NAME}, min_matrix_columns)
148 auto A = make_shared<op::Parameter>(element::f32, shape_a);
150 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), ParameterVector{A});
152 auto backend = runtime::Backend::create("${BACKEND_NAME}");
154 // Create some tensors for input/output
155 auto a = backend->create_tensor(element::f32, shape_a);
156 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
157 auto result = backend->create_tensor(element::f32, shape_rt);
159 auto handle = backend->compile(f);
160 handle->call_with_validate({result}, {a});
161 EXPECT_TRUE(test::all_close_f(
162 (vector<float>{1, 2}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
164 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
165 // input tensors, so let's do this too.
166 EXPECT_TRUE(test::all_close_f(
167 (vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
170 NGRAPH_TEST(${BACKEND_NAME}, min_matrix_rows)
173 auto A = make_shared<op::Parameter>(element::f32, shape_a);
175 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), ParameterVector{A});
177 auto backend = runtime::Backend::create("${BACKEND_NAME}");
179 // Create some tensors for input/output
180 auto a = backend->create_tensor(element::f32, shape_a);
181 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
182 auto result = backend->create_tensor(element::f32, shape_rt);
184 auto handle = backend->compile(f);
185 handle->call_with_validate({result}, {a});
186 EXPECT_TRUE(test::all_close_f(
187 (vector<float>{1, 3, 5}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
189 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
190 // input tensors, so let's do this too.
191 EXPECT_TRUE(test::all_close_f(
192 (vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
195 NGRAPH_TEST(${BACKEND_NAME}, min_matrix_rows_int32)
198 auto A = make_shared<op::Parameter>(element::i32, shape_a);
200 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), ParameterVector{A});
202 auto backend = runtime::Backend::create("${BACKEND_NAME}");
204 // Create some tensors for input/output
205 auto a = backend->create_tensor(element::i32, shape_a);
206 copy_data(a, vector<int32_t>{1, 2, 3, 4, 5, 6});
207 auto result = backend->create_tensor(element::i32, shape_rt);
209 auto handle = backend->compile(f);
210 handle->call_with_validate({result}, {a});
211 EXPECT_EQ((vector<int32_t>{1, 3, 5}), read_vector<int32_t>(result));
213 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
214 // input tensors, so let's do this too.
215 EXPECT_EQ((vector<int32_t>{1, 2, 3, 4, 5, 6}), read_vector<int32_t>(a));
218 NGRAPH_TEST(${BACKEND_NAME}, min_matrix_rows_zero)
221 auto A = make_shared<op::Parameter>(element::f32, shape_a);
223 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), ParameterVector{A});
225 auto backend = runtime::Backend::create("${BACKEND_NAME}");
227 // Create some tensors for input/output
228 auto a = backend->create_tensor(element::f32, shape_a);
229 copy_data(a, vector<float>{});
230 auto result = backend->create_tensor(element::f32, shape_rt);
231 copy_data(result, vector<float>({3, 3, 3}));
233 auto handle = backend->compile(f);
234 handle->call_with_validate({result}, {a});
235 EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity(),
236 std::numeric_limits<float>::infinity(),
237 std::numeric_limits<float>::infinity()}),
238 read_vector<float>(result));
240 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
241 // input tensors, so let's do this too.
243 test::all_close_f((vector<float>{}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
246 NGRAPH_TEST(${BACKEND_NAME}, min_matrix_cols_zero)
248 // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
250 auto A = make_shared<op::Parameter>(element::f32, shape_a);
252 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), ParameterVector{A});
254 auto backend = runtime::Backend::create("${BACKEND_NAME}");
256 // Create some tensors for input/output
257 auto a = backend->create_tensor(element::f32, shape_a);
258 copy_data(a, vector<float>{});
259 auto result = backend->create_tensor(element::f32, shape_rt);
260 copy_data(result, vector<float>({3, 3}));
262 auto handle = backend->compile(f);
263 handle->call_with_validate({result}, {a});
264 EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity(),
265 std::numeric_limits<float>::infinity()}),
266 read_vector<float>(result));
268 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
269 // input tensors, so let's do this too.
271 test::all_close_f((vector<float>{}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
274 NGRAPH_TEST(${BACKEND_NAME}, min_vector_zero)
277 auto A = make_shared<op::Parameter>(element::f32, shape_a);
279 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), ParameterVector{A});
281 auto backend = runtime::Backend::create("${BACKEND_NAME}");
283 // Create some tensors for input/output
284 auto a = backend->create_tensor(element::f32, shape_a);
285 copy_data(a, vector<float>{});
286 auto result = backend->create_tensor(element::f32, shape_rt);
287 copy_data(result, vector<float>({3}));
289 auto handle = backend->compile(f);
290 handle->call_with_validate({result}, {a});
291 EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity()}), read_vector<float>(result));
293 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
294 // input tensors, so let's do this too.
296 test::all_close_f((vector<float>{}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
299 NGRAPH_TEST(${BACKEND_NAME}, min_matrix_to_scalar_zero_by_zero)
302 auto A = make_shared<op::Parameter>(element::f32, shape_a);
304 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), ParameterVector{A});
306 auto backend = runtime::Backend::create("${BACKEND_NAME}");
308 // Create some tensors for input/output
309 auto a = backend->create_tensor(element::f32, shape_a);
310 copy_data(a, vector<float>{});
311 auto result = backend->create_tensor(element::f32, shape_rt);
312 copy_data(result, vector<float>({3}));
314 auto handle = backend->compile(f);
315 handle->call_with_validate({result}, {a});
316 EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity()}), read_vector<float>(result));
318 // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
319 // input tensors, so let's do this too.
321 test::all_close_f((vector<float>{}), read_vector<float>(a), MIN_FLOAT_TOLERANCE_BITS));
324 NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_matrix_most_sig)
326 Shape shape_a{3, 3, 3};
327 auto A = make_shared<op::Parameter>(element::f32, shape_a);
328 Shape shape_rt{3, 3};
329 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), ParameterVector{A});
331 auto backend = runtime::Backend::create("${BACKEND_NAME}");
333 // Create some tensors for input/output
334 auto a = backend->create_tensor(element::f32, shape_a);
335 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
336 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
337 auto result = backend->create_tensor(element::f32, shape_rt);
339 auto handle = backend->compile(f);
340 handle->call_with_validate({result}, {a});
341 EXPECT_TRUE(test::all_close_f((vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9}),
342 read_vector<float>(result),
343 MIN_FLOAT_TOLERANCE_BITS));
346 NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_matrix_least_sig)
348 Shape shape_a{3, 3, 3};
349 auto A = make_shared<op::Parameter>(element::f32, shape_a);
350 Shape shape_rt{3, 3};
351 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{2}), 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>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
358 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
359 auto result = backend->create_tensor(element::f32, shape_rt);
361 auto handle = backend->compile(f);
362 handle->call_with_validate({result}, {a});
363 EXPECT_TRUE(test::all_close_f((vector<float>{1, 4, 7, 10, 13, 16, 19, 22, 25}),
364 read_vector<float>(result),
365 MIN_FLOAT_TOLERANCE_BITS));
368 NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_vector)
370 Shape shape_a{3, 3, 3};
371 auto A = make_shared<op::Parameter>(element::f32, shape_a);
373 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), ParameterVector{A});
375 auto backend = runtime::Backend::create("${BACKEND_NAME}");
377 // Create some tensors for input/output
378 auto a = backend->create_tensor(element::f32, shape_a);
379 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
380 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
381 auto result = backend->create_tensor(element::f32, shape_rt);
383 auto handle = backend->compile(f);
384 handle->call_with_validate({result}, {a});
385 EXPECT_TRUE(test::all_close_f(
386 (vector<float>{1, 2, 3}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
389 NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_scalar)
391 Shape shape_a{3, 3, 3};
392 auto A = make_shared<op::Parameter>(element::f32, shape_a);
394 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1, 2}), ParameterVector{A});
396 auto backend = runtime::Backend::create("${BACKEND_NAME}");
398 // Create some tensors for input/output
399 auto a = backend->create_tensor(element::f32, shape_a);
400 copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
401 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1});
402 auto result = backend->create_tensor(element::f32, shape_rt);
404 auto handle = backend->compile(f);
405 handle->call_with_validate({result}, {a});
406 EXPECT_TRUE(test::all_close_f(
407 (vector<float>{1}), read_vector<float>(result), MIN_FLOAT_TOLERANCE_BITS));
410 NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_scalar_int32)
412 Shape shape_a{3, 3, 3};
413 auto A = make_shared<op::Parameter>(element::i32, shape_a);
415 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1, 2}), ParameterVector{A});
417 auto backend = runtime::Backend::create("${BACKEND_NAME}");
419 // Create some tensors for input/output
420 auto a = backend->create_tensor(element::i32, shape_a);
421 copy_data(a, vector<int32_t>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
422 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1});
423 auto result = backend->create_tensor(element::i32, shape_rt);
425 auto handle = backend->compile(f);
426 handle->call_with_validate({result}, {a});
427 EXPECT_EQ((vector<int32_t>{1}), read_vector<int32_t>(result));
430 NGRAPH_TEST(${BACKEND_NAME}, min_3d_eliminate_zero_dim)
432 Shape shape_a{3, 0, 2};
433 auto A = make_shared<op::Parameter>(element::f32, shape_a);
434 Shape shape_rt{3, 2};
435 auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), ParameterVector{A});
437 auto backend = runtime::Backend::create("${BACKEND_NAME}");
439 // Create some tensors for input/output
440 auto a = backend->create_tensor(element::f32, shape_a);
441 copy_data(a, vector<float>{});
442 auto result = backend->create_tensor(element::f32, shape_rt);
444 // Overwrite the initial result vector to make sure we're not just coincidentally getting the
446 copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});
448 float inf = std::numeric_limits<float>::infinity();
450 auto handle = backend->compile(f);
451 handle->call_with_validate({result}, {a});
452 EXPECT_EQ((vector<float>{inf, inf, inf, inf, inf, inf}), read_vector<float>(result));