blob: 00897cc3b093818edca3b2cc2617cfc9b21925f3 [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 {
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +010081 case DType_FP32:
James Ward8b390432022-08-12 20:48:56 +010082 case DType_FP16:
Eric Kunzee5e26762020-10-13 16:11:07 -070083 case DType_INT32:
84 this->fcn = [](InEigenType a) -> OutEigenType { return a > (InEigenType)0 ? a : (-a); };
85 break;
86 default:
Kevin Chengacb550f2021-06-29 15:32:19 -070087 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -070088 }
89
90 return 0;
91}
92
93template <int Rank, DType Dtype>
94int OpBitwiseNot<Rank, Dtype>::register_fcn()
95{
96 switch (Dtype)
97 {
Kevin Cheng3a478572021-01-22 17:21:02 -080098 case DType_INT8:
Eric Kunzee5e26762020-10-13 16:11:07 -070099 case DType_INT16:
100 case DType_INT32:
101 this->fcn = [](InEigenType a) -> OutEigenType { return ~a; };
102 break;
103 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700104 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700105 }
106
107 return 0;
108}
109
110template <int Rank, DType Dtype>
111int OpCeil<Rank, Dtype>::register_fcn()
112{
113 switch (Dtype)
114 {
James Ward8b390432022-08-12 20:48:56 +0100115 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100116 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700117 this->fcn = [](InEigenType a) -> OutEigenType { return ceilf(a); };
118 break;
119 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700120 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700121 }
122
123 return 0;
124}
125
126template <int Rank, DType Dtype>
127int OpClz<Rank, Dtype>::register_fcn()
128{
129 int32_t num_bits;
130 switch (Dtype)
131 {
132 case DType_INT32:
133 num_bits = 32;
134 break;
135 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700136 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700137 }
138
139 this->fcn = [num_bits](int32_t a) -> int32_t {
140 int32_t leading_zeros = 0;
141 for (int bit = num_bits - 1; bit >= 0; bit--)
142 {
143 if (((a >> bit) & 0x1) == 0)
144 {
145 leading_zeros++;
146 }
147 else
148 {
149 break;
150 }
151 }
152 return leading_zeros;
153 };
154
155 return 0;
156}
157
158template <int Rank, DType Dtype>
159int OpExp<Rank, Dtype>::register_fcn()
160{
161 switch (Dtype)
162 {
James Ward8b390432022-08-12 20:48:56 +0100163 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100164 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700165 this->fcn = [](InEigenType a) -> OutEigenType { return expf(a); };
166 break;
167 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700168 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700169 }
170
171 return 0;
172}
173
174template <int Rank, DType Dtype>
175int OpFloor<Rank, Dtype>::register_fcn()
176{
177 switch (Dtype)
178 {
James Ward8b390432022-08-12 20:48:56 +0100179 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100180 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700181 this->fcn = [](InEigenType a) -> OutEigenType { return floorf(a); };
182 break;
183 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700184 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700185 }
186
187 return 0;
188}
189
190template <int Rank, DType Dtype>
191int OpLog<Rank, Dtype>::register_fcn()
192{
193 switch (Dtype)
194 {
James Ward8b390432022-08-12 20:48:56 +0100195 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100196 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700197 this->fcn = [](InEigenType a) -> OutEigenType { return logf(a); };
198 break;
199 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700200 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700201 }
202
203 return 0;
204}
205
206template <int Rank, DType Dtype>
207int OpLogicalNot<Rank, Dtype>::register_fcn()
208{
209 switch (Dtype)
210 {
211 case DType_BOOL:
212 this->fcn = [](InEigenType a) -> OutEigenType { return !a; };
213 break;
214 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700215 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700216 }
217
218 return 0;
219}
220
221template <int Rank, DType Dtype>
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000222OpNegate<Rank, Dtype>::OpNegate(SubgraphTraverser* sgt_,
223 TosaAttributeBase* attribute_,
224 uint64_t id_)
225 : UnaryNode<Rank, Dtype>(sgt_, Op_NEGATE, id_)
226{
227 INIT_ATTRIBUTE(Negate);
228
229 register_fcn();
230}
231
232template <int Rank, DType Dtype>
233OpNegate<Rank, Dtype>::~OpNegate()
234{
235 if (attribute)
236 delete attribute;
237}
238
239template <int Rank, DType Dtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700240int OpNegate<Rank, Dtype>::register_fcn()
241{
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000242 ERROR_IF(Dtype != DType_INT8 && attribute->input1_zp() != 0, "OpNegate: zeropoint only for int8_t");
243 ERROR_IF(Dtype != DType_INT8 && attribute->output_zp() != 0, "OpNegate: zeropoint only for int8_t");
Kevin Chengacb550f2021-06-29 15:32:19 -0700244
Eric Kunzee5e26762020-10-13 16:11:07 -0700245 switch (Dtype)
246 {
James Ward8b390432022-08-12 20:48:56 +0100247 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100248 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700249 this->fcn = [](InEigenType a) -> OutEigenType {
250 InEigenType result = -(a);
251 return result;
252 };
253 break;
254 case DType_INT16:
255 case DType_INT32:
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000256 this->fcn = [this](InEigenType a) -> OutEigenType {
257 int64_t res_in_64 = 0L - a;
Jeremy Johnson0e463642022-05-03 12:10:23 +0100258 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
259 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
260 REQUIRE(res_in_64 <= i32_max_in_64 && res_in_64 >= i32_min_in_64, "OpNegate: result not in acc type range (int32)");
261
262 int64_t max_clip_in_64, min_clip_in_64;
263 if (Dtype == DType_INT16)
264 {
265 max_clip_in_64 = static_cast<int64_t>(std::numeric_limits<int16_t>::max());
266 min_clip_in_64 = static_cast<int64_t>(std::numeric_limits<int16_t>::min());
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000267 }
268 else
269 {
Jeremy Johnson0e463642022-05-03 12:10:23 +0100270 max_clip_in_64 = i32_max_in_64;
271 min_clip_in_64 = i32_min_in_64;
Jeremy Johnson81ee53d2022-03-23 15:32:34 +0000272 }
Jeremy Johnson0e463642022-05-03 12:10:23 +0100273 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 -0700274 };
275 break;
Kevin Cheng3a478572021-01-22 17:21:02 -0800276 case DType_INT8:
Eric Kunzee5e26762020-10-13 16:11:07 -0700277 this->fcn = [this](InEigenType a) -> OutEigenType {
Eric Kunzeb5fabec2022-06-07 05:20:44 +0000278 int64_t res_in_64 = 0 - (a - attribute->input1_zp());
Jeremy Johnson0e463642022-05-03 12:10:23 +0100279 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
280 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
281 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 +0000282 res_in_64 += attribute->output_zp();
Jeremy Johnson0e463642022-05-03 12:10:23 +0100283 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 -0700284 return result;
285 };
286 break;
287 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700288 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700289 }
290
291 return 0;
292}
293
294template <int Rank, DType Dtype>
295int OpReciprocal<Rank, Dtype>::register_fcn()
296{
297 switch (Dtype)
298 {
James Ward8b390432022-08-12 20:48:56 +0100299 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100300 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700301 this->fcn = [](InEigenType a) -> OutEigenType { return 1.0 / a; };
302 break;
303 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700304 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700305 }
306
307 return 0;
308}
309
310template <int Rank, DType Dtype>
311int OpRsqrt<Rank, Dtype>::register_fcn()
312{
313 switch (Dtype)
314 {
James Ward8b390432022-08-12 20:48:56 +0100315 case DType_FP16:
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100316 case DType_FP32:
Eric Kunzee5e26762020-10-13 16:11:07 -0700317 this->fcn = [](InEigenType a) -> OutEigenType { return 1.0 / sqrtf(a); };
318 break;
319 default:
Kevin Chengacb550f2021-06-29 15:32:19 -0700320 ERROR_IF(true, "unsupported DType %s", EnumNamesDType()[Dtype]);
Eric Kunzee5e26762020-10-13 16:11:07 -0700321 }
322
323 return 0;
324}
325
326// template explicit instantiation
James Ward8b390432022-08-12 20:48:56 +0100327DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100328DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700329DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpAbs, INT32);
330
Kevin Cheng3a478572021-01-22 17:21:02 -0800331DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700332DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT16);
333DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpBitwiseNot, INT32);
334
James Ward8b390432022-08-12 20:48:56 +0100335DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpCeil, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100336DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpCeil, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700337
338DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpClz, INT32);
339
James Ward8b390432022-08-12 20:48:56 +0100340DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpExp, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100341DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpExp, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700342
James Ward8b390432022-08-12 20:48:56 +0100343DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpFloor, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100344DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpFloor, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700345
James Ward8b390432022-08-12 20:48:56 +0100346DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLog, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100347DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLog, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700348
349DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpLogicalNot, BOOL);
350
James Ward8b390432022-08-12 20:48:56 +0100351DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100352DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, FP32);
Kevin Cheng3a478572021-01-22 17:21:02 -0800353DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700354DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT16);
355DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpNegate, INT32);
356
James Ward8b390432022-08-12 20:48:56 +0100357DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpRsqrt, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100358DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpRsqrt, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700359
James Ward8b390432022-08-12 20:48:56 +0100360DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpReciprocal, FP16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100361DEF_INSTANTIATE_RANK0_6_ONE_RANK_ONE_TYPE(OpReciprocal, FP32);