Imported Upstream version 1.8.0
[platform/core/ml/nnfw.git] / runtime / onert / backend / cpu / ops / OperationUtils.h
1 /*
2  * Copyright (c) 2018 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 #ifndef __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__
18 #define __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__
19
20 #include <backend/IPortableTensor.h>
21
22 #include <cker/Shape.h>
23 #include <cker/Types.h>
24 #include <iostream>
25 #include <ir/DataType.h>
26 #include <ir/InternalType.h>
27 #include <ir/Operand.h>
28 #include <ir/Padding.h>
29
30 #include <limits>
31 #include <vector>
32
33 using OperandType = onert::ir::DataType;
34
35 namespace onert
36 {
37 namespace backend
38 {
39 namespace cpu
40 {
41 namespace ops
42 {
43
44 union DataPtr {
45   uint8_t *u8;
46   int8_t *i8;
47   uint32_t *u32;
48   int32_t *i32;
49   bool *b;
50   float *f;
51   int64_t *i64;
52   void *v;
53 };
54
55 union ConstDataPtr {
56   const uint8_t *u8;
57   const int8_t *i8;
58   const uint32_t *u32;
59   const int32_t *i32;
60   const bool *b;
61   const float *f;
62   const int64_t *i64;
63   const void *v;
64 };
65
66 uint32_t getNumberOfDimensions(const IPortableTensor *tensor);
67
68 uint32_t getNumberOfElements(const IPortableTensor *tensor);
69
70 uint32_t getSizeOfDimension(const IPortableTensor *tensor, uint32_t dimensionIdx);
71
72 inline nnfw::cker::Shape getExtendedTensorShape(const IPortableTensor *tensor)
73 {
74   assert(tensor);
75   const int32_t extended_rank = 4;
76   int32_t raw_shape[extended_rank];
77   uint32_t src = extended_rank - tensor->num_dimensions();
78   for (uint32_t i = 0; i < extended_rank; ++i)
79   {
80     if (i < src)
81     {
82       raw_shape[i] = 1;
83     }
84     else
85     {
86       raw_shape[i] = tensor->dimension(i - src);
87     }
88   }
89
90   return nnfw::cker::Shape(extended_rank, raw_shape);
91 }
92
93 inline nnfw::cker::Shape getTensorShape(const IPortableTensor *tensor)
94 {
95   if (tensor == nullptr)
96     return nnfw::cker::Shape();
97
98   assert(tensor->layout() == ir::Layout::NHWC);
99   constexpr int kMaxSmallSize = 8;
100   int32_t raw_shape_small[kMaxSmallSize];
101   std::vector<int32_t> raw_shape_vec;
102   auto rank = tensor->num_dimensions();
103   int32_t *data = nullptr;
104   if (rank > kMaxSmallSize)
105   {
106     raw_shape_vec.resize(rank);
107     data = raw_shape_vec.data();
108   }
109   else
110   {
111     data = raw_shape_small;
112   }
113
114   for (uint32_t i = 0; i < rank; ++i)
115   {
116     data[i] = tensor->dimension(i);
117   }
118   return nnfw::cker::Shape(rank, data);
119 }
120
121 inline nnfw::cker::FusedActivationFunctionType
122 convertActivationType(const ir::Activation activation)
123 {
124   switch (activation)
125   {
126     case ir::Activation::NONE:
127       return nnfw::cker::FusedActivationFunctionType::kNone;
128     case ir::Activation::RELU:
129       return nnfw::cker::FusedActivationFunctionType::kRelu;
130     case ir::Activation::RELU1:
131       return nnfw::cker::FusedActivationFunctionType::kRelu1;
132     case ir::Activation::RELU6:
133       return nnfw::cker::FusedActivationFunctionType::kRelu6;
134     default:
135       throw std::runtime_error{"CPU backend: Cannot convert activation type"};
136   }
137 }
138
139 inline int32_t getAxis(uint32_t rank, int32_t axis, ir::Layout frontend_layout)
140 {
141   auto ret = axis;
142
143   if (axis < 0)
144   {
145     ret += rank;
146   }
147
148   // NCHW -> NHWC
149   if (frontend_layout == ir::Layout::NCHW)
150   {
151     int32_t permutation[4] = {0, 3, 1, 2};
152     ret = permutation[ret];
153   }
154
155   return ret;
156 }
157
158 void QuantizeMultiplier(double double_multiplier, int32_t *quantized_multiplier, int *shift);
159
160 void GetQuantizedConvolutionMultiplier(const IPortableTensor *inputDescr,
161                                        const IPortableTensor *filterDescr,
162                                        const IPortableTensor *biasDescr,
163                                        const IPortableTensor *outputDescr, double *multiplier);
164
165 void QuantizeMultiplierGreaterThanOne(double double_multiplier, int32_t *quantized_multiplier,
166                                       int *left_shift);
167
168 template <typename T>
169 void CalculateActivationRange(ir::Activation activation, T *activation_min, T *activation_max)
170 {
171   if (activation == ir::Activation::RELU)
172   {
173     *activation_min = 0;
174     *activation_max = std::numeric_limits<T>::max();
175   }
176   else if (activation == ir::Activation::RELU6)
177   {
178     *activation_min = 0;
179     *activation_max = 6;
180   }
181   else if (activation == ir::Activation::RELU1)
182   {
183     *activation_min = -1;
184     *activation_max = 1;
185   }
186   else if (activation == ir::Activation::SIGMOID)
187   {
188     *activation_min = 0;
189     *activation_max = 1;
190   }
191   else if (activation == ir::Activation::NONE)
192   {
193     *activation_min = std::numeric_limits<T>::lowest();
194     *activation_max = std::numeric_limits<T>::max();
195   }
196   else
197   {
198     std::cout << "Unsupported fused activation function." << std::endl;
199   }
200 }
201
202 void CalculateActivationRangeUint8(ir::Activation activation, const IPortableTensor *output,
203                                    int32_t *act_min, int32_t *act_max);
204
205 bool HaveSameShapes(const IPortableTensor *input1, const IPortableTensor *input2);
206
207 int32_t CalculateInputRadius(int input_integer_bits, int input_left_shift);
208
209 uint32_t sizeOfData(OperandType type, const std::vector<int32_t> &dimensions);
210
211 nnfw::cker::PaddingType getPaddingType(ir::PaddingType ir_padding_type);
212
213 std::vector<int32_t> getReducerAxes(const IPortableTensor *axes);
214
215 } // namespace ops
216 } // namespace cpu
217 } // namespace backend
218 } // namespace onert
219
220 #endif // __NNFW_SUPPORT_NNAPI_OPERATION_UTILS_H__