Imported Upstream version 1.18.0
[platform/core/ml/nnfw.git] / compiler / luci-interpreter / src / kernels / AveragePool2D.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 "kernels/AveragePool2D.h"
18
19 #include "kernels/Utils.h"
20
21 #include <tensorflow/lite/kernels/internal/reference/integer_ops/pooling.h>
22 #include <tensorflow/lite/kernels/internal/reference/pooling.h>
23
24 #include <stdexcept>
25
26 namespace luci_interpreter
27 {
28
29 namespace kernels
30 {
31
32 AveragePool2D::AveragePool2D(const Tensor *input, Tensor *output, const Pool2DParams &params)
33   : KernelWithParams<Pool2DParams>({input}, {output}, params)
34 {
35 }
36
37 void AveragePool2D::configure()
38 {
39   if (input()->element_type() != output()->element_type())
40   {
41     throw std::runtime_error("Input Tensor and Output Tensor Type must be same");
42   }
43   if (input()->shape().num_dims() != 4)
44   {
45     throw std::runtime_error("Input Tensor Shape must be 4-D");
46   }
47   const Shape &input_shape = input()->shape();
48
49   const int32_t batches = input_shape.dim(0);
50   const int32_t input_height = input_shape.dim(1);
51   const int32_t input_width = input_shape.dim(2);
52   const int32_t depth = input_shape.dim(3);
53
54   const int32_t output_height =
55     computeOutputSize(_params.padding, input_height, _params.filter_height, _params.stride_height);
56   const int32_t output_width =
57     computeOutputSize(_params.padding, input_width, _params.filter_width, _params.stride_width);
58
59   _padding_height =
60     computePadding(_params.stride_height, 1, input_height, _params.filter_height, output_height);
61   _padding_width =
62     computePadding(_params.stride_width, 1, input_width, _params.filter_width, output_width);
63   if (input()->element_type() == DataType::U8)
64   {
65     LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
66     LUCI_INTERPRETER_CHECK(output()->zero_point() == input()->zero_point());
67   }
68   else if (input()->element_type() == DataType::S16)
69   {
70     LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
71     LUCI_INTERPRETER_CHECK(input()->zero_point() == 0 && output()->zero_point() == 0);
72   }
73   else if (input()->element_type() == DataType::S8)
74   {
75     LUCI_INTERPRETER_CHECK(std::abs(output()->scale() - input()->scale()) <= 1.0e-6);
76     LUCI_INTERPRETER_CHECK(output()->zero_point() == input()->zero_point());
77   }
78   output()->resize({batches, output_height, output_width, depth});
79 }
80
81 void AveragePool2D::execute() const
82 {
83   switch (input()->element_type())
84   {
85     case DataType::FLOAT32:
86       evalFloat();
87       break;
88     case DataType::U8:
89       evalQuantized();
90       break;
91     case DataType::S16:
92       evalSInt16();
93       break;
94     case DataType::S8:
95       evalSInt8();
96       break;
97     default:
98       throw std::runtime_error("Unsupported type.");
99   }
100 }
101
102 void AveragePool2D::evalFloat() const
103 {
104   float activation_min{};
105   float activation_max{};
106   calculateActivationRange(_params.activation, &activation_min, &activation_max);
107
108   tflite::PoolParams params{};
109   params.padding_values.height = _padding_height;
110   params.padding_values.width = _padding_width;
111   params.stride_height = _params.stride_height;
112   params.stride_width = _params.stride_width;
113   params.filter_height = _params.filter_height;
114   params.filter_width = _params.filter_width;
115   params.float_activation_min = activation_min;
116   params.float_activation_max = activation_max;
117
118   tflite::reference_ops::AveragePool(params, getTensorShape(input()), getTensorData<float>(input()),
119                                      getTensorShape(output()), getTensorData<float>(output()));
120 }
121
122 void AveragePool2D::evalQuantized() const
123 {
124   int32_t activation_min{};
125   int32_t activation_max{};
126   calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
127
128   tflite::PoolParams params{};
129   params.padding_values.height = _padding_height;
130   params.padding_values.width = _padding_width;
131   params.stride_height = _params.stride_height;
132   params.stride_width = _params.stride_width;
133   params.filter_height = _params.filter_height;
134   params.filter_width = _params.filter_width;
135   params.quantized_activation_min = activation_min;
136   params.quantized_activation_max = activation_max;
137
138   tflite::reference_ops::AveragePool(params, getTensorShape(input()),
139                                      getTensorData<uint8_t>(input()), getTensorShape(output()),
140                                      getTensorData<uint8_t>(output()));
141 }
142
143 void AveragePool2D::evalSInt8() const
144 {
145   int32_t activation_min{};
146   int32_t activation_max{};
147   calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
148   tflite::PoolParams params{};
149   params.padding_values.height = _padding_height;
150   params.padding_values.width = _padding_width;
151   params.stride_height = _params.stride_height;
152   params.stride_width = _params.stride_width;
153   params.filter_height = _params.filter_height;
154   params.filter_width = _params.filter_width;
155   params.quantized_activation_min = activation_min;
156   params.quantized_activation_max = activation_max;
157
158   tflite::reference_integer_ops::AveragePool(
159     params, getTensorShape(input()), getTensorData<int8_t>(input()), getTensorShape(output()),
160     getTensorData<int8_t>(output()));
161 }
162
163 void AveragePool2D::evalSInt16() const
164 {
165   int32_t activation_min{};
166   int32_t activation_max{};
167   calculateActivationRangeQuantized(_params.activation, output(), &activation_min, &activation_max);
168
169   tflite::PoolParams params{};
170   params.padding_values.height = _padding_height;
171   params.padding_values.width = _padding_width;
172   params.stride_height = _params.stride_height;
173   params.stride_width = _params.stride_width;
174   params.filter_height = _params.filter_height;
175   params.filter_width = _params.filter_width;
176   params.quantized_activation_min = activation_min;
177   params.quantized_activation_max = activation_max;
178
179   tflite::reference_integer_ops::AveragePool(
180     params, getTensorShape(input()), getTensorData<int16_t>(input()), //
181     getTensorShape(output()), getTensorData<int16_t>(output()));
182 }
183
184 } // namespace kernels
185 } // namespace luci_interpreter