/* * Copyright (c) 2019 Samsung Electronics Co., Ltd. All Rights Reserved * * 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. */ #include "NodeExecution.h" #include "locomotiv/NodeData.h" #include "NodeDataImpl.h" #include "NodeDomain.h" #include #include #include #include #include #include using nncc::core::ADT::tensor::Shape; using nncc::core::ADT::tensor::LexicalLayout; using nncc::core::ADT::tensor::make_buffer; using nncc::core::ADT::tensor::IndexEnumerator; /* test case generated from the following: x = tf.constant([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18], shape=[1, 3, 3, 2], dtype=tf.float32) y = tf.constant([0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1], shape=[1, 3, 3, 2], dtype=tf.float32) out = tf.math.multiply(x, y) with tf.Session() as sess: print(sess.run(out)) */ TEST(NodeExecution_EltwiseMul, f32) { float x_val[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}; float y_val[] = {0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1}; float out_val[] = {0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8}; // make EltwiseMul(Pull, Pull) auto g = loco::make_graph(); Shape input_shape{1, 3, 3, 2}; // NHWC auto inp_lhs = g->nodes()->create(); { inp_lhs->dtype(loco::DataType::FLOAT32); inp_lhs->shape({1, 3, 3, 2}); } auto inp_rhs = g->nodes()->create(); { inp_rhs->dtype(loco::DataType::FLOAT32); inp_rhs->shape({1, 3, 3, 2}); } auto eltwise_mul = g->nodes()->create(); { eltwise_mul->lhs(inp_lhs); eltwise_mul->rhs(inp_rhs); } // Make and assign data to two pull nodes auto inp_lhs_buf = make_buffer(input_shape); { int n = 0; for (IndexEnumerator e{inp_lhs_buf.shape()}; e.valid(); e.advance()) { inp_lhs_buf.at(e.current()) = x_val[n++]; } } auto inp_rhs_buf = make_buffer(input_shape); { int n = 0; for (IndexEnumerator e{inp_rhs_buf.shape()}; e.valid(); e.advance()) { inp_rhs_buf.at(e.current()) = y_val[n++]; } } auto inp_lhs_data = locomotiv::make_data(inp_lhs_buf); locomotiv::annot_data(inp_lhs, std::move(inp_lhs_data)); locomotiv::annot_domain(inp_lhs, loco::Domain::Tensor); auto inp_rhs_data = locomotiv::make_data(inp_rhs_buf); locomotiv::annot_data(inp_rhs, std::move(inp_rhs_data)); locomotiv::annot_domain(inp_rhs, loco::Domain::Tensor); // run the network locomotiv::NodeExecution::get().run(eltwise_mul); // get result auto eltwise_mul_data = locomotiv::annot_data(eltwise_mul); // comparing the result ASSERT_NE(eltwise_mul_data, nullptr); ASSERT_EQ(loco::DataType::FLOAT32, eltwise_mul_data->dtype()); ASSERT_EQ(Shape({1, 3, 3, 2}), *(eltwise_mul_data->shape())); uint32_t n = 0; for (IndexEnumerator e{*(eltwise_mul_data->shape())}; e.valid(); e.advance()) { ASSERT_FLOAT_EQ(out_val[n++], eltwise_mul_data->as_f32_bufptr()->at(e.current())); } ASSERT_EQ(loco::Domain::Tensor, locomotiv::annot_domain(eltwise_mul)); }