blob: 8b79e581042793d6600353adb0b82a067022a8e3 [file] [log] [blame]
Eric Kunzee5e26762020-10-13 16:11:07 -07001
James Ward8b390432022-08-12 20:48:56 +01002// Copyright (c) 2020-2022, 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 {
James Ward24dbc422022-10-19 12:20:31 +010081 case DType_FP32: // No fpTrunc for FP32 as it is a no-op
Eric Kunzee5e26762020-10-13 16:11:07 -070082 case DType_INT32:
83 this->fcn = [](InEigenType a) -> OutEigenType { return a > (InEigenType)0 ? a : (-a); };
84 break;
James Ward24dbc422022-10-19 12:20:31 +010085 case DType_FP16:
86 case DType_BF16:
87 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(a > (InEigenType)0 ? a : (-a)); };
88 break;
Eric Kunzee5e26762020-10-13 16:11:07 -070089 default:
Kevin Chengacb550f2021-06-29 15:32:19 -070090 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -070091 }
92
93 return 0;
94}
95
96template <int Rank, DType Dtype>
97int OpBitwiseNot<Rank, Dtype>::register_fcn()
98{
99 switch (Dtype)
100 {
Kevin Cheng3a478572021-01-22 17:21:02 -0800101 case DType_INT8:
Eric Kunzee5e26762020-10-13 16:11:07 -0700102 case DType_INT16:
103 case DType_INT32:
104 this->fcn = [](InEigenType a) -> OutEigenType { return ~a; };
105 break;
106 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700107 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700108 }
109
110 return 0;
111}
112
113template <int Rank, DType Dtype>
114int OpCeil<Rank, Dtype>::register_fcn()
115{
116 switch (Dtype)
117 {
James Ward8b390432022-08-12 20:48:56 +0100118 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100119 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100120 case DType_FP32:
James Ward24dbc422022-10-19 12:20:31 +0100121 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(ceilf(a)); };
Eric Kunzee5e26762020-10-13 16:11:07 -0700122 break;
123 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700124 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700125 }
126
127 return 0;
128}
129
130template <int Rank, DType Dtype>
131int OpClz<Rank, Dtype>::register_fcn()
132{
133 int32_t num_bits;
134 switch (Dtype)
135 {
136 case DType_INT32:
137 num_bits = 32;
138 break;
139 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700140 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700141 }
142
143 this->fcn = [num_bits](int32_t a) -> int32_t {
144 int32_t leading_zeros = 0;
145 for (int bit = num_bits - 1; bit >= 0; bit--)
146 {
147 if (((a >> bit) & 0x1) == 0)
148 {
149 leading_zeros++;
150 }
151 else
152 {
153 break;
154 }
155 }
156 return leading_zeros;
157 };
158
159 return 0;
160}
161
162template <int Rank, DType Dtype>
163int OpExp<Rank, Dtype>::register_fcn()
164{
165 switch (Dtype)
166 {
James Ward8b390432022-08-12 20:48:56 +0100167 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100168 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100169 case DType_FP32:
James Ward24dbc422022-10-19 12:20:31 +0100170 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(expf(a)); };
Eric Kunzee5e26762020-10-13 16:11:07 -0700171 break;
172 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700173 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700174 }
175
176 return 0;
177}
178
179template <int Rank, DType Dtype>
180int OpFloor<Rank, Dtype>::register_fcn()
181{
182 switch (Dtype)
183 {
James Ward8b390432022-08-12 20:48:56 +0100184 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100185 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100186 case DType_FP32:
James Ward24dbc422022-10-19 12:20:31 +0100187 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(floorf(a)); };
Eric Kunzee5e26762020-10-13 16:11:07 -0700188 break;
189 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700190 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700191 }
192
193 return 0;
194}
195
196template <int Rank, DType Dtype>
197int OpLog<Rank, Dtype>::register_fcn()
198{
199 switch (Dtype)
200 {
James Ward8b390432022-08-12 20:48:56 +0100201 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100202 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100203 case DType_FP32:
James Ward24dbc422022-10-19 12:20:31 +0100204 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(logf(a)); };
Eric Kunzee5e26762020-10-13 16:11:07 -0700205 break;
206 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700207 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700208 }
209
210 return 0;
211}
212
213template <int Rank, DType Dtype>
214int OpLogicalNot<Rank, Dtype>::register_fcn()
215{
216 switch (Dtype)
217 {
218 case DType_BOOL:
219 this->fcn = [](InEigenType a) -> OutEigenType { return !a; };
220 break;
221 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700222 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700223 }
224
225 return 0;
226}
227
228template <int Rank, DType Dtype>
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000229OpNegate<Rank, Dtype>::OpNegate(SubgraphTraverser* sgt_,
230 TosaAttributeBase* attribute_,
231 uint64_t id_)
232 : UnaryNode<Rank, Dtype>(sgt_, Op_NEGATE, id_)
233{
234 INIT_ATTRIBUTE(Negate);
235
236 register_fcn();
237}
238
239template <int Rank, DType Dtype>
240OpNegate<Rank, Dtype>::~OpNegate()
241{
242 if (attribute)
243 delete attribute;
244}
245
246template <int Rank, DType Dtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700247int OpNegate<Rank, Dtype>::register_fcn()
248{
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000249 ERROR_IF(Dtype != DType_INT8 && attribute->input1_zp() != 0, "OpNegate: zeropoint only for int8_t");
250 ERROR_IF(Dtype != DType_INT8 && attribute->output_zp() != 0, "OpNegate: zeropoint only for int8_t");
Kevin Chengacb550f2021-06-29 15:32:19 -0700251
Eric Kunzee5e26762020-10-13 16:11:07 -0700252 switch (Dtype)
253 {
James Ward8b390432022-08-12 20:48:56 +0100254 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100255 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100256 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700257 this->fcn = [](InEigenType a) -> OutEigenType {
258 InEigenType result = -(a);
James Ward24dbc422022-10-19 12:20:31 +0100259 return fpTrunc<Dtype>(result);
Eric Kunzee5e26762020-10-13 16:11:07 -0700260 };
261 break;
262 case DType_INT16:
263 case DType_INT32:
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000264 this->fcn = [this](InEigenType a) -> OutEigenType {
265 int64_t res_in_64 = 0L - a;
Jeremy Johnson0e463642022-05-03 12:10:23 +0100266 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
267 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
268 REQUIRE(res_in_64 <= i32_max_in_64 && res_in_64 >= i32_min_in_64, "OpNegate: result not in acc type range (int32)");
269
270 int64_t max_clip_in_64, min_clip_in_64;
271 if (Dtype == DType_INT16)
272 {
273 max_clip_in_64 = static_cast<int64_t>(std::numeric_limits<int16_t>::max());
274 min_clip_in_64 = static_cast<int64_t>(std::numeric_limits<int16_t>::min());
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000275 }
276 else
277 {
Jeremy Johnson0e463642022-05-03 12:10:23 +0100278 max_clip_in_64 = i32_max_in_64;
279 min_clip_in_64 = i32_min_in_64;
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000280 }
Jeremy Johnson0e463642022-05-03 12:10:23 +0100281 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 -0700282 };
283 break;
Kevin Cheng3a478572021-01-22 17:21:02 -0800284 case DType_INT8:
Eric Kunzee5e26762020-10-13 16:11:07 -0700285 this->fcn = [this](InEigenType a) -> OutEigenType {
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000286 int64_t res_in_64 = 0 - (a - attribute->input1_zp());
Jeremy Johnson0e463642022-05-03 12:10:23 +0100287 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
288 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
289 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 +0000290 res_in_64 += attribute->output_zp();
Jeremy Johnson0e463642022-05-03 12:10:23 +0100291 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 -0700292 return result;
293 };
294 break;
295 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700296 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700297 }
298
299 return 0;
300}
301
302template <int Rank, DType Dtype>
303int OpReciprocal<Rank, Dtype>::register_fcn()
304{
305 switch (Dtype)
306 {
James Ward8b390432022-08-12 20:48:56 +0100307 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100308 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100309 case DType_FP32:
James Ward24dbc422022-10-19 12:20:31 +0100310 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(1.0 / a); };
Eric Kunzee5e26762020-10-13 16:11:07 -0700311 break;
312 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700313 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700314 }
315
316 return 0;
317}
318
319template <int Rank, DType Dtype>
320int OpRsqrt<Rank, Dtype>::register_fcn()
321{
322 switch (Dtype)
323 {
James Ward8b390432022-08-12 20:48:56 +0100324 case DType_FP16:
James Ward24dbc422022-10-19 12:20:31 +0100325 case DType_BF16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100326 case DType_FP32:
James Ward24dbc422022-10-19 12:20:31 +0100327 this->fcn = [](InEigenType a) -> OutEigenType { return fpTrunc<Dtype>(1.0 / sqrtf(a)); };
Eric Kunzee5e26762020-10-13 16:11:07 -0700328 break;
329 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700330 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700331 }
332
333 return 0;
334}
335
336// template explicit instantiation
Jared Smolens98c281f2022-12-20 15:09:25 -0800337DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, BOOL);
338DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, FP16);
339DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, BF16);
340DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, FP32);
341DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, INT8);
342DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, INT16);
343DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(UnaryNode, INT32);
344
James Ward8b390432022-08-12 20:48:56 +0100345DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100346DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100347DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700348DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, INT32);
349
Kevin Cheng3a478572021-01-22 17:21:02 -0800350DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700351DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT16);
352DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT32);
353
James Ward8b390432022-08-12 20:48:56 +0100354DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpCeil, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100355DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpCeil, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100356DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpCeil, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700357
358DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpClz, INT32);
359
James Ward8b390432022-08-12 20:48:56 +0100360DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpExp, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100361DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpExp, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100362DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpExp, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700363
James Ward8b390432022-08-12 20:48:56 +0100364DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpFloor, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100365DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpFloor, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100366DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpFloor, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700367
James Ward8b390432022-08-12 20:48:56 +0100368DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLog, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100369DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLog, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100370DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLog, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700371
372DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLogicalNot, BOOL);
373
James Ward8b390432022-08-12 20:48:56 +0100374DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100375DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100376DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, FP32);
Kevin Cheng3a478572021-01-22 17:21:02 -0800377DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700378DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT16);
379DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT32);
380
James Ward8b390432022-08-12 20:48:56 +0100381DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpRsqrt, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100382DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpRsqrt, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100383DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpRsqrt, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700384
James Ward8b390432022-08-12 20:48:56 +0100385DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpReciprocal, FP16);
James Ward24dbc422022-10-19 12:20:31 +0100386DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpReciprocal, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100387DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpReciprocal, FP32);