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 "ElementwiseBinaryLayer.h"
19 #include "OperationUtils.h"
21 #include <cker/operation/LogicalOr.h>
22 #include <cker/operation/MaxMin.h>
36 void logicalOrGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs,
37 IPortableTensor *output)
39 if (!HaveSameShapes(lhs, rhs))
41 nnfw::cker::LogicalOrBroadcast<T>(
42 getTensorShape(lhs), reinterpret_cast<const T *>(lhs->buffer()), getTensorShape(rhs),
43 reinterpret_cast<const T *>(rhs->buffer()), getTensorShape(output),
44 reinterpret_cast<T *>(output->buffer()));
48 nnfw::cker::LogicalOrElementwise<T>(
49 getTensorShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
50 reinterpret_cast<const T *>(rhs->buffer()), reinterpret_cast<T *>(output->buffer()));
55 void maximumGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs, IPortableTensor *output)
57 nnfw::cker::Max<T>(getTensorShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
58 getTensorShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
59 getTensorShape(output), reinterpret_cast<T *>(output->buffer()));
63 void minimumGeneric(const IPortableTensor *lhs, const IPortableTensor *rhs, IPortableTensor *output)
65 nnfw::cker::Min<T>(getTensorShape(lhs), reinterpret_cast<const T *>(lhs->buffer()),
66 getTensorShape(rhs), reinterpret_cast<const T *>(rhs->buffer()),
67 getTensorShape(output), reinterpret_cast<T *>(output->buffer()));
70 bool haveSameQauntInfo(const IPortableTensor *lhs, const IPortableTensor *rhs,
71 const IPortableTensor *output)
73 return (lhs->data_scale() == rhs->data_scale() && lhs->data_scale() == output->data_scale()) &&
74 (lhs->data_offset() == rhs->data_offset() && lhs->data_offset() == output->data_offset());
78 void ElementwiseBinaryLayer::configure(const IPortableTensor *lhs, const IPortableTensor *rhs,
79 IPortableTensor *output, const ElementwiseBinaryType op_type)
81 assert(lhs != nullptr);
82 assert(rhs != nullptr);
83 assert(output != nullptr);
91 case ElementwiseBinaryType::kLogicalOr:
92 if ((_lhs->data_type() == OperandType::BOOL8) && (_rhs->data_type() == OperandType::BOOL8))
94 _kernel = logicalOrGeneric<bool>;
98 throw std::runtime_error{"LogicalOr: Unsupported data type"};
101 case ElementwiseBinaryType::kMax:
102 if (_lhs->data_type() == OperandType::QUANT_UINT8_ASYMM)
104 if (!haveSameQauntInfo(_lhs, _rhs, _output))
106 throw std::runtime_error("Max NYI for quantized");
108 _kernel = maximumGeneric<uint8_t>;
110 else if (_lhs->data_type() == OperandType::FLOAT32)
112 _kernel = maximumGeneric<float>;
116 throw std::runtime_error{"Max: unsupported data type"};
119 case ElementwiseBinaryType::kMin:
120 if (_lhs->data_type() == OperandType::QUANT_UINT8_ASYMM)
122 if (!haveSameQauntInfo(_lhs, _rhs, _output))
124 throw std::runtime_error("Min NYI for quantized");
126 _kernel = minimumGeneric<uint8_t>;
128 else if (_lhs->data_type() == OperandType::INT32)
130 _kernel = minimumGeneric<int32_t>;
132 else if (_lhs->data_type() == OperandType::FLOAT32)
134 _kernel = minimumGeneric<float>;
138 throw std::runtime_error{"Min: unsupported data type"};
142 throw std::runtime_error{"ElementwiseBinary: Unsupported ElementwiseBinary type"};
146 void ElementwiseBinaryLayer::run() { _kernel(_lhs, _rhs, _output); }
150 } // namespace backend