blob: 8ef1e3c5d6c7926b6390ef3cadde59a1900ea65f [file] [log] [blame]
Eric Kunzee5e26762020-10-13 16:11:07 -07001
Kevin Cheng3a478572021-01-22 17:21:02 -08002// Copyright (c) 2020-2021, ARM Limited.
Eric Kunzee5e26762020-10-13 16:11:07 -07003//
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#include "ewise_unary.h"
17#include "quant_util.h"
18#include "template_types.h"
19#include <cmath>
20
21using namespace TosaReference;
22using namespace Eigen;
23using namespace tosa;
24
25template <int Rank, DType Dtype>
Kevin Chengacb550f2021-06-29 15:32:19 -070026UnaryNode<Rank, Dtype>::UnaryNode(SubgraphTraverser* sgt_, const Op& op_, uint64_t id_)
27 : GraphNode(sgt_, op_, id_)
Eric Kunzee5e26762020-10-13 16:11:07 -070028{
29 setRequiredOperands(1, 1);
30 setRequiredRank(0, 6);
31
Eric Kunzeb5fabec2022-06-07 05:20:44 +000032 fcn = [](InEigenType a) -> OutEigenType {
33 ASSERT_MSG(0, "In default UnaryNode function, missing function registration");
34 return OutEigenType();
35 };
Eric Kunzee5e26762020-10-13 16:11:07 -070036}
37
38template <int Rank, DType Dtype>
39UnaryNode<Rank, Dtype>::~UnaryNode()
40{}
41
42template <int Rank, DType Dtype>
43int UnaryNode<Rank, Dtype>::checkTensorAttributes()
44{
45 if (validateRequiredOperands())
46 return 1;
47
48 if (validateRequiredRank(inputs[0]) || validateRequiredRank(outputs[0]))
49 {
50 return 1;
51 }
52
53 // output and input must be the same types
Kevin Chengc72b59c2021-09-29 16:57:55 -070054 if (inputs[0]->matchRankTypeShape(*outputs[0]))
Eric Kunzee5e26762020-10-13 16:11:07 -070055 {
Kevin Chengc72b59c2021-09-29 16:57:55 -070056 printNodeValidationError("UnaryNode: input and output rank/type/shape must match");
Eric Kunzee5e26762020-10-13 16:11:07 -070057 return 1;
58 }
59
60 a = dynamic_cast<TosaReference::TensorTemplate<TIn>*>(inputs[0]);
61 result = dynamic_cast<TosaReference::TensorTemplate<TOut>*>(outputs[0]);
62
63 ASSERT_MEM(a && result);
64
65 return 0;
66}
67
68template <int Rank, DType Dtype>
69int UnaryNode<Rank, Dtype>::eval()
70{
71 this->result->getTensor() = this->a->getTensor().unaryExpr(this->fcn);
72
73 return GraphNode::eval();
74}
75
76template <int Rank, DType Dtype>
77int OpAbs<Rank, Dtype>::register_fcn()
78{
79 switch (Dtype)
80 {
81 case DType_FLOAT:
82 case DType_INT32:
83 this->fcn = [](InEigenType a) -> OutEigenType { return a > (InEigenType)0 ? a : (-a); };
84 break;
85 default:
Kevin Chengacb550f2021-06-29 15:32:19 -070086 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -070087 }
88
89 return 0;
90}
91
92template <int Rank, DType Dtype>
93int OpBitwiseNot<Rank, Dtype>::register_fcn()
94{
95 switch (Dtype)
96 {
Kevin Cheng3a478572021-01-22 17:21:02 -080097 case DType_INT8:
Eric Kunzee5e26762020-10-13 16:11:07 -070098 case DType_INT16:
99 case DType_INT32:
100 this->fcn = [](InEigenType a) -> OutEigenType { return ~a; };
101 break;
102 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700103 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700104 }
105
106 return 0;
107}
108
109template <int Rank, DType Dtype>
110int OpCeil<Rank, Dtype>::register_fcn()
111{
112 switch (Dtype)
113 {
114 case DType_FLOAT:
115 this->fcn = [](InEigenType a) -> OutEigenType { return ceilf(a); };
116 break;
117 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700118 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700119 }
120
121 return 0;
122}
123
124template <int Rank, DType Dtype>
125int OpClz<Rank, Dtype>::register_fcn()
126{
127 int32_t num_bits;
128 switch (Dtype)
129 {
130 case DType_INT32:
131 num_bits = 32;
132 break;
133 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700134 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700135 }
136
137 this->fcn = [num_bits](int32_t a) -> int32_t {
138 int32_t leading_zeros = 0;
139 for (int bit = num_bits - 1; bit >= 0; bit--)
140 {
141 if (((a >> bit) & 0x1) == 0)
142 {
143 leading_zeros++;
144 }
145 else
146 {
147 break;
148 }
149 }
150 return leading_zeros;
151 };
152
153 return 0;
154}
155
156template <int Rank, DType Dtype>
157int OpExp<Rank, Dtype>::register_fcn()
158{
159 switch (Dtype)
160 {
161 case DType_FLOAT:
162 this->fcn = [](InEigenType a) -> OutEigenType { return expf(a); };
163 break;
164 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700165 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700166 }
167
168 return 0;
169}
170
171template <int Rank, DType Dtype>
172int OpFloor<Rank, Dtype>::register_fcn()
173{
174 switch (Dtype)
175 {
176 case DType_FLOAT:
177 this->fcn = [](InEigenType a) -> OutEigenType { return floorf(a); };
178 break;
179 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700180 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700181 }
182
183 return 0;
184}
185
186template <int Rank, DType Dtype>
187int OpLog<Rank, Dtype>::register_fcn()
188{
189 switch (Dtype)
190 {
191 case DType_FLOAT:
192 this->fcn = [](InEigenType a) -> OutEigenType { return logf(a); };
193 break;
194 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700195 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700196 }
197
198 return 0;
199}
200
201template <int Rank, DType Dtype>
202int OpLogicalNot<Rank, Dtype>::register_fcn()
203{
204 switch (Dtype)
205 {
206 case DType_BOOL:
207 this->fcn = [](InEigenType a) -> OutEigenType { return !a; };
208 break;
209 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700210 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700211 }
212
213 return 0;
214}
215
216template <int Rank, DType Dtype>
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000217OpNegate<Rank, Dtype>::OpNegate(SubgraphTraverser* sgt_,
218 TosaAttributeBase* attribute_,
219 uint64_t id_)
220 : UnaryNode<Rank, Dtype>(sgt_, Op_NEGATE, id_)
221{
222 INIT_ATTRIBUTE(Negate);
223
224 register_fcn();
225}
226
227template <int Rank, DType Dtype>
228OpNegate<Rank, Dtype>::~OpNegate()
229{
230 if (attribute)
231 delete attribute;
232}
233
234template <int Rank, DType Dtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700235int OpNegate<Rank, Dtype>::register_fcn()
236{
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000237 ERROR_IF(Dtype != DType_INT8 && attribute->input1_zp() != 0, "OpNegate: zeropoint only for int8_t");
238 ERROR_IF(Dtype != DType_INT8 && attribute->output_zp() != 0, "OpNegate: zeropoint only for int8_t");
Kevin Chengacb550f2021-06-29 15:32:19 -0700239
Eric Kunzee5e26762020-10-13 16:11:07 -0700240 switch (Dtype)
241 {
242 case DType_FLOAT:
243 this->fcn = [](InEigenType a) -> OutEigenType {
244 InEigenType result = -(a);
245 return result;
246 };
247 break;
248 case DType_INT16:
249 case DType_INT32:
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000250 this->fcn = [this](InEigenType a) -> OutEigenType {
251 int64_t res_in_64 = 0L - a;
Jeremy Johnson0e463642022-05-03 12:10:23 +0100252 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
253 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
254 REQUIRE(res_in_64 <= i32_max_in_64 && res_in_64 >= i32_min_in_64, "OpNegate: result not in acc type range (int32)");
255
256 int64_t max_clip_in_64, min_clip_in_64;
257 if (Dtype == DType_INT16)
258 {
259 max_clip_in_64 = static_cast<int64_t>(std::numeric_limits<int16_t>::max());
260 min_clip_in_64 = static_cast<int64_t>(std::numeric_limits<int16_t>::min());
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000261 }
262 else
263 {
Jeremy Johnson0e463642022-05-03 12:10:23 +0100264 max_clip_in_64 = i32_max_in_64;
265 min_clip_in_64 = i32_min_in_64;
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000266 }
Jeremy Johnson0e463642022-05-03 12:10:23 +0100267 return static_cast<InEigenType>(std::min<int64_t>(max_clip_in_64, std::max<int64_t>(min_clip_in_64, res_in_64)));
Eric Kunzee5e26762020-10-13 16:11:07 -0700268 };
269 break;
Kevin Cheng3a478572021-01-22 17:21:02 -0800270 case DType_INT8:
Eric Kunzee5e26762020-10-13 16:11:07 -0700271 this->fcn = [this](InEigenType a) -> OutEigenType {
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000272 int64_t res_in_64 = 0 - (a - attribute->input1_zp());
Jeremy Johnson0e463642022-05-03 12:10:23 +0100273 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
274 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
275 REQUIRE(res_in_64 <= i32_max_in_64 && res_in_64 >= i32_min_in_64, "OpNegate: result not in acc type range (int32)");
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000276 res_in_64 += attribute->output_zp();
Jeremy Johnson0e463642022-05-03 12:10:23 +0100277 InEigenType result = static_cast<InEigenType>(std::min(std::max(res_in_64, static_cast<int64_t>(QMin)), static_cast<int64_t>(QMax)));
Eric Kunzee5e26762020-10-13 16:11:07 -0700278 return result;
279 };
280 break;
281 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700282 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700283 }
284
285 return 0;
286}
287
288template <int Rank, DType Dtype>
289int OpReciprocal<Rank, Dtype>::register_fcn()
290{
291 switch (Dtype)
292 {
293 case DType_FLOAT:
294 this->fcn = [](InEigenType a) -> OutEigenType { return 1.0 / a; };
295 break;
296 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700297 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700298 }
299
300 return 0;
301}
302
303template <int Rank, DType Dtype>
304int OpRsqrt<Rank, Dtype>::register_fcn()
305{
306 switch (Dtype)
307 {
308 case DType_FLOAT:
309 this->fcn = [](InEigenType a) -> OutEigenType { return 1.0 / sqrtf(a); };
310 break;
311 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700312 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700313 }
314
315 return 0;
316}
317
318// template explicit instantiation
319DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, FLOAT);
320DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, INT32);
321
Kevin Cheng3a478572021-01-22 17:21:02 -0800322DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700323DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT16);
324DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT32);
325
326DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpCeil, FLOAT);
327
328DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpClz, INT32);
329
330DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpExp, FLOAT);
331
332DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpFloor, FLOAT);
333
334DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLog, FLOAT);
335
336DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLogicalNot, BOOL);
337
338DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, FLOAT);
Kevin Cheng3a478572021-01-22 17:21:02 -0800339DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700340DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT16);
341DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT32);
342
343DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpRsqrt, FLOAT);
344
345DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpReciprocal, FLOAT);