2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All Rights Reserved
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
17 #include "ElementwiseUnaryLayer.h"
19 #include "OperationUtils.h"
21 #include <cker/operation/Dequantize.h>
22 #include <cker/operation/Elementwise.h>
23 #include <cker/operation/Erf.h>
24 #include <cker/operation/Exp.h>
25 #include <cker/operation/LogicalNot.h>
26 #include <cker/operation/Quantize.h>
27 #include <cker/operation/Round.h>
40 void absFloat32(const IPortableTensor *input, IPortableTensor *output)
42 nnfw::cker::Abs(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
43 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
46 template <typename FromT>
47 void castPtr(const FromT *in, DataPtr out, int num_elements, ir::DataType data_type_out)
49 switch (data_type_out)
51 case ir::DataType::FLOAT32:
52 std::transform(in, in + num_elements, out.f, [](FromT a) { return static_cast<float>(a); });
54 case ir::DataType::INT32:
55 std::transform(in, in + num_elements, out.i32,
56 [](FromT a) { return static_cast<int32_t>(a); });
58 case ir::DataType::UINT32:
59 std::transform(in, in + num_elements, out.u32,
60 [](FromT a) { return static_cast<uint32_t>(a); });
62 case ir::DataType::UINT8:
63 std::transform(in, in + num_elements, out.u8,
64 [](FromT a) { return static_cast<uint8_t>(a); });
66 case ir::DataType::BOOL8:
67 std::transform(in, in + num_elements, out.b, [](FromT a) { return static_cast<bool>(a); });
69 case ir::DataType::INT64:
70 std::transform(in, in + num_elements, out.i64,
71 [](FromT a) { return static_cast<int64_t>(a); });
74 throw std::runtime_error("Cast: Not supported output type" +
75 std::to_string((int)data_type_out));
79 void cast(const IPortableTensor *input, IPortableTensor *output)
81 auto input_buf = input->buffer();
82 auto output_buf = output->buffer();
83 const auto in = *reinterpret_cast<const DataPtr *>(&input_buf);
84 auto out = *reinterpret_cast<DataPtr *>(&output_buf);
86 auto input_shape = getTensorShape(input);
87 auto output_shape = getTensorShape(output);
88 const auto num_elements = MatchingFlatSize(input_shape, output_shape);
90 switch (input->data_type())
92 case ir::DataType::FLOAT32:
93 castPtr(in.f, out, num_elements, output->data_type());
95 case ir::DataType::INT32:
96 castPtr(in.i32, out, num_elements, output->data_type());
98 case ir::DataType::UINT32:
99 castPtr(in.u32, out, num_elements, output->data_type());
101 case ir::DataType::UINT8:
102 castPtr(in.u8, out, num_elements, output->data_type());
104 case ir::DataType::BOOL8:
105 castPtr(in.b, out, num_elements, output->data_type());
107 case ir::DataType::INT64:
108 castPtr(in.i64, out, num_elements, output->data_type());
111 throw std::runtime_error("Cast: unsupported data type" +
112 std::to_string((int)input->data_type()));
116 void cosFloat32(const IPortableTensor *input, IPortableTensor *output)
118 nnfw::cker::Cos(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
119 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
122 void dequantizeInt8(const IPortableTensor *input, IPortableTensor *output)
124 nnfw::cker::Dequantize(getTensorShape(input), reinterpret_cast<const int8_t *>(input->buffer()),
125 getTensorShape(output), reinterpret_cast<float *>(output->buffer()),
126 input->data_scale(), input->data_offset());
129 void dequantizeUint8(const IPortableTensor *input, IPortableTensor *output)
131 nnfw::cker::Dequantize(getTensorShape(input), reinterpret_cast<const uint8_t *>(input->buffer()),
132 getTensorShape(output), reinterpret_cast<float *>(output->buffer()),
133 input->data_scale(), input->data_offset());
136 void expFloat32(const IPortableTensor *input, IPortableTensor *output)
138 nnfw::cker::Exp(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
139 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
142 void erfFloat32(const IPortableTensor *input, IPortableTensor *output)
144 nnfw::cker::Erf(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
145 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
148 void floorFloat32(const IPortableTensor *input, IPortableTensor *output)
150 nnfw::cker::Floor(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
151 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
154 void logFloat32(const IPortableTensor *input, IPortableTensor *output)
156 nnfw::cker::Log(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
157 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
160 void logicalNot(const IPortableTensor *input, IPortableTensor *output)
162 nnfw::cker::LogicalNot(getTensorShape(input), reinterpret_cast<const bool *>(input->buffer()),
163 getTensorShape(output), reinterpret_cast<bool *>(output->buffer()));
166 template <typename T> void neg(const IPortableTensor *input, IPortableTensor *output)
168 nnfw::cker::Neg<T>(getTensorShape(input), reinterpret_cast<const T *>(input->buffer()),
169 getTensorShape(output), reinterpret_cast<T *>(output->buffer()));
172 template <typename InputT, typename OutputT>
173 void affineQuantize(const IPortableTensor *input, IPortableTensor *output)
175 nnfw::cker::Quantize(getTensorShape(input), reinterpret_cast<const InputT *>(input->buffer()),
176 getTensorShape(output), reinterpret_cast<OutputT *>(output->buffer()),
177 output->data_scale(), output->data_offset());
180 void roundFloat32(const IPortableTensor *input, IPortableTensor *output)
182 nnfw::cker::Round(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
183 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
186 void rsqrtFloat32(const IPortableTensor *input, IPortableTensor *output)
188 nnfw::cker::Rsqrt(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
189 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
192 void sinFloat32(const IPortableTensor *input, IPortableTensor *output)
194 nnfw::cker::Sin(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
195 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
198 void sqrtFloat32(const IPortableTensor *input, IPortableTensor *output)
200 nnfw::cker::Sqrt(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
201 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
204 void squareFloat32(const IPortableTensor *input, IPortableTensor *output)
206 nnfw::cker::Square(getTensorShape(input), reinterpret_cast<const float *>(input->buffer()),
207 getTensorShape(output), reinterpret_cast<float *>(output->buffer()));
210 template <typename T> void zerosLikeFloat32(const IPortableTensor *input, IPortableTensor *output)
212 if (!HaveSameShapes(input, output))
213 throw std::runtime_error{"ZerosLike: input and output shape don't match."};
215 auto element_size = getTensorShape(input).FlatSize();
217 memset(reinterpret_cast<T *>(output->buffer()), 0, element_size * sizeof(T));
221 void ElementwiseUnaryLayer::configure(const IPortableTensor *input, IPortableTensor *output,
222 const ElementwiseUnaryType op_type)
224 assert(input != nullptr);
225 assert(output != nullptr);
232 case ElementwiseUnaryType::kAbs:
233 if ((input->data_type() == OperandType::FLOAT32))
235 _kernel = absFloat32;
239 throw std::runtime_error{"Abs: Unsupported data type"};
242 case ElementwiseUnaryType::kCast:
245 case ElementwiseUnaryType::kCos:
246 if ((input->data_type() == OperandType::FLOAT32))
248 _kernel = cosFloat32;
252 throw std::runtime_error{"Cos: Unsupported data type"};
255 case ElementwiseUnaryType::kDequantize:
256 if ((input->data_type() == OperandType::QUANT_UINT8_ASYMM))
258 _kernel = dequantizeUint8;
260 else if ((input->data_type() == OperandType::QUANT_INT8_ASYMM) ||
261 (input->data_type() == OperandType::QUANT_INT8_SYMM))
263 _kernel = dequantizeInt8;
267 throw std::runtime_error{"Dequantize: Unsupported data type"};
270 case ElementwiseUnaryType::kExp:
271 if ((input->data_type() == OperandType::FLOAT32))
273 _kernel = expFloat32;
277 throw std::runtime_error{"Exp: Unsupported data type"};
280 case ElementwiseUnaryType::kErf:
281 if ((input->data_type() == OperandType::FLOAT32))
283 _kernel = erfFloat32;
287 throw std::runtime_error{"Exp: Unsupported data type"};
290 case ElementwiseUnaryType::kFloor:
291 if ((input->data_type() == OperandType::FLOAT32))
293 _kernel = floorFloat32;
297 throw std::runtime_error{"Floor: Unsupported data type"};
300 case ElementwiseUnaryType::kLog:
301 if ((input->data_type() == OperandType::FLOAT32))
303 _kernel = logFloat32;
307 throw std::runtime_error{"Log: Unsupported data type"};
310 case ElementwiseUnaryType::kLogicalNot:
311 if ((input->data_type() == OperandType::BOOL8))
313 _kernel = logicalNot;
317 throw std::runtime_error{"LogicalNot: Unsupported data type"};
320 case ElementwiseUnaryType::kNeg:
321 if ((input->data_type() == OperandType::FLOAT32))
323 _kernel = neg<float>;
325 else if ((input->data_type() == OperandType::INT64))
327 _kernel = neg<int64_t>;
329 else if ((input->data_type() == OperandType::INT32))
331 _kernel = neg<int32_t>;
335 throw std::runtime_error{"Neg: Unsupported data type"};
338 case ElementwiseUnaryType::kQuantize:
339 if ((input->data_type() == OperandType::FLOAT32))
341 _kernel = affineQuantize<float, uint8_t>;
345 throw std::runtime_error{"Quantize: Unsupported data type"};
348 case ElementwiseUnaryType::kRound:
349 if ((input->data_type() == OperandType::FLOAT32))
351 _kernel = roundFloat32;
355 throw std::runtime_error{"Round: Unsupported data type"};
358 case ElementwiseUnaryType::kRSqrt:
359 if ((input->data_type() == OperandType::FLOAT32))
361 _kernel = rsqrtFloat32;
365 throw std::runtime_error{"RSqrt: Unsupported data type"};
368 case ElementwiseUnaryType::kSin:
369 if ((input->data_type() == OperandType::FLOAT32))
371 _kernel = sinFloat32;
375 throw std::runtime_error{"Sin: Unsupported data type"};
378 case ElementwiseUnaryType::kSqrt:
379 if ((input->data_type() == OperandType::FLOAT32))
381 _kernel = sqrtFloat32;
385 throw std::runtime_error{"Sqrt: Unsupported data type"};
388 case ElementwiseUnaryType::kSquare:
389 if ((input->data_type() == OperandType::FLOAT32))
391 _kernel = squareFloat32;
395 throw std::runtime_error{"Square: Unsupported data type"};
398 case ElementwiseUnaryType::kZerosLike:
399 if (input->data_type() == OperandType::FLOAT32)
401 _kernel = zerosLikeFloat32<float>;
403 else if (input->data_type() == OperandType::INT32)
405 _kernel = zerosLikeFloat32<int32_t>;
409 throw std::runtime_error{"ZerosLike: Unsupported data type"};
413 throw std::runtime_error{"ElementwiseBinary: Unsupported ElementwiseBinary type"};
417 void ElementwiseUnaryLayer::run() { _kernel(_input, _output); }
421 } // namespace backend