Imported Upstream version 1.25.0
[platform/core/ml/nnfw.git] / onert-micro / luci-interpreter / src / kernels / MaxPool2D.cpp
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *    http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "Builders.h"
18
19 #include "kernels/Utils.h"
20 #include "PALMaxPool2D.h"
21
22 namespace luci_interpreter
23 {
24 void configure_kernel_CircleMaxPool2D(const circle::Operator *cur_op,
25                                       BaseRuntimeGraph *runtime_graph)
26 {
27   const auto input_index = cur_op->inputs()->operator[](0);
28   const auto output_index = cur_op->outputs()->operator[](0);
29
30   assert(input_index != -1);
31   assert(output_index != -1);
32
33   const auto input = runtime_graph->getCircleTensorByIndex(input_index);
34   const auto output = runtime_graph->getCircleTensorByIndex(output_index);
35
36   LUCI_INTERPRETER_CHECK(Tensor::element_type(input) == Tensor::element_type(output));
37   assert(Tensor::num_dims(input) == 4);
38
39 #ifndef DIS_QUANT
40   if (Tensor::element_type(input) == DataType::U8)
41   {
42     LUCI_INTERPRETER_CHECK(std::abs(Tensor::scale(output) - Tensor::scale(input)) <= 1.0e-6);
43     LUCI_INTERPRETER_CHECK(Tensor::zero_point(output) == Tensor::zero_point(input));
44   }
45   else if (Tensor::element_type(input) == DataType::S16)
46   {
47     LUCI_INTERPRETER_CHECK(std::abs(Tensor::scale(output) - Tensor::scale(input)) <= 1.0e-6);
48     LUCI_INTERPRETER_CHECK(Tensor::zero_point(input) == 0 && Tensor::zero_point(output) == 0);
49   }
50 #endif // DIS_QUANT
51 }
52
53 void execute_kernel_CircleMaxPool2D(const circle::Operator *cur_op, BaseRuntimeGraph *runtime_graph)
54 {
55   const auto input_index = cur_op->inputs()->operator[](0);
56   const auto output_index = cur_op->outputs()->operator[](0);
57
58   assert(input_index != -1);
59   assert(output_index != -1);
60
61   const auto input = runtime_graph->getCircleTensorByIndex(input_index);
62   auto output = runtime_graph->getCircleTensorByIndex(output_index);
63
64   const auto *options = cur_op->builtin_options_as_Pool2DOptions();
65
66   const int32_t input_height = Tensor::dim(input, 1);
67   const int32_t input_width = Tensor::dim(input, 2);
68
69   const int32_t output_height = kernels::computeOutputSize(
70     luci_padding(options->padding()), input_height, options->filter_height(), options->stride_h());
71   const int32_t output_width = kernels::computeOutputSize(
72     luci_padding(options->padding()), input_width, options->filter_width(), options->stride_w());
73
74   const auto padding_height = kernels::computePadding(options->stride_h(), 1, input_height,
75                                                       options->filter_height(), output_height);
76   const auto padding_width = kernels::computePadding(options->stride_w(), 1, input_width,
77                                                      options->filter_width(), output_width);
78
79   const auto *input_data = runtime_graph->getDataByTensor(input);
80   auto *output_data = runtime_graph->getDataByTensor(output);
81
82   float activation_min{};
83   float activation_max{};
84   kernels::calculateActivationRange(luci_actfunc(options->fused_activation_function()),
85                                     &activation_min, &activation_max);
86   luci_interpreter_pal::PoolParams params{};
87   params.padding_values.height = padding_height;
88   params.padding_values.width = padding_width;
89   params.stride_height = options->stride_h();
90   params.stride_width = options->stride_w();
91   params.filter_height = options->filter_height();
92   params.filter_width = options->filter_width();
93   params.float_activation_min = activation_min;
94   params.float_activation_max = activation_max;
95
96   switch (Tensor::element_type(input))
97   {
98 #ifndef DIS_FLOAT
99     case DataType::FLOAT32:
100       luci_interpreter_pal::MaxPool(
101         params, kernels::getTensorShape(input), kernels::getTensorData<float>(input_data),
102         kernels::getTensorShape(output), kernels::getTensorData<float>(output_data));
103       break;
104 #endif // DIS_FLOAT
105 #ifndef DIS_QUANT
106     case DataType::U8:
107       luci_interpreter_pal::MaxPool(
108         params, kernels::getTensorShape(input), kernels::getTensorData<uint8_t>(input_data),
109         kernels::getTensorShape(output), kernels::getTensorData<uint8_t>(output_data));
110       break;
111     case DataType::S16:
112       luci_interpreter_pal::MaxPool(
113         params, kernels::getTensorShape(input), kernels::getTensorData<int16_t>(input_data),
114         kernels::getTensorShape(output), kernels::getTensorData<int16_t>(output_data));
115       break;
116 #endif // DIS_QUANT
117     default:
118       assert(false && "Unsupported type.");
119   }
120 }
121
122 } // namespace luci_interpreter