backend_test.in.cpp 221 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
//*****************************************************************************
// Copyright 2017-2018 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//*****************************************************************************
Scott Cyphers's avatar
Scott Cyphers committed
16

17
#include <algorithm>
Nick Korovaiko's avatar
Nick Korovaiko committed
18
#include <algorithm>
Robert Kimball's avatar
Robert Kimball committed
19
#include <cinttypes>
Robert Kimball's avatar
Robert Kimball committed
20
#include <cmath>
21
#include <cstdlib>
22
#include <random>
23
#include <string>
Scott Cyphers's avatar
Scott Cyphers committed
24 25
#include "gtest/gtest.h"

26
#include "ngraph/autodiff/adjoints.hpp"
27
#include "ngraph/graph_util.hpp"
Robert Kimball's avatar
Robert Kimball committed
28
#include "ngraph/log.hpp"
29
#include "ngraph/ngraph.hpp"
30
#include "ngraph/op/experimental/generate_mask.hpp"
31
#include "ngraph/serializer.hpp"
32
#include "ngraph/state/rng_state.hpp"
33
#include "util/all_close.hpp"
34
#include "util/all_close_f.hpp"
35
#include "util/ndarray.hpp"
36
#include "util/random.hpp"
37
#include "util/test_control.hpp"
38
#include "util/test_tools.hpp"
Scott Cyphers's avatar
Scott Cyphers committed
39 40 41 42

using namespace std;
using namespace ngraph;

43 44
static string s_manifest = "${MANIFEST}";

45 46 47 48 49 50 51 52 53 54 55
static const vector<element::Type> s_known_element_types = {element::from<float>(),
                                                            element::from<double>(),
                                                            element::from<int8_t>(),
                                                            element::from<int16_t>(),
                                                            element::from<int32_t>(),
                                                            element::from<int64_t>(),
                                                            element::from<uint8_t>(),
                                                            element::from<uint16_t>(),
                                                            element::from<uint32_t>(),
                                                            element::from<uint64_t>()};

56 57 58 59
class UnhandledOp : public ngraph::op::Op
{
public:
    UnhandledOp(const std::shared_ptr<Node>& arg)
60
        : Op("Unsupported_op", check_single_output_args({arg}))
61
    {
62
        constructor_validate_and_infer_types();
63 64 65 66 67
    }
    shared_ptr<Node> copy_with_new_args(const NodeVector& new_args) const override
    {
        return make_shared<UnhandledOp>(new_args[0]);
    }
68 69 70 71 72 73

protected:
    void validate_and_infer_types() override
    {
        set_output_type(0, get_input_element_type(0), get_input_partial_shape(0));
    }
74 75 76 77 78 79 80 81 82 83
};

NGRAPH_TEST(${BACKEND_NAME}, unhandled_op)
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto unhandled = make_shared<UnhandledOp>(A);
    auto f = make_shared<Function>(unhandled, op::ParameterVector{A});
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

84 85
    shared_ptr<runtime::Tensor> a = backend->create_tensor<float>(shape);
    shared_ptr<runtime::Tensor> result = backend->create_tensor<float>(shape);
86 87 88
    ASSERT_THROW(backend->call_with_validate(f, {result}, {a}), unsupported_op);
}

89
NGRAPH_TEST(${BACKEND_NAME}, function_name)
90 91 92 93 94 95
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(A + B, op::ParameterVector{A, B}, "funky func name");

96
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
97 98

    // Create some tensors for input/output
99 100 101
    shared_ptr<runtime::Tensor> a = backend->create_tensor<float>(shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor<float>(shape);
    shared_ptr<runtime::Tensor> result = backend->create_tensor<float>(shape);
102 103 104 105

    copy_data(a, test::NDArray<float, 2>({{1, 2}, {3, 4}}).get_vector());
    copy_data(b, test::NDArray<float, 2>({{5, 6}, {7, 8}}).get_vector());

106
    backend->call_with_validate(f, {result}, {a, b});
107 108 109 110
    EXPECT_EQ(read_vector<float>(result),
              (test::NDArray<float, 2>({{6, 8}, {10, 12}})).get_vector());
}

111
NGRAPH_TEST(${BACKEND_NAME}, node_name)
112 113 114 115 116 117 118 119
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto C = A + B;
    C->set_name("a node name");
    auto f = make_shared<Function>(C, op::ParameterVector{A, B});

120
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
121 122

    // Create some tensors for input/output
123 124 125
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, shape);
126 127 128 129

    copy_data(a, test::NDArray<float, 2>({{1, 2}, {3, 4}}).get_vector());
    copy_data(b, test::NDArray<float, 2>({{5, 6}, {7, 8}}).get_vector());

130
    backend->call_with_validate(f, {result}, {a, b});
131 132 133 134
    EXPECT_EQ(read_vector<float>(result),
              (test::NDArray<float, 2>({{6, 8}, {10, 12}})).get_vector());
}

135
NGRAPH_TEST(${BACKEND_NAME}, aliased_output)
136
{
137
    Shape shape{2, 2};
138 139
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
140
    auto C = A + B;
141
    auto D = A * B;
142 143
    auto E = op::Constant::create(element::f32, shape, {1, 2, 3, 4});
    auto f = make_shared<Function>(NodeVector{C, C, D, D, C, E, E}, op::ParameterVector{A, B});
144

145
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
146 147

    // Create some tensors for input/output
148 149 150 151 152 153 154 155 156
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out1 = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out2 = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out3 = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out4 = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out5 = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out6 = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> out7 = backend->create_tensor(element::f32, shape);
157 158 159

    copy_data(a, vector<float>{0, 1, 2, 3});
    copy_data(b, vector<float>{1, 2, 3, 4});
160 161
    vector<float> expectedC{1, 3, 5, 7};
    vector<float> expectedD{0, 2, 6, 12};
162
    vector<float> expectedE{1, 2, 3, 4};
163

164
    backend->call_with_validate(f, {out1, out2, out3, out4, out5, out6, out7}, {a, b});
165 166 167 168 169
    EXPECT_EQ(expectedC, read_vector<float>(out1));
    EXPECT_EQ(expectedC, read_vector<float>(out2));
    EXPECT_EQ(expectedD, read_vector<float>(out3));
    EXPECT_EQ(expectedD, read_vector<float>(out4));
    EXPECT_EQ(expectedC, read_vector<float>(out5));
170 171
    EXPECT_EQ(expectedE, read_vector<float>(out6));
    EXPECT_EQ(expectedE, read_vector<float>(out7));
172 173
}

174
NGRAPH_TEST(${BACKEND_NAME}, parameter_as_output)
175
{
176
    Shape shape{3, 4};
177
    auto A = make_shared<op::Parameter>(element::f32, shape);
178
    auto f = make_shared<Function>(A, op::ParameterVector{A});
179

180
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
181 182

    // Create some tensors for input/output
183 184
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, shape);
185 186 187 188 189

    vector<float> expected{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11};
    vector<float> zero(shape_size(shape), 0);
    copy_data(a, expected);

190
    backend->call_with_validate(f, {result}, {a});
191
    EXPECT_EQ(read_vector<float>(result), expected);
192 193
}

194
NGRAPH_TEST(${BACKEND_NAME}, abc)
Scott Cyphers's avatar
Scott Cyphers committed
195
{
196
    Shape shape{2, 2};
197 198 199
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto C = make_shared<op::Parameter>(element::f32, shape);
200
    auto f = make_shared<Function>((A + B) * C, op::ParameterVector{A, B, C});
Scott Cyphers's avatar
Scott Cyphers committed
201

202
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Scott Cyphers's avatar
Scott Cyphers committed
203 204

    // Create some tensors for input/output
205 206 207 208
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> c = backend->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, shape);
Robert Kimball's avatar
Robert Kimball committed
209

210 211 212
    copy_data(a, test::NDArray<float, 2>({{1, 2}, {3, 4}}).get_vector());
    copy_data(b, test::NDArray<float, 2>({{5, 6}, {7, 8}}).get_vector());
    copy_data(c, test::NDArray<float, 2>({{9, 10}, {11, 12}}).get_vector());
Scott Cyphers's avatar
Scott Cyphers committed
213

214
    backend->call_with_validate(f, {result}, {a, b, c});
215
    EXPECT_EQ(read_vector<float>(result),
216
              (test::NDArray<float, 2>({{54, 80}, {110, 144}})).get_vector());
Scott Cyphers's avatar
Scott Cyphers committed
217

218
    backend->call_with_validate(f, {result}, {b, a, c});
219
    EXPECT_EQ(read_vector<float>(result),
220
              (test::NDArray<float, 2>({{54, 80}, {110, 144}})).get_vector());
Scott Cyphers's avatar
Scott Cyphers committed
221

222
    backend->call_with_validate(f, {result}, {a, c, b});
223
    EXPECT_EQ(read_vector<float>(result),
224
              (test::NDArray<float, 2>({{50, 72}, {98, 128}})).get_vector());
Scott Cyphers's avatar
Scott Cyphers committed
225
}
226

227
NGRAPH_TEST(${BACKEND_NAME}, abc_int64)
228
{
229
    Shape shape{2, 2};
230 231 232
    auto A = make_shared<op::Parameter>(element::i64, shape);
    auto B = make_shared<op::Parameter>(element::i64, shape);
    auto C = make_shared<op::Parameter>(element::i64, shape);
233
    auto f = make_shared<Function>((A + B) * C, op::ParameterVector{A, B, C});
234

235
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
236 237

    // Create some tensors for input/output
238
    auto a = backend->create_tensor(element::i64, shape);
239
    copy_data(a, vector<int64_t>{1, 2, 3, 4});
240
    auto b = backend->create_tensor(element::i64, shape);
241
    copy_data(b, vector<int64_t>{5, 6, 7, 8});
242
    auto c = backend->create_tensor(element::i64, shape);
243
    copy_data(c, vector<int64_t>{9, 10, 11, 12});
244
    auto result = backend->create_tensor(element::i64, shape);
245

246
    backend->call_with_validate(f, {result}, {a, b, c});
247
    EXPECT_EQ((vector<int64_t>{54, 80, 110, 144}), read_vector<int64_t>(result));
248

249
    backend->call_with_validate(f, {result}, {b, a, c});
250
    EXPECT_EQ((vector<int64_t>{54, 80, 110, 144}), read_vector<int64_t>(result));
251

252
    backend->call_with_validate(f, {result}, {a, c, b});
253
    EXPECT_EQ((vector<int64_t>{50, 72, 98, 128}), read_vector<int64_t>(result));
254 255
}

256
// Multiple retrive values
257
NGRAPH_TEST(${BACKEND_NAME}, multiple_result)
258
{
259
    Shape shape{2, 2};
260 261 262
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto C = make_shared<op::Parameter>(element::f32, shape);
263 264 265
    auto A_add_B = make_shared<op::Add>(A, B);
    auto A_add_B_mul_C = make_shared<op::Multiply>(A_add_B, C);

266 267
    auto f =
        make_shared<Function>(NodeVector{A_add_B, A_add_B_mul_C}, op::ParameterVector{A, B, C});
268

269
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
270

271
    auto a = backend->create_tensor(element::f32, shape);
272
    copy_data(a, vector<float>{1, 2, 3, 4});
273
    auto b = backend->create_tensor(element::f32, shape);
274
    copy_data(b, vector<float>{5, 6, 7, 8});
275
    auto c = backend->create_tensor(element::f32, shape);
276 277
    copy_data(c, vector<float>{9, 10, 11, 12});

278 279
    auto r0 = backend->create_tensor(element::f32, shape);
    auto r1 = backend->create_tensor(element::f32, shape);
280

281
    backend->call_with_validate(f, {r0, r1}, {a, b, c});
282

283 284
    EXPECT_EQ((vector<float>{6, 8, 10, 12}), read_vector<float>(r0));
    EXPECT_EQ((vector<float>{54, 80, 110, 144}), read_vector<float>(r1));
285 286
}

287
NGRAPH_TEST(${BACKEND_NAME}, batch_norm_one_output)
288 289 290 291 292 293 294 295 296 297 298 299 300 301
{
    auto shape_in = Shape{2, 3};
    auto shape_mean = Shape{3};

    auto A = make_shared<op::Parameter>(element::f64, shape_in);
    auto Mean =
        op::Constant::create(element::f64, shape_mean, {0.00396654, -1.25294404, 1.16651872});
    auto Variance =
        op::Constant::create(element::f64, shape_mean, {2.40871689, 1.44969511, 0.23469392});
    auto Beta =
        op::Constant::create(element::f64, shape_mean, {2.14211921, -0.75733924, 0.42210531});
    auto Gamma =
        op::Constant::create(element::f64, shape_mean, {1.75437676, 0.37950502, 1.13727544});

302
    auto BN = make_shared<op::BatchNormInference>(1e-3, Gamma, Beta, A, Mean, Variance);
303 304 305 306 307 308 309 310 311 312 313 314 315 316
    auto f = make_shared<Function>(BN, op::ParameterVector{A});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f64, shape_in);
    copy_data(
        a,
        vector<double>{-1.97431703, -2.06521307, 0.54122217, 2.53375939, -0.22342691, 0.45340773});

    auto result = backend->create_tensor(element::f64, shape_in);
    vector<double> expected_result{
        -0.09365749, -1.01327395, -1.04269195, 5.00118923, -0.43295258, -1.24840283};

317
    backend->call_with_validate(f, {result}, {a});
318 319 320
    EXPECT_TRUE(test::all_close(vector<double>{expected_result}, read_vector<double>(result)));
}

321
NGRAPH_TEST(${BACKEND_NAME}, batch_norm_three_outputs)
322 323 324 325 326 327 328 329 330 331
{
    auto shape_in = Shape{2, 3};
    auto shape_mean = Shape{3};

    auto A = make_shared<op::Parameter>(element::f64, shape_in);
    auto Beta =
        op::Constant::create(element::f64, shape_mean, {2.14211921, -0.75733924, 0.42210531});
    auto Gamma =
        op::Constant::create(element::f64, shape_mean, {1.75437676, 0.37950502, 1.13727544});

332
    auto BN = make_shared<op::BatchNormTraining>(1e-3, Gamma, Beta, A);
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352

    auto f0 =
        make_shared<Function>(make_shared<op::GetOutputElement>(BN, 0), op::ParameterVector{A});
    auto f1 =
        make_shared<Function>(make_shared<op::GetOutputElement>(BN, 1), op::ParameterVector{A});
    auto f2 =
        make_shared<Function>(make_shared<op::GetOutputElement>(BN, 2), op::ParameterVector{A});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f64, shape_in);
    copy_data(
        a,
        vector<double>{-1.97431703, -2.06521307, 0.54122217, 2.53375939, -0.22342691, 0.45340773});

    auto result0 = backend->create_tensor(element::f64, shape_in);
    vector<double> expected_result0{
        0.3879149, -1.13662076, 1.34494817, 3.89632344, -0.37805778, -0.50073695};

353
    backend->call_with_validate(f0, {result0}, {a});
354 355 356 357 358
    EXPECT_TRUE(test::all_close(vector<double>{expected_result0}, read_vector<double>(result0)));

    auto result1 = backend->create_tensor(element::f64, shape_mean);
    vector<double> expected_result1{0.27972114, -1.14431989, 0.49731493};

359
    backend->call_with_validate(f1, {result1}, {a});
360 361 362 363 364
    EXPECT_TRUE(test::all_close(vector<double>{expected_result1}, read_vector<double>(result1)));

    auto result2 = backend->create_tensor(element::f64, shape_mean);
    vector<double> expected_result2{5.08068895e+00, 8.48043919e-01, 1.92784308e-03};

365
    backend->call_with_validate(f2, {result2}, {a});
366 367 368
    EXPECT_TRUE(test::all_close(vector<double>{expected_result2}, read_vector<double>(result2)));
}

369
NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_colwise)
370
{
371
    Shape shape_a{2, 2};
372
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
373
    Shape shape_b{2, 3};
374
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
375
    Shape shape_c{2, 3};
376
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
377
    Shape shape_r{2, 8};
378 379
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 1),
                                   op::ParameterVector{A, B, C});
380

381
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
382 383

    // Create some tensors for input/output
384
    auto a = backend->create_tensor(element::f32, shape_a);
Robert Kimball's avatar
Robert Kimball committed
385
    copy_data(a, vector<float>{2, 4, 8, 16});
386
    auto b = backend->create_tensor(element::f32, shape_b);
Robert Kimball's avatar
Robert Kimball committed
387
    copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
388
    auto c = backend->create_tensor(element::f32, shape_c);
Robert Kimball's avatar
Robert Kimball committed
389
    copy_data(c, vector<float>{2, 3, 5, 7, 11, 13});
390
    auto result = backend->create_tensor(element::f32, shape_r);
391

392
    backend->call_with_validate(f, {result}, {a, b, c});
393
    EXPECT_EQ((vector<float>{2, 4, 1, 2, 4, 2, 3, 5, 8, 16, 8, 16, 32, 7, 11, 13}),
394
              read_vector<float>(result));
395 396
}

397
NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_rowwise)
398
{
399
    Shape shape_a{2, 2};
400
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
401
    Shape shape_b{3, 2};
402
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
403
    Shape shape_c{3, 2};
404
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
405
    Shape shape_r{8, 2};
406 407
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
                                   op::ParameterVector{A, B, C});
408

409
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
410 411

    // Create some tensors for input/output
412
    auto a = backend->create_tensor(element::f32, shape_a);
Robert Kimball's avatar
Robert Kimball committed
413
    copy_data(a, vector<float>{2, 4, 8, 16});
414
    auto b = backend->create_tensor(element::f32, shape_b);
Robert Kimball's avatar
Robert Kimball committed
415
    copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
416
    auto c = backend->create_tensor(element::f32, shape_c);
Robert Kimball's avatar
Robert Kimball committed
417
    copy_data(c, vector<float>{2, 3, 5, 7, 11, 13});
418
    auto result = backend->create_tensor(element::f32, shape_r);
419

420
    backend->call_with_validate(f, {result}, {a, b, c});
421
    EXPECT_EQ((vector<float>{2, 4, 8, 16, 1, 2, 4, 8, 16, 32, 2, 3, 5, 7, 11, 13}),
422
              read_vector<float>(result));
423 424
}

425
NGRAPH_TEST(${BACKEND_NAME}, concat_matrix_int64)
426
{
427
    Shape shape_a{2, 2};
428
    auto A = make_shared<op::Parameter>(element::i64, shape_a);
429
    Shape shape_b{3, 2};
430
    auto B = make_shared<op::Parameter>(element::i64, shape_b);
431
    Shape shape_c{3, 2};
432
    auto C = make_shared<op::Parameter>(element::i64, shape_c);
433
    Shape shape_r{8, 2};
434 435
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
                                   op::ParameterVector{A, B, C});
436

437
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
438 439

    // Create some tensors for input/output
440
    auto a = backend->create_tensor(element::i64, shape_a);
441
    copy_data(a, vector<int64_t>{2, 4, 8, 16});
442
    auto b = backend->create_tensor(element::i64, shape_b);
443
    copy_data(b, vector<int64_t>{1, 2, 4, 8, 16, 32});
444
    auto c = backend->create_tensor(element::i64, shape_c);
445
    copy_data(c, vector<int64_t>{2, 3, 5, 7, 11, 13});
446
    auto result = backend->create_tensor(element::i64, shape_r);
447

448
    backend->call_with_validate(f, {result}, {a, b, c});
449
    EXPECT_EQ((vector<int64_t>{2, 4, 8, 16, 1, 2, 4, 8, 16, 32, 2, 3, 5, 7, 11, 13}),
450
              read_vector<int64_t>(result));
451 452
}

Fenglei's avatar
Fenglei committed
453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501
// Params to drive concat_vector_large testing variations
class concat_vector_params : public ::testing::TestWithParam<int>
{
protected:
    concat_vector_params() { num_inputs = GetParam(); }
    uint32_t num_inputs;
};

NGRAPH_TEST_P(${BACKEND_NAME}, concat_vector_params, concat_vector_large)
{
    Shape shape_a{1};
    NodeVector inputs;
    op::ParameterVector inputs_param;
    for (uint32_t i = 0; i < num_inputs; i++)
    {
        auto A = make_shared<op::Parameter>(element::f32, shape_a);
        inputs_param.push_back(A);
        inputs.push_back(A);
    }
    Shape shape_r{num_inputs};
    auto f = make_shared<Function>(make_shared<op::Concat>(inputs, 0), inputs_param);

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    std::vector<std::shared_ptr<runtime::Tensor>> inputs_value;
    std::vector<float> ref_result;
    for (uint32_t i = 0; i < num_inputs; i++)
    {
        auto a = backend->create_tensor(element::f32, shape_a);
        copy_data(a, vector<float>{static_cast<float>(i)});
        ref_result.push_back(static_cast<float>(i));
        inputs_value.push_back(a);
    }
    auto result = backend->create_tensor(element::f32, shape_r);

    backend->call_with_validate(f, {result}, inputs_value);
    EXPECT_EQ(ref_result, read_vector<float>(result));
}

// concat_vector_large case generation
// Add thhosw tests to cover paramter space overflow:
// cuda kernel parameter space have limit, if there is large number of parameters,
// there will be overflow for parameter space.
NGRAPH_INSTANTIATE_TEST_CASE_P(${BACKEND_NAME},
                               input_sizes,
                               concat_vector_params,
                               testing::Values(100, 128, 999));

502
NGRAPH_TEST(${BACKEND_NAME}, concat_vector)
503
{
504
    Shape shape_a{4};
505
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
506
    Shape shape_b{6};
507
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
508
    Shape shape_c{2};
509
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
510
    Shape shape_r{12};
511 512
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
                                   op::ParameterVector{A, B, C});
513

514
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
515 516

    // Create some tensors for input/output
517
    auto a = backend->create_tensor(element::f32, shape_a);
Robert Kimball's avatar
Robert Kimball committed
518
    copy_data(a, vector<float>{2, 4, 8, 16});
519
    auto b = backend->create_tensor(element::f32, shape_b);
Robert Kimball's avatar
Robert Kimball committed
520
    copy_data(b, vector<float>{1, 2, 4, 8, 16, 32});
521
    auto c = backend->create_tensor(element::f32, shape_c);
Robert Kimball's avatar
Robert Kimball committed
522
    copy_data(c, vector<float>{18, 19});
523
    auto result = backend->create_tensor(element::f32, shape_r);
524

525
    backend->call_with_validate(f, {result}, {a, b, c});
526
    EXPECT_EQ((vector<float>{2, 4, 8, 16, 1, 2, 4, 8, 16, 32, 18, 19}), read_vector<float>(result));
527 528
}

529
NGRAPH_TEST(${BACKEND_NAME}, concat_4d_tensor)
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549
{
    Shape shape{1, 1, 1, 1};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto C = make_shared<op::Parameter>(element::f32, shape);
    Shape shape_r{3, 1, 1, 1};
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
                                   op::ParameterVector{A, B, C});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{1});
    auto b = backend->create_tensor(element::f32, shape);
    copy_data(b, vector<float>{2});
    auto c = backend->create_tensor(element::f32, shape);
    copy_data(c, vector<float>{3});
    auto result = backend->create_tensor(element::f32, shape_r);

550
    backend->call_with_validate(f, {result}, {a, b, c});
551 552 553
    EXPECT_EQ((vector<float>{1, 2, 3}), read_vector<float>(result));
}

554
NGRAPH_TEST(${BACKEND_NAME}, concat_2d_tensor)
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
{
    Shape shape{1, 1};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto C = make_shared<op::Parameter>(element::f32, shape);
    Shape shape_r{3, 1};
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{A, B, C}, 0),
                                   op::ParameterVector{A, B, C});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{1});
    auto b = backend->create_tensor(element::f32, shape);
    copy_data(b, vector<float>{2});
    auto c = backend->create_tensor(element::f32, shape);
    copy_data(c, vector<float>{3});
    auto result = backend->create_tensor(element::f32, shape_r);

575
    backend->call_with_validate(f, {result}, {a, b, c});
576 577 578
    EXPECT_EQ((vector<float>{1, 2, 3}), read_vector<float>(result));
}

579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_2d_tensor)
{
    Shape shape{1, 1};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto add1 = make_shared<op::Add>(A, B);
    auto C = make_shared<op::Parameter>(element::f32, shape);
    auto D = make_shared<op::Parameter>(element::f32, shape);
    auto add2 = make_shared<op::Add>(C, D);
    auto subtract = make_shared<op::Subtract>(C, A);
    Shape shape_r{3, 1};
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{add1, add2, subtract}, 0),
                                   op::ParameterVector{A, B, C, D});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{1});
    auto b = backend->create_tensor(element::f32, shape);
    copy_data(b, vector<float>{2});
    auto c = backend->create_tensor(element::f32, shape);
    copy_data(c, vector<float>{3});
    auto d = backend->create_tensor(element::f32, shape);
    copy_data(d, vector<float>{4});
    auto result = backend->create_tensor(element::f32, shape_r);

    backend->call_with_validate(f, {result}, {a, b, c, d});
    EXPECT_EQ((vector<float>{3, 7, 2}), read_vector<float>(result));
}

NGRAPH_TEST(${BACKEND_NAME}, concat_in_place_propagate_2d_tensor)
{
    Shape shape{1, 1};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto add1 = make_shared<op::Add>(A, B);
    auto C = make_shared<op::Parameter>(element::f32, shape);
    auto D = make_shared<op::Parameter>(element::f32, shape);
    auto add2 = make_shared<op::Add>(C, D);
    auto concat1 = make_shared<op::Concat>(NodeVector{add1, add2}, 0);
    auto subtract = make_shared<op::Subtract>(C, A);
    Shape shape_r{3, 1};
    auto f = make_shared<Function>(make_shared<op::Concat>(NodeVector{concat1, subtract}, 0),
                                   op::ParameterVector{A, B, C, D});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{1});
    auto b = backend->create_tensor(element::f32, shape);
    copy_data(b, vector<float>{2});
    auto c = backend->create_tensor(element::f32, shape);
    copy_data(c, vector<float>{3});
    auto d = backend->create_tensor(element::f32, shape);
    copy_data(d, vector<float>{4});
    auto result = backend->create_tensor(element::f32, shape_r);

    backend->call_with_validate(f, {result}, {a, b, c, d});
    EXPECT_EQ((vector<float>{3, 7, 2}), read_vector<float>(result));
}

642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686
// from numpy import *
// a=linspace(1,2*3*4*3*2,2*3*4*3*2)
// b=linspace(1000+1,1000+2*3*3*3*2,2*3*3*3*2)
// c=linspace(2000+1,2000+2*3*2*3*2,2*3*2*3*2)
// a.shape=(2,3,4,3,2)
// b.shape=(2,3,3,3,2)
// c.shape=(2,3,2,3,2)
// z=concatenate((a,b,c),axis=2)
// z.shape=(2*3*(4+3+2)*3*2)
// set_printoptions(suppress=True)
// print(z)
//
// [    1.     2.     3.     4.     5.     6.     7.     8.     9.    10.
//     11.    12.    13.    14.    15.    16.    17.    18.    19.    20.
//     21.    22.    23.    24.  1001.  1002.  1003.  1004.  1005.  1006.
//   1007.  1008.  1009.  1010.  1011.  1012.  1013.  1014.  1015.  1016.
//   1017.  1018.  2001.  2002.  2003.  2004.  2005.  2006.  2007.  2008.
//   2009.  2010.  2011.  2012.    25.    26.    27.    28.    29.    30.
//     31.    32.    33.    34.    35.    36.    37.    38.    39.    40.
//     41.    42.    43.    44.    45.    46.    47.    48.  1019.  1020.
//   1021.  1022.  1023.  1024.  1025.  1026.  1027.  1028.  1029.  1030.
//   1031.  1032.  1033.  1034.  1035.  1036.  2013.  2014.  2015.  2016.
//   2017.  2018.  2019.  2020.  2021.  2022.  2023.  2024.    49.    50.
//     51.    52.    53.    54.    55.    56.    57.    58.    59.    60.
//     61.    62.    63.    64.    65.    66.    67.    68.    69.    70.
//     71.    72.  1037.  1038.  1039.  1040.  1041.  1042.  1043.  1044.
//   1045.  1046.  1047.  1048.  1049.  1050.  1051.  1052.  1053.  1054.
//   2025.  2026.  2027.  2028.  2029.  2030.  2031.  2032.  2033.  2034.
//   2035.  2036.    73.    74.    75.    76.    77.    78.    79.    80.
//     81.    82.    83.    84.    85.    86.    87.    88.    89.    90.
//     91.    92.    93.    94.    95.    96.  1055.  1056.  1057.  1058.
//   1059.  1060.  1061.  1062.  1063.  1064.  1065.  1066.  1067.  1068.
//   1069.  1070.  1071.  1072.  2037.  2038.  2039.  2040.  2041.  2042.
//   2043.  2044.  2045.  2046.  2047.  2048.    97.    98.    99.   100.
//    101.   102.   103.   104.   105.   106.   107.   108.   109.   110.
//    111.   112.   113.   114.   115.   116.   117.   118.   119.   120.
//   1073.  1074.  1075.  1076.  1077.  1078.  1079.  1080.  1081.  1082.
//   1083.  1084.  1085.  1086.  1087.  1088.  1089.  1090.  2049.  2050.
//   2051.  2052.  2053.  2054.  2055.  2056.  2057.  2058.  2059.  2060.
//    121.   122.   123.   124.   125.   126.   127.   128.   129.   130.
//    131.   132.   133.   134.   135.   136.   137.   138.   139.   140.
//    141.   142.   143.   144.  1091.  1092.  1093.  1094.  1095.  1096.
//   1097.  1098.  1099.  1100.  1101.  1102.  1103.  1104.  1105.  1106.
//   1107.  1108.  2061.  2062.  2063.  2064.  2065.  2066.  2067.  2068.
//   2069.  2070.  2071.  2072.]
687
NGRAPH_TEST(${BACKEND_NAME}, concat_5d)
688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706
{
    vector<float> a_data(2 * 3 * 4 * 3 * 2);
    for (int i = 0; i < 2 * 3 * 4 * 3 * 2; i++)
    {
        a_data[i] = float(i + 1);
    }

    vector<float> b_data(2 * 3 * 3 * 3 * 2);
    for (int i = 0; i < 2 * 3 * 3 * 3 * 2; i++)
    {
        b_data[i] = 1000 + float(i + 1);
    }

    vector<float> c_data(2 * 3 * 2 * 3 * 2);
    for (int i = 0; i < 2 * 3 * 2 * 3 * 2; i++)
    {
        c_data[i] = 2000 + float(i + 1);
    }

707
    Shape shape_a{2, 3, 4, 3, 2};
708
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
709
    Shape shape_b{2, 3, 3, 3, 2};
710
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
711
    Shape shape_c{2, 3, 2, 3, 2};
712
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
713
    Shape shape_r{2, 3, 9, 3, 2};
714

715 716
    auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 2);
    auto f = make_shared<Function>(r, op::ParameterVector{A, B, C});
717

718
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
719 720

    // Create some tensors for input/output
721
    auto a = backend->create_tensor(element::f32, shape_a);
722
    copy_data(a, a_data);
723
    auto b = backend->create_tensor(element::f32, shape_b);
724
    copy_data(b, b_data);
725
    auto c = backend->create_tensor(element::f32, shape_c);
726 727
    copy_data(c, c_data);

728
    auto result = backend->create_tensor(element::f32, shape_r);
729

730
    backend->call_with_validate(f, {result}, {a, b, c});
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759
    EXPECT_EQ(
        (vector<float>{
            1.,    2.,    3.,    4.,    5.,    6.,    7.,    8.,    9.,    10.,   11.,   12.,
            13.,   14.,   15.,   16.,   17.,   18.,   19.,   20.,   21.,   22.,   23.,   24.,
            1001., 1002., 1003., 1004., 1005., 1006., 1007., 1008., 1009., 1010., 1011., 1012.,
            1013., 1014., 1015., 1016., 1017., 1018., 2001., 2002., 2003., 2004., 2005., 2006.,
            2007., 2008., 2009., 2010., 2011., 2012., 25.,   26.,   27.,   28.,   29.,   30.,
            31.,   32.,   33.,   34.,   35.,   36.,   37.,   38.,   39.,   40.,   41.,   42.,
            43.,   44.,   45.,   46.,   47.,   48.,   1019., 1020., 1021., 1022., 1023., 1024.,
            1025., 1026., 1027., 1028., 1029., 1030., 1031., 1032., 1033., 1034., 1035., 1036.,
            2013., 2014., 2015., 2016., 2017., 2018., 2019., 2020., 2021., 2022., 2023., 2024.,
            49.,   50.,   51.,   52.,   53.,   54.,   55.,   56.,   57.,   58.,   59.,   60.,
            61.,   62.,   63.,   64.,   65.,   66.,   67.,   68.,   69.,   70.,   71.,   72.,
            1037., 1038., 1039., 1040., 1041., 1042., 1043., 1044., 1045., 1046., 1047., 1048.,
            1049., 1050., 1051., 1052., 1053., 1054., 2025., 2026., 2027., 2028., 2029., 2030.,
            2031., 2032., 2033., 2034., 2035., 2036., 73.,   74.,   75.,   76.,   77.,   78.,
            79.,   80.,   81.,   82.,   83.,   84.,   85.,   86.,   87.,   88.,   89.,   90.,
            91.,   92.,   93.,   94.,   95.,   96.,   1055., 1056., 1057., 1058., 1059., 1060.,
            1061., 1062., 1063., 1064., 1065., 1066., 1067., 1068., 1069., 1070., 1071., 1072.,
            2037., 2038., 2039., 2040., 2041., 2042., 2043., 2044., 2045., 2046., 2047., 2048.,
            97.,   98.,   99.,   100.,  101.,  102.,  103.,  104.,  105.,  106.,  107.,  108.,
            109.,  110.,  111.,  112.,  113.,  114.,  115.,  116.,  117.,  118.,  119.,  120.,
            1073., 1074., 1075., 1076., 1077., 1078., 1079., 1080., 1081., 1082., 1083., 1084.,
            1085., 1086., 1087., 1088., 1089., 1090., 2049., 2050., 2051., 2052., 2053., 2054.,
            2055., 2056., 2057., 2058., 2059., 2060., 121.,  122.,  123.,  124.,  125.,  126.,
            127.,  128.,  129.,  130.,  131.,  132.,  133.,  134.,  135.,  136.,  137.,  138.,
            139.,  140.,  141.,  142.,  143.,  144.,  1091., 1092., 1093., 1094., 1095., 1096.,
            1097., 1098., 1099., 1100., 1101., 1102., 1103., 1104., 1105., 1106., 1107., 1108.,
            2061., 2062., 2063., 2064., 2065., 2066., 2067., 2068., 2069., 2070., 2071., 2072.}),
760
        read_vector<float>(result));
761 762
}

763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786
NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_1d_last)
{
    Shape shape_a{4};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_b{0};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_r{4};

    auto r = make_shared<op::Concat>(NodeVector{A, B}, 0);
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    vector<float> a_data{1, 2, 3, 4};
    vector<float> b_data(0);

    auto a = backend->create_tensor(element::f32, shape_a);
    copy_data(a, a_data);
    auto b = backend->create_tensor(element::f32, shape_b);
    copy_data(b, b_data);

    auto result = backend->create_tensor(element::f32, shape_r);

787
    backend->call_with_validate(f, {result}, {a, b});
788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(result));
}

NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_1d_middle)
{
    Shape shape_a{4};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_b{0};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_c{4};
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
    Shape shape_r{8};

    auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 0);
    auto f = make_shared<Function>(r, op::ParameterVector{A, B, C});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    vector<float> a_data{1, 2, 3, 4};
    vector<float> b_data(0);
    vector<float> c_data{5, 6, 7, 8};

    auto a = backend->create_tensor(element::f32, shape_a);
    copy_data(a, a_data);
    auto b = backend->create_tensor(element::f32, shape_b);
    copy_data(b, b_data);
    auto c = backend->create_tensor(element::f32, shape_c);
    copy_data(c, c_data);

    auto result = backend->create_tensor(element::f32, shape_r);

820
    backend->call_with_validate(f, {result}, {a, b, c});
821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6, 7, 8}), read_vector<float>(result));
}

NGRAPH_TEST(${BACKEND_NAME}, concat_zero_length_4d_middle)
{
    Shape shape_a{2, 2, 1, 1};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_b{2, 2, 0, 1};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_c{2, 2, 1, 1};
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
    Shape shape_r{2, 2, 2, 1};

    auto r = make_shared<op::Concat>(NodeVector{A, B, C}, 2);
    auto f = make_shared<Function>(r, op::ParameterVector{A, B, C});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    vector<float> a_data{1, 2, 3, 4};
    vector<float> b_data(0);
    vector<float> c_data{5, 6, 7, 8};

    auto a = backend->create_tensor(element::f32, shape_a);
    copy_data(a, a_data);
    auto b = backend->create_tensor(element::f32, shape_b);
    copy_data(b, b_data);
    auto c = backend->create_tensor(element::f32, shape_c);
    copy_data(c, c_data);

    auto result = backend->create_tensor(element::f32, shape_r);

853
    backend->call_with_validate(f, {result}, {a, b, c});
854 855 856
    EXPECT_EQ((vector<float>{1, 5, 2, 6, 3, 7, 4, 8}), read_vector<float>(result));
}

857
NGRAPH_TEST(${BACKEND_NAME}, lrn)
858
{
859
    Shape shape{2, 3, 2, 1};
860
    auto A = make_shared<op::Parameter>(element::f32, shape);
861 862
    auto lrn = make_shared<op::LRN>(A, 1., 2., 1., 3);
    auto f = make_shared<Function>(lrn, op::ParameterVector{A});
863

864
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
865

866
    vector<float> args{0.0f, 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f};
867
    auto a = backend->create_tensor(element::f32, shape);
868 869
    copy_data(a, args);

870
    auto result = backend->create_tensor(element::f32, shape);
871
    backend->call_with_validate(f, {result}, {a});
872

873 874 875 876 877 878 879 880 881 882 883 884 885
    vector<float> expected{0.f,
                           0.05325444f,
                           0.03402646f,
                           0.01869806f,
                           0.06805293f,
                           0.03287071f,
                           0.00509002f,
                           0.00356153f,
                           0.00174719f,
                           0.0012555f,
                           0.00322708f,
                           0.00235574f};
    EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result)));
886 887
}

888
NGRAPH_TEST(${BACKEND_NAME}, select)
889
{
890 891
    Shape shape{2, 2, 2};
    auto A = make_shared<op::Parameter>(element::boolean, shape);
892
    auto B = make_shared<op::Parameter>(element::f32, shape);
893 894
    auto C = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Select>(A, B, C), op::ParameterVector{A, B, C});
895

896
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
897 898

    // Create some tensors for input/output
899 900
    auto a = backend->create_tensor(element::boolean, shape);
    copy_data(a, vector<char>{0, 1, 1, 0, 0, 1, 0, 1});
901
    auto b = backend->create_tensor(element::f32, shape);
902
    copy_data(b, vector<float>{1, 2, 3, 4, 5, 6, 7, 8});
903
    auto c = backend->create_tensor(element::f32, shape);
904
    copy_data(c, vector<float>{11, 12, 13, 14, 15, 16, 17, 18});
905
    auto result = backend->create_tensor(element::f32, shape);
906

907 908
    backend->call_with_validate(f, {result}, {a, b, c});
    EXPECT_EQ((vector<float>{11, 2, 3, 14, 15, 6, 17, 8}), read_vector<float>(result));
909 910
}

911
NGRAPH_TEST(${BACKEND_NAME}, tensor_constant)
912
{
913 914 915
    Shape shape{2, 2, 2};
    auto A = op::Constant::create(element::f32, shape, {1, 2, 3, 4, 5, 6, 7, 8});
    auto f = make_shared<Function>(A, op::ParameterVector{});
916

917
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
918 919

    // Create some tensors for input/output
920
    auto result = backend->create_tensor(element::f32, shape);
921

922 923
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6, 7, 8}), read_vector<float>(result));
924 925
}

926
NGRAPH_TEST(${BACKEND_NAME}, tensor_2constant)
927
{
928 929 930
    Shape shape{2, 2, 2};
    auto A = op::Constant::create(element::f32, shape, {1, 2, 3, 4, 5, 6, 7, 8});
    auto f = make_shared<Function>(NodeVector{A, A}, op::ParameterVector{});
931

932
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
933 934

    // Create some tensors for input/output
935 936
    auto result0 = backend->create_tensor(element::f32, shape);
    auto result1 = backend->create_tensor(element::f32, shape);
937

938 939 940
    backend->call_with_validate(f, {result0, result1}, {});
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6, 7, 8}), read_vector<float>(result0));
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6, 7, 8}), read_vector<float>(result1));
941 942
}

943
NGRAPH_TEST(${BACKEND_NAME}, tensor_constant_with_op)
944
{
945
    Shape shape{2, 2, 2};
946 947
    auto A = op::Constant::create(element::f32, shape, {-1, 2, 3, -4, 5, -6, -7, 8});
    auto f = make_shared<Function>(make_shared<op::Abs>(A), op::ParameterVector{});
948

949
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
950 951

    // Create some tensors for input/output
952
    auto result = backend->create_tensor(element::f32, shape);
953

954 955
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6, 7, 8}), read_vector<float>(result));
956 957
}

958
NGRAPH_TEST(${BACKEND_NAME}, constant_multi_use)
959
{
960 961
    auto A = make_shared<op::Constant>(element::i32, Shape{}, std::vector<std::string>{"388"});
    auto f = make_shared<Function>(A, op::ParameterVector{});
962
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
963

964 965 966
    std::shared_ptr<runtime::Tensor> r1 = backend->create_tensor(element::i32, Shape{});
    backend->call_with_validate(f, {r1}, std::vector<std::shared_ptr<runtime::Tensor>>{});
    EXPECT_EQ(read_vector<int>(r1), std::vector<int>{388});
967

968 969 970
    std::shared_ptr<runtime::Tensor> r2 = backend->create_tensor(element::i32, Shape{});
    backend->call_with_validate(f, {r2}, std::vector<std::shared_ptr<runtime::Tensor>>{});
    EXPECT_EQ(read_vector<int>(r2), std::vector<int>{388});
971 972
}

973
NGRAPH_TEST(${BACKEND_NAME}, function_call)
974
{
975 976
    // First create "f(A,B,C) = (A+B)*C".
    Shape shape{2, 2};
977 978
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
979 980
    auto C = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>((A + B) * C, op::ParameterVector{A, B, C});
981

982 983 984 985 986 987 988 989
    // Now make "g(X,Y,Z) = f(X,Y,Z) + f(X,Y,Z)"
    auto X = make_shared<op::Parameter>(element::f32, shape);
    auto Y = make_shared<op::Parameter>(element::f32, shape);
    auto Z = make_shared<op::Parameter>(element::f32, shape);
    auto g =
        make_shared<Function>(make_shared<op::FunctionCall>(f, NodeVector{X + Y, Y + Z, Z + X}) +
                                  make_shared<op::FunctionCall>(f, NodeVector{X, Y, Z}),
                              op::ParameterVector{X, Y, Z});
990

991
    // Now call g on some test vectors.
992
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
993

994 995 996 997 998 999 1000
    auto x = backend->create_tensor(element::f32, shape);
    copy_data(x, vector<float>{1, 2, 3, 4});
    auto y = backend->create_tensor(element::f32, shape);
    copy_data(y, vector<float>{5, 6, 7, 8});
    auto z = backend->create_tensor(element::f32, shape);
    copy_data(z, vector<float>{9, 10, 11, 12});
    auto result = backend->create_tensor(element::f32, shape);
1001

1002 1003
    backend->call_with_validate(g, {result}, {x, y, z});
    EXPECT_EQ((vector<float>{254, 368, 502, 656}), read_vector<float>(result));
1004

1005 1006 1007 1008 1009
    backend->call_with_validate(g, {result}, {y, x, z});
    EXPECT_EQ((vector<float>{278, 400, 542, 704}), read_vector<float>(result));

    backend->call_with_validate(g, {result}, {x, z, y});
    EXPECT_EQ((vector<float>{194, 296, 418, 560}), read_vector<float>(result));
1010 1011
}

1012
NGRAPH_TEST(${BACKEND_NAME}, convert_int32_float32)
1013
{
1014
    Shape shape{2, 2};
1015 1016 1017
    auto A = make_shared<op::Parameter>(element::i32, shape);
    auto f =
        make_shared<Function>(make_shared<op::Convert>(A, element::f32), op::ParameterVector{A});
1018

1019
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1020 1021

    // Create some tensors for input/output
1022 1023
    auto a = backend->create_tensor(element::i32, shape);
    copy_data(a, vector<int32_t>{1, 2, 3, 4});
1024
    auto result = backend->create_tensor(element::f32, shape);
1025

1026
    backend->call_with_validate(f, {result}, {a});
1027
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(result));
1028 1029
}

1030
NGRAPH_TEST(${BACKEND_NAME}, convert_uint16_float32)
1031
{
1032 1033 1034 1035
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::u16, shape);
    auto f =
        make_shared<Function>(make_shared<op::Convert>(A, element::f32), op::ParameterVector{A});
1036

1037
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1038 1039

    // Create some tensors for input/output
1040 1041 1042
    auto a = backend->create_tensor(element::u16, shape);
    copy_data(a, vector<uint16_t>{1, 2, 3, 4});
    auto result = backend->create_tensor(element::f32, shape);
1043

1044 1045
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(result));
1046 1047
}

1048
NGRAPH_TEST(${BACKEND_NAME}, convert_int32_bool)
1049
{
1050 1051 1052 1053
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::i32, shape);
    auto f = make_shared<Function>(make_shared<op::Convert>(A, element::boolean),
                                   op::ParameterVector{A});
1054

1055
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1056 1057

    // Create some tensors for input/output
1058 1059 1060
    auto a = backend->create_tensor(element::i32, shape);
    copy_data(a, vector<int32_t>{1, 2, 3, 4});
    auto result = backend->create_tensor(element::boolean, shape);
1061

1062 1063
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<char>{1, 2, 3, 4}), read_vector<char>(result));
1064 1065
}

1066
NGRAPH_TEST(${BACKEND_NAME}, convert_float32_bool)
1067
{
1068 1069 1070 1071
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Convert>(A, element::boolean),
                                   op::ParameterVector{A});
1072

1073
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1074 1075

    // Create some tensors for input/output
1076 1077 1078
    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{1, 2, 3, 4});
    auto result = backend->create_tensor(element::boolean, shape);
1079

1080 1081
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<char>{1, 2, 3, 4}), read_vector<char>(result));
1082 1083
}

1084
NGRAPH_TEST(${BACKEND_NAME}, slice_scalar)
1085
{
1086
    Shape shape_a{};
1087
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1088
    Shape shape_r{};
1089 1090
    auto r = make_shared<op::Slice>(A, Coordinate{}, Coordinate{});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1091

1092
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1093 1094

    // Create some tensors for input/output
1095
    auto a = backend->create_tensor(element::f32, shape_a);
1096
    copy_data(a, vector<float>{312});
1097
    auto result = backend->create_tensor(element::f32, shape_r);
1098

1099 1100
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{312}), read_vector<float>(result));
1101 1102
}

1103
NGRAPH_TEST(${BACKEND_NAME}, slice_matrix)
1104
{
1105
    Shape shape_a{4, 4};
1106
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1107 1108 1109
    Shape shape_r{3, 2};
    auto r = make_shared<op::Slice>(A, Coordinate{0, 1}, Coordinate{3, 3});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1110

1111
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1112 1113

    // Create some tensors for input/output
1114
    auto a = backend->create_tensor(element::f32, shape_a);
1115
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
1116
    auto result = backend->create_tensor(element::f32, shape_r);
1117

1118 1119
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{2, 3, 6, 7, 10, 11}), read_vector<float>(result));
1120 1121
}

1122
NGRAPH_TEST(${BACKEND_NAME}, slice_vector)
1123
{
1124
    Shape shape_a{16};
1125
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1126 1127 1128
    Shape shape_r{12};
    auto r = make_shared<op::Slice>(A, Coordinate{2}, Coordinate{14});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1129

1130
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1131 1132

    // Create some tensors for input/output
1133
    auto a = backend->create_tensor(element::f32, shape_a);
1134
    copy_data(a, vector<float>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
1135
    auto result = backend->create_tensor(element::f32, shape_r);
1136

1137 1138
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13}), read_vector<float>(result));
1139 1140
}

1141
NGRAPH_TEST(${BACKEND_NAME}, slice_matrix_strided)
1142
{
1143
    Shape shape_a{4, 4};
1144
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1145 1146 1147
    Shape shape_r{2, 2};
    auto r = make_shared<op::Slice>(A, Coordinate{1, 0}, Coordinate{4, 4}, Strides{2, 3});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1148

1149
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1150 1151

    // Create some tensors for input/output
1152
    auto a = backend->create_tensor(element::f32, shape_a);
1153
    copy_data(a, vector<float>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
1154
    auto result = backend->create_tensor(element::f32, shape_r);
1155

1156 1157
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{4, 7, 12, 15}), read_vector<float>(result));
1158 1159
}

1160
NGRAPH_TEST(${BACKEND_NAME}, slice_3d)
1161
{
1162
    Shape shape_a{4, 4, 4};
1163
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1164 1165 1166
    Shape shape_r{2, 2, 2};
    auto r = make_shared<op::Slice>(A, Coordinate{1, 1, 1}, Coordinate{3, 3, 3});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1167

1168
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1169 1170

    // Create some tensors for input/output
1171
    auto a = backend->create_tensor(element::f32, shape_a);
1172
    copy_data(a, vector<float>{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
1173

1174 1175 1176 1177 1178
                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,

                               32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,

                               48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63});
1179
    auto result = backend->create_tensor(element::f32, shape_r);
1180

1181 1182
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{21, 22, 25, 26, 37, 38, 41, 42}), read_vector<float>(result));
1183 1184
}

1185
NGRAPH_TEST(${BACKEND_NAME}, slice_3d_strided)
1186
{
1187
    Shape shape_a{4, 4, 4};
1188
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1189 1190 1191
    Shape shape_r{2, 2, 2};
    auto r = make_shared<op::Slice>(A, Coordinate{0, 0, 0}, Coordinate{4, 4, 4}, Strides{2, 2, 2});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1192

1193
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1194 1195

    // Create some tensors for input/output
1196
    auto a = backend->create_tensor(element::f32, shape_a);
1197
    copy_data(a, vector<float>{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
1198

1199
                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1200

1201
                               32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1202

1203
                               48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63});
1204
    auto result = backend->create_tensor(element::f32, shape_r);
1205

1206 1207
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{0, 2, 8, 10, 32, 34, 40, 42}), read_vector<float>(result));
1208 1209
}

1210
NGRAPH_TEST(${BACKEND_NAME}, slice_3d_strided_different_strides)
1211
{
1212
    Shape shape_a{4, 4, 4};
1213
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1214 1215 1216
    Shape shape_r{2, 2, 2};
    auto r = make_shared<op::Slice>(A, Coordinate{0, 0, 0}, Coordinate{4, 4, 4}, Strides{2, 2, 3});
    auto f = make_shared<Function>(r, op::ParameterVector{A});
1217 1218 1219 1220 1221

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape_a);
1222
    copy_data(a, vector<float>{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
1223

1224
                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1225

1226
                               32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
1227

1228
                               48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63});
1229
    auto result = backend->create_tensor(element::f32, shape_r);
1230

1231 1232
    backend->call_with_validate(f, {result}, {a});
    EXPECT_EQ((vector<float>{0, 3, 8, 11, 32, 35, 40, 43}), read_vector<float>(result));
1233 1234
}

1235
NGRAPH_TEST(${BACKEND_NAME}, scalar_constant_float32)
1236
{
1237 1238
    auto r = op::Constant::create(element::f32, Shape{}, {4.75});
    auto f = make_shared<Function>(r, op::ParameterVector{});
1239

1240
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1241 1242

    // Create some tensors for input/output
1243
    auto result = backend->create_tensor(element::f32, Shape{});
1244

1245 1246
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ(vector<float>{4.75f}, read_vector<float>(result));
1247 1248
}

1249
NGRAPH_TEST(${BACKEND_NAME}, scalar_constant_int64)
1250
{
1251 1252
    auto r = op::Constant::create(element::i64, Shape{}, {2112});
    auto f = make_shared<Function>(r, op::ParameterVector{});
1253

1254
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1255 1256

    // Create some tensors for input/output
1257
    auto result = backend->create_tensor(element::i64, Shape{});
1258

1259 1260
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ(vector<int64_t>{2112}, read_vector<int64_t>(result));
1261 1262
}

1263
NGRAPH_TEST(${BACKEND_NAME}, tensor_constant_float32)
1264
{
1265 1266 1267
    Shape shape{2, 2};
    auto r = op::Constant::create(element::f32, shape, {4.75, 4.5, -5.25, 0.0});
    auto f = make_shared<Function>(r, op::ParameterVector{});
1268

1269
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1270 1271

    // Create some tensors for input/output
1272
    auto result = backend->create_tensor(element::f32, shape);
1273

1274 1275
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ((vector<float>{4.75f, 4.5f, -5.25f, 0.0f}), read_vector<float>(result));
1276 1277
}

1278
NGRAPH_TEST(${BACKEND_NAME}, tensor_constant_int64)
1279
{
1280 1281 1282
    Shape shape{2, 2};
    auto r = op::Constant::create(element::i64, shape, {2112, 1848, 1776, 1964});
    auto f = make_shared<Function>(r, op::ParameterVector{});
1283

1284
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1285 1286

    // Create some tensors for input/output
1287
    auto result = backend->create_tensor(element::i64, shape);
1288

1289 1290
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ((vector<int64_t>{2112, 1848, 1776, 1964}), read_vector<int64_t>(result));
1291 1292
}

1293 1294
// TODO: Kahan sum only works in limited cases with CPU / Interpreter backend
NGRAPH_TEST(${BACKEND_NAME}, kahan_sum_to_scalar)
1295
{
1296
    Shape shape{2, 2};
1297
    auto A = make_shared<op::Parameter>(element::f32, shape);
1298
    auto f = make_shared<Function>(make_shared<op::Sum>(A, AxisSet{0, 1}), op::ParameterVector{A});
1299

1300
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1301 1302

    // Create some tensors for input/output
1303
    float epsilon = 9.5367431640625e-7f;
1304
    auto a = backend->create_tensor(element::f32, shape);
1305 1306
    copy_data(a, vector<float>{epsilon, -1.f, 0.f, 1.f});
    auto result = backend->create_tensor(element::f32, Shape{});
1307

1308
    backend->call_with_validate(f, {result}, {a});
1309
    EXPECT_TRUE(test::all_close_f(vector<float>{epsilon}, read_vector<float>(result)));
1310 1311
}

1312 1313
// TODO: Kahan sum only works in limited cases with CPU / Interpreter backend
NGRAPH_TEST(${BACKEND_NAME}, kahan_sum_3d_to_vector)
1314
{
1315
    Shape shape_a{3, 3, 3};
1316
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1317 1318
    Shape shape_rt{3};
    auto f = make_shared<Function>(make_shared<op::Sum>(A, AxisSet{0, 1}), op::ParameterVector{A});
1319

1320
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1321 1322

    // Create some tensors for input/output
1323
    auto a = backend->create_tensor(element::f32, shape_a);
1324 1325 1326 1327 1328 1329 1330
    float epsilon_a = 1.220703125e-4f;
    float epsilon_b = 3.0517578125e-5f;
    float epsilon_c = 7.62939453125e-6f;
    copy_data(a, vector<float>{1,  1,  1,  1,  1,  1,  epsilon_a, epsilon_b, epsilon_c,
                               1,  1,  1,  1,  1,  1,  -1,        -1,        -1,
                               -1, -1, -1, -1, -1, -1, -1,        -1,        -1});
    auto result = backend->create_tensor(element::f32, shape_rt);
1331

1332
    backend->call_with_validate(f, {result}, {a});
1333 1334
    EXPECT_TRUE(test::all_close_f(vector<float>{epsilon_a, epsilon_b, epsilon_c},
                                  read_vector<float>(result)));
1335 1336
}

1337
NGRAPH_TEST(${BACKEND_NAME}, constant_equality_bool)
1338
{
1339 1340 1341 1342 1343 1344 1345 1346
    Shape shape{4};
    // auto A = make_shared<op::Parameter>(element::boolean, shape);
    // auto B = make_shared<op::Parameter>(element::boolean, shape);
    // auto f = make_shared<Function>(make_shared<op::Equal>(A, B), op::ParameterVector{A, B});

    auto A = op::Constant::create(element::boolean, shape, {true, false, true, false});
    auto B = op::Constant::create(element::boolean, shape, {true, true, true, true});
    auto f = make_shared<Function>(make_shared<op::Equal>(A, B), op::ParameterVector{});
1347

1348
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1349 1350

    // Create some tensors for input/output
1351
    auto result = backend->create_tensor(element::boolean, shape);
1352

1353 1354
    backend->call_with_validate(f, {result}, {});
    EXPECT_EQ((vector<char>{true, false, true, false}), read_vector<char>(result));
1355 1356
}

1357
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_scalar)
Nick Korovaiko's avatar
Nick Korovaiko committed
1358
{
1359
    Shape shape_a{};
1360
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1361
    Shape shape_b{};
1362
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1363 1364
    Shape shape_r{};
    auto r = make_shared<op::ReplaceSlice>(A, B, Coordinate{}, Coordinate{});
1365
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});
Nick Korovaiko's avatar
Nick Korovaiko committed
1366 1367 1368

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

1369
    // Create some tensors for input/output
1370
    auto a = backend->create_tensor(element::f32, shape_a);
1371
    copy_data(a, vector<float>{312});
1372
    auto b = backend->create_tensor(element::f32, shape_b);
1373
    copy_data(b, vector<float>{808});
1374
    auto result = backend->create_tensor(element::f32, shape_r);
Nick Korovaiko's avatar
Nick Korovaiko committed
1375

1376
    backend->call_with_validate(f, {result}, {a, b});
1377
    EXPECT_EQ((vector<float>{808}), read_vector<float>(result));
Nick Korovaiko's avatar
Nick Korovaiko committed
1378 1379
}

1380
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_matrix_inplace)
1381
{
1382
    Shape shape_a{4, 4};
1383
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1384 1385 1386
    auto abs_A = make_shared<op::Abs>(A);

    Shape shape_b{3, 2};
1387
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1388 1389 1390 1391
    Shape shape_r{4, 4};
    auto r = make_shared<op::ReplaceSlice>(abs_A, B, Coordinate{0, 1}, Coordinate{3, 3});
    auto abs_r = make_shared<op::Abs>(r);
    auto f = make_shared<Function>(abs_r, op::ParameterVector{A, B});
1392

1393
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1394 1395

    // Create some tensors for input/output
1396
    auto a = backend->create_tensor(element::f32, shape_a);
1397
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
1398
    auto b = backend->create_tensor(element::f32, shape_b);
1399
    copy_data(b, vector<float>{102, 103, 106, 107, 110, 111});
1400
    auto result = backend->create_tensor(element::f32, shape_r);
1401

1402
    backend->call_with_validate(f, {result}, {a, b});
1403
    EXPECT_EQ((vector<float>{1, 102, 103, 4, 5, 106, 107, 8, 9, 110, 111, 12, 13, 14, 15, 16}),
1404
              read_vector<float>(result));
1405 1406
}

1407
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_matrix)
1408
{
1409
    Shape shape_a{4, 4};
1410
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1411
    Shape shape_b{3, 2};
1412
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1413 1414
    Shape shape_r{4, 4};
    auto r = make_shared<op::ReplaceSlice>(A, B, Coordinate{0, 1}, Coordinate{3, 3});
1415
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});
1416

1417
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1418 1419

    // Create some tensors for input/output
1420
    auto a = backend->create_tensor(element::f32, shape_a);
1421
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16});
1422
    auto b = backend->create_tensor(element::f32, shape_b);
1423
    copy_data(b, vector<float>{102, 103, 106, 107, 110, 111});
1424
    auto result = backend->create_tensor(element::f32, shape_r);
1425

1426
    backend->call_with_validate(f, {result}, {a, b});
1427
    EXPECT_EQ((vector<float>{1, 102, 103, 4, 5, 106, 107, 8, 9, 110, 111, 12, 13, 14, 15, 16}),
1428
              read_vector<float>(result));
1429 1430
}

1431
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_vector)
1432
{
1433
    Shape shape_a{16};
1434
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1435
    Shape shape_b{12};
1436
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1437 1438
    Shape shape_r{16};
    auto r = make_shared<op::ReplaceSlice>(A, B, Coordinate{2}, Coordinate{14});
1439
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});
1440 1441 1442 1443

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1444
    auto a = backend->create_tensor(element::f32, shape_a);
1445
    copy_data(a, vector<float>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15});
1446
    auto b = backend->create_tensor(element::f32, shape_b);
1447
    copy_data(b, vector<float>{102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113});
1448
    auto result = backend->create_tensor(element::f32, shape_r);
1449 1450

    backend->call_with_validate(f, {result}, {a, b});
1451 1452 1453
    EXPECT_EQ(
        (vector<float>{0, 1, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 14, 15}),
        read_vector<float>(result));
1454 1455
}

1456
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_3d)
1457
{
1458
    Shape shape_a{4, 4, 4};
1459
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1460
    Shape shape_b{2, 2, 2};
1461
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1462 1463
    Shape shape_r{4, 4, 4};
    auto r = make_shared<op::ReplaceSlice>(A, B, Coordinate{1, 1, 1}, Coordinate{3, 3, 3});
1464
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});
1465 1466 1467 1468

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1469
    auto a = backend->create_tensor(element::f32, shape_a);
1470
    copy_data(a, vector<float>{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
1471

1472
                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
Adam Procter's avatar
Adam Procter committed
1473

1474
                               32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
Adam Procter's avatar
Adam Procter committed
1475

1476
                               48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63});
1477
    auto b = backend->create_tensor(element::f32, shape_b);
1478
    copy_data(b, vector<float>{921, 922, 925, 926, 937, 938, 941, 942});
1479
    auto result = backend->create_tensor(element::f32, shape_r);
Adam Procter's avatar
Adam Procter committed
1480

1481
    backend->call_with_validate(f, {result}, {a, b});
1482
    EXPECT_EQ((vector<float>{0,  1,  2,  3,  4,  5,   6,   7,  8,  9,   10,  11, 12, 13, 14, 15,
Adam Procter's avatar
Adam Procter committed
1483

1484
                             16, 17, 18, 19, 20, 921, 922, 23, 24, 925, 926, 27, 28, 29, 30, 31,
Adam Procter's avatar
Adam Procter committed
1485

1486 1487 1488 1489 1490
                             32, 33, 34, 35, 36, 937, 938, 39, 40, 941, 942, 43, 44, 45, 46, 47,

                             48, 49, 50, 51, 52, 53,  54,  55, 56, 57,  58,  59, 60, 61, 62, 63}),
              read_vector<float>(result));
}
1491

1492
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_3d_strided)
1493
{
1494
    Shape shape_a{4, 4, 4};
1495
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1496
    Shape shape_b{2, 2, 2};
1497
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1498 1499 1500
    Shape shape_r{4, 4, 4};
    auto r = make_shared<op::ReplaceSlice>(
        A, B, Coordinate{0, 0, 0}, Coordinate{4, 4, 4}, Strides{2, 2, 2});
1501
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});
1502 1503 1504 1505

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1506
    auto a = backend->create_tensor(element::f32, shape_a);
1507 1508 1509 1510 1511
    copy_data(a, vector<float>{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,

                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,

                               32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
Adam Procter's avatar
Adam Procter committed
1512

1513 1514 1515
                               48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63});
    auto b = backend->create_tensor(element::f32, shape_b);
    copy_data(b, vector<float>{900, 902, 908, 910, 932, 934, 940, 942});
1516
    auto result = backend->create_tensor(element::f32, shape_r);
1517 1518

    backend->call_with_validate(f, {result}, {a, b});
1519
    EXPECT_EQ((vector<float>{900, 1,  902, 3,  4,  5,  6,  7,  908, 9,  910, 11, 12, 13, 14, 15,
Adam Procter's avatar
Adam Procter committed
1520

1521
                             16,  17, 18,  19, 20, 21, 22, 23, 24,  25, 26,  27, 28, 29, 30, 31,
Adam Procter's avatar
Adam Procter committed
1522

1523
                             932, 33, 934, 35, 36, 37, 38, 39, 940, 41, 942, 43, 44, 45, 46, 47,
Adam Procter's avatar
Adam Procter committed
1524

1525 1526
                             48,  49, 50,  51, 52, 53, 54, 55, 56,  57, 58,  59, 60, 61, 62, 63}),
              read_vector<float>(result));
1527 1528
}

1529
NGRAPH_TEST(${BACKEND_NAME}, replace_slice_3d_strided_different_strides)
1530
{
1531 1532 1533 1534 1535 1536 1537
    Shape shape_a{4, 4, 4};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_b{2, 2, 2};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_r{4, 4, 4};
    auto r = make_shared<op::ReplaceSlice>(
        A, B, Coordinate{0, 0, 0}, Coordinate{4, 4, 4}, Strides{2, 2, 3});
1538
    auto f = make_shared<Function>(r, op::ParameterVector{A, B});
1539 1540 1541 1542

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1543 1544 1545 1546
    auto a = backend->create_tensor(element::f32, shape_a);
    copy_data(a, vector<float>{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,

                               16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
Adam Procter's avatar
Adam Procter committed
1547

1548 1549 1550 1551 1552 1553
                               32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,

                               48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63});
    auto b = backend->create_tensor(element::f32, shape_b);
    copy_data(b, vector<float>{900, 903, 908, 911, 932, 935, 940, 943});
    auto result = backend->create_tensor(element::f32, shape_r);
1554 1555

    backend->call_with_validate(f, {result}, {a, b});
1556 1557 1558 1559 1560 1561 1562 1563
    EXPECT_EQ((vector<float>{900, 1,  2,  903, 4,  5,  6,  7,  908, 9,  10, 911, 12, 13, 14, 15,

                             16,  17, 18, 19,  20, 21, 22, 23, 24,  25, 26, 27,  28, 29, 30, 31,

                             932, 33, 34, 935, 36, 37, 38, 39, 940, 41, 42, 943, 44, 45, 46, 47,

                             48,  49, 50, 51,  52, 53, 54, 55, 56,  57, 58, 59,  60, 61, 62, 63}),
              read_vector<float>(result));
1564 1565
}

1566
NGRAPH_TEST(${BACKEND_NAME}, reverse_0d)
1567
{
1568
    Shape shape{};
1569
    auto A = make_shared<op::Parameter>(element::f32, shape);
1570
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{}), op::ParameterVector{A});
1571

1572
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1573 1574

    // Create some tensors for input/output
1575
    auto a = backend->create_tensor(element::f32, shape);
1576
    copy_data(a, vector<float>{6});
1577
    auto result = backend->create_tensor(element::f32, shape);
1578

1579
    backend->call_with_validate(f, {result}, {a});
1580
    EXPECT_EQ((vector<float>{6}), read_vector<float>(result));
1581 1582
}

1583
NGRAPH_TEST(${BACKEND_NAME}, reverse_1d_nochange)
1584
{
1585
    Shape shape{8};
1586
    auto A = make_shared<op::Parameter>(element::f32, shape);
1587
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{}), op::ParameterVector{A});
1588

1589
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1590 1591

    // Create some tensors for input/output
1592
    auto a = backend->create_tensor(element::f32, shape);
1593
    copy_data(a, vector<float>{0, 1, 2, 3, 4, 5, 6, 7});
1594
    auto result = backend->create_tensor(element::f32, shape);
1595

1596
    backend->call_with_validate(f, {result}, {a});
1597
    EXPECT_EQ((vector<float>{0, 1, 2, 3, 4, 5, 6, 7}), read_vector<float>(result));
1598 1599
}

1600
NGRAPH_TEST(${BACKEND_NAME}, reverse_1d_0)
1601
{
1602
    Shape shape{8};
1603
    auto A = make_shared<op::Parameter>(element::f32, shape);
1604
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0}), op::ParameterVector{A});
1605

1606
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1607 1608

    // Create some tensors for input/output
1609
    auto a = backend->create_tensor(element::f32, shape);
1610
    copy_data(a, vector<float>{0, 1, 2, 3, 4, 5, 6, 7});
1611
    auto result = backend->create_tensor(element::f32, shape);
1612

1613
    backend->call_with_validate(f, {result}, {a});
1614
    EXPECT_EQ((vector<float>{7, 6, 5, 4, 3, 2, 1, 0}), read_vector<float>(result));
1615 1616
}

1617
NGRAPH_TEST(${BACKEND_NAME}, reverse_2d_nochange)
1618
{
1619
    Shape shape{4, 3};
1620
    auto A = make_shared<op::Parameter>(element::f32, shape);
1621
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{}), op::ParameterVector{A});
1622

1623
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1624 1625

    // Create some tensors for input/output
1626
    auto a = backend->create_tensor(element::f32, shape);
1627 1628
    copy_data(a,
              test::NDArray<float, 2>({{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}).get_vector());
1629
    auto result = backend->create_tensor(element::f32, shape);
1630

1631
    backend->call_with_validate(f, {result}, {a});
1632 1633
    EXPECT_EQ(
        (test::NDArray<float, 2>({{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}).get_vector()),
1634
        read_vector<float>(result));
1635 1636
}

1637
NGRAPH_TEST(${BACKEND_NAME}, reverse_2d_0)
1638
{
1639
    Shape shape{4, 3};
1640
    auto A = make_shared<op::Parameter>(element::f32, shape);
1641
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0}), op::ParameterVector{A});
1642 1643 1644 1645 1646

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape);
1647 1648
    copy_data(a,
              test::NDArray<float, 2>({{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}).get_vector());
1649 1650
    auto result = backend->create_tensor(element::f32, shape);

1651
    backend->call_with_validate(f, {result}, {a});
1652 1653
    EXPECT_EQ(
        (test::NDArray<float, 2>({{9, 10, 11}, {6, 7, 8}, {3, 4, 5}, {0, 1, 2}}).get_vector()),
1654
        read_vector<float>(result));
1655 1656
}

1657
NGRAPH_TEST(${BACKEND_NAME}, reverse_2d_1)
1658
{
1659
    Shape shape{4, 3};
1660
    auto A = make_shared<op::Parameter>(element::f32, shape);
1661
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{1}), op::ParameterVector{A});
1662

1663
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1664 1665

    // Create some tensors for input/output
1666
    auto a = backend->create_tensor(element::f32, shape);
1667 1668
    copy_data(a,
              test::NDArray<float, 2>({{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}).get_vector());
1669
    auto result = backend->create_tensor(element::f32, shape);
1670

1671
    backend->call_with_validate(f, {result}, {a});
1672 1673
    EXPECT_EQ(
        (test::NDArray<float, 2>({{2, 1, 0}, {5, 4, 3}, {8, 7, 6}, {11, 10, 9}}).get_vector()),
1674
        read_vector<float>(result));
1675 1676
}

1677
NGRAPH_TEST(${BACKEND_NAME}, reverse_2d_01)
1678
{
1679
    Shape shape{4, 3};
1680
    auto A = make_shared<op::Parameter>(element::f32, shape);
1681 1682
    auto f =
        make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0, 1}), op::ParameterVector{A});
1683 1684 1685 1686

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1687
    auto a = backend->create_tensor(element::f32, shape);
1688 1689
    copy_data(a,
              test::NDArray<float, 2>({{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}).get_vector());
1690
    auto result = backend->create_tensor(element::f32, shape);
1691

1692
    backend->call_with_validate(f, {result}, {a});
1693 1694
    EXPECT_EQ(
        (test::NDArray<float, 2>({{11, 10, 9}, {8, 7, 6}, {5, 4, 3}, {2, 1, 0}}).get_vector()),
1695
        read_vector<float>(result));
1696 1697
}

1698
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_nochange)
1699
{
1700
    Shape shape{2, 4, 3};
1701
    auto A = make_shared<op::Parameter>(element::f32, shape);
1702
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{}), op::ParameterVector{A});
1703

1704
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1705 1706

    // Create some tensors for input/output
1707
    auto a = backend->create_tensor(element::f32, shape);
1708 1709 1710 1711
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1712
    auto result = backend->create_tensor(element::f32, shape);
1713

1714
    backend->call_with_validate(f, {result}, {a});
1715 1716 1717
    EXPECT_EQ((test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                        {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                   .get_vector()),
1718
              read_vector<float>(result));
1719 1720
}

1721
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_0)
1722
{
1723
    Shape shape{2, 4, 3};
1724
    auto A = make_shared<op::Parameter>(element::f32, shape);
1725
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0}), op::ParameterVector{A});
1726

1727
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1728

1729
    // Create some tensors for input/output
1730
    auto a = backend->create_tensor(element::f32, shape);
1731 1732 1733 1734
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1735
    auto result = backend->create_tensor(element::f32, shape);
1736

1737
    backend->call_with_validate(f, {result}, {a});
1738 1739 1740
    EXPECT_EQ((test::NDArray<float, 3>({{{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}},
                                        {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}}})
                   .get_vector()),
1741
              read_vector<float>(result));
1742
}
1743

1744
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_1)
1745
{
1746
    Shape shape{2, 4, 3};
1747
    auto A = make_shared<op::Parameter>(element::f32, shape);
1748
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{1}), op::ParameterVector{A});
1749

1750
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1751 1752

    // Create some tensors for input/output
1753
    auto a = backend->create_tensor(element::f32, shape);
1754 1755 1756 1757
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1758
    auto result = backend->create_tensor(element::f32, shape);
1759

1760
    backend->call_with_validate(f, {result}, {a});
1761 1762 1763
    EXPECT_EQ((test::NDArray<float, 3>({{{9, 10, 11}, {6, 7, 8}, {3, 4, 5}, {0, 1, 2}},
                                        {{21, 22, 23}, {18, 19, 20}, {15, 16, 17}, {12, 13, 14}}})
                   .get_vector()),
1764
              read_vector<float>(result));
1765 1766
}

1767
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_2)
1768
{
1769
    Shape shape{2, 4, 3};
1770
    auto A = make_shared<op::Parameter>(element::f32, shape);
1771
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{2}), op::ParameterVector{A});
1772

1773
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1774 1775

    // Create some tensors for input/output
1776
    auto a = backend->create_tensor(element::f32, shape);
1777 1778 1779 1780
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1781
    auto result = backend->create_tensor(element::f32, shape);
1782

1783
    backend->call_with_validate(f, {result}, {a});
1784 1785 1786
    EXPECT_EQ((test::NDArray<float, 3>({{{2, 1, 0}, {5, 4, 3}, {8, 7, 6}, {11, 10, 9}},
                                        {{14, 13, 12}, {17, 16, 15}, {20, 19, 18}, {23, 22, 21}}})
                   .get_vector()),
1787
              read_vector<float>(result));
1788 1789
}

1790
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_01)
1791
{
1792
    Shape shape{2, 4, 3};
1793
    auto A = make_shared<op::Parameter>(element::f32, shape);
1794 1795
    auto f =
        make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0, 1}), op::ParameterVector{A});
1796

1797
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1798 1799

    // Create some tensors for input/output
1800
    auto a = backend->create_tensor(element::f32, shape);
1801 1802 1803 1804
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1805
    auto result = backend->create_tensor(element::f32, shape);
1806

1807
    backend->call_with_validate(f, {result}, {a});
1808 1809 1810
    EXPECT_EQ((test::NDArray<float, 3>({{{21, 22, 23}, {18, 19, 20}, {15, 16, 17}, {12, 13, 14}},
                                        {{9, 10, 11}, {6, 7, 8}, {3, 4, 5}, {0, 1, 2}}})
                   .get_vector()),
1811
              read_vector<float>(result));
1812 1813
}

1814
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_02)
1815
{
1816
    Shape shape{2, 4, 3};
1817
    auto A = make_shared<op::Parameter>(element::f32, shape);
1818 1819
    auto f =
        make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0, 2}), op::ParameterVector{A});
1820

1821
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1822 1823

    // Create some tensors for input/output
1824
    auto a = backend->create_tensor(element::f32, shape);
1825 1826 1827 1828
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1829
    auto result = backend->create_tensor(element::f32, shape);
1830

1831
    backend->call_with_validate(f, {result}, {a});
1832 1833 1834
    EXPECT_EQ((test::NDArray<float, 3>({{{14, 13, 12}, {17, 16, 15}, {20, 19, 18}, {23, 22, 21}},
                                        {{2, 1, 0}, {5, 4, 3}, {8, 7, 6}, {11, 10, 9}}})
                   .get_vector()),
1835
              read_vector<float>(result));
1836 1837
}

1838
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_12)
1839
{
1840
    Shape shape{2, 4, 3};
1841
    auto A = make_shared<op::Parameter>(element::f32, shape);
1842 1843
    auto f =
        make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{1, 2}), op::ParameterVector{A});
1844

1845
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1846 1847

    // Create some tensors for input/output
1848
    auto a = backend->create_tensor(element::f32, shape);
1849 1850 1851 1852
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1853
    auto result = backend->create_tensor(element::f32, shape);
1854

1855
    backend->call_with_validate(f, {result}, {a});
1856 1857 1858
    EXPECT_EQ((test::NDArray<float, 3>({{{11, 10, 9}, {8, 7, 6}, {5, 4, 3}, {2, 1, 0}},
                                        {{23, 22, 21}, {20, 19, 18}, {17, 16, 15}, {14, 13, 12}}})
                   .get_vector()),
1859
              read_vector<float>(result));
1860 1861
}

1862
NGRAPH_TEST(${BACKEND_NAME}, reverse_3d_012)
1863
{
1864
    Shape shape{2, 4, 3};
1865
    auto A = make_shared<op::Parameter>(element::f32, shape);
1866 1867
    auto f = make_shared<Function>(make_shared<op::Reverse>(A, AxisSet{0, 1, 2}),
                                   op::ParameterVector{A});
1868

1869
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1870 1871

    // Create some tensors for input/output
1872
    auto a = backend->create_tensor(element::f32, shape);
1873 1874 1875 1876
    copy_data(a,
              test::NDArray<float, 3>({{{0, 1, 2}, {3, 4, 5}, {6, 7, 8}, {9, 10, 11}},
                                       {{12, 13, 14}, {15, 16, 17}, {18, 19, 20}, {21, 22, 23}}})
                  .get_vector());
1877
    auto result = backend->create_tensor(element::f32, shape);
1878

1879
    backend->call_with_validate(f, {result}, {a});
1880 1881 1882
    EXPECT_EQ((test::NDArray<float, 3>({{{23, 22, 21}, {20, 19, 18}, {17, 16, 15}, {14, 13, 12}},
                                        {{11, 10, 9}, {8, 7, 6}, {5, 4, 3}, {2, 1, 0}}})
                   .get_vector()),
1883
              read_vector<float>(result));
1884
}
1885

1886
NGRAPH_TEST(${BACKEND_NAME}, numeric_float_nan)
1887
{
1888
    Shape shape{5};
Robert Kimball's avatar
Robert Kimball committed
1889 1890
    auto A = op::Constant::create(element::f32, shape, {-2.5f, 25.5f, 2.25f, NAN, 6.0f});
    auto B = op::Constant::create(element::f32, shape, {10.0f, 5.0f, 2.25f, 10.0f, NAN});
1891
    auto f = make_shared<Function>(make_shared<op::Equal>(A, B), op::ParameterVector{});
1892

1893
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1894 1895

    // Create some tensors for input/output
1896
    auto result = backend->create_tensor(element::boolean, shape);
1897
    backend->call_with_validate(f, {result}, {});
1898
    EXPECT_EQ((vector<char>{false, false, true, false, false}), read_vector<char>(result));
1899 1900
}

1901
NGRAPH_TEST(${BACKEND_NAME}, numeric_double_nan)
1902
{
1903
    Shape shape{5};
Robert Kimball's avatar
Robert Kimball committed
1904 1905
    auto A = op::Constant::create(element::f64, shape, {-2.5f, 25.5f, 2.25f, NAN, 6.0f});
    auto B = op::Constant::create(element::f64, shape, {10.0f, 5.0f, 2.25f, 10.0f, NAN});
1906
    auto f = make_shared<Function>(make_shared<op::Equal>(A, B), op::ParameterVector{});
1907

1908
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1909 1910

    // Create some tensors for input/output
1911
    auto result = backend->create_tensor(element::boolean, shape);
1912
    backend->call_with_validate(f, {result}, {});
1913
    EXPECT_EQ((vector<char>{false, false, true, false, false}), read_vector<char>(result));
1914
}
1915

1916
NGRAPH_TEST(${BACKEND_NAME}, numeric_float_inf)
1917
{
1918
    Shape shape{5};
Robert Kimball's avatar
Robert Kimball committed
1919 1920
    auto A = op::Constant::create(element::f32, shape, {-2.5f, 25.5f, 2.25f, INFINITY, 6.0f});
    auto B = op::Constant::create(element::f32, shape, {10.0f, 5.0f, 2.25f, 10.0f, -INFINITY});
1921
    auto f = make_shared<Function>(make_shared<op::Equal>(A, B), op::ParameterVector{});
1922 1923 1924 1925

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1926
    auto result = backend->create_tensor(element::boolean, shape);
1927
    backend->call_with_validate(f, {result}, {});
1928
    EXPECT_EQ((vector<char>{false, false, true, false, false}), read_vector<char>(result));
1929 1930
}

1931
NGRAPH_TEST(${BACKEND_NAME}, numeric_double_inf)
1932
{
1933
    Shape shape{5};
Robert Kimball's avatar
Robert Kimball committed
1934 1935
    auto A = op::Constant::create(element::f64, shape, {-2.5f, 25.5f, 2.25f, INFINITY, 6.0f});
    auto B = op::Constant::create(element::f64, shape, {10.0f, 5.0f, 2.25f, 10.0f, -INFINITY});
1936
    auto f = make_shared<Function>(make_shared<op::Equal>(A, B), op::ParameterVector{});
1937 1938 1939 1940

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
1941
    auto result = backend->create_tensor(element::boolean, shape);
1942
    backend->call_with_validate(f, {result}, {});
1943
    EXPECT_EQ((vector<char>{false, false, true, false, false}), read_vector<char>(result));
1944 1945
}

1946 1947 1948
//
// From the XLA docs: https://www.tensorflow.org/performance/xla/operation_semantics#selectandscatter
//
1949
NGRAPH_TEST(${BACKEND_NAME}, select_and_scatter_with_overlap)
1950
{
1951
    Shape shape_sel_a{};
1952
    auto SEL_A = make_shared<op::Parameter>(element::f32, shape_sel_a);
1953
    Shape shape_sel_b{};
1954
    auto SEL_B = make_shared<op::Parameter>(element::f32, shape_sel_b);
1955 1956
    auto sel_f = make_shared<Function>(make_shared<op::Greater>(SEL_A, SEL_B),
                                       op::ParameterVector{SEL_A, SEL_B});
1957

1958
    Shape shape_scatter_a{};
1959
    auto SCATTER_A = make_shared<op::Parameter>(element::f32, shape_scatter_a);
1960
    Shape shape_scatter_b{};
1961 1962
    auto SCATTER_B = make_shared<op::Parameter>(element::f32, shape_scatter_b);
    auto scatter_f =
1963
        make_shared<Function>(SCATTER_A + SCATTER_B, op::ParameterVector{SCATTER_A, SCATTER_B});
1964

1965
    Shape shape_a{4, 5};
1966
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
1967
    Shape shape_b{2, 2};
1968
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
1969
    Shape shape_c{};
1970
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
1971 1972
    Shape shape_r{4, 5};
    Shape window_shape{2, 3};
1973 1974 1975
    auto window_strides = Strides{2, 2};
    auto f = make_shared<Function>(
        make_shared<op::SelectAndScatter>(A, B, C, sel_f, scatter_f, window_shape, window_strides),
1976
        op::ParameterVector{A, B, C});
1977

1978
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
1979

1980
    // Create some tensors for input/output
1981
    auto a = backend->create_tensor(element::f32, shape_a);
1982 1983 1984 1985
    copy_data(a,
              test::NDArray<float, 2>(
                  {{7, 2, 5, 3, 8}, {3, 8, 9, 3, 4}, {1, 5, 7, 5, 6}, {0, 6, 2, 10, 2}})
                  .get_vector());
1986
    auto b = backend->create_tensor(element::f32, shape_b);
1987
    copy_data(b, test::NDArray<float, 2>({{2, 6}, {3, 1}}).get_vector());
1988
    auto c = backend->create_tensor(element::f32, shape_c);
1989
    copy_data(c, vector<float>{0});
1990
    auto result = backend->create_tensor(element::f32, shape_r);
1991

1992
    backend->call_with_validate(f, {result}, {a, b, c});
1993 1994 1995
    EXPECT_EQ((test::NDArray<float, 2>(
                   {{0, 0, 0, 0, 0}, {0, 0, 8, 0, 0}, {0, 0, 3, 0, 0}, {0, 0, 0, 1, 0}})
                   .get_vector()),
1996
              read_vector<float>(result));
1997 1998
}

1999 2000 2001
//
// From the XLA docs: https://www.tensorflow.org/performance/xla/operation_semantics#selectandscatter
//
2002
NGRAPH_TEST(${BACKEND_NAME}, select_and_scatter_without_overlap)
2003
{
2004
    Shape shape_sel_a{};
2005
    auto SEL_A = make_shared<op::Parameter>(element::f32, shape_sel_a);
2006
    Shape shape_sel_b{};
2007
    auto SEL_B = make_shared<op::Parameter>(element::f32, shape_sel_b);
2008 2009
    auto sel_f = make_shared<Function>(make_shared<op::Greater>(SEL_A, SEL_B),
                                       op::ParameterVector{SEL_A, SEL_B});
2010

2011
    Shape shape_scatter_a{};
2012
    auto SCATTER_A = make_shared<op::Parameter>(element::f32, shape_scatter_a);
2013
    Shape shape_scatter_b{};
2014 2015
    auto SCATTER_B = make_shared<op::Parameter>(element::f32, shape_scatter_b);
    auto scatter_f =
2016
        make_shared<Function>(SCATTER_A + SCATTER_B, op::ParameterVector{SCATTER_A, SCATTER_B});
2017

2018
    Shape shape_a{4, 6};
2019
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2020
    Shape shape_b{2, 2};
2021
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2022
    Shape shape_c{};
2023
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
2024 2025
    Shape shape_r{4, 6};
    Shape window_shape{2, 3};
2026
    auto window_strides = Strides{2, 3};
2027
    auto f = make_shared<Function>(
2028
        make_shared<op::SelectAndScatter>(A, B, C, sel_f, scatter_f, window_shape, window_strides),
2029
        op::ParameterVector{A, B, C});
2030

2031
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2032 2033

    // Create some tensors for input/output
2034
    auto a = backend->create_tensor(element::f32, shape_a);
2035
    copy_data(a,
2036 2037
              test::NDArray<float, 2>(
                  {{7, 2, 5, 3, 10, 2}, {3, 8, 9, 3, 4, 2}, {1, 5, 7, 5, 6, 1}, {0, 6, 2, 7, 2, 8}})
2038
                  .get_vector());
2039
    auto b = backend->create_tensor(element::f32, shape_b);
2040
    copy_data(b, test::NDArray<float, 2>({{2, 6}, {3, 1}}).get_vector());
2041
    auto c = backend->create_tensor(element::f32, shape_c);
2042
    copy_data(c, vector<float>{0});
2043
    auto result = backend->create_tensor(element::f32, shape_r);
2044

2045
    backend->call_with_validate(f, {result}, {a, b, c});
2046 2047 2048
    EXPECT_EQ((test::NDArray<float, 2>(
                   {{0, 0, 0, 0, 6, 0}, {0, 0, 2, 0, 0, 0}, {0, 0, 3, 0, 0, 0}, {0, 0, 0, 0, 0, 1}})
                   .get_vector()),
2049
              read_vector<float>(result));
2050 2051
}

2052 2053 2054
//
// Adapted from the XLA docs to provide an example in >2D: https://www.tensorflow.org/performance/xla/operation_semantics#selectandscatter
//
2055
NGRAPH_TEST(${BACKEND_NAME}, select_and_scatter_3d_without_overlap)
2056
{
2057
    Shape shape_sel_a{};
2058
    auto SEL_A = make_shared<op::Parameter>(element::f32, shape_sel_a);
2059
    Shape shape_sel_b{};
2060
    auto SEL_B = make_shared<op::Parameter>(element::f32, shape_sel_b);
2061 2062
    auto sel_f = make_shared<Function>(make_shared<op::Greater>(SEL_A, SEL_B),
                                       op::ParameterVector{SEL_A, SEL_B});
2063

2064
    Shape shape_scatter_a{};
2065
    auto SCATTER_A = make_shared<op::Parameter>(element::f32, shape_scatter_a);
2066
    Shape shape_scatter_b{};
2067 2068
    auto SCATTER_B = make_shared<op::Parameter>(element::f32, shape_scatter_b);
    auto scatter_f =
2069
        make_shared<Function>(SCATTER_A + SCATTER_B, op::ParameterVector{SCATTER_A, SCATTER_B});
2070

2071
    Shape shape_a{2, 4, 6};
2072
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2073
    Shape shape_b{1, 2, 2};
2074
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2075
    Shape shape_c{};
2076
    auto C = make_shared<op::Parameter>(element::f32, shape_c);
2077 2078
    Shape shape_r{2, 4, 6};
    Shape window_shape{2, 2, 3};
2079
    auto window_strides = Strides{2, 2, 3};
2080
    auto f = make_shared<Function>(
2081
        make_shared<op::SelectAndScatter>(A, B, C, sel_f, scatter_f, window_shape, window_strides),
2082
        op::ParameterVector{A, B, C});
2083

2084
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2085 2086

    // Create some tensors for input/output
2087
    auto a = backend->create_tensor(element::f32, shape_a);
2088 2089 2090 2091 2092 2093
    copy_data(
        a,
        test::NDArray<float, 3>(
            {{{7, 2, 5, 3, 10, 2}, {3, 8, 9, 3, 4, 2}, {1, 5, 7, 5, 6, 1}, {0, 6, 2, 7, 2, 8}},
             {{2, 5, 8, 3, 4, 2}, {1, 2, 8, 4, 5, 2}, {10, 2, 3, 4, 1, 0}, {4, 1, 2, 4, 5, 7}}})
            .get_vector());
2094
    auto b = backend->create_tensor(element::f32, shape_b);
2095
    copy_data(b, test::NDArray<float, 3>({{{2, 6}, {3, 1}}}).get_vector());
2096
    auto c = backend->create_tensor(element::f32, shape_c);
2097
    copy_data(c, vector<float>{0});
2098
    auto result = backend->create_tensor(element::f32, shape_r);
2099

2100
    backend->call_with_validate(f, {result}, {a, b, c});
2101 2102 2103 2104 2105
    EXPECT_EQ(
        (test::NDArray<float, 3>(
             {{{0, 0, 0, 0, 6, 0}, {0, 0, 2, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 1}},
              {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {3, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}}})
             .get_vector()),
2106
        read_vector<float>(result));
2107 2108
}

2109
template <typename OP>
2110
void make_unary_empty_test(const string& backend_name)
2111
{
2112
    Shape shape{0};
2113

2114 2115
    op::ParameterVector params;
    NodeVector result_list;
2116 2117 2118 2119 2120 2121
    for (size_t i = 0; i < s_known_element_types.size(); i++)
    {
        shared_ptr<op::Parameter> p = make_shared<op::Parameter>(s_known_element_types[i], shape);
        params.push_back(p);
        result_list.push_back(make_shared<OP>(p));
    }
2122

2123
    auto f = make_shared<Function>(result_list, params);
2124
    auto backend = runtime::Backend::create(backend_name);
2125

2126 2127
    vector<shared_ptr<runtime::Tensor>> inputs;
    vector<shared_ptr<runtime::Tensor>> outputs;
2128 2129
    for (size_t i = 0; i < s_known_element_types.size(); i++)
    {
2130 2131
        inputs.push_back(backend->create_tensor(s_known_element_types[i], shape));
        outputs.push_back(backend->create_tensor(s_known_element_types[i], shape));
2132
    }
2133

2134
    backend->call_with_validate(f, outputs, inputs);
2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156

    EXPECT_EQ(read_vector<float>(inputs[0]).size(), 0);
    EXPECT_EQ(read_vector<double>(inputs[1]).size(), 0);
    EXPECT_EQ(read_vector<int8_t>(inputs[2]).size(), 0);
    EXPECT_EQ(read_vector<int16_t>(inputs[3]).size(), 0);
    EXPECT_EQ(read_vector<int32_t>(inputs[4]).size(), 0);
    EXPECT_EQ(read_vector<int64_t>(inputs[5]).size(), 0);
    EXPECT_EQ(read_vector<uint8_t>(inputs[6]).size(), 0);
    EXPECT_EQ(read_vector<uint16_t>(inputs[7]).size(), 0);
    EXPECT_EQ(read_vector<uint32_t>(inputs[8]).size(), 0);
    EXPECT_EQ(read_vector<uint64_t>(inputs[9]).size(), 0);

    EXPECT_EQ(read_vector<float>(outputs[0]).size(), 0);
    EXPECT_EQ(read_vector<double>(outputs[1]).size(), 0);
    EXPECT_EQ(read_vector<int8_t>(outputs[2]).size(), 0);
    EXPECT_EQ(read_vector<int16_t>(outputs[3]).size(), 0);
    EXPECT_EQ(read_vector<int32_t>(outputs[4]).size(), 0);
    EXPECT_EQ(read_vector<int64_t>(outputs[5]).size(), 0);
    EXPECT_EQ(read_vector<uint8_t>(outputs[6]).size(), 0);
    EXPECT_EQ(read_vector<uint16_t>(outputs[7]).size(), 0);
    EXPECT_EQ(read_vector<uint32_t>(outputs[8]).size(), 0);
    EXPECT_EQ(read_vector<uint64_t>(outputs[9]).size(), 0);
2157 2158
}

2159 2160
template <typename OP>
void make_binary_empty_test(const string& backend_name, bool is_comparison = false)
2161
{
2162
    Shape shape{0};
2163
    op::ParameterVector A;
2164 2165 2166 2167
    for (size_t i = 0; i < s_known_element_types.size(); i++)
    {
        A.push_back(make_shared<op::Parameter>(s_known_element_types[i], shape));
    }
2168

2169
    NodeVector result_list;
2170 2171 2172 2173
    for (shared_ptr<op::Parameter> p : A)
    {
        result_list.push_back(make_shared<OP>(p, p));
    }
2174

2175
    auto f = make_shared<Function>(result_list, A);
2176
    auto backend = runtime::Backend::create(backend_name);
2177

2178 2179
    vector<shared_ptr<runtime::Tensor>> inputs;
    vector<shared_ptr<runtime::Tensor>> outputs;
2180 2181
    for (size_t i = 0; i < s_known_element_types.size(); i++)
    {
2182
        inputs.push_back(backend->create_tensor(s_known_element_types[i], shape));
2183 2184
        if (is_comparison)
        {
2185
            outputs.push_back(backend->create_tensor(element::from<char>(), shape));
2186 2187 2188
        }
        else
        {
2189
            outputs.push_back(backend->create_tensor(s_known_element_types[i], shape));
2190 2191
        }
    }
2192

2193
    backend->call_with_validate(f, outputs, inputs);
2194

2195 2196 2197 2198 2199 2200 2201 2202 2203 2204
    EXPECT_EQ(read_vector<float>(inputs[0]).size(), 0);
    EXPECT_EQ(read_vector<double>(inputs[1]).size(), 0);
    EXPECT_EQ(read_vector<int8_t>(inputs[2]).size(), 0);
    EXPECT_EQ(read_vector<int16_t>(inputs[3]).size(), 0);
    EXPECT_EQ(read_vector<int32_t>(inputs[4]).size(), 0);
    EXPECT_EQ(read_vector<int64_t>(inputs[5]).size(), 0);
    EXPECT_EQ(read_vector<uint8_t>(inputs[6]).size(), 0);
    EXPECT_EQ(read_vector<uint16_t>(inputs[7]).size(), 0);
    EXPECT_EQ(read_vector<uint32_t>(inputs[8]).size(), 0);
    EXPECT_EQ(read_vector<uint64_t>(inputs[9]).size(), 0);
2205

2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231
    if (is_comparison)
    {
        EXPECT_EQ(read_vector<char>(outputs[0]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[1]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[2]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[3]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[4]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[5]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[6]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[7]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[8]).size(), 0);
        EXPECT_EQ(read_vector<char>(outputs[9]).size(), 0);
    }
    else
    {
        EXPECT_EQ(read_vector<float>(outputs[0]).size(), 0);
        EXPECT_EQ(read_vector<double>(outputs[1]).size(), 0);
        EXPECT_EQ(read_vector<int8_t>(outputs[2]).size(), 0);
        EXPECT_EQ(read_vector<int16_t>(outputs[3]).size(), 0);
        EXPECT_EQ(read_vector<int32_t>(outputs[4]).size(), 0);
        EXPECT_EQ(read_vector<int64_t>(outputs[5]).size(), 0);
        EXPECT_EQ(read_vector<uint8_t>(outputs[6]).size(), 0);
        EXPECT_EQ(read_vector<uint16_t>(outputs[7]).size(), 0);
        EXPECT_EQ(read_vector<uint32_t>(outputs[8]).size(), 0);
        EXPECT_EQ(read_vector<uint64_t>(outputs[9]).size(), 0);
    }
2232
}
2233

2234
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_abs)
2235
{
2236
    make_unary_empty_test<op::Abs>("${BACKEND_NAME}");
2237
}
2238

2239
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_ceiling)
2240
{
2241
    make_unary_empty_test<op::Ceiling>("${BACKEND_NAME}");
2242
}
2243

2244
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_exp)
2245
{
2246 2247
}

2248
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_floor)
2249
{
2250
    make_unary_empty_test<op::Floor>("${BACKEND_NAME}");
2251
}
2252

2253
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_log)
2254
{
2255
    make_unary_empty_test<op::Log>("${BACKEND_NAME}");
2256
}
2257

2258
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_negative)
2259
{
2260
    make_unary_empty_test<op::Negative>("${BACKEND_NAME}");
2261
}
2262

2263
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_not)
2264
{
2265
    Shape shape{0};
2266
    auto A = make_shared<op::Parameter>(element::from<char>(), shape);
2267
    auto f = make_shared<Function>(make_shared<op::Not>(A), op::ParameterVector{A});
2268 2269 2270

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

2271 2272
    auto a = backend->create_tensor(element::from<char>(), shape);
    auto result = backend->create_tensor(element::from<char>(), shape);
2273 2274

    backend->call_with_validate(f, {result}, {a});
2275 2276 2277 2278 2279 2280

    auto in_vec = read_vector<char>(a);
    auto out_vec = read_vector<char>(result);

    EXPECT_EQ(in_vec.size(), 0);
    EXPECT_EQ(out_vec.size(), 0);
2281 2282
}

2283
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_sign)
2284
{
2285
    make_unary_empty_test<op::Sign>("${BACKEND_NAME}");
2286
}
2287

2288
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_sqrt)
2289
{
2290
    make_unary_empty_test<op::Sqrt>("${BACKEND_NAME}");
2291
}
2292

2293
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_sin)
2294
{
2295
    make_unary_empty_test<op::Sin>("${BACKEND_NAME}");
2296 2297
}

2298
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_sinh)
2299
{
2300
    make_unary_empty_test<op::Sinh>("${BACKEND_NAME}");
2301
}
2302

2303
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_cos)
2304
{
2305
    make_unary_empty_test<op::Cos>("${BACKEND_NAME}");
2306
}
2307

2308
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_cosh)
2309
{
2310
    make_unary_empty_test<op::Cosh>("${BACKEND_NAME}");
2311
}
2312

2313
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_tan)
2314
{
2315
    make_unary_empty_test<op::Tan>("${BACKEND_NAME}");
2316 2317
}

2318
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_tanh)
2319
{
2320
    make_unary_empty_test<op::Tanh>("${BACKEND_NAME}");
2321
}
2322

2323
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_asin)
2324
{
2325
    make_unary_empty_test<op::Asin>("${BACKEND_NAME}");
2326
}
2327

2328
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_acos)
2329
{
2330
    make_unary_empty_test<op::Acos>("${BACKEND_NAME}");
2331
}
2332

2333
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_atan)
2334
{
2335
    make_unary_empty_test<op::Atan>("${BACKEND_NAME}");
2336
}
2337

2338
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_add)
2339
{
2340
    make_binary_empty_test<op::Add>("${BACKEND_NAME}");
2341
}
2342

2343
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_divide)
2344
{
2345
    make_binary_empty_test<op::Divide>("${BACKEND_NAME}");
2346
}
2347

2348
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_eq)
2349
{
2350
    make_binary_empty_test<op::Equal>("${BACKEND_NAME}", true);
2351
}
2352

2353
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_greater)
2354
{
2355
    make_binary_empty_test<op::Greater>("${BACKEND_NAME}", true);
2356
}
2357

2358
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_greatereq)
2359
{
2360
    make_binary_empty_test<op::GreaterEq>("${BACKEND_NAME}", true);
2361
}
2362

2363
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_less)
2364
{
2365
    make_binary_empty_test<op::Less>("${BACKEND_NAME}", true);
2366 2367
}

2368
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_lesseq)
2369
{
2370
    make_binary_empty_test<op::LessEq>("${BACKEND_NAME}", true);
2371
}
2372

2373
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_maximum)
2374
{
2375
    make_binary_empty_test<op::Maximum>("${BACKEND_NAME}");
2376
}
2377

2378
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_minimum)
2379
{
2380
    make_binary_empty_test<op::Minimum>("${BACKEND_NAME}");
2381
}
2382

2383
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_multiply)
2384
{
2385
    make_binary_empty_test<op::Multiply>("${BACKEND_NAME}");
2386 2387
}

2388
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_not_equal)
2389
{
2390
    make_binary_empty_test<op::NotEqual>("${BACKEND_NAME}", true);
2391
}
2392

2393
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_power)
2394
{
2395
    make_binary_empty_test<op::Power>("${BACKEND_NAME}");
2396
}
2397

2398
NGRAPH_TEST(${BACKEND_NAME}, zero_sized_subtract)
2399
{
2400
    make_binary_empty_test<op::Subtract>("${BACKEND_NAME}");
2401 2402
}

2403
NGRAPH_TEST(${BACKEND_NAME}, convolution_outlining)
2404
{
2405
    Shape shape_a{1, 2, 2, 2};
2406
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2407
    Shape shape_b{2, 2, 1, 1};
2408
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2409
    Shape shape_r{1, 2, 2, 2};
Jayaram Bobba's avatar
Jayaram Bobba committed
2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423
    auto conv1 = make_shared<op::Convolution>(A,
                                              B,
                                              Strides{1, 1},
                                              Strides{1, 1},
                                              CoordinateDiff{0, 0},
                                              CoordinateDiff{0, 0},
                                              Strides{1, 1});
    auto conv2 = make_shared<op::Convolution>(conv1,
                                              B,
                                              Strides{1, 1},
                                              Strides{1, 1},
                                              CoordinateDiff{0, 0},
                                              CoordinateDiff{0, 0},
                                              Strides{1, 1});
2424
    auto f = make_shared<Function>(conv2, op::ParameterVector{A, B});
2425 2426 2427 2428 2429

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape_a);
Jayaram Bobba's avatar
Jayaram Bobba committed
2430
    copy_data(a, vector<float>{1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f});
2431
    auto b = backend->create_tensor(element::f32, shape_b);
Jayaram Bobba's avatar
Jayaram Bobba committed
2432
    copy_data(b, vector<float>{1.0f, 1.0f, 1.0f, 1.0f});
2433 2434
    auto result = backend->create_tensor(element::f32, shape_r);

Jayaram Bobba's avatar
Jayaram Bobba committed
2435
    vector<float> expected_result{4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f, 4.0f};
2436

2437
    backend->call_with_validate(f, {result}, {a, b});
2438
    EXPECT_EQ(vector<float>{expected_result}, read_vector<float>(result));
2439 2440
}

2441
NGRAPH_TEST(${BACKEND_NAME}, computation_reuse)
2442
{
2443
    Shape shape_a{1, 16, 2, 2};
2444
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460
    Shape shape_b{32, 16, 1, 1};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_r{1, 32, 2, 2};
    auto conv = make_shared<op::Convolution>(A,
                                             B,
                                             Strides{1, 1},
                                             Strides{1, 1},
                                             CoordinateDiff{0, 0},
                                             CoordinateDiff{0, 0},
                                             Strides{1, 1});
    Shape pool_shape{1, 1};
    auto pool = make_shared<op::AvgPool>(conv, pool_shape);
    auto bias = make_shared<op::Broadcast>(
        op::Constant::create(element::f32, Shape{}, {2.14}), shape_r, AxisSet{0, 1, 2, 3});
    auto result_op = make_shared<op::Result>(pool + bias);
    auto f = make_shared<Function>(ResultVector{result_op}, op::ParameterVector{A, B});
2461

2462
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2463

2464 2465 2466 2467 2468 2469 2470
    vector<float> input(64, 1.0f);
    vector<float> weights(512, 0.5f);
    vector<float> rv(128);

    auto a = backend->create_tensor(element::f32, shape_a, input.data());
    auto b = backend->create_tensor(element::f32, shape_b, weights.data());
    auto result = backend->create_tensor(element::f32, shape_r, rv.data());
2471

2472
    backend->call_with_validate(f, {result}, {a, b});
2473

2474 2475 2476
    vector<float> rv_saved(rv);

    b->set_stale(false);
2477
    backend->call_with_validate(f, {result}, {a, b});
2478
    EXPECT_EQ(rv_saved, rv);
2479 2480
}

2481
NGRAPH_TEST(${BACKEND_NAME}, pad_interior_1d)
2482
{
2483
    Shape shape_a{6};
2484
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2485
    Shape shape_b{};
2486
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2487 2488 2489 2490
    Shape shape_r{16};
    Shape padding_below{0};
    Shape padding_above{0};
    Shape padding_interior{2};
2491 2492
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2493
        op::ParameterVector{A, B});
2494

2495
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2496 2497

    // Create some tensors for input/output
2498
    auto a = backend->create_tensor(element::f32, shape_a);
2499
    copy_data(a, test::NDArray<float, 1>({1, 2, 3, 4, 5, 6}).get_vector());
2500
    auto b = backend->create_tensor(element::f32, shape_b);
2501
    copy_data(b, vector<float>{2112});
2502
    auto result = backend->create_tensor(element::f32, shape_r);
2503

2504
    backend->call_with_validate(f, {result}, {a, b});
2505 2506 2507
    EXPECT_EQ((test::NDArray<float, 1>(
                   {1, 2112, 2112, 2, 2112, 2112, 3, 2112, 2112, 4, 2112, 2112, 5, 2112, 2112, 6})
                   .get_vector()),
2508
              read_vector<float>(result));
2509 2510
}

2511
NGRAPH_TEST(${BACKEND_NAME}, pad_exterior_1d)
2512
{
2513
    Shape shape_a{6};
2514
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2515
    Shape shape_b{};
2516
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2517 2518 2519 2520
    Shape shape_r{15};
    Shape padding_below{4};
    Shape padding_above{5};
    Shape padding_interior{0};
2521 2522
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2523
        op::ParameterVector{A, B});
2524

2525
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2526 2527

    // Create some tensors for input/output
2528
    auto a = backend->create_tensor(element::f32, shape_a);
2529
    copy_data(a, test::NDArray<float, 1>({1, 2, 3, 4, 5, 6}).get_vector());
2530
    auto b = backend->create_tensor(element::f32, shape_b);
2531
    copy_data(b, vector<float>{2112});
2532
    auto result = backend->create_tensor(element::f32, shape_r);
2533

2534
    backend->call_with_validate(f, {result}, {a, b});
2535 2536 2537
    EXPECT_EQ((test::NDArray<float, 1>(
                   {2112, 2112, 2112, 2112, 1, 2, 3, 4, 5, 6, 2112, 2112, 2112, 2112, 2112})
                   .get_vector()),
2538
              read_vector<float>(result));
2539 2540
}

2541
NGRAPH_TEST(${BACKEND_NAME}, pad_interior_exterior_1d)
2542
{
2543
    Shape shape_a{6};
2544
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2545
    Shape shape_b{};
2546
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2547 2548 2549 2550
    Shape shape_r{25};
    Shape padding_below{4};
    Shape padding_above{5};
    Shape padding_interior{2};
2551 2552
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2553
        op::ParameterVector{A, B});
2554

2555
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2556 2557

    // Create some tensors for input/output
2558
    auto a = backend->create_tensor(element::f32, shape_a);
2559
    copy_data(a, test::NDArray<float, 1>({1, 2, 3, 4, 5, 6}).get_vector());
2560
    auto b = backend->create_tensor(element::f32, shape_b);
2561
    copy_data(b, vector<float>{2112});
2562
    auto result = backend->create_tensor(element::f32, shape_r);
2563

2564
    backend->call_with_validate(f, {result}, {a, b});
2565 2566 2567 2568
    EXPECT_EQ((test::NDArray<float, 1>({2112, 2112, 2112, 2112, 1,    2112, 2112, 2, 2112,
                                        2112, 3,    2112, 2112, 4,    2112, 2112, 5, 2112,
                                        2112, 6,    2112, 2112, 2112, 2112, 2112})
                   .get_vector()),
2569
              read_vector<float>(result));
2570 2571
}

2572
NGRAPH_TEST(${BACKEND_NAME}, pad_interior_exterior_2d)
2573
{
2574
    Shape shape_a{2, 3};
2575
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2576
    Shape shape_b{};
2577
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2578 2579 2580 2581
    Shape shape_r{7, 6};
    Shape padding_below{1, 0};
    Shape padding_above{2, 1};
    Shape padding_interior{2, 1};
2582 2583
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2584
        op::ParameterVector{A, B});
2585

2586
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2587 2588

    // Create some tensors for input/output
2589
    auto a = backend->create_tensor(element::f32, shape_a);
2590
    copy_data(a, test::NDArray<float, 2>({{1, 2, 3}, {4, 5, 6}}).get_vector());
2591
    auto b = backend->create_tensor(element::f32, shape_b);
2592
    copy_data(b, vector<float>{9});
2593
    auto result = backend->create_tensor(element::f32, shape_r);
2594

2595
    backend->call_with_validate(f, {result}, {a, b});
2596 2597 2598 2599 2600 2601 2602 2603
    EXPECT_EQ((test::NDArray<float, 2>({{9, 9, 9, 9, 9, 9},
                                        {1, 9, 2, 9, 3, 9},
                                        {9, 9, 9, 9, 9, 9},
                                        {9, 9, 9, 9, 9, 9},
                                        {4, 9, 5, 9, 6, 9},
                                        {9, 9, 9, 9, 9, 9},
                                        {9, 9, 9, 9, 9, 9}})
                   .get_vector()),
2604
              read_vector<float>(result));
2605 2606
}

2607
NGRAPH_TEST(${BACKEND_NAME}, pad_exterior_2d_0x0)
2608
{
2609
    Shape shape_a{0, 0};
2610
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2611
    Shape shape_b{};
2612
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2613 2614 2615 2616
    Shape shape_r{5, 5};
    Shape padding_below{2, 3};
    Shape padding_above{3, 2};
    Shape padding_interior{0, 0};
2617 2618
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2619
        op::ParameterVector{A, B});
2620

2621
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2622 2623

    // Create some tensors for input/output
2624
    auto a = backend->create_tensor(element::f32, shape_a);
2625
    // copy_data(a, test::NDArray<float, 2>({{}}).get_vector());
2626
    auto b = backend->create_tensor(element::f32, shape_b);
2627
    copy_data(b, vector<float>{2112});
2628
    auto result = backend->create_tensor(element::f32, shape_r);
2629

2630
    backend->call_with_validate(f, {result}, {a, b});
2631 2632 2633 2634 2635 2636
    EXPECT_EQ((test::NDArray<float, 2>({{2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112}})
                   .get_vector()),
2637
              read_vector<float>(result));
2638 2639
}

2640
NGRAPH_TEST(${BACKEND_NAME}, pad_exterior_2d_0x3)
2641
{
2642
    Shape shape_a{0, 3};
2643
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2644
    Shape shape_b{};
2645
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2646 2647 2648 2649
    Shape shape_r{5, 5};
    Shape padding_below{2, 1};
    Shape padding_above{3, 1};
    Shape padding_interior{0, 0};
2650 2651
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2652
        op::ParameterVector{A, B});
2653

2654
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2655 2656

    // Create some tensors for input/output
2657
    auto a = backend->create_tensor(element::f32, shape_a);
2658
    // copy_data(a, test::NDArray<float, 2>({}).get_vector());
2659
    auto b = backend->create_tensor(element::f32, shape_b);
2660
    copy_data(b, vector<float>{2112});
2661
    auto result = backend->create_tensor(element::f32, shape_r);
2662

2663
    backend->call_with_validate(f, {result}, {a, b});
2664 2665 2666 2667 2668 2669
    EXPECT_EQ((test::NDArray<float, 2>({{2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112}})
                   .get_vector()),
2670
              read_vector<float>(result));
2671 2672
}

2673
NGRAPH_TEST(${BACKEND_NAME}, pad_exterior_2d_3x0)
2674
{
2675
    Shape shape_a{3, 0};
2676
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2677
    Shape shape_b{};
2678
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2679 2680 2681 2682
    Shape shape_r{5, 5};
    Shape padding_below{1, 3};
    Shape padding_above{1, 2};
    Shape padding_interior{0, 0};
2683 2684
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2685
        op::ParameterVector{A, B});
2686

2687
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2688 2689

    // Create some tensors for input/output
2690
    auto a = backend->create_tensor(element::f32, shape_a);
2691
    // copy_data(a, test::NDArray<float, 2>({}).get_vector());
2692
    auto b = backend->create_tensor(element::f32, shape_b);
2693
    copy_data(b, vector<float>{2112});
2694
    auto result = backend->create_tensor(element::f32, shape_r);
2695

2696
    backend->call_with_validate(f, {result}, {a, b});
2697 2698 2699 2700 2701 2702
    EXPECT_EQ((test::NDArray<float, 2>({{2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112},
                                        {2112, 2112, 2112, 2112, 2112}})
                   .get_vector()),
2703
              read_vector<float>(result));
2704 2705
}

2706
NGRAPH_TEST(${BACKEND_NAME}, pad_exterior_4d_1x2x2x2)
Jai Menon's avatar
Jai Menon committed
2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719
{
    Shape shape_a{1, 2, 2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_b{};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_r{1, 2, 4, 4};
    Shape padding_below{0, 0, 1, 1};
    Shape padding_above{0, 0, 1, 1};
    Shape padding_interior{0, 0, 0, 0};
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
        op::ParameterVector{A, B});

2720
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
Jai Menon's avatar
Jai Menon committed
2721 2722

    // Create some tensors for input/output
2723
    auto a = backend->create_tensor(element::f32, shape_a);
Jai Menon's avatar
Jai Menon committed
2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739
    // clang-format off
    copy_data(a, test::NDArray<float, 4>(
        {
            {
                {
                    {0.0f, 0.0f},
                    {0.0f, 0.0f}
                },
                {
                    {0.0f, 0.0f},
                    {0.0f, 0.0f}
                }
            }
        }).get_vector());
    // clang-format on

2740
    auto b = backend->create_tensor(element::f32, shape_b);
Jai Menon's avatar
Jai Menon committed
2741 2742
    copy_data(b, vector<float>{42});

2743
    auto result = backend->create_tensor(element::f32, shape_r);
Jai Menon's avatar
Jai Menon committed
2744

2745
    backend->call_with_validate(f, {result}, {a, b});
Jai Menon's avatar
Jai Menon committed
2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767
    // clang-format off
    EXPECT_EQ((test::NDArray<float, 4>(
        {
            {
                {
                    {42.0f, 42.0f, 42.0f, 42.0f},
                    {42.0f, 0.0f, 0.0f, 42.0f},
                    {42.0f, 0.0f, 0.0f, 42.0f},
                    {42.0f, 42.0f, 42.0f, 42.0f}
                },
                {
                    {42.0f, 42.0f, 42.0f, 42.0f},
                    {42.0f, 0.0f, 0.0f, 42.0f},
                    {42.0f, 0.0f, 0.0f, 42.0f},
                    {42.0f, 42.0f, 42.0f, 42.0f}
                }
            }
        }).get_vector()),
        read_vector<float>(result));
    // clang-format on
}

2768 2769 2770 2771 2772
// This is a regression test for one of TF's unit tests, which was failing.
// The problem was inappropriate handling of the shape computation for a
// zero-length axis with interior padding. Rather than subtract 1 from the
// source shape and multiply by the interior padding (which causes underflow),
// we should just count the pre-interior-padding length as zero.
2773
NGRAPH_TEST(${BACKEND_NAME}, pad_interior_exterior_4d_2x0x3x2)
2774
{
2775
    Shape shape_a{2, 0, 3, 2};
2776
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
2777
    Shape shape_b{};
2778
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
2779 2780 2781 2782
    Shape padding_below{1, 0, 0, 0};
    Shape padding_above{0, 2, 0, 0};
    Shape padding_interior{2, 1, 0, 0};
    Shape shape_r{5, 2, 3, 2};
2783 2784
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
2785
        op::ParameterVector{A, B});
2786

2787
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2788 2789

    // Create some tensors for input/output
2790
    auto a = backend->create_tensor(element::f32, shape_a);
2791
    // copy_data(a, test::NDArray<float, 2>({}).get_vector());
2792
    auto b = backend->create_tensor(element::f32, shape_b);
2793
    copy_data(b, vector<float>{2112});
2794
    auto result = backend->create_tensor(element::f32, shape_r);
2795 2796 2797

    vector<float> expected(5 * 2 * 3 * 2, 2112);

2798
    backend->call_with_validate(f, {result}, {a, b});
2799
    EXPECT_EQ(expected, read_vector<float>(result));
2800
}
2801

2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 2868 2869 2870 2871 2872 2873 2874 2875 2876 2877 2878 2879 2880 2881
// This test covers the case with multiple image and with asymetric pad
// bug has been found on nvGPU side now covered by this test
NGRAPH_TEST(${BACKEND_NAME}, pad_2channel_2image_asym)
{
    Shape shape_a{2, 2, 4, 4};
    auto window_movement_strides = Strides{2, 2};
    Shape padding_below{0, 0, 0, 0};
    Shape padding_above{0, 0, 2, 2};
    Shape padding_interior{0, 0, 0, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_b{};
    auto B = make_shared<op::Parameter>(element::f32, shape_b);
    Shape shape_r{2, 2, 6, 6};
    auto f = make_shared<Function>(
        make_shared<op::Pad>(A, B, padding_below, padding_above, padding_interior),
        op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::f32, shape_a);
    copy_data(a,
              test::NDArray<float, 4>({{{{0, 1, 0, 2}, // img 0 chan 0
                                         {0, 3, 2, 0},
                                         {2, 0, 0, 0},
                                         {0, 2, 1, 0}},

                                        {{0, 0, 0, 2}, // img 0 chan 1
                                         {0, 2, 3, 0},
                                         {2, 0, 1, 0},
                                         {2, 0, 0, 0}}},

                                       {{{0, 2, 1, 1}, // img 1 chan 0
                                         {0, 0, 2, 0},
                                         {0, 0, 1, 2},
                                         {0, 0, 0, 0}},

                                        {{2, 1, 0, 0}, // img 1 chan 1
                                         {0, 2, 0, 0},
                                         {1, 1, 2, 0},
                                         {1, 0, 0, 0}}}})
                  .get_vector());

    auto b = backend->create_tensor(element::f32, shape_b);
    copy_data(b, vector<float>{42});

    auto result = backend->create_tensor(element::f32, shape_r);

    backend->call_with_validate(f, {result}, {a, b});
    EXPECT_EQ((test::NDArray<float, 4>({{{{0, 1, 0, 2, 42, 42}, // img 0 chan 0
                                          {0, 3, 2, 0, 42, 42},
                                          {2, 0, 0, 0, 42, 42},
                                          {0, 2, 1, 0, 42, 42},
                                          {42, 42, 42, 42, 42, 42},
                                          {42, 42, 42, 42, 42, 42}},

                                         {{0, 0, 0, 2, 42, 42}, // img 1 chan 0
                                          {0, 2, 3, 0, 42, 42},
                                          {2, 0, 1, 0, 42, 42},
                                          {2, 0, 0, 0, 42, 42},
                                          {42, 42, 42, 42, 42, 42},
                                          {42, 42, 42, 42, 42, 42}}},

                                        {{{0, 2, 1, 1, 42, 42}, // img 1 chan 0
                                          {0, 0, 2, 0, 42, 42},
                                          {0, 0, 1, 2, 42, 42},
                                          {0, 0, 0, 0, 42, 42},
                                          {42, 42, 42, 42, 42, 42},
                                          {42, 42, 42, 42, 42, 42}},

                                         {{2, 1, 0, 0, 42, 42}, // img 1 chan 1
                                          {0, 2, 0, 0, 42, 42},
                                          {1, 1, 2, 0, 42, 42},
                                          {1, 0, 0, 0, 42, 42},
                                          {42, 42, 42, 42, 42, 42},
                                          {42, 42, 42, 42, 42, 42}}}})
                   .get_vector()),
              read_vector<float>(result));
}

2882
// Trivial case with no reduced axes.
2883
NGRAPH_TEST(${BACKEND_NAME}, product_trivial)
2884 2885 2886
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
2887
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{}), op::ParameterVector{A});
2888

2889
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2890 2891

    // Create some tensors for input/output
2892
    auto a = backend->create_tensor(element::f32, shape);
2893
    copy_data(a, vector<float>{1, 2, 3, 4});
2894
    auto result = backend->create_tensor(element::f32, shape);
2895

2896
    backend->call_with_validate(f, {result}, {a});
2897 2898 2899 2900
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(result));
}

// Failure has been reported at 5D for some reason
2901
NGRAPH_TEST(${BACKEND_NAME}, product_trivial_5d)
2902 2903 2904
{
    Shape shape{2, 2, 2, 2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
2905
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{}), op::ParameterVector{A});
2906

2907
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2908 2909

    // Create some tensors for input/output
2910
    auto a = backend->create_tensor(element::f32, shape);
2911 2912
    copy_data(a, vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
2913
    auto result = backend->create_tensor(element::f32, shape);
2914

2915
    backend->call_with_validate(f, {result}, {a});
2916 2917 2918 2919 2920
    EXPECT_EQ((vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}),
              read_vector<float>(result));
}

2921
NGRAPH_TEST(${BACKEND_NAME}, product_to_scalar)
2922 2923 2924
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
2925 2926
    auto f =
        make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), op::ParameterVector{A});
2927

2928
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2929 2930

    // Create some tensors for input/output
2931
    auto a = backend->create_tensor(element::f32, shape);
2932
    copy_data(a, vector<float>{1, 2, 3, 4});
2933
    auto result = backend->create_tensor(element::f32, Shape{});
2934

2935
    backend->call_with_validate(f, {result}, {a});
2936 2937 2938 2939 2940 2941 2942
    EXPECT_EQ((vector<float>{24}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(a));
}

2943
NGRAPH_TEST(${BACKEND_NAME}, product_matrix_columns)
2944 2945 2946 2947
{
    Shape shape_a{3, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{2};
2948
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), op::ParameterVector{A});
2949

2950
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2951 2952

    // Create some tensors for input/output
2953
    auto a = backend->create_tensor(element::f32, shape_a);
2954
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
2955
    auto result = backend->create_tensor(element::f32, shape_rt);
2956

2957
    backend->call_with_validate(f, {result}, {a});
2958 2959 2960 2961 2962 2963 2964
    EXPECT_EQ((vector<float>{15, 48}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a));
}

2965
NGRAPH_TEST(${BACKEND_NAME}, product_matrix_rows)
2966 2967 2968 2969
{
    Shape shape_a{3, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
2970
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{1}), op::ParameterVector{A});
2971

2972
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2973 2974

    // Create some tensors for input/output
2975
    auto a = backend->create_tensor(element::f32, shape_a);
2976
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
2977
    auto result = backend->create_tensor(element::f32, shape_rt);
2978

2979
    backend->call_with_validate(f, {result}, {a});
2980 2981 2982 2983 2984 2985 2986
    EXPECT_EQ((vector<float>{2, 12, 30}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a));
}

2987
NGRAPH_TEST(${BACKEND_NAME}, product_matrix_rows_zero)
2988 2989 2990 2991
{
    Shape shape_a{3, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
2992
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{1}), op::ParameterVector{A});
2993

2994
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
2995 2996

    // Create some tensors for input/output
2997
    auto a = backend->create_tensor(element::f32, shape_a);
2998
    copy_data(a, vector<float>{});
2999
    auto result = backend->create_tensor(element::f32, shape_rt);
3000 3001
    copy_data(result, vector<float>({3, 3, 3}));

3002
    backend->call_with_validate(f, {result}, {a});
3003 3004 3005 3006 3007 3008 3009
    EXPECT_EQ((vector<float>{1, 1, 1}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3010
NGRAPH_TEST(${BACKEND_NAME}, product_matrix_cols_zero)
3011 3012 3013 3014 3015
{
    // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
    Shape shape_a{0, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{2};
3016
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), op::ParameterVector{A});
3017

3018
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3019 3020

    // Create some tensors for input/output
3021
    auto a = backend->create_tensor(element::f32, shape_a);
3022
    copy_data(a, vector<float>{});
3023
    auto result = backend->create_tensor(element::f32, shape_rt);
3024 3025
    copy_data(result, vector<float>({3, 3}));

3026
    backend->call_with_validate(f, {result}, {a});
3027 3028 3029 3030 3031 3032 3033
    EXPECT_EQ((vector<float>{1, 1}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3034
NGRAPH_TEST(${BACKEND_NAME}, product_vector_zero)
3035 3036 3037 3038
{
    Shape shape_a{0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3039
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), op::ParameterVector{A});
3040

3041
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3042 3043

    // Create some tensors for input/output
3044
    auto a = backend->create_tensor(element::f32, shape_a);
3045
    copy_data(a, vector<float>{});
3046
    auto result = backend->create_tensor(element::f32, shape_rt);
3047 3048
    copy_data(result, vector<float>({3}));

3049
    backend->call_with_validate(f, {result}, {a});
3050 3051 3052 3053 3054 3055 3056
    EXPECT_EQ((vector<float>{1}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3057
NGRAPH_TEST(${BACKEND_NAME}, product_matrix_to_scalar_zero_by_zero)
3058 3059 3060 3061
{
    Shape shape_a{0, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3062 3063
    auto f =
        make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), op::ParameterVector{A});
3064

3065
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3066 3067

    // Create some tensors for input/output
3068
    auto a = backend->create_tensor(element::f32, shape_a);
3069
    copy_data(a, vector<float>{});
3070
    auto result = backend->create_tensor(element::f32, shape_rt);
3071 3072
    copy_data(result, vector<float>({3}));

3073
    backend->call_with_validate(f, {result}, {a});
3074 3075 3076 3077 3078 3079 3080
    EXPECT_EQ((vector<float>{1}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3081
NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_matrix_most_sig)
3082 3083 3084 3085
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 3};
3086
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0}), op::ParameterVector{A});
3087

3088
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3089 3090

    // Create some tensors for input/output
3091
    auto a = backend->create_tensor(element::f32, shape_a);
3092 3093
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3094
    auto result = backend->create_tensor(element::f32, shape_rt);
3095

3096
    backend->call_with_validate(f, {result}, {a});
3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108
    EXPECT_EQ((vector<float>{1 * 10 * 19,
                             2 * 11 * 20,
                             3 * 12 * 21,
                             4 * 13 * 22,
                             5 * 14 * 23,
                             6 * 15 * 24,
                             7 * 16 * 25,
                             8 * 17 * 26,
                             9 * 18 * 27}),
              read_vector<float>(result));
}

3109
NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_matrix_least_sig)
3110 3111 3112 3113
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 3};
3114
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{2}), op::ParameterVector{A});
3115

3116
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3117 3118

    // Create some tensors for input/output
3119
    auto a = backend->create_tensor(element::f32, shape_a);
3120 3121
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3122
    auto result = backend->create_tensor(element::f32, shape_rt);
3123

3124
    backend->call_with_validate(f, {result}, {a});
3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136
    EXPECT_EQ((vector<float>{1 * 2 * 3,
                             4 * 5 * 6,
                             7 * 8 * 9,
                             10 * 11 * 12,
                             13 * 14 * 15,
                             16 * 17 * 18,
                             19 * 20 * 21,
                             22 * 23 * 24,
                             25 * 26 * 27}),
              read_vector<float>(result));
}

3137
NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_vector)
3138 3139 3140 3141
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3142 3143
    auto f =
        make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1}), op::ParameterVector{A});
3144

3145
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3146 3147

    // Create some tensors for input/output
3148
    auto a = backend->create_tensor(element::f32, shape_a);
3149 3150
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3151
    auto result = backend->create_tensor(element::f32, shape_rt);
3152

3153
    backend->call_with_validate(f, {result}, {a});
3154 3155 3156 3157 3158 3159
    EXPECT_EQ((vector<float>{1.0f * 10.0f * 19.0f * 4.0f * 13.0f * 22.0f * 7.0f * 16.0f * 25.0f,
                             2.0f * 11.0f * 20.0f * 5.0f * 14.0f * 23.0f * 8.0f * 17.0f * 26.0f,
                             3.0f * 12.0f * 21.0f * 6.0f * 15.0f * 24.0f * 9.0f * 18.0f * 27.0f}),
              read_vector<float>(result));
}

3160
NGRAPH_TEST(${BACKEND_NAME}, product_3d_to_scalar)
3161 3162 3163 3164
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3165 3166
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{0, 1, 2}),
                                   op::ParameterVector{A});
3167

3168
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3169 3170

    // Create some tensors for input/output
3171
    auto a = backend->create_tensor(element::f32, shape_a);
3172 3173
    copy_data(a, vector<float>{1,  2,  3,  4,  5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                               13, 12, 11, 10, 9, 8, 7, 6, 5, 4,  3,  2,  1});
3174
    auto result = backend->create_tensor(element::f32, shape_rt);
3175

3176
    backend->call_with_validate(f, {result}, {a});
Fenglei's avatar
Fenglei committed
3177 3178 3179 3180 3181
    EXPECT_TRUE(test::all_close(vector<float>{1.0f * 10.0f * 9.0f * 4.0f * 13.0f * 6.0f * 7.0f *
                                              12.0f * 3.0f * 2.0f * 11.0f * 8.0f * 5.0f * 14.0f *
                                              5.0f * 8.0f * 11.0f * 2.0f * 3.0f * 12.0f * 7.0f *
                                              6.0f * 13.0f * 4.0f * 9.0f * 10.0f * 1.0f},
                                read_vector<float>(result)));
3182 3183
}

3184
NGRAPH_TEST(${BACKEND_NAME}, product_3d_eliminate_zero_dim)
3185 3186 3187 3188
{
    Shape shape_a{3, 0, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 2};
3189
    auto f = make_shared<Function>(make_shared<op::Product>(A, AxisSet{1}), op::ParameterVector{A});
3190

3191
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3192 3193

    // Create some tensors for input/output
3194
    auto a = backend->create_tensor(element::f32, shape_a);
3195
    copy_data(a, vector<float>{});
3196
    auto result = backend->create_tensor(element::f32, shape_rt);
3197 3198 3199 3200

    // Overwrite the initial result vector to make sure we're not just coincidentally getting the right value.
    copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});

3201
    backend->call_with_validate(f, {result}, {a});
3202 3203 3204 3205
    EXPECT_EQ((vector<float>{1, 1, 1, 1, 1, 1}), read_vector<float>(result));
}

// Trivial case with no reduced axes.
3206
NGRAPH_TEST(${BACKEND_NAME}, max_trivial)
3207 3208 3209
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
3210
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{}), op::ParameterVector{A});
3211

3212
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3213 3214

    // Create some tensors for input/output
3215
    auto a = backend->create_tensor(element::f32, shape);
3216
    copy_data(a, vector<float>{1, 2, 3, 4});
3217
    auto result = backend->create_tensor(element::f32, shape);
3218

3219
    backend->call_with_validate(f, {result}, {a});
3220 3221 3222 3223
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(result));
}

// Failure has been reported at 5D for some reason
3224
NGRAPH_TEST(${BACKEND_NAME}, max_trivial_5d)
3225 3226 3227
{
    Shape shape{2, 2, 2, 2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
3228
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{}), op::ParameterVector{A});
3229

3230
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3231 3232

    // Create some tensors for input/output
3233
    auto a = backend->create_tensor(element::f32, shape);
3234 3235
    copy_data(a, vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
3236
    auto result = backend->create_tensor(element::f32, shape);
3237

3238
    backend->call_with_validate(f, {result}, {a});
3239 3240 3241 3242 3243
    EXPECT_EQ((vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}),
              read_vector<float>(result));
}

3244
NGRAPH_TEST(${BACKEND_NAME}, max_to_scalar)
3245 3246 3247
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
3248
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0, 1}), op::ParameterVector{A});
3249

3250
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3251 3252

    // Create some tensors for input/output
3253
    auto a = backend->create_tensor(element::f32, shape);
3254
    copy_data(a, vector<float>{1, 2, 3, 4});
3255
    auto result = backend->create_tensor(element::f32, Shape{});
3256

3257
    backend->call_with_validate(f, {result}, {a});
3258 3259 3260 3261 3262 3263 3264
    EXPECT_EQ((vector<float>{4}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(a));
}

3265
NGRAPH_TEST(${BACKEND_NAME}, max_matrix_columns)
3266 3267 3268 3269
{
    Shape shape_a{3, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{2};
3270
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0}), op::ParameterVector{A});
3271

3272
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3273 3274

    // Create some tensors for input/output
3275
    auto a = backend->create_tensor(element::f32, shape_a);
3276
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
3277
    auto result = backend->create_tensor(element::f32, shape_rt);
3278

3279
    backend->call_with_validate(f, {result}, {a});
3280 3281 3282 3283 3284 3285 3286
    EXPECT_EQ((vector<float>{5, 6}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a));
}

3287
NGRAPH_TEST(${BACKEND_NAME}, max_matrix_rows)
3288 3289 3290 3291
{
    Shape shape_a{3, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3292
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{1}), op::ParameterVector{A});
3293

3294
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3295 3296

    // Create some tensors for input/output
3297
    auto a = backend->create_tensor(element::f32, shape_a);
3298
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
3299
    auto result = backend->create_tensor(element::f32, shape_rt);
3300

3301
    backend->call_with_validate(f, {result}, {a});
3302 3303 3304 3305 3306 3307 3308
    EXPECT_EQ((vector<float>{2, 4, 6}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a));
}

3309
NGRAPH_TEST(${BACKEND_NAME}, max_matrix_rows_zero)
3310 3311 3312 3313
{
    Shape shape_a{3, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3314
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{1}), op::ParameterVector{A});
3315

3316
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3317 3318

    // Create some tensors for input/output
3319
    auto a = backend->create_tensor(element::f32, shape_a);
3320
    copy_data(a, vector<float>{});
3321
    auto result = backend->create_tensor(element::f32, shape_rt);
3322 3323
    copy_data(result, vector<float>({3, 3, 3}));

3324
    backend->call_with_validate(f, {result}, {a});
3325 3326 3327 3328 3329 3330 3331 3332 3333 3334
    EXPECT_EQ((vector<float>{-std::numeric_limits<float>::infinity(),
                             -std::numeric_limits<float>::infinity(),
                             -std::numeric_limits<float>::infinity()}),
              read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3335
NGRAPH_TEST(${BACKEND_NAME}, max_matrix_cols_zero)
3336 3337 3338 3339 3340
{
    // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
    Shape shape_a{0, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{2};
3341
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0}), op::ParameterVector{A});
3342

3343
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3344 3345

    // Create some tensors for input/output
3346
    auto a = backend->create_tensor(element::f32, shape_a);
3347
    copy_data(a, vector<float>{});
3348
    auto result = backend->create_tensor(element::f32, shape_rt);
3349 3350
    copy_data(result, vector<float>({3, 3}));

3351
    backend->call_with_validate(f, {result}, {a});
3352 3353 3354 3355 3356 3357 3358 3359 3360
    EXPECT_EQ((vector<float>{-std::numeric_limits<float>::infinity(),
                             -std::numeric_limits<float>::infinity()}),
              read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3361
NGRAPH_TEST(${BACKEND_NAME}, max_vector_zero)
3362 3363 3364 3365
{
    Shape shape_a{0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3366
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0}), op::ParameterVector{A});
3367

3368
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3369 3370

    // Create some tensors for input/output
3371
    auto a = backend->create_tensor(element::f32, shape_a);
3372
    copy_data(a, vector<float>{});
3373
    auto result = backend->create_tensor(element::f32, shape_rt);
3374 3375
    copy_data(result, vector<float>({3}));

3376
    backend->call_with_validate(f, {result}, {a});
3377 3378 3379 3380 3381 3382 3383
    EXPECT_EQ((vector<float>{-std::numeric_limits<float>::infinity()}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3384
NGRAPH_TEST(${BACKEND_NAME}, max_matrix_to_scalar_zero_by_zero)
3385 3386 3387 3388
{
    Shape shape_a{0, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3389
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0, 1}), op::ParameterVector{A});
3390

3391
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3392 3393

    // Create some tensors for input/output
3394
    auto a = backend->create_tensor(element::f32, shape_a);
3395
    copy_data(a, vector<float>{});
3396
    auto result = backend->create_tensor(element::f32, shape_rt);
3397 3398
    copy_data(result, vector<float>({3}));

3399
    backend->call_with_validate(f, {result}, {a});
3400 3401 3402 3403 3404 3405 3406
    EXPECT_EQ((vector<float>{-std::numeric_limits<float>::infinity()}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3407
NGRAPH_TEST(${BACKEND_NAME}, max_3d_to_matrix_most_sig)
3408 3409 3410 3411
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 3};
3412
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0}), op::ParameterVector{A});
3413

3414
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3415 3416

    // Create some tensors for input/output
3417
    auto a = backend->create_tensor(element::f32, shape_a);
3418 3419
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3420
    auto result = backend->create_tensor(element::f32, shape_rt);
3421

3422
    backend->call_with_validate(f, {result}, {a});
3423 3424 3425
    EXPECT_EQ((vector<float>{19, 20, 21, 22, 23, 24, 25, 26, 27}), read_vector<float>(result));
}

3426
NGRAPH_TEST(${BACKEND_NAME}, max_3d_to_matrix_least_sig)
3427 3428 3429 3430
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 3};
3431
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{2}), op::ParameterVector{A});
3432

3433
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3434 3435

    // Create some tensors for input/output
3436
    auto a = backend->create_tensor(element::f32, shape_a);
3437 3438
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3439
    auto result = backend->create_tensor(element::f32, shape_rt);
3440

3441
    backend->call_with_validate(f, {result}, {a});
3442 3443 3444
    EXPECT_EQ((vector<float>{3, 6, 9, 12, 15, 18, 21, 24, 27}), read_vector<float>(result));
}

3445
NGRAPH_TEST(${BACKEND_NAME}, max_3d_to_vector)
3446 3447 3448 3449
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3450
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{0, 1}), op::ParameterVector{A});
3451

3452
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3453 3454

    // Create some tensors for input/output
3455
    auto a = backend->create_tensor(element::f32, shape_a);
3456 3457
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3458
    auto result = backend->create_tensor(element::f32, shape_rt);
3459

3460
    backend->call_with_validate(f, {result}, {a});
3461 3462 3463
    EXPECT_EQ((vector<float>{25.0f, 26.0f, 27.0f}), read_vector<float>(result));
}

3464
NGRAPH_TEST(${BACKEND_NAME}, max_3d_to_scalar)
3465 3466 3467 3468
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3469 3470
    auto f =
        make_shared<Function>(make_shared<op::Max>(A, AxisSet{0, 1, 2}), op::ParameterVector{A});
3471

3472
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3473 3474

    // Create some tensors for input/output
3475
    auto a = backend->create_tensor(element::f32, shape_a);
3476 3477
    copy_data(a, vector<float>{1,  2,  3,  4,  5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                               13, 12, 11, 10, 9, 8, 7, 6, 5, 4,  3,  2,  1});
3478
    auto result = backend->create_tensor(element::f32, shape_rt);
3479

3480
    backend->call_with_validate(f, {result}, {a});
3481 3482 3483
    EXPECT_EQ((vector<float>{14.0f}), read_vector<float>(result));
}

3484
NGRAPH_TEST(${BACKEND_NAME}, max_3d_eliminate_zero_dim)
3485 3486 3487 3488
{
    Shape shape_a{3, 0, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 2};
3489
    auto f = make_shared<Function>(make_shared<op::Max>(A, AxisSet{1}), op::ParameterVector{A});
3490

3491
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3492 3493

    // Create some tensors for input/output
3494
    auto a = backend->create_tensor(element::f32, shape_a);
3495
    copy_data(a, vector<float>{});
3496
    auto result = backend->create_tensor(element::f32, shape_rt);
3497 3498 3499 3500 3501 3502

    // Overwrite the initial result vector to make sure we're not just coincidentally getting the right value.
    copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});

    float mi = -std::numeric_limits<float>::infinity();

3503
    backend->call_with_validate(f, {result}, {a});
3504 3505 3506 3507
    EXPECT_EQ((vector<float>{mi, mi, mi, mi, mi, mi}), read_vector<float>(result));
}

// Trivial case with no reduced axes.
3508
NGRAPH_TEST(${BACKEND_NAME}, min_trivial)
3509 3510 3511
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
3512
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{}), op::ParameterVector{A});
3513

3514
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3515 3516

    // Create some tensors for input/output
3517
    auto a = backend->create_tensor(element::f32, shape);
3518
    copy_data(a, vector<float>{1, 2, 3, 4});
3519
    auto result = backend->create_tensor(element::f32, shape);
3520

3521
    backend->call_with_validate(f, {result}, {a});
3522 3523 3524 3525
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(result));
}

// Failure has been reported at 5D for some reason
3526
NGRAPH_TEST(${BACKEND_NAME}, min_trivial_5d)
3527 3528 3529
{
    Shape shape{2, 2, 2, 2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
3530
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{}), op::ParameterVector{A});
3531

3532
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3533 3534

    // Create some tensors for input/output
3535
    auto a = backend->create_tensor(element::f32, shape);
3536 3537
    copy_data(a, vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                               1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1});
3538
    auto result = backend->create_tensor(element::f32, shape);
3539

3540
    backend->call_with_validate(f, {result}, {a});
3541 3542 3543 3544 3545
    EXPECT_EQ((vector<float>{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
                             1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}),
              read_vector<float>(result));
}

3546
NGRAPH_TEST(${BACKEND_NAME}, min_to_scalar)
3547 3548 3549
{
    Shape shape{2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape);
3550
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), op::ParameterVector{A});
3551

3552
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3553 3554

    // Create some tensors for input/output
3555
    auto a = backend->create_tensor(element::f32, shape);
3556
    copy_data(a, vector<float>{1, 2, 3, 4});
3557
    auto result = backend->create_tensor(element::f32, Shape{});
3558

3559
    backend->call_with_validate(f, {result}, {a});
3560 3561 3562 3563 3564 3565 3566
    EXPECT_EQ((vector<float>{1}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4}), read_vector<float>(a));
}

3567
NGRAPH_TEST(${BACKEND_NAME}, min_matrix_columns)
3568 3569 3570 3571
{
    Shape shape_a{3, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{2};
3572
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), op::ParameterVector{A});
3573

3574
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3575 3576

    // Create some tensors for input/output
3577
    auto a = backend->create_tensor(element::f32, shape_a);
3578
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
3579
    auto result = backend->create_tensor(element::f32, shape_rt);
3580

3581
    backend->call_with_validate(f, {result}, {a});
3582 3583 3584 3585 3586 3587 3588
    EXPECT_EQ((vector<float>{1, 2}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a));
}

3589
NGRAPH_TEST(${BACKEND_NAME}, min_matrix_rows)
3590 3591 3592 3593
{
    Shape shape_a{3, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3594
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), op::ParameterVector{A});
3595

3596
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3597 3598

    // Create some tensors for input/output
3599
    auto a = backend->create_tensor(element::f32, shape_a);
3600
    copy_data(a, vector<float>{1, 2, 3, 4, 5, 6});
3601
    auto result = backend->create_tensor(element::f32, shape_rt);
3602

3603
    backend->call_with_validate(f, {result}, {a});
3604 3605 3606 3607 3608 3609 3610
    EXPECT_EQ((vector<float>{1, 3, 5}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6}), read_vector<float>(a));
}

3611
NGRAPH_TEST(${BACKEND_NAME}, min_matrix_rows_zero)
3612 3613 3614 3615
{
    Shape shape_a{3, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3616
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), op::ParameterVector{A});
3617

3618
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3619 3620

    // Create some tensors for input/output
3621
    auto a = backend->create_tensor(element::f32, shape_a);
3622
    copy_data(a, vector<float>{});
3623
    auto result = backend->create_tensor(element::f32, shape_rt);
3624 3625
    copy_data(result, vector<float>({3, 3, 3}));

3626
    backend->call_with_validate(f, {result}, {a});
3627 3628 3629 3630 3631 3632 3633 3634 3635 3636
    EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity(),
                             std::numeric_limits<float>::infinity(),
                             std::numeric_limits<float>::infinity()}),
              read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3637
NGRAPH_TEST(${BACKEND_NAME}, min_matrix_cols_zero)
3638 3639 3640 3641 3642
{
    // Now the reduction (g(x:float32[2,2],y:float32[]) = reduce(x,y,f,axes={})).
    Shape shape_a{0, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{2};
3643
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), op::ParameterVector{A});
3644

3645
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3646 3647

    // Create some tensors for input/output
3648
    auto a = backend->create_tensor(element::f32, shape_a);
3649
    copy_data(a, vector<float>{});
3650
    auto result = backend->create_tensor(element::f32, shape_rt);
3651 3652
    copy_data(result, vector<float>({3, 3}));

3653
    backend->call_with_validate(f, {result}, {a});
3654 3655 3656 3657 3658 3659 3660 3661 3662
    EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity(),
                             std::numeric_limits<float>::infinity()}),
              read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3663
NGRAPH_TEST(${BACKEND_NAME}, min_vector_zero)
3664 3665 3666 3667
{
    Shape shape_a{0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3668
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), op::ParameterVector{A});
3669

3670
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3671 3672

    // Create some tensors for input/output
3673
    auto a = backend->create_tensor(element::f32, shape_a);
3674
    copy_data(a, vector<float>{});
3675
    auto result = backend->create_tensor(element::f32, shape_rt);
3676 3677
    copy_data(result, vector<float>({3}));

3678
    backend->call_with_validate(f, {result}, {a});
3679 3680 3681 3682 3683 3684 3685
    EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity()}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3686
NGRAPH_TEST(${BACKEND_NAME}, min_matrix_to_scalar_zero_by_zero)
3687 3688 3689 3690
{
    Shape shape_a{0, 0};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3691
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), op::ParameterVector{A});
3692

3693
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3694 3695

    // Create some tensors for input/output
3696
    auto a = backend->create_tensor(element::f32, shape_a);
3697
    copy_data(a, vector<float>{});
3698
    auto result = backend->create_tensor(element::f32, shape_rt);
3699 3700
    copy_data(result, vector<float>({3}));

3701
    backend->call_with_validate(f, {result}, {a});
3702 3703 3704 3705 3706 3707 3708
    EXPECT_EQ((vector<float>{std::numeric_limits<float>::infinity()}), read_vector<float>(result));

    // For some reason I'm feeling extra paranoid about making sure reduction doesn't clobber the
    // input tensors, so let's do this too.
    EXPECT_EQ((vector<float>{}), read_vector<float>(a));
}

3709
NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_matrix_most_sig)
3710 3711 3712 3713
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 3};
3714
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0}), op::ParameterVector{A});
3715

3716
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3717 3718

    // Create some tensors for input/output
3719
    auto a = backend->create_tensor(element::f32, shape_a);
3720 3721
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3722
    auto result = backend->create_tensor(element::f32, shape_rt);
3723

3724
    backend->call_with_validate(f, {result}, {a});
3725 3726 3727
    EXPECT_EQ((vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9}), read_vector<float>(result));
}

3728
NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_matrix_least_sig)
3729 3730 3731 3732
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 3};
3733
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{2}), op::ParameterVector{A});
3734

3735
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3736 3737

    // Create some tensors for input/output
3738
    auto a = backend->create_tensor(element::f32, shape_a);
3739 3740
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3741
    auto result = backend->create_tensor(element::f32, shape_rt);
3742

3743
    backend->call_with_validate(f, {result}, {a});
3744 3745 3746
    EXPECT_EQ((vector<float>{1, 4, 7, 10, 13, 16, 19, 22, 25}), read_vector<float>(result));
}

3747
NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_vector)
3748 3749 3750 3751
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3};
3752
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1}), op::ParameterVector{A});
3753

3754
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3755 3756

    // Create some tensors for input/output
3757
    auto a = backend->create_tensor(element::f32, shape_a);
3758 3759
    copy_data(a, vector<float>{1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14,
                               15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27});
3760
    auto result = backend->create_tensor(element::f32, shape_rt);
3761

3762
    backend->call_with_validate(f, {result}, {a});
3763 3764 3765
    EXPECT_EQ((vector<float>{1, 2, 3}), read_vector<float>(result));
}

3766
NGRAPH_TEST(${BACKEND_NAME}, min_3d_to_scalar)
3767 3768 3769 3770
{
    Shape shape_a{3, 3, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{};
3771 3772
    auto f =
        make_shared<Function>(make_shared<op::Min>(A, AxisSet{0, 1, 2}), op::ParameterVector{A});
3773

3774
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3775 3776

    // Create some tensors for input/output
3777
    auto a = backend->create_tensor(element::f32, shape_a);
3778 3779
    copy_data(a, vector<float>{1,  2,  3,  4,  5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
                               13, 12, 11, 10, 9, 8, 7, 6, 5, 4,  3,  2,  1});
3780
    auto result = backend->create_tensor(element::f32, shape_rt);
3781

3782
    backend->call_with_validate(f, {result}, {a});
3783 3784 3785
    EXPECT_EQ((vector<float>{1}), read_vector<float>(result));
}

3786
NGRAPH_TEST(${BACKEND_NAME}, min_3d_eliminate_zero_dim)
3787 3788 3789 3790
{
    Shape shape_a{3, 0, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    Shape shape_rt{3, 2};
3791
    auto f = make_shared<Function>(make_shared<op::Min>(A, AxisSet{1}), op::ParameterVector{A});
3792

3793
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3794 3795

    // Create some tensors for input/output
3796
    auto a = backend->create_tensor(element::f32, shape_a);
3797
    copy_data(a, vector<float>{});
3798
    auto result = backend->create_tensor(element::f32, shape_rt);
3799 3800 3801 3802 3803 3804

    // Overwrite the initial result vector to make sure we're not just coincidentally getting the right value.
    copy_data(result, vector<float>{2112, 2112, 2112, 2112, 2112, 2112});

    float inf = std::numeric_limits<float>::infinity();

3805
    backend->call_with_validate(f, {result}, {a});
3806 3807
    EXPECT_EQ((vector<float>{inf, inf, inf, inf, inf, inf}), read_vector<float>(result));
}
3808

3809 3810 3811 3812 3813 3814 3815 3816
NGRAPH_TEST(${BACKEND_NAME}, sigmoid_n1c1h2w2)
{
    auto input = make_shared<op::Parameter>(element::f32, Shape{1, 1, 2, 2});
    auto sigmoid_node = make_shared<op::Sigmoid>(input);
    auto func = make_shared<Function>(sigmoid_node, op::ParameterVector{input});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

3817 3818
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, input->get_shape());
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, input->get_shape());
3819 3820 3821 3822

    vector<float> dataA{1.0f, 4.0f, 1.0f, 4.0f};
    copy_data(a, dataA);

3823
    backend->call_with_validate(func, {result}, {a});
3824 3825 3826 3827 3828 3829 3830 3831 3832 3833 3834 3835
    vector<float> expected{0.73105858f, 0.98201379f, 0.73105858f, 0.98201379f};
    ASSERT_TRUE(read_vector<float>(result) == expected);
}

NGRAPH_TEST(${BACKEND_NAME}, sigmoid_n1c1h4)
{
    auto input = make_shared<op::Parameter>(element::f32, Shape{1, 1, 4});
    auto sigmoid_node = make_shared<op::Sigmoid>(input);
    auto func = make_shared<Function>(sigmoid_node, op::ParameterVector{input});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

3836 3837
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, input->get_shape());
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, input->get_shape());
3838 3839 3840 3841

    vector<float> dataA{1.0f, 4.0f, 1.0f, 4.0f};
    copy_data(a, dataA);

3842
    backend->call_with_validate(func, {result}, {a});
3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854
    vector<float> expected{0.73105858f, 0.98201379f, 0.73105858f, 0.98201379f};
    ASSERT_TRUE(read_vector<float>(result) == expected);
}

NGRAPH_TEST(${BACKEND_NAME}, sigmoid_bprop_n1c1h4)
{
    auto input = make_shared<op::Parameter>(element::f32, Shape{1, 1, 4});
    auto delta = make_shared<op::Parameter>(element::f32, Shape{1, 1, 4});
    auto sigmoid_node = make_shared<op::SigmoidBackprop>(input, delta);
    auto func = make_shared<Function>(sigmoid_node, op::ParameterVector{input, delta});
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

3855 3856 3857
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::f32, input->get_shape());
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::f32, delta->get_shape());
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::f32, input->get_shape());
3858 3859 3860 3861 3862 3863

    vector<float> dataA{1.0f, 4.0f, 1.0f, 4.0f};
    vector<float> dataB{1.0f, 1.0f, 1.0f, 1.0f};

    copy_data(a, dataA);
    copy_data(b, dataB);
3864
    backend->call_with_validate(func, {result}, {a, b});
3865 3866 3867 3868 3869

    vector<float> expected{0.196612f, 0.0176627f, 0.196612f, 0.0176627f};
    EXPECT_TRUE(test::all_close(expected, read_vector<float>(result)));
}

3870
NGRAPH_TEST(${BACKEND_NAME}, relu_2Dfprop)
3871 3872 3873 3874 3875
{
    auto shape_a = Shape{2, 5};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    auto relu = make_shared<op::Relu>(A);
    auto shape_rt = Shape{2, 5};
3876
    auto f = make_shared<Function>(relu, op::ParameterVector{A});
3877

3878
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3879

3880
    auto a = backend->create_tensor(element::f32, shape_a);
3881
    copy_data(a, vector<float>{1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5});
3882
    auto result = backend->create_tensor(element::f32, shape_rt);
3883 3884
    vector<float> expected{1, 8, 0, 17, 0, 1, 8, 0, 17, 0};

3885
    backend->call_with_validate(f, {result}, {a});
3886 3887 3888
    EXPECT_EQ(read_vector<float>(result), expected);
}

3889
NGRAPH_TEST(${BACKEND_NAME}, relu_4Dfprop)
3890 3891 3892 3893 3894
{
    auto shape_a = Shape{2, 2, 2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    auto relu = make_shared<op::Relu>(A);
    auto shape_rt = Shape{2, 2, 2, 2};
3895
    auto f = make_shared<Function>(relu, op::ParameterVector{A});
3896

3897
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3898

3899
    auto a = backend->create_tensor(element::f32, shape_a);
3900
    copy_data(a, vector<float>{1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5, 1});
3901
    auto result = backend->create_tensor(element::f32, shape_rt);
3902 3903
    vector<float> expected{1, 8, 0, 17, 0, 1, 8, 0, 17, 0, 1, 8, 0, 17, 0, 1};

3904
    backend->call_with_validate(f, {result}, {a});
3905 3906 3907
    EXPECT_EQ(read_vector<float>(result), expected);
}

3908
NGRAPH_TEST(${BACKEND_NAME}, fuse_max_with_constant_zero_input_as_relu)
3909 3910 3911 3912 3913 3914
{
    auto shape_a = Shape{2, 5};
    auto A = op::Constant::create(element::f32, shape_a, {0, 0, 0, 0, 0, 0, 0, 0, 0, 0});
    auto B = make_shared<op::Parameter>(element::f32, shape_a);
    auto max = make_shared<op::Maximum>(A, B);
    auto shape_rt = Shape{2, 5};
3915
    auto f = make_shared<Function>(max, op::ParameterVector{B});
3916

3917
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3918

3919
    auto b = backend->create_tensor(element::f32, shape_a);
3920
    copy_data(b, vector<float>{1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5});
3921
    auto result = backend->create_tensor(element::f32, shape_rt);
3922 3923
    vector<float> expected{1, 8, 0, 17, 0, 1, 8, 0, 17, 0};

3924
    backend->call_with_validate(f, {result}, {b});
3925 3926 3927
    EXPECT_EQ(read_vector<float>(result), expected);
}

3928
NGRAPH_TEST(${BACKEND_NAME}, relu_2Dbackprop)
3929 3930 3931 3932 3933 3934
{
    auto shape_a = Shape{2, 5};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    auto delta_val = make_shared<op::Parameter>(element::f32, shape_a);
    auto relu = make_shared<op::ReluBackprop>(A, delta_val);
    auto shape_rt = Shape{2, 5};
3935
    auto f = make_shared<Function>(relu, op::ParameterVector{A, delta_val});
3936

3937
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3938

3939
    auto a = backend->create_tensor(element::f32, shape_a);
3940
    copy_data(a, vector<float>{1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5});
3941
    auto delta = backend->create_tensor(element::f32, shape_a);
3942
    copy_data(delta, vector<float>{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
3943
    auto result = backend->create_tensor(element::f32, shape_rt);
3944 3945
    vector<float> expected{1, 2, 0, 4, 0, 6, 7, 0, 9, 0};

3946
    backend->call_with_validate(f, {result}, {a, delta});
3947 3948 3949
    EXPECT_EQ(read_vector<float>(result), expected);
}

3950
NGRAPH_TEST(${BACKEND_NAME}, relu_4Dbackprop)
3951 3952 3953 3954 3955 3956
{
    auto shape_a = Shape{2, 2, 2, 2};
    auto A = make_shared<op::Parameter>(element::f32, shape_a);
    auto delta_val = make_shared<op::Parameter>(element::f32, shape_a);
    auto relu = make_shared<op::ReluBackprop>(A, delta_val);
    auto shape_rt = Shape{2, 2, 2, 2};
3957
    auto f = make_shared<Function>(relu, op::ParameterVector{A, delta_val});
3958

3959
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
3960

3961
    auto a = backend->create_tensor(element::f32, shape_a);
3962
    copy_data(a, vector<float>{1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5, 1});
3963
    auto delta = backend->create_tensor(element::f32, shape_a);
3964
    copy_data(delta, vector<float>{1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5, 1, 8, -8, 17, -0.5, 1});
3965
    auto result = backend->create_tensor(element::f32, shape_rt);
3966 3967
    vector<float> expected{1, 8, 0, 17, 0, 1, 8, 0, 17, 0, 1, 8, 0, 17, 0, 1};

3968
    backend->call_with_validate(f, {result}, {a, delta});
3969 3970
    EXPECT_EQ(read_vector<float>(result), expected);
}
adstraw's avatar
adstraw committed
3971

3972
NGRAPH_TEST(${BACKEND_NAME}, softmax_all)
adstraw's avatar
adstraw committed
3973 3974 3975 3976 3977 3978
{
    Shape shape{2, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f =
        make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{0, 1}), op::ParameterVector{A});

3979
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
adstraw's avatar
adstraw committed
3980

3981
    auto a = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
3982
    copy_data(a, vector<float>{-3, -2, -1, 0, 1, 2});
3983
    auto result = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
3984 3985 3986

    auto d = expf(-3) + expf(-2) + expf(-1) + expf(0) + expf(1) + expf(2);

3987
    backend->call_with_validate(f, {result}, {a});
adstraw's avatar
adstraw committed
3988 3989
    vector<float> expected{
        expf(-3) / d, expf(-2) / d, expf(-1) / d, expf(0) / d, expf(1) / d, expf(2) / d};
3990
    EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result)));
adstraw's avatar
adstraw committed
3991 3992 3993

    // empty AxisSet is the same as "full" AxisSet
    f = make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{}), op::ParameterVector{A});
3994
    backend = runtime::Backend::create("${BACKEND_NAME}");
adstraw's avatar
adstraw committed
3995

3996
    backend->call_with_validate(f, {result}, {a});
3997
    EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result)));
adstraw's avatar
adstraw committed
3998 3999
}

4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018
NGRAPH_TEST(${BACKEND_NAME}, softmax_axis_3d)
{
    Shape shape{2, 2, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{0}), op::ParameterVector{A});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{-10, -20, -30, -40, -50, -60, -1, -2, -3, -4, -5, -6});
    auto result = backend->create_tensor(element::f32, shape);

    auto d0 = expf(-10) + expf(-1);
    auto d1 = expf(-20) + expf(-2);
    auto d2 = expf(-30) + expf(-3);
    auto d3 = expf(-40) + expf(-4);
    auto d4 = expf(-50) + expf(-5);
    auto d5 = expf(-60) + expf(-6);

4019
    backend->call_with_validate(f, {result}, {a});
4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035
    vector<float> expected{expf(-10) / d0,
                           expf(-20) / d1,
                           expf(-30) / d2,
                           expf(-40) / d3,
                           expf(-50) / d4,
                           expf(-60) / d5,
                           expf(-1) / d0,
                           expf(-2) / d1,
                           expf(-3) / d2,
                           expf(-4) / d3,
                           expf(-5) / d4,
                           expf(-6) / d5};

    EXPECT_TRUE(test::all_close(expected, read_vector<float>(result)));
}

4036
NGRAPH_TEST(${BACKEND_NAME}, softmax_axis)
adstraw's avatar
adstraw committed
4037 4038 4039 4040 4041
{
    Shape shape{2, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{1}), op::ParameterVector{A});

4042
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
adstraw's avatar
adstraw committed
4043

4044
    auto a = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
4045
    copy_data(a, vector<float>{-10, -20, -30, -40, -50, -60});
4046
    auto result = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
4047 4048 4049 4050

    auto d0 = expf(-10) + expf(-20) + expf(-30);
    auto d1 = expf(-40) + expf(-50) + expf(-60);

4051
    backend->call_with_validate(f, {result}, {a});
adstraw's avatar
adstraw committed
4052 4053 4054 4055 4056 4057
    vector<float> expected{expf(-10) / d0,
                           expf(-20) / d0,
                           expf(-30) / d0,
                           expf(-40) / d1,
                           expf(-50) / d1,
                           expf(-60) / d1};
4058
    EXPECT_TRUE(test::all_close_f(expected, read_vector<float>(result)));
adstraw's avatar
adstraw committed
4059 4060
}

4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076
NGRAPH_TEST(${BACKEND_NAME}, softmax_axis_2)
{
    Shape shape{2, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{0}), op::ParameterVector{A});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{-10, -20, -30, -40, -50, -60});
    auto result = backend->create_tensor(element::f32, shape);

    auto d0 = expf(-10) + expf(-40);
    auto d1 = expf(-20) + expf(-50);
    auto d2 = expf(-30) + expf(-60);

4077
    backend->call_with_validate(f, {result}, {a});
4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098
    vector<float> expected{expf(-10) / d0,
                           expf(-20) / d1,
                           expf(-30) / d2,
                           expf(-40) / d0,
                           expf(-50) / d1,
                           expf(-60) / d2};
    EXPECT_TRUE(test::all_close(expected, read_vector<float>(result)));
}

NGRAPH_TEST(${BACKEND_NAME}, softmax_axis_3d_trivial)
{
    Shape shape{1, 2, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{0}), op::ParameterVector{A});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    auto a = backend->create_tensor(element::f32, shape);
    copy_data(a, vector<float>{-10, -20, -30, -40, -50, -60});
    auto result = backend->create_tensor(element::f32, shape);

4099
    backend->call_with_validate(f, {result}, {a});
4100 4101 4102 4103
    vector<float> expected{1, 1, 1, 1, 1, 1};
    EXPECT_TRUE(test::all_close(expected, read_vector<float>(result)));
}

4104
NGRAPH_TEST(${BACKEND_NAME}, softmax_underflow)
adstraw's avatar
adstraw committed
4105 4106 4107 4108 4109
{
    Shape shape{2, 3};
    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Softmax>(A, AxisSet{0}), op::ParameterVector{A});

4110
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
adstraw's avatar
adstraw committed
4111 4112 4113

    auto low = std::numeric_limits<float>::lowest();

4114
    auto a = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
4115
    copy_data(a, vector<float>{low, 1, 2, 3, 4, 5});
4116
    auto result = backend->create_tensor(element::f32, shape);
adstraw's avatar
adstraw committed
4117 4118 4119 4120 4121

    auto d0 = expf(low) + expf(3);
    auto d1 = expf(1) + expf(4);
    auto d2 = expf(2) + expf(5);

4122
    backend->call_with_validate(f, {result}, {a});
adstraw's avatar
adstraw committed
4123 4124 4125 4126
    vector<float> expected{
        expf(low) / d0, expf(1) / d1, expf(2) / d2, expf(3) / d0, expf(4) / d1, expf(5) / d2};
    EXPECT_TRUE(test::all_close(expected, read_vector<float>(result)));
}
4127

4128
NGRAPH_TEST(${BACKEND_NAME}, multiple_backends)
4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143
{
    Shape shape{2, 2};
    auto A1 = make_shared<op::Parameter>(element::f32, shape);
    auto B1 = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(A1 + B1, op::ParameterVector{A1, B1});

    auto A2 = make_shared<op::Parameter>(element::f32, shape);
    auto B2 = make_shared<op::Parameter>(element::f32, shape);
    auto g = make_shared<Function>(A2 * B2, op::ParameterVector{A2, B2});

    auto backend1 = runtime::Backend::create("${BACKEND_NAME}");

    auto backend2 = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
4144 4145 4146
    shared_ptr<runtime::Tensor> a1 = backend1->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> b1 = backend1->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> result1 = backend1->create_tensor(element::f32, shape);
4147

4148 4149 4150
    shared_ptr<runtime::Tensor> a2 = backend2->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> b2 = backend2->create_tensor(element::f32, shape);
    shared_ptr<runtime::Tensor> result2 = backend2->create_tensor(element::f32, shape);
4151 4152 4153 4154 4155 4156 4157

    copy_data(a1, test::NDArray<float, 2>({{1, 2}, {3, 4}}).get_vector());
    copy_data(b1, test::NDArray<float, 2>({{5, 6}, {7, 8}}).get_vector());

    copy_data(a2, test::NDArray<float, 2>({{1, 2}, {3, 4}}).get_vector());
    copy_data(b2, test::NDArray<float, 2>({{5, 6}, {7, 8}}).get_vector());

4158
    backend1->call_with_validate(f, {result1}, {a1, b1});
4159 4160 4161
    EXPECT_EQ(read_vector<float>(result1),
              (test::NDArray<float, 2>({{6, 8}, {10, 12}})).get_vector());

4162
    backend2->call_with_validate(g, {result2}, {a2, b2});
4163 4164 4165 4166
    EXPECT_EQ(read_vector<float>(result2),
              (test::NDArray<float, 2>({{5, 12}, {21, 32}})).get_vector());
}

4167
NGRAPH_TEST(${BACKEND_NAME}, tensorview_custom_mem)
4168
{
4169
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
4170 4171 4172 4173 4174 4175 4176 4177

    Shape shape{2, 2};

    auto make_external = [&]() {
        auto A = make_shared<op::Parameter>(element::f32, shape);
        auto B = make_shared<op::Parameter>(element::f32, shape);
        auto f = make_shared<Function>(make_shared<op::Divide>(A, B), op::ParameterVector{A, B});

4178
        return f;
4179 4180
    };

4181
    auto f = make_external();
4182 4183 4184 4185

    vector<float> av{2, 4, 8, 16};
    vector<float> bv{1, 2, 4, 8};
    // use custom mem with tensorview, no need to copy data
4186 4187
    auto a = backend->create_tensor(element::f32, shape, av.data());
    auto b = backend->create_tensor(element::f32, shape, bv.data());
4188 4189 4190

    // use custom mem with result tensorview
    vector<float> rv{0, 0, 0, 0};
4191
    auto result = backend->create_tensor(element::f32, shape, rv.data());
4192 4193

    // result should be in memory without needing explict read
4194
    backend->call_with_validate(f, {result}, {a, b});
4195 4196
    EXPECT_EQ((vector<float>{2, 2, 2, 2}), rv);
}
4197

4198
NGRAPH_TEST(${BACKEND_NAME}, validate_call_input_count)
4199 4200 4201 4202 4203 4204 4205 4206 4207 4208 4209 4210 4211
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    Shape shape{2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Add>(A, B), op::ParameterVector{A, B});

    auto a = backend->create_tensor(element::f32, shape);
    auto b = backend->create_tensor(element::f32, shape);
    auto c = backend->create_tensor(element::f32, shape);

4212
    EXPECT_ANY_THROW(backend->call_with_validate(f, {c}, {a}));
4213 4214
}

4215
NGRAPH_TEST(${BACKEND_NAME}, validate_call_input_type)
4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226 4227 4228
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    Shape shape{2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Add>(A, B), op::ParameterVector{A, B});

    auto a = backend->create_tensor(element::i32, shape);
    auto b = backend->create_tensor(element::f32, shape);
    auto c = backend->create_tensor(element::f32, shape);

4229
    EXPECT_ANY_THROW(backend->call_with_validate(f, {c}, {a, b}));
4230 4231
}

4232
NGRAPH_TEST(${BACKEND_NAME}, validate_call_input_shape)
4233 4234 4235 4236 4237 4238 4239 4240 4241 4242 4243 4244 4245
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    Shape shape{2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Add>(A, B), op::ParameterVector{A, B});

    auto a = backend->create_tensor(element::f32, {2, 3});
    auto b = backend->create_tensor(element::f32, shape);
    auto c = backend->create_tensor(element::f32, shape);

4246
    EXPECT_ANY_THROW(backend->call_with_validate(f, {c}, {a, b}));
4247 4248
}

4249
NGRAPH_TEST(${BACKEND_NAME}, validate_call_output_count)
4250 4251 4252 4253 4254 4255 4256 4257 4258 4259 4260 4261 4262 4263
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    Shape shape{2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Add>(A, B), op::ParameterVector{A, B});

    auto a = backend->create_tensor(element::f32, shape);
    auto b = backend->create_tensor(element::f32, shape);
    auto c = backend->create_tensor(element::f32, shape);
    auto d = backend->create_tensor(element::f32, shape);

4264
    EXPECT_ANY_THROW(backend->call_with_validate(f, {c, d}, {a, b}));
4265 4266
}

4267
NGRAPH_TEST(${BACKEND_NAME}, validate_call_output_type)
4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    Shape shape{2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Add>(A, B), op::ParameterVector{A, B});

    auto a = backend->create_tensor(element::i32, shape);
    auto b = backend->create_tensor(element::f32, shape);
    auto c = backend->create_tensor(element::f32, shape);

4281
    EXPECT_ANY_THROW(backend->call_with_validate(f, {a}, {b, c}));
4282 4283
}

4284
NGRAPH_TEST(${BACKEND_NAME}, validate_call_output_shape)
4285 4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297
{
    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    Shape shape{2, 2};

    auto A = make_shared<op::Parameter>(element::f32, shape);
    auto B = make_shared<op::Parameter>(element::f32, shape);
    auto f = make_shared<Function>(make_shared<op::Add>(A, B), op::ParameterVector{A, B});

    auto a = backend->create_tensor(element::f32, {2, 3});
    auto b = backend->create_tensor(element::f32, shape);
    auto c = backend->create_tensor(element::f32, shape);

4298
    EXPECT_ANY_THROW(backend->call_with_validate(f, {a}, {c, b}));
4299
}
4300

4301
NGRAPH_TEST(${BACKEND_NAME}, logical_and)
4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316
{
    Shape shape{2, 2, 2};
    auto A = make_shared<op::Parameter>(element::boolean, shape);
    auto B = make_shared<op::Parameter>(element::boolean, shape);
    auto f = make_shared<Function>(make_shared<op::And>(A, B), op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::boolean, shape);
    copy_data(a, vector<char>{1, 0, 1, 1, 1, 0, 1, 0});
    auto b = backend->create_tensor(element::boolean, shape);
    copy_data(b, vector<char>{0, 0, 1, 0, 0, 1, 1, 0});
    auto result = backend->create_tensor(element::boolean, shape);

4317
    backend->call_with_validate(f, {result}, {a, b});
4318 4319 4320
    EXPECT_EQ((vector<char>{0, 0, 1, 0, 0, 0, 1, 0}), read_vector<char>(result));
}

4321
NGRAPH_TEST(${BACKEND_NAME}, logical_or)
4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336
{
    Shape shape{2, 2, 2};
    auto A = make_shared<op::Parameter>(element::boolean, shape);
    auto B = make_shared<op::Parameter>(element::boolean, shape);
    auto f = make_shared<Function>(make_shared<op::Or>(A, B), op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto a = backend->create_tensor(element::boolean, shape);
    copy_data(a, vector<char>{1, 0, 1, 1, 1, 0, 1, 0});
    auto b = backend->create_tensor(element::boolean, shape);
    copy_data(b, vector<char>{0, 0, 1, 0, 0, 1, 1, 0});
    auto result = backend->create_tensor(element::boolean, shape);

4337
    backend->call_with_validate(f, {result}, {a, b});
4338 4339
    EXPECT_EQ((vector<char>{1, 0, 1, 1, 1, 1, 1, 0}), read_vector<char>(result));
}
4340

4341
NGRAPH_TEST(${BACKEND_NAME}, batchnorm_fprop_b1c2h2w2)
4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352
{
    auto input_shape = Shape{1, 2, 2, 2};
    auto input = make_shared<op::Parameter>(element::f32, input_shape);
    auto mean_shape = Shape{2};
    auto var_shape = Shape{2};
    auto gamma_shape = Shape{2};
    auto gamma = make_shared<op::Parameter>(element::f32, gamma_shape);
    auto beta_shape = Shape{2};
    auto beta = make_shared<op::Parameter>(element::f32, beta_shape);
    double eps = 0.001;
    auto shape_r = Shape{1, 2, 2, 2};
4353
    auto bn = make_shared<op::BatchNormTraining>(eps, gamma, beta, input);
4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394

    auto output_rt = std::make_shared<op::GetOutputElement>(bn, 0);
    auto mean_rt = std::make_shared<op::GetOutputElement>(bn, 1);
    auto variance_rt = std::make_shared<op::GetOutputElement>(bn, 2);

    auto f = make_shared<Function>(NodeVector{output_rt, mean_rt, variance_rt},
                                   op::ParameterVector{input, gamma, beta});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
    auto _input = backend->create_tensor(element::f32, Shape{1, 2, 2, 2});

    copy_data(_input,
              vector<float>{0.54881352f,
                            0.71518934f,
                            0.60276335f,
                            0.54488319f,
                            0.42365479f,
                            0.64589411f,
                            0.4375872f,
                            0.89177299f});
    auto _gamma = backend->create_tensor(element::f32, gamma_shape);
    copy_data(_gamma, vector<float>{1.0f, 1.0f});
    auto _beta = backend->create_tensor(element::f32, beta_shape);
    copy_data(_beta, vector<float>{0.0f, 0.0f});
    auto bn_output = backend->create_tensor(element::f32, shape_r);
    auto result_mean = backend->create_tensor(element::f32, mean_shape);
    auto result_variance = backend->create_tensor(element::f32, var_shape);

    vector<float> expected_result{-0.71498716f,
                                  1.48388731f,
                                  -0.00196938f,
                                  -0.76693159f,
                                  -0.91316032f,
                                  0.23943391f,
                                  -0.84090298f,
                                  1.51462936f};
    vector<float> expected_mean{0.602912f, 0.599727f};
    vector<float> expected_variance{0.00472505f, 0.0361782f};

4395 4396
    backend->call_with_validate(
        f, {bn_output, result_mean, result_variance}, {_input, _gamma, _beta});
4397 4398 4399 4400 4401 4402 4403

    EXPECT_TRUE(test::all_close(expected_result, read_vector<float>(bn_output), 1e-5f, 1e-6f));
    EXPECT_TRUE(test::all_close(expected_mean, read_vector<float>(result_mean), 1e-5f, 1e-6f));
    EXPECT_TRUE(
        test::all_close(expected_variance, read_vector<float>(result_variance), 1e-5f, 1e-6f));
}

4404
NGRAPH_TEST(${BACKEND_NAME}, batchnorm_fprop_b2c2h2w1)
4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415
{
    auto input_shape = Shape{2, 2, 2, 1};
    auto input = make_shared<op::Parameter>(element::f32, input_shape);
    auto mean_shape = Shape{2};
    auto var_shape = Shape{2};
    auto gamma_shape = Shape{2};
    auto gamma = make_shared<op::Parameter>(element::f32, gamma_shape);
    auto beta_shape = Shape{2};
    auto beta = make_shared<op::Parameter>(element::f32, beta_shape);
    double eps = 0.001;
    auto shape_r = Shape{2, 2, 2, 1};
4416
    auto bn = make_shared<op::BatchNormTraining>(eps, gamma, beta, input);
4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448

    auto output_rt = std::make_shared<op::GetOutputElement>(bn, 0);
    auto mean_rt = std::make_shared<op::GetOutputElement>(bn, 1);
    auto variance_rt = std::make_shared<op::GetOutputElement>(bn, 2);

    auto f = make_shared<Function>(NodeVector{output_rt, mean_rt, variance_rt},
                                   op::ParameterVector{input, gamma, beta});
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    // Create some tensors for input/output
    auto _input = backend->create_tensor(element::f32, input_shape);
    copy_data(_input,
              vector<float>{0.54881352f,
                            0.71518934f,
                            0.60276335f,
                            0.54488319f,
                            0.42365479f,
                            0.64589411f,
                            0.4375872f,
                            0.89177299f});

    auto _gamma = backend->create_tensor(element::f32, gamma_shape);
    copy_data(_gamma, vector<float>{1.0f, 1.0f});
    auto _beta = backend->create_tensor(element::f32, beta_shape);
    copy_data(_beta, vector<float>{0.0f, 0.0f});
    auto bn_output = backend->create_tensor(element::f32, shape_r);
    auto result_mean = backend->create_tensor(element::f32, mean_shape);
    auto result_variance = backend->create_tensor(element::f32, var_shape);

    vector<float> expected_result{
        -0.30327f, 1.1561f, -0.0963782f, -0.434702f, -1.4011f, 0.548275f, -1.06187f, 1.59295f};
    vector<float> expected_mean{0.583388f, 0.619252f};
    vector<float> expected_variance{0.0119972f, 0.0282681f};
4449 4450
    backend->call_with_validate(
        f, {bn_output, result_mean, result_variance}, {_input, _gamma, _beta});
4451 4452 4453 4454 4455 4456 4457

    EXPECT_TRUE(test::all_close(expected_result, read_vector<float>(bn_output)));
    EXPECT_TRUE(test::all_close(expected_mean, read_vector<float>(result_mean)));
    EXPECT_TRUE(
        test::all_close(expected_variance, read_vector<float>(result_variance), 1e-5f, 1e-6f));
}

4458
NGRAPH_TEST(${BACKEND_NAME}, batchnorm_bprop_n4c3h2w2)
4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472
{
    auto input_shape = Shape{4, 3, 2, 2};
    auto shape_mean = Shape{3};
    auto input = make_shared<op::Parameter>(element::f32, input_shape);
    auto mean_shape = Shape{3};
    auto mean = make_shared<op::Parameter>(element::f32, mean_shape);
    auto var_shape = Shape{3};
    auto var = make_shared<op::Parameter>(element::f32, var_shape);
    auto gamma_shape = Shape{3};
    auto gamma = make_shared<op::Parameter>(element::f32, gamma_shape);
    auto beta_shape = Shape{3};
    auto beta = make_shared<op::Parameter>(element::f32, beta_shape);
    double eps = 0.001;
    auto shape_r = Shape{4, 3, 2, 2};
4473
    auto bn = make_shared<op::BatchNormTraining>(eps, gamma, beta, input);
4474 4475 4476 4477 4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501
    auto bn_dx = make_shared<op::GetOutputElement>(bn, 0);
    auto bn_dgamma = make_shared<op::GetOutputElement>(bn, 1);
    auto bn_dbeta = make_shared<op::GetOutputElement>(bn, 2);

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    auto _input = backend->create_tensor(element::f32, input_shape);
    vector<float> dataInput{
        10.76331902f, 11.51178265f, 10.31018162f, 12.2993021f,  14.17626667f, 14.63498497f,
        13.63494492f, 13.84248161f, 11.34602547f, 13.22014618f, 10.46686649f, 10.39842987f,
        12.94806862f, 11.71670246f, 14.94438076f, 13.13236618f, 13.40889645f, 12.76128387f,
        11.34430027f, 11.86629677f, 11.11464024f, 10.93221283f, 11.95324039f, 10.96581173f,
        13.05455494f, 14.41404247f, 13.11169434f, 11.26559448f, 10.89965153f, 14.08202171f,
        11.12685776f, 12.58428574f, 12.59247875f, 13.00187492f, 12.66310215f, 10.06655025f,
        12.62048626f, 14.47942352f, 13.84950638f, 10.61425877f, 11.47936344f, 13.06011772f,
        13.63069057f, 12.31748772f, 13.84555244f, 10.95815468f, 12.78933334f, 12.75389099f};
    copy_data(_input, dataInput);
    auto _mean = backend->create_tensor(element::f32, mean_shape);
    copy_data(_mean, vector<float>{12.56472874f, 12.80312157f, 11.81676865f});
    auto _var = backend->create_tensor(element::f32, var_shape);
    copy_data(_var, vector<float>{1.94557643f, 1.32772446f, 1.28163588f});

    auto _gamma = backend->create_tensor(element::f32, gamma_shape);
    copy_data(_gamma, vector<float>{2.0f, 2.0f, 2.0f});
    auto _beta = backend->create_tensor(element::f32, beta_shape);
    copy_data(_beta, vector<float>{1.0f, 1.0f, 1.0f});
    auto result = backend->create_tensor(element::f32, shape_r);

4502
    shared_ptr<runtime::Tensor> _delta = backend->create_tensor(element::f32, shape_r);
4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521
    vector<float> deltaData(shape_size(shape_r), 20.0f);
    copy_data(_delta, deltaData);

    auto f = make_shared<Function>(NodeVector{bn_dx, bn_dgamma, bn_dbeta},
                                   op::ParameterVector{mean, var, input, gamma, beta});

    auto C = std::make_shared<op::Parameter>(element::f32, shape_r);

    auto zero = ngraph::make_zero(bn_dgamma->get_element_type(), bn_dgamma->get_shape());
    ngraph::autodiff::Adjoints adjoints(NodeVector{bn_dx, bn_dgamma, bn_dbeta},
                                        NodeVector{C, zero, zero});

    auto dinput = adjoints.backprop_node(input);
    auto dgamma = adjoints.backprop_node(gamma);
    auto dbeta = adjoints.backprop_node(beta);

    auto df = make_shared<Function>(NodeVector{dinput, dgamma, dbeta},
                                    op::ParameterVector{mean, var, input, gamma, beta, C});

4522
    // roundtrip serialization
4523 4524 4525 4526
    string js = serialize(df, 4);
    istringstream in(js);
    df = deserialize(in);

4527 4528 4529
    shared_ptr<runtime::Tensor> _dinput = backend->create_tensor(element::f32, shape_r);
    shared_ptr<runtime::Tensor> _dgamma = backend->create_tensor(element::f32, gamma_shape);
    shared_ptr<runtime::Tensor> _dbeta = backend->create_tensor(element::f32, beta_shape);
4530

4531 4532
    backend->call_with_validate(
        df, {_dinput, _dgamma, _dbeta}, {_mean, _var, _input, _gamma, _beta, _delta});
4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553

    vector<float> expected_input{
        8.17051607e-06f,  4.77576657e-06f,  1.02257760e-05f,  1.20387525e-06f,  -1.73868522e-06f,
        3.84632768e-06f,  -1.07932050e-05f, -2.57458956e-06f, -2.22166714e-06f, -8.38779043e-06f,
        -2.48082982e-06f, 5.89238360e-06f,  -2.52895109e-07f, -8.68433445e-06f, -5.82726737e-06f,
        8.84659658e-06f,  3.03944108e-05f,  4.05480879e-05f,  1.84123158e-05f,  2.30061178e-05f,
        1.34087590e-05f,  -9.26072571e-07f, -3.22908454e-05f, -2.07365116e-05f, -4.21330941e-05f,
        2.83083100e-05f,  -3.71039101e-05f, -4.84390640e-06f, -2.93012376e-05f, 5.68858087e-06f,
        1.83181458e-05f,  -1.07494506e-05f, -2.32429103e-06f, 6.92914809e-06f,  -6.66512321e-06f,
        -7.00302840e-06f, -3.46675184e-06f, -4.36748381e-06f, 6.73822226e-07f,  -4.20158993e-06f,
        3.83005061e-06f,  5.85143729e-06f,  4.17875243e-06f,  -8.64167783e-06f, 1.00170803e-05f,
        -4.23939666e-06f, 4.80201680e-06f,  4.62702078e-06f};

    ASSERT_TRUE(ngraph::test::all_close(read_vector<float>(_dinput), expected_input, 1e-3f, 1e-4f));
    vector<float> expected_dgamma{7.06315041e-05f, -2.35289335e-04f, -5.06639481e-05f};
    ASSERT_TRUE(
        ngraph::test::all_close(read_vector<float>(_dgamma), expected_dgamma, 1e-2f, 1e-3f));
    vector<float> expected_dbeta{320.f, 320.f, 320.f};
    ASSERT_TRUE(ngraph::test::all_close(read_vector<float>(_dbeta), expected_dbeta, 1e-4f, 1e-8f));
}

4554
NGRAPH_TEST(${BACKEND_NAME}, batchnorm_fprop_inference_b2c2h2w1)
4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567
{
    auto input_shape = Shape{2, 2, 2, 1};
    auto input = make_shared<op::Parameter>(element::f32, input_shape);
    auto mean_shape = Shape{2};
    auto mean = make_shared<op::Parameter>(element::f32, mean_shape);
    auto var_shape = Shape{2};
    auto var = make_shared<op::Parameter>(element::f32, var_shape);
    auto gamma_shape = Shape{2};
    auto gamma = make_shared<op::Parameter>(element::f32, gamma_shape);
    auto beta_shape = Shape{2};
    auto beta = make_shared<op::Parameter>(element::f32, beta_shape);
    double eps = 0.001;
    auto shape_r = Shape{2, 2, 2, 1};
4568
    auto bn = make_shared<op::BatchNormInference>(eps, gamma, beta, input, mean, var);
4569 4570 4571 4572 4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592

    auto f = make_shared<Function>(bn, op::ParameterVector{input, gamma, beta, mean, var});
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    // Create some tensors for input/output
    auto _input = backend->create_tensor(element::f32, input_shape);
    copy_data(_input,
              vector<float>{0.54881352f,
                            0.71518934f,
                            0.60276335f,
                            0.54488319f,
                            0.42365479f,
                            0.64589411f,
                            0.4375872f,
                            0.89177299f});

    auto _gamma = backend->create_tensor(element::f32, gamma_shape);
    copy_data(_gamma, vector<float>{1.0f, 1.0f});
    auto _beta = backend->create_tensor(element::f32, beta_shape);
    copy_data(_beta, vector<float>{0.0f, 0.0f});
    auto _mean = backend->create_tensor(element::f32, mean_shape);
    copy_data(_mean, vector<float>{0.583388f, 0.619252f});
    auto _var = backend->create_tensor(element::f32, var_shape);
    copy_data(_var, vector<float>{0.0119972f, 0.0282681f});
    auto bn_output = backend->create_tensor(element::f32, shape_r);
4593

4594 4595
    vector<float> expected_result{
        -0.30327f, 1.1561f, -0.0963782f, -0.434702f, -1.4011f, 0.548275f, -1.06187f, 1.59295f};
4596
    backend->call_with_validate(f, {bn_output}, {_input, _gamma, _beta, _mean, _var});
4597 4598 4599 4600 4601

    ASSERT_TRUE(
        ngraph::test::all_close(expected_result, read_vector<float>(bn_output), 1e-3f, 1e-4f));
}

4602
#if 0
4603
NGRAPH_TEST(${BACKEND_NAME}, batchnorm_fprop_globalstats_b2c2w2h1)
4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616
{
    auto input_shape = Shape{2, 2, 2, 1};
    auto input = make_shared<op::Parameter>(element::f32, input_shape);
    auto mean_shape = Shape{2};
    auto mean = make_shared<op::Parameter>(element::f32, mean_shape);
    auto var_shape = Shape{2};
    auto var = make_shared<op::Parameter>(element::f32, var_shape);
    auto gamma_shape = Shape{2};
    auto gamma = make_shared<op::Parameter>(element::f32, gamma_shape);
    auto beta_shape = Shape{2};
    auto beta = make_shared<op::Parameter>(element::f32, beta_shape);
    double eps = 0.001;
    auto shape_r = Shape{2, 2, 2, 1};
4617
    auto bn = make_shared<op::BatchNormTraining>(eps, gamma, beta, input, mean, var);
4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641

    auto f = make_shared<Function>(bn, op::ParameterVector{gamma, beta, input, mean, var});
    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    // Create some tensors for input/output
    auto _input = backend->create_tensor(element::f32, input_shape);
    copy_data(_input,
              vector<float>{0.54881352f,
                            0.71518934f,
                            0.60276335f,
                            0.54488319f,
                            0.42365479f,
                            0.64589411f,
                            0.4375872f,
                            0.89177299f});

    auto _gamma = backend->create_tensor(element::f32, gamma_shape);
    copy_data(_gamma, vector<float>{1.0f, 1.0f});
    auto _beta = backend->create_tensor(element::f32, beta_shape);
    copy_data(_beta, vector<float>{0.0f, 0.0f});
    auto _mean = backend->create_tensor(element::f32, mean_shape);
    copy_data(_mean, vector<float>{0.583388f, 0.619252f});
    auto _var = backend->create_tensor(element::f32, var_shape);
    copy_data(_var, vector<float>{0.0119972f, 0.0282681f});
    auto bn_output = backend->create_tensor(element::f32, shape_r);
4642

4643 4644
    vector<float> expected_result{
        -0.30327f, 1.1561f, -0.0963782f, -0.434702f, -1.4011f, 0.548275f, -1.06187f, 1.59295f};
4645
    backend->call_with_validate(f, {bn_output}, {_gamma, _beta, _input, _mean, _var});
4646 4647 4648 4649

    ASSERT_TRUE(
        ngraph::test::all_close(expected_result, read_vector<float>(bn_output), 1e-3f, 1e-4f));
}
4650
#endif
4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667

NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n2c3h4w2)
{
    Shape shape{2, 3, 4, 2};
    Shape seq_len_shape{4};
    auto A = make_shared<op::Parameter>(element::i32, shape);
    auto B = make_shared<op::Parameter>(element::i32, seq_len_shape);

    size_t batch_axis = 2;
    size_t sequence_axis = 1;
    auto rs = std::make_shared<op::ReverseSequence>(A, B, batch_axis, sequence_axis);

    auto f = make_shared<Function>(rs, op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
4668 4669
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::i32, shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::i32, seq_len_shape);
4670

4671
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::i32, shape);
4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687

    std::vector<int> input{
        0,  0, 3,  0, 6,  0, 9,  0, 1,  0, 4,  0, 7,  0, 10, 0, 2,  0, 5,  0, 8,  0, 11, 0,
        12, 0, 15, 0, 18, 0, 21, 0, 13, 0, 16, 0, 19, 0, 22, 0, 14, 0, 17, 0, 20, 0, 23, 0,
    };

    std::vector<int> seq_lenghts{1, 2, 1, 2};
    copy_data(b, seq_lenghts);

    std::vector<int> expected{
        0,  0, 4,  0, 6,  0, 10, 0, 1,  0, 3,  0, 7,  0, 9,  0, 2,  0, 5,  0, 8,  0, 11, 0,

        12, 0, 16, 0, 18, 0, 22, 0, 13, 0, 15, 0, 19, 0, 21, 0, 14, 0, 17, 0, 20, 0, 23, 0};

    copy_data(a, input);

4688
    backend->call_with_validate(f, {result}, {a, b});
4689 4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708
    EXPECT_EQ(read_vector<int>(result), expected);
}

NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n4c3h2w2)
{
    Shape shape{4, 3, 2, 2};
    auto A = make_shared<op::Parameter>(element::i32, shape);
    Shape seq_len_shape{4};
    auto B = make_shared<op::Parameter>(element::i32, seq_len_shape);

    size_t batch_axis = 0;
    size_t sequence_axis = 1;

    auto rs = std::make_shared<op::ReverseSequence>(A, B, batch_axis, sequence_axis);

    auto f = make_shared<Function>(rs, op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
4709 4710
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::i32, shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::i32, seq_len_shape);
4711

4712
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::i32, shape);
4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726

    std::vector<int> seq_lenghts{1, 2, 3, 3};
    copy_data(b, seq_lenghts);

    std::vector<int> input{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
                           16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                           32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47};

    std::vector<int> expected{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 16, 17, 18, 19,
                              12, 13, 14, 15, 20, 21, 22, 23, 32, 33, 34, 35, 28, 29, 30, 31,
                              24, 25, 26, 27, 44, 45, 46, 47, 40, 41, 42, 43, 36, 37, 38, 39};

    copy_data(a, input);

4727
    backend->call_with_validate(f, {result}, {a, b});
4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747
    EXPECT_EQ(read_vector<int>(result), expected);
}

NGRAPH_TEST(${BACKEND_NAME}, reverse_sequence_n4d2c3h2w2)
{
    Shape shape{4, 2, 3, 2, 2};
    auto A = make_shared<op::Parameter>(element::i32, shape);
    Shape seq_len_shape{4};
    auto B = make_shared<op::Parameter>(element::i32, seq_len_shape);

    size_t batch_axis = 0;
    size_t sequence_axis = 2;

    auto rs = std::make_shared<op::ReverseSequence>(A, B, batch_axis, sequence_axis);

    auto f = make_shared<Function>(rs, op::ParameterVector{A, B});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    // Create some tensors for input/output
4748 4749
    shared_ptr<runtime::Tensor> a = backend->create_tensor(element::i32, shape);
    shared_ptr<runtime::Tensor> b = backend->create_tensor(element::i32, seq_len_shape);
4750

4751
    shared_ptr<runtime::Tensor> result = backend->create_tensor(element::i32, shape);
4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771

    std::vector<int> input{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
                           16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
                           32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
                           48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
                           64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
                           80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95};

    std::vector<int> expected{0,  1,  2,  3,  4,  5,  6,  7,  8,  9,  10, 11, 12, 13, 14, 15,
                              16, 17, 18, 19, 20, 21, 22, 23, 28, 29, 30, 31, 24, 25, 26, 27,
                              32, 33, 34, 35, 40, 41, 42, 43, 36, 37, 38, 39, 44, 45, 46, 47,
                              48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
                              64, 65, 66, 67, 68, 69, 70, 71, 76, 77, 78, 79, 72, 73, 74, 75,
                              80, 81, 82, 83, 88, 89, 90, 91, 84, 85, 86, 87, 92, 93, 94, 95};

    copy_data(a, input);

    std::vector<int> seq_lenghts{1, 2, 1, 2};
    copy_data(b, seq_lenghts);

4772
    backend->call_with_validate(f, {result}, {a, b});
4773 4774
    EXPECT_EQ(read_vector<int>(result), expected);
}
Nick Korovaiko's avatar
Nick Korovaiko committed
4775

4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805
NGRAPH_TEST(${BACKEND_NAME}, generate_mask)
{
    Shape scalar{};
    Shape result_shape{1, 128};
    const unsigned int seed = 777;
    auto training = op::Constant::create(element::f32, Shape{}, {1});
    auto gen_mask = make_shared<op::GenerateMask>(training, result_shape, element::f32, seed, 0.5);
    auto gen_mask2 = make_shared<op::GenerateMask>(training, result_shape, element::f32, seed, 0.5);
    auto f = make_shared<Function>(NodeVector{gen_mask, gen_mask2}, op::ParameterVector{});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");

    auto is_not_zero_or_one = [](float num) { return num != 0.f && num != 1.f; };

    auto result_tv1 = backend->create_tensor<float>(result_shape);
    auto result_tv2 = backend->create_tensor<float>(result_shape);
    backend->call_with_validate(f, {result_tv1, result_tv2}, {});
    auto result1 = read_vector<float>(result_tv1);
    auto result2 = read_vector<float>(result_tv2);
    ASSERT_EQ(result1, result2);
    ASSERT_FALSE(std::any_of(result1.begin(), result1.end(), is_not_zero_or_one));
    backend->call_with_validate(f, {result_tv1, result_tv2}, {});
    auto result1_2 = read_vector<float>(result_tv1);
    auto result2_2 = read_vector<float>(result_tv2);
    ASSERT_NE(result1, result1_2);
    ASSERT_FALSE(std::any_of(result1_2.begin(), result1_2.end(), is_not_zero_or_one));
    ASSERT_NE(result2, result2_2);
    ASSERT_FALSE(std::any_of(result2_2.begin(), result2_2.end(), is_not_zero_or_one));
}

4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817
NGRAPH_TEST(${BACKEND_NAME}, quantize)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::u8;

    typedef float input_c_type;
    typedef uint8_t output_c_type;

4818
    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY;
4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {2});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {1});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
    // divide by scale                2  2  2  2  2  2  2  2  2  2  2   2
    // equals (rounded)               0  1  1  2  2  3  3  4  4  5  5   6
    // plus offset                    1  1  1  1  1  1  1  1  1  1  1   1
    // equals                         1  2  2  3  3  4  4  5  5  6  6   7

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7}),
              read_vector<output_c_type>(y));
}

4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874
NGRAPH_TEST(${BACKEND_NAME}, dequantize)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::u8;
    auto output_type = element::f32;

    typedef uint8_t input_c_type;
    typedef float output_c_type;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(output_type, scale_offset_shape, {2});
    auto offset = op::Constant::create(input_type, scale_offset_shape, {1});
    auto dequantize = make_shared<op::Dequantize>(X, scale, offset, output_type, quantization_axes);
    auto f = make_shared<Function>(dequantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7});
    // minus offset                   1  1  1  1  1  1  1  1  1  1  1  1
    // eqauls                         0  1  1  2  2  3  3  4  4  5  5  6
    // multiplied by scale            2  2  2  2  2  2  2  2  2  2  2  2
    // equals                         0  2  2  4  4  6  6  8  8 10 10 12

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{0, 2, 2, 4, 4, 6, 6, 8, 8, 10, 10, 12}),
              read_vector<output_c_type>(y));
}

4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906
NGRAPH_TEST(${BACKEND_NAME}, dequantize_zero_offset)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::u8;
    auto output_type = element::f32;

    typedef uint8_t input_c_type;
    typedef float output_c_type;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(output_type, scale_offset_shape, {2});
    auto offset = op::Constant::create(input_type, scale_offset_shape, {0});
    auto dequantize = make_shared<op::Dequantize>(X, scale, offset, output_type, quantization_axes);
    auto f = make_shared<Function>(dequantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7});
    // minus offset                   0  0  0  0  0  0  0  0  0  0  0  0
    // multiplied by scale            2  2  2  2  2  2  2  2  2  2  2  2
    // equals                         2  4  4  6  6  8  8  10 10 12 12 14

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 4, 4, 6, 6, 8, 8, 10, 10, 12, 12, 14}),
              read_vector<output_c_type>(y));
}

4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918
NGRAPH_TEST(${BACKEND_NAME}, quantize_axes)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape{4};
    AxisSet quantization_axes{0};

    auto input_type = element::f32;
    auto output_type = element::u8;

    typedef float input_c_type;
    typedef uint8_t output_c_type;

4919
    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY;
4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {2, 3, 4, 5});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {10, 20, 30, 40});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11});
    // divided by scale               2  2  2  3  3  3  4  4  4  5  5   5
    // equals (rounded)               0  1  1  1  1  2  2  2  2  2  2   2
    // plus offset                   10 10 10 20 20 20 30 30 30 40 40  40
    // equals                        10 11 11 21 21 22 32 32 32 42 42  42

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{10, 11, 11, 21, 21, 22, 32, 32, 32, 42, 42, 42}),
              read_vector<output_c_type>(y));
}

4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975
NGRAPH_TEST(${BACKEND_NAME}, dequantize_axes)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape{4};
    AxisSet quantization_axes{0};

    auto input_type = element::u8;
    auto output_type = element::f32;

    typedef uint8_t input_c_type;
    typedef float output_c_type;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(output_type, scale_offset_shape, {2, 3, 4, 5});
    auto offset = op::Constant::create(input_type, scale_offset_shape, {10, 20, 30, 40});
    auto dequantize = make_shared<op::Dequantize>(X, scale, offset, output_type, quantization_axes);
    auto f = make_shared<Function>(dequantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{10, 11, 11, 21, 21, 22, 32, 32, 32, 42, 42, 42});
    // minus offset                   10  10  10  20  20  20  30  30  30  40  40  40
    // equals                          0   1   1   1   1   2   2   2   2   2   2   2
    // multiplied by scale             2   2   2   3   3   3   4   4   4   5   5   5
    // equals                          0   2   2   3   3   6   8   8   8  10  10  10

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{0, 2, 2, 3, 3, 6, 8, 8, 8, 10, 10, 10}),
              read_vector<output_c_type>(y));
}

4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987
NGRAPH_TEST(${BACKEND_NAME}, quantize_int8)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

4988
    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY;
4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {2});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {1});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11});
    // divide by scale                2   2  2   2  2   2  2   2  2   2  2    2
    // equals (rounded)               0  -1  1  -2  2  -3  3  -4  4  -5  5   -6
    // plus offset                    1   1  1   1  1   1  1   1  1   1  1    1
    // equals                         1   0  2  -1  3  -2  4  -3  5  -4  6   -5

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{1, 0, 2, -1, 3, -2, 4, -3, 5, -4, 6, -5}),
              read_vector<output_c_type>(y));
}

5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044
NGRAPH_TEST(${BACKEND_NAME}, dequantize_int8)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::i8;
    auto output_type = element::f32;

    typedef int8_t input_c_type;
    typedef float output_c_type;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(output_type, scale_offset_shape, {2});
    auto offset = op::Constant::create(input_type, scale_offset_shape, {1});
    auto dequantize = make_shared<op::Dequantize>(X, scale, offset, output_type, quantization_axes);
    auto f = make_shared<Function>(dequantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{1, 0, 2, -1, 3, -2, 4, -3, 5, -4, 6, -5});
    // minus offset                   1  1  1   1  1   1  1   1  1   1  1   1
    // equals                         0 -1  1  -2  2  -3  3  -4  4  -5  5  -6
    // multiplied by scale            2  2  2   2  2   2  2   2  2   2  2   2
    // equals                         0 -2  2  -4  4  -6  6  -8  8 -10 10 -12

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{0, -2, 2, -4, 4, -6, 6, -8, 8, -10, 10, -12}),
              read_vector<output_c_type>(y));
}

5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056
NGRAPH_TEST(${BACKEND_NAME}, quantize_clamp)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

5057
    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_INFINITY;
5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {0.00001});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {1});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{0, -1, 2, -3, 4, -5, 6, -7, 8, -9, 10, -11});

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ(
        (vector<output_c_type>{1, -128, 127, -128, 127, -128, 127, -128, 127, -128, 127, -128}),
        read_vector<output_c_type>(y));
}
5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244 5245 5246 5247 5248 5249 5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296 5297 5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347 5348 5349 5350 5351 5352 5353 5354 5355 5356 5357 5358

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_NEAREST_TOWARD_ZERO)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_ZERO;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               2   2   3  -2   -2   -3   3   3   4   -3   -3   -4

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 2, 3, -2, -2, -3, 3, 3, 4, -3, -3, -4}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_NEAREST_UPWARD)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_UPWARD;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               2   3   3  -2   -2   -3   3   4   4   -3   -3   -4

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 3, 3, -2, -2, -3, 3, 4, 4, -3, -3, -4}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_NEAREST_DOWNWARD)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_DOWNWARD;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               2   2   3  -2   -3   -3   3   3   4   -3   -4   -4

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 2, 3, -2, -3, -3, 3, 3, 4, -3, -4, -4}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_NEAREST_TOWARD_EVEN)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_NEAREST_TOWARD_EVEN;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               2   2   3  -2   -2   -3   3   4   4   -3   -4   -4

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 2, 3, -2, -2, -3, 3, 4, 4, -3, -4, -4}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_TOWARD_INFINITY)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_TOWARD_INFINITY;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize = make_shared<op::Quantize>(
        X,
        scale,
        offset,
        output_type,
        quantization_axes,
        static_cast<op::Quantize::RoundMode>(static_cast<int>(round_mode)));
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               3   3   3  -3   -3   -3   4   4   4   -4   -4   -4

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{3, 3, 3, -3, -3, -3, 4, 4, 4, -4, -4, -4}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_TOWARD_ZERO)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_TOWARD_ZERO;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize = make_shared<op::Quantize>(
        X,
        scale,
        offset,
        output_type,
        quantization_axes,
        static_cast<op::Quantize::RoundMode>(static_cast<int>(round_mode)));
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               2   2   2  -2   -2   -2   3   3   3   -3   -3   -3

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 2, 2, -2, -2, -2, 3, 3, 3, -3, -3, -3}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_UP)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_UP;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               3   3   3  -2   -2   -2   4   4   4   -3   -3   -3

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{3, 3, 3, -2, -2, -2, 4, 4, 4, -3, -3, -3}),
              read_vector<output_c_type>(y));
}

NGRAPH_TEST(${BACKEND_NAME}, quantize_ROUND_DOWN)
{
    Shape input_shape{4, 3};
    Shape scale_offset_shape;
    AxisSet quantization_axes;

    auto input_type = element::f32;
    auto output_type = element::i8;

    typedef float input_c_type;
    typedef int8_t output_c_type;

    op::Quantize::RoundMode round_mode = op::Quantize::RoundMode::ROUND_DOWN;

    auto X = make_shared<op::Parameter>(input_type, input_shape);
    auto scale = op::Constant::create(input_type, scale_offset_shape, {4});
    auto offset = op::Constant::create(output_type, scale_offset_shape, {0});
    auto quantize =
        make_shared<op::Quantize>(X, scale, offset, output_type, quantization_axes, round_mode);
    auto f = make_shared<Function>(quantize, op::ParameterVector{X});

    auto backend = runtime::Backend::create("${BACKEND_NAME}");
    auto x = backend->create_tensor(input_type, input_shape);
    auto y = backend->create_tensor(output_type, input_shape);

    copy_data(x, vector<input_c_type>{9, 10, 11, -9, -10, -11, 13, 14, 15, -13, -14, -15});
    // divide by scale                4   4   4   4    4    4   4   4   4    4    4    4
    // equals (rounded)               2   2   2  -3   -3   -3   3   3   3   -4   -4   -4

    backend->call_with_validate(f, {y}, {x});
    EXPECT_EQ((vector<output_c_type>{2, 2, 2, -3, -3, -3, 3, 3, 3, -4, -4, -4}),
              read_vector<output_c_type>(y));
}
5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371 5372 5373 5374 5375 5376 5377 5378 5379 5380 5381 5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433

NGRAPH_TEST(${BACKEND_NAME}, batchnorm_fprop_bprop)
{
    Shape sca{1};
    Shape vec{1, 1, 1, 2};
    double eps = 1.0e-04;

    auto g = std::make_shared<op::Parameter>(element::f32, sca);
    auto b = std::make_shared<op::Parameter>(element::f32, sca);
    auto input = std::make_shared<op::Parameter>(element::f32, vec);
    auto bn_fp = std::make_shared<op::BatchNormTraining>(eps, g, b, input);
    auto bnorm = std::make_shared<op::GetOutputElement>(bn_fp, 0);
    auto mean = std::make_shared<op::GetOutputElement>(bn_fp, 1);
    auto var = std::make_shared<op::GetOutputElement>(bn_fp, 2);

    auto delta = std::make_shared<op::Parameter>(element::f32, vec);
    auto bn_bp =
        std::make_shared<op::BatchNormTrainingBackprop>(eps, g, b, bnorm, mean, var, delta);
    auto dx = std::make_shared<op::GetOutputElement>(bn_bp, 0);

    std::vector<std::vector<float>> args = {
        {1.0f},       // gamma
        {1.0f},       // beta
        {1.1f, 1.0f}, // x
        {1.0f, 1.0f}, // dy
    };

    auto func = std::make_shared<Function>(dx, op::ParameterVector{g, b, input, delta});
    auto results = execute(func, args, "${BACKEND_NAME}");
    EXPECT_TRUE(test::all_close_f(std::vector<float>{350.957, -388.67}, results.at(0)));
}

NGRAPH_TEST(${BACKEND_NAME}, batchnorm_fprop_bprop_2step)
{
    Shape sca{1};
    Shape vec{1, 1, 1, 2};
    double eps = 1.0e-04;

    auto g = std::make_shared<op::Parameter>(element::f32, sca);
    auto b = std::make_shared<op::Parameter>(element::f32, sca);
    auto input = std::make_shared<op::Parameter>(element::f32, vec);
    auto bn_fp = std::make_shared<op::BatchNormTraining>(eps, g, b, input);
    auto bnorm = std::make_shared<op::GetOutputElement>(bn_fp, 0);
    auto mean = std::make_shared<op::GetOutputElement>(bn_fp, 1);
    auto var = std::make_shared<op::GetOutputElement>(bn_fp, 2);

    auto func_bn =
        std::make_shared<Function>(NodeVector{bnorm, mean, var}, op::ParameterVector{g, b, input});

    std::vector<std::vector<float>> args = {
        {1.0f},       // gamma
        {1.0f},       // beta
        {1.1f, 1.0f}, // x
    };
    auto results = execute(func_bn, args, "${BACKEND_NAME}");

    g = std::make_shared<op::Parameter>(element::f32, sca);
    b = std::make_shared<op::Parameter>(element::f32, sca);
    auto bn_output = std::make_shared<op::Parameter>(element::f32, vec);
    auto m = std::make_shared<op::Parameter>(element::f32, sca);
    auto v = std::make_shared<op::Parameter>(element::f32, sca);
    auto delta = std::make_shared<op::Parameter>(element::f32, vec);
    auto bn_bp = std::make_shared<op::BatchNormTrainingBackprop>(eps, g, b, bn_output, m, v, delta);
    auto dx = std::make_shared<op::GetOutputElement>(bn_bp, 0);

    args.pop_back();               // remove x
    args.push_back(results.at(0)); // bn_output
    args.push_back(results.at(1)); // m
    args.push_back(results.at(2)); // v
    args.push_back({1.0f, 1.0f});  // dy

    auto func = std::make_shared<Function>(dx, op::ParameterVector{g, b, bn_output, m, v, delta});
    results = execute(func, args, "${BACKEND_NAME}");
    EXPECT_TRUE(test::all_close_f(std::vector<float>{350.957, -388.67}, results.at(0)));
}