Imported Upstream version 1.9.0
[platform/core/ml/nnfw.git] / runtime / onert / backend / cpu / ops / ElementwiseUnaryLayer.cc
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 "ElementwiseUnaryLayer.h"
18
19 #include "OperationUtils.h"
20
21 #include <cker/operation/Elementwise.h>
22 #include <cker/operation/Erf.h>
23 #include <cker/operation/Exp.h>
24 #include <cker/operation/LogicalNot.h>
25 #include <cker/operation/Quantize.h>
26 #include <cker/operation/Round.h>
27
28 namespace onert
29 {
30 namespace backend
31 {
32 namespace cpu
33 {
34 namespace ops
35 {
36
37 namespace
38 {
39 void absFloat32(const IPortableTensor *input, IPortableTensor *output)
40 {
41   nnfw::cker::Abs(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
42                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
43 }
44
45 template <typename FromT>
46 void castPtr(const FromT *in, DataPtr out, int num_elements, ir::DataType data_type_out)
47 {
48   switch (data_type_out)
49   {
50     case ir::DataType::FLOAT32:
51       std::transform(in, in + num_elements, out.f, [](FromT a) { return static_cast<float>(a); });
52       return;
53     case ir::DataType::INT32:
54       std::transform(in, in + num_elements, out.i32,
55                      [](FromT a) { return static_cast<int32_t>(a); });
56       return;
57     case ir::DataType::UINT32:
58       std::transform(in, in + num_elements, out.u32,
59                      [](FromT a) { return static_cast<uint32_t>(a); });
60       return;
61     case ir::DataType::UINT8:
62       std::transform(in, in + num_elements, out.u8,
63                      [](FromT a) { return static_cast<uint8_t>(a); });
64       return;
65     case ir::DataType::BOOL8:
66       std::transform(in, in + num_elements, out.b, [](FromT a) { return static_cast<bool>(a); });
67       return;
68     case ir::DataType::INT64:
69       std::transform(in, in + num_elements, out.i64,
70                      [](FromT a) { return static_cast<int64_t>(a); });
71       return;
72     default:
73       throw std::runtime_error("Cast: Not supported output type" +
74                                std::to_string((int)data_type_out));
75   }
76 }
77
78 void cast(const IPortableTensor *input, IPortableTensor *output)
79 {
80   auto input_buf = input->buffer();
81   auto output_buf = output->buffer();
82   const auto in = *reinterpret_cast<const DataPtr *>(&input_buf);
83   auto out = *reinterpret_cast<DataPtr *>(&output_buf);
84
85   auto input_shape = getTensorShape(input);
86   auto output_shape = getTensorShape(output);
87   const auto num_elements = MatchingFlatSize(input_shape, output_shape);
88
89   switch (input->data_type())
90   {
91     case ir::DataType::FLOAT32:
92       castPtr(in.f, out, num_elements, output->data_type());
93       return;
94     case ir::DataType::INT32:
95       castPtr(in.i32, out, num_elements, output->data_type());
96       return;
97     case ir::DataType::UINT32:
98       castPtr(in.u32, out, num_elements, output->data_type());
99       return;
100     case ir::DataType::UINT8:
101       castPtr(in.u8, out, num_elements, output->data_type());
102       return;
103     case ir::DataType::BOOL8:
104       castPtr(in.b, out, num_elements, output->data_type());
105       return;
106     case ir::DataType::INT64:
107       castPtr(in.i64, out, num_elements, output->data_type());
108       return;
109     default:
110       throw std::runtime_error("Cast: unsupported data type" +
111                                std::to_string((int)input->data_type()));
112   }
113 }
114
115 void cosFloat32(const IPortableTensor *input, IPortableTensor *output)
116 {
117   nnfw::cker::Cos(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
118                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
119 }
120
121 void expFloat32(const IPortableTensor *input, IPortableTensor *output)
122 {
123   nnfw::cker::Exp(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
124                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
125 }
126
127 void erfFloat32(const IPortableTensor *input, IPortableTensor *output)
128 {
129   nnfw::cker::Erf(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
130                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
131 }
132
133 void logFloat32(const IPortableTensor *input, IPortableTensor *output)
134 {
135   nnfw::cker::Log(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
136                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
137 }
138
139 void logicalNot(const IPortableTensor *input, IPortableTensor *output)
140 {
141   nnfw::cker::LogicalNot(getTensorShape(input), reinterpret_cast<const bool *>(input->buffer()),
142                          getTensorShape(output), reinterpret_cast<bool *>(output->buffer()));
143 }
144
145 void negFloat32(const IPortableTensor *input, IPortableTensor *output)
146 {
147   nnfw::cker::Neg(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
148                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
149 }
150
151 template <typename InputT, typename OutputT>
152 void affineQuantize(const IPortableTensor *input, IPortableTensor *output)
153 {
154   nnfw::cker::Quantize(getTensorShape(input), reinterpret_cast<const InputT *>(input->buffer()),
155                        getTensorShape(output), reinterpret_cast<OutputT *>(output->buffer()),
156                        output->data_scale(), output->data_offset());
157 }
158
159 void roundFloat32(const IPortableTensor *input, IPortableTensor *output)
160 {
161   nnfw::cker::Round(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
162                     getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
163 }
164
165 void rsqrtFloat32(const IPortableTensor *input, IPortableTensor *output)
166 {
167   nnfw::cker::Rsqrt(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
168                     getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
169 }
170
171 void sinFloat32(const IPortableTensor *input, IPortableTensor *output)
172 {
173   nnfw::cker::Sin(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
174                   getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
175 }
176
177 template <typename T> void zerosLikeFloat32(const IPortableTensor *input, IPortableTensor *output)
178 {
179   if (!HaveSameShapes(input, output))
180     throw std::runtime_error{"ZerosLike: input and output shape don't match."};
181
182   auto element_size = getTensorShape(input).FlatSize();
183
184   memset(reinterpret_cast<T *>(output->buffer()), 0, element_size * sizeof(T));
185 }
186 } // namespace
187
188 void ElementwiseUnaryLayer::configure(const IPortableTensor *input, IPortableTensor *output,
189                                       const ElementwiseUnaryType op_type)
190 {
191   assert(input != nullptr);
192   assert(output != nullptr);
193
194   _input = input;
195   _output = output;
196
197   switch (op_type)
198   {
199     case ElementwiseUnaryType::kAbs:
200       if ((input->data_type() == OperandType::FLOAT32))
201       {
202         _kernel = absFloat32;
203       }
204       else
205       {
206         throw std::runtime_error{"Abs: Unsupported data type"};
207       }
208       break;
209     case ElementwiseUnaryType::kCast:
210       _kernel = cast;
211       break;
212     case ElementwiseUnaryType::kCos:
213       if ((input->data_type() == OperandType::FLOAT32))
214       {
215         _kernel = cosFloat32;
216       }
217       else
218       {
219         throw std::runtime_error{"Cos: Unsupported data type"};
220       }
221       break;
222     case ElementwiseUnaryType::kExp:
223       if ((input->data_type() == OperandType::FLOAT32))
224       {
225         _kernel = expFloat32;
226       }
227       else
228       {
229         throw std::runtime_error{"Exp: Unsupported data type"};
230       }
231       break;
232     case ElementwiseUnaryType::kErf:
233       if ((input->data_type() == OperandType::FLOAT32))
234       {
235         _kernel = erfFloat32;
236       }
237       else
238       {
239         throw std::runtime_error{"Exp: Unsupported data type"};
240       }
241       break;
242     case ElementwiseUnaryType::kLog:
243       if ((input->data_type() == OperandType::FLOAT32))
244       {
245         _kernel = logFloat32;
246       }
247       else
248       {
249         throw std::runtime_error{"Log: Unsupported  data type"};
250       }
251       break;
252     case ElementwiseUnaryType::kLogicalNot:
253       if ((input->data_type() == OperandType::BOOL8))
254       {
255         _kernel = logicalNot;
256       }
257       else
258       {
259         throw std::runtime_error{"LogicalNot: Unsupported  data type"};
260       }
261       break;
262     case ElementwiseUnaryType::kNeg:
263       if ((input->data_type() == OperandType::FLOAT32))
264       {
265         _kernel = negFloat32;
266       }
267       else
268       {
269         throw std::runtime_error{"Neg: Unsupported  data type"};
270       }
271       break;
272     case ElementwiseUnaryType::kQuantize:
273       if ((input->data_type() == OperandType::FLOAT32))
274       {
275         _kernel = affineQuantize<float, uint8_t>;
276       }
277       else
278       {
279         throw std::runtime_error{"Quantize: Unsupported  data type"};
280       }
281       break;
282     case ElementwiseUnaryType::kRound:
283       if ((input->data_type() == OperandType::FLOAT32))
284       {
285         _kernel = roundFloat32;
286       }
287       else
288       {
289         throw std::runtime_error{"Round: Unsupported  data type"};
290       }
291       break;
292     case ElementwiseUnaryType::kRSqrt:
293       if ((input->data_type() == OperandType::FLOAT32))
294       {
295         _kernel = rsqrtFloat32;
296       }
297       else
298       {
299         throw std::runtime_error{"RSqrt: Unsupported  data type"};
300       }
301       break;
302     case ElementwiseUnaryType::kSin:
303       if ((input->data_type() == OperandType::FLOAT32))
304       {
305         _kernel = sinFloat32;
306       }
307       else
308       {
309         throw std::runtime_error{"Sin: Unsupported  data type"};
310       }
311       break;
312     case ElementwiseUnaryType::kZerosLike:
313       if (input->data_type() == OperandType::FLOAT32)
314       {
315         _kernel = zerosLikeFloat32<float>;
316       }
317       else if (input->data_type() == OperandType::INT32)
318       {
319         _kernel = zerosLikeFloat32<int32_t>;
320       }
321       else
322       {
323         throw std::runtime_error{"ZerosLike: Unsupported data type"};
324       }
325       break;
326     default:
327       throw std::runtime_error{"ElementwiseBinary: Unsupported ElementwiseBinary type"};
328   }
329 }
330
331 void ElementwiseUnaryLayer::run() { _kernel(_input, _output); }
332
333 } // namespace ops
334 } // namespace cpu
335 } // namespace backend
336 } // namespace onert