blob: 835b656f4d377a44249f17b09000435abaaf40ed [file] [log] [blame]
Eric Kunzee5e26762020-10-13 16:11:07 -07001
Jerry Ged6a04612023-12-15 22:45:39 +00002// Copyright (c) 2020-2024, 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 "type_conversion.h"
James Ward736fd1a2023-01-23 17:13:37 +000017#include "arith_util.h"
Won Jeon2c34b462024-02-06 18:37:00 +000018#include "float_utils.h"
Jerry Ge9c9c8da2023-07-19 23:08:16 +000019#include "half.hpp"
20#include "quant_util.h"
Eric Kunzee5e26762020-10-13 16:11:07 -070021#include "template_types.h"
22#include <cmath>
23
24using namespace TosaReference;
25using namespace Eigen;
26using namespace tosa;
27
Won Jeon2c34b462024-02-06 18:37:00 +000028using fp16 = tosa::reference::internal::float_t<int16_t, 5, true, true, true>;
29using bf16 = tosa::reference::internal::float_t<int16_t, 8, true, true, true>;
30using fp32 = tosa::reference::internal::float_t<int32_t, 8, true, true, true>;
31using fp8e4m3 = tosa::reference::internal::float_t<int8_t, 4, true, true, false>;
32using fp8e5m2 = tosa::reference::internal::float_t<int8_t, 5, true, true, true>;
33
Tai Lya4d748b2023-03-28 22:06:56 +000034template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Jerry Ge9c9c8da2023-07-19 23:08:16 +000035OpRescale<Rank, InDtype, OutDtype>::OpRescale(SubgraphTraverser* sgt_, TosaAttributeBase* attribute_, uint64_t id_)
Kevin Chengacb550f2021-06-29 15:32:19 -070036 : GraphNode(sgt_, Op_RESCALE, id_)
Eric Kunzee5e26762020-10-13 16:11:07 -070037{
Tai Ly6e1e2bc2024-03-01 20:59:32 +000038 setRequiredOperands(3, 1);
Eric Kunzee5e26762020-10-13 16:11:07 -070039 INIT_ATTRIBUTE(Rescale);
40}
41
Tai Lya4d748b2023-03-28 22:06:56 +000042template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -070043OpRescale<Rank, InDtype, OutDtype>::~OpRescale()
44{
45 if (attribute)
46 delete attribute;
47}
48
Tai Lya4d748b2023-03-28 22:06:56 +000049template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -070050int OpRescale<Rank, InDtype, OutDtype>::checkTensorAttributes()
51{
Jerry Gea793f462023-04-11 00:05:02 +000052 // Check Tosa Level
53 auto tosa_level = g_func_config.tosa_level;
54 LEVEL_CHECK(Rank <= tosa_level.MAX_RANK, "Rank should be smaller than or equal to MAX_RANK");
55
Eric Kunzee5e26762020-10-13 16:11:07 -070056 if (validateRequiredOperands())
57 return 1;
58
Eric Kunzee5e26762020-10-13 16:11:07 -070059 // output and input must be the same rank and size
60 if (inputs[0]->matchRankSize(*outputs[0]))
61 {
62 printNodeValidationError("OpRescale: input and output rank/size must match");
63 return 1;
64 }
65
66 in = dynamic_cast<TosaReference::TensorTemplate<TIn>*>(inputs[0]);
67 out = dynamic_cast<TosaReference::TensorTemplate<TOut>*>(outputs[0]);
68
69 ASSERT_MEM(in && out);
70
Tai Ly6e1e2bc2024-03-01 20:59:32 +000071 multiplierI32 = dynamic_cast<TosaReference::TensorTemplate<TMultiplierI32>*>(inputs[1]);
72 multiplierI16 = dynamic_cast<TosaReference::TensorTemplate<TMultiplierI16>*>(inputs[1]);
73 shift = dynamic_cast<TosaReference::TensorTemplate<TShift>*>(inputs[2]);
74 ASSERT_MEM(shift);
75
76 if (attribute->scale32())
77 {
78 ASSERT_MEM(multiplierI32);
79 }
80 else
81 {
82 ASSERT_MEM(multiplierI16);
83 }
84
Tai Lya4d748b2023-03-28 22:06:56 +000085 if ((InDtype != TOSA_REF_TYPE_INT8) && (InDtype != TOSA_REF_TYPE_UINT8) && (InDtype != TOSA_REF_TYPE_UINT16) &&
86 (attribute->input_zp() != 0))
Kevin Chengcc61be32021-10-14 17:09:57 -070087 {
Tai Lya4d748b2023-03-28 22:06:56 +000088 printNodeValidationError("OpRescale: Input TOSA_REF_TYPE not INT8/UINT8/UINT16 and zero point not 0");
Kevin Chengcc61be32021-10-14 17:09:57 -070089 return 1;
90 }
91
Tai Lya4d748b2023-03-28 22:06:56 +000092 if ((OutDtype != TOSA_REF_TYPE_INT8) && (OutDtype != TOSA_REF_TYPE_UINT8) && (OutDtype != TOSA_REF_TYPE_UINT16) &&
93 (attribute->output_zp() != 0))
Kevin Chengcc61be32021-10-14 17:09:57 -070094 {
Tai Lya4d748b2023-03-28 22:06:56 +000095 printNodeValidationError("OpRescale: Output TOSA_REF_TYPE not INT8/UINT8/UINT16 and zero point not 0");
Jeremy Johnsonf7f78ae2022-05-25 15:26:38 +010096 return 1;
97 }
98
Tai Lya4d748b2023-03-28 22:06:56 +000099 if ((InDtype == TOSA_REF_TYPE_UINT16) && ((attribute->input_zp() != 0) && (attribute->input_zp() != 32768)))
Jeremy Johnsonf7f78ae2022-05-25 15:26:38 +0100100 {
Tai Lya4d748b2023-03-28 22:06:56 +0000101 printNodeValidationError("OpRescale: Input TOSA_REF_TYPE UINT16 and zero point not 0 or 32768");
Jeremy Johnsonf7f78ae2022-05-25 15:26:38 +0100102 return 1;
103 }
104
Tai Lya4d748b2023-03-28 22:06:56 +0000105 if ((OutDtype == TOSA_REF_TYPE_UINT16) && ((attribute->output_zp() != 0) && (attribute->output_zp() != 32768)))
Jeremy Johnsonf7f78ae2022-05-25 15:26:38 +0100106 {
Tai Lya4d748b2023-03-28 22:06:56 +0000107 printNodeValidationError("OpRescale: Output TOSA_REF_TYPE UINT16 and zero point not 0 or 32768");
Kevin Chengcc61be32021-10-14 17:09:57 -0700108 return 1;
109 }
110
Tai Lya4d748b2023-03-28 22:06:56 +0000111 if (attribute->scale32() && (InDtype == TOSA_REF_TYPE_INT48))
Kevin Chengcc61be32021-10-14 17:09:57 -0700112 {
113 printNodeValidationError("OpRescale: Scale set to true but input type is INT48");
114 return 1;
115 }
116
117 if ((!attribute->scale32()) && attribute->double_round())
118 {
119 printNodeValidationError("OpRescale: Scale set to false but double round set to true");
120 return 1;
121 }
122
Eric Kunzee5e26762020-10-13 16:11:07 -0700123 return 0;
124}
125
Eric Kunzea8098c02023-09-07 00:31:54 +0000126// helpers to convert types
127static int64_t zero_extend(int8_t val)
128{
129 uint8_t* rval = reinterpret_cast<uint8_t*>(&val);
130 return static_cast<int64_t>(*rval);
131}
132static int64_t zero_extend(int16_t val)
133{
134 uint16_t* rval = reinterpret_cast<uint16_t*>(&val);
135 return static_cast<int64_t>(*rval);
136}
137
Tai Lya4d748b2023-03-28 22:06:56 +0000138template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700139int OpRescale<Rank, InDtype, OutDtype>::eval()
140{
Tai Ly6e1e2bc2024-03-01 20:59:32 +0000141 int32_t input_zp = attribute->input_zp();
142 int32_t output_zp = attribute->output_zp();
143 std::vector<int32_t> multiplier;
144 std::vector<int32_t> shift;
145 bool scale32 = attribute->scale32();
146 bool double_round = attribute->double_round();
147 bool per_channel = attribute->per_channel();
148 bool input_unsigned = attribute->input_unsigned();
149 bool output_unsigned = attribute->output_unsigned();
Eric Kunzee5e26762020-10-13 16:11:07 -0700150
TatWai Chong08fe7a52024-03-21 14:34:33 -0700151 int32_t QMin = output_unsigned ? getUnsignedMinimum<OutDtype>() : getSignedMinimum<OutDtype>();
152 int32_t QMax = output_unsigned ? getUnsignedMaximum<OutDtype>() : getSignedMaximum<OutDtype>();
153
Eric Kunzee5e26762020-10-13 16:11:07 -0700154 // reshape [d0, d1, ..., dn] into [d0 * d1 ..., dn]
155 Eigen::array<Eigen::Index, 2> shape_2d;
156 shape_2d[0] = 1;
157 if (Rank > 0)
158 {
159 for (int i = 0; i < Rank - 1; i++)
160 {
161 shape_2d[0] *= this->in->getShape()[i];
162 }
163 shape_2d[1] = this->in->getShape()[Rank - 1];
164 }
165 else
166 {
167 shape_2d[1] = 1;
168 }
169 ETensor2<InEigenType> input_reshaped = this->in->getTensor().reshape(shape_2d);
170
171 ETensor2<OutEigenType> output_2d(shape_2d);
172
Tai Ly6e1e2bc2024-03-01 20:59:32 +0000173 if (scale32)
174 {
175 auto multiplier_val = this->multiplierI32->getTensor();
176 for (int i = 0; i < multiplier_val.size(); i++)
177 {
178 multiplier.push_back(static_cast<int32_t>(multiplier_val(i)));
179 }
180 }
181 else
182 {
183 auto multiplier_val = this->multiplierI16->getTensor();
184 for (int i = 0; i < multiplier_val.size(); i++)
185 {
186 multiplier.push_back(static_cast<int32_t>(multiplier_val(i)));
187 }
188 }
189 auto shift_val = this->shift->getTensor();
190 for (int i = 0; i < shift_val.size(); i++)
191 {
192 shift.push_back(static_cast<int32_t>(shift_val(i)));
193 }
194
Eric Kunzee5e26762020-10-13 16:11:07 -0700195 if (per_channel)
196 {
197 ETensor2<InEigenType> curr_channel_slice_prescaled;
198 ETensor2<OutEigenType> curr_channel_slice_postscaled;
199 int32_t channel_multiplier, channel_shift;
200 Eigen::array<Eigen::Index, 2> begin, size;
201 size = Eigen::array<Eigen::Index, 2>({ shape_2d[0], 1 });
Kevin Chengacb550f2021-06-29 15:32:19 -0700202 try
Eric Kunzee5e26762020-10-13 16:11:07 -0700203 {
Kevin Chengacb550f2021-06-29 15:32:19 -0700204 for (int32_t i = 0; i < shape_2d[1]; i++)
Eric Kunzee5e26762020-10-13 16:11:07 -0700205 {
TatWai Chong08fe7a52024-03-21 14:34:33 -0700206 begin = Eigen::array<Eigen::Index, 2>({ 0, i });
207 curr_channel_slice_prescaled = input_reshaped.slice(begin, size);
208 channel_multiplier = multiplier[i];
209 channel_shift = shift[i];
210 curr_channel_slice_postscaled =
211 curr_channel_slice_prescaled.unaryExpr([=](InEigenType in_val) -> OutEigenType {
Eric Kunzea8098c02023-09-07 00:31:54 +0000212 int64_t input_zp_shifted;
213 if (input_unsigned)
214 {
215 int64_t in_val64;
216 int64_t in_zp64;
217 switch (GetNumBits<InDtype>::value)
218 {
219 case 8:
220 in_val64 = zero_extend(static_cast<int8_t>(in_val));
221 in_zp64 = zero_extend(static_cast<int8_t>(input_zp));
222 break;
223 case 16:
224 in_val64 = zero_extend(static_cast<int16_t>(in_val));
225 in_zp64 = zero_extend(static_cast<int16_t>(input_zp));
226 break;
227 default:
228 in_val64 = static_cast<int64_t>(in_val);
229 in_zp64 = static_cast<int64_t>(input_zp);
230 break;
231 }
232 input_zp_shifted = in_val64 - in_zp64;
233 }
234 else
235 {
236 input_zp_shifted = in_val - input_zp;
237 }
Kevin Chengacb550f2021-06-29 15:32:19 -0700238 int32_t scaled;
239 if (scale32)
Eric Kunzea8098c02023-09-07 00:31:54 +0000240 scaled = TosaReference::QuantUtil::apply_scale_32(static_cast<int32_t>(input_zp_shifted),
241 channel_multiplier, channel_shift,
242 double_round);
Kevin Chengacb550f2021-06-29 15:32:19 -0700243 else
244 scaled = TosaReference::QuantUtil::apply_scale_16(input_zp_shifted, channel_multiplier,
245 channel_shift);
Eric Kunzea8098c02023-09-07 00:31:54 +0000246 int64_t output_zp_extended;
247 if (output_unsigned)
248 {
249 switch (GetNumBits<OutDtype>::value)
250 {
251 case 8:
252 output_zp_extended = zero_extend(static_cast<int8_t>(output_zp));
253 break;
254 case 16:
255 output_zp_extended = zero_extend(static_cast<int16_t>(output_zp));
256 break;
257 default:
258 output_zp_extended = static_cast<int64_t>(output_zp);
259 break;
260 }
261 }
262 else
263 {
264 output_zp_extended = static_cast<int64_t>(output_zp);
265 }
266 int64_t res_in_64 = static_cast<int64_t>(scaled) + output_zp_extended;
Jeremy Johnsondf628d42023-01-10 14:40:54 +0000267 int64_t i32_max_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::max());
268 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
269 if (res_in_64 > i32_max_in_64 || res_in_64 < i32_min_in_64)
270 {
Jerry Ge9c9c8da2023-07-19 23:08:16 +0000271 std::string desc = "scaling result [" + std::to_string(scaled) + "] plus output_zp [" +
272 std::to_string(output_zp) + "] not in i32 range";
Jeremy Johnsondf628d42023-01-10 14:40:54 +0000273 throw desc;
274 }
275 OutEigenType out_val = static_cast<OutEigenType>(res_in_64);
Kevin Chengacb550f2021-06-29 15:32:19 -0700276 out_val = std::max<OutEigenType>(out_val, QMin);
277 out_val = std::min<OutEigenType>(out_val, QMax);
278 return out_val;
279 });
280
281 for (int32_t j = 0; j < shape_2d[0]; j++)
282 {
283 output_2d(j, i) = curr_channel_slice_postscaled(j, 0);
284 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700285 }
286 }
Kevin Chengacb550f2021-06-29 15:32:19 -0700287 catch (std::string desc)
288 {
Jeremy Johnsondf628d42023-01-10 14:40:54 +0000289 REQUIRE(false, "OpRescale failure: %s.", desc.c_str());
Kevin Chengacb550f2021-06-29 15:32:19 -0700290 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700291 }
292 else
293 {
294 int32_t tensor_multiplier = multiplier[0];
295 int32_t tensor_shift = shift[0];
Kevin Chengacb550f2021-06-29 15:32:19 -0700296 try
297 {
TatWai Chong08fe7a52024-03-21 14:34:33 -0700298 output_2d = input_reshaped.unaryExpr([=](InEigenType in_val) -> OutEigenType {
299 int64_t input_zp_shifted;
300 if (input_unsigned)
301 {
302 int64_t in_val64;
303 int64_t in_zp64;
304 switch (GetNumBits<InDtype>::value)
Eric Kunzea8098c02023-09-07 00:31:54 +0000305 {
TatWai Chong08fe7a52024-03-21 14:34:33 -0700306 case 8:
307 in_val64 = zero_extend(static_cast<int8_t>(in_val));
308 in_zp64 = zero_extend(static_cast<int8_t>(input_zp));
309 break;
310 case 16:
311 in_val64 = zero_extend(static_cast<int16_t>(in_val));
312 in_zp64 = zero_extend(static_cast<int16_t>(input_zp));
313 break;
314 default:
315 in_val64 = static_cast<int64_t>(in_val);
316 in_zp64 = static_cast<int64_t>(input_zp);
317 break;
Eric Kunzea8098c02023-09-07 00:31:54 +0000318 }
TatWai Chong08fe7a52024-03-21 14:34:33 -0700319 input_zp_shifted = in_val64 - in_zp64;
320 }
321 else
322 {
323 input_zp_shifted = in_val - input_zp;
324 }
325 int32_t scaled;
326 if (scale32)
327 scaled = TosaReference::QuantUtil::apply_scale_32(input_zp_shifted, tensor_multiplier, tensor_shift,
328 double_round);
329 else
330 scaled =
331 TosaReference::QuantUtil::apply_scale_16(input_zp_shifted, tensor_multiplier, tensor_shift);
Jeremy Johnsondf628d42023-01-10 14:40:54 +0000332
TatWai Chong08fe7a52024-03-21 14:34:33 -0700333 int64_t output_zp_extended;
334 if (output_unsigned)
335 {
336 switch (GetNumBits<OutDtype>::value)
Eric Kunzea8098c02023-09-07 00:31:54 +0000337 {
TatWai Chong08fe7a52024-03-21 14:34:33 -0700338 case 8:
339 output_zp_extended = zero_extend(static_cast<int8_t>(output_zp));
340 break;
341 case 16:
342 output_zp_extended = zero_extend(static_cast<int16_t>(output_zp));
343 break;
344 default:
345 output_zp_extended = static_cast<int64_t>(output_zp);
346 break;
Eric Kunzea8098c02023-09-07 00:31:54 +0000347 }
TatWai Chong08fe7a52024-03-21 14:34:33 -0700348 }
349 else
350 {
351 output_zp_extended = static_cast<int64_t>(output_zp);
352 }
353 int64_t res_in_64 = static_cast<int64_t>(scaled) + output_zp_extended;
354 int64_t i32_max_in_64 = IsSignedInt<OutDtype>()
355 ? static_cast<int64_t>(std::numeric_limits<int32_t>::max())
356 : static_cast<int64_t>(std::numeric_limits<uint32_t>::max());
357 int64_t i32_min_in_64 = static_cast<int64_t>(std::numeric_limits<int32_t>::min());
Eric Kunzea8098c02023-09-07 00:31:54 +0000358
TatWai Chong08fe7a52024-03-21 14:34:33 -0700359 if (res_in_64 > i32_max_in_64 || res_in_64 < i32_min_in_64)
360 {
361 std::string desc = "scaling result [" + std::to_string(scaled) + "] plus output_zp [" +
362 std::to_string(output_zp) + "] not in i32 range";
363 throw desc;
364 }
365
366 OutEigenType out_val = static_cast<OutEigenType>(res_in_64);
367 out_val = std::max<OutEigenType>(out_val, QMin);
368 out_val = std::min<OutEigenType>(out_val, QMax);
369 return out_val;
370 });
Kevin Chengacb550f2021-06-29 15:32:19 -0700371 }
372 catch (std::string desc)
373 {
Jeremy Johnsondf628d42023-01-10 14:40:54 +0000374 REQUIRE(false, "OpRescale failure: %s.", desc.c_str());
Kevin Chengacb550f2021-06-29 15:32:19 -0700375 }
Eric Kunzee5e26762020-10-13 16:11:07 -0700376 }
377
378 // reshape [d0 * d1 ..., dn] back to [d0, d1, ..., dn]
379 Eigen::array<Eigen::Index, Rank> output_shape;
380 for (int i = 0; i < Rank; i++)
381 {
382 output_shape[i] = this->out->getShape()[i];
383 }
384 this->out->getTensor() = output_2d.reshape(output_shape);
385
386 return GraphNode::eval();
387}
388
Tai Lya4d748b2023-03-28 22:06:56 +0000389template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Jerry Ge9c9c8da2023-07-19 23:08:16 +0000390OpCast<Rank, InDtype, OutDtype>::OpCast(SubgraphTraverser* sgt_, TosaAttributeBase* attribute_, uint64_t id_)
Kevin Chengacb550f2021-06-29 15:32:19 -0700391 : GraphNode(sgt_, Op_CAST, id_)
Eric Kunzee5e26762020-10-13 16:11:07 -0700392{
393 setRequiredOperands(1, 1);
394 setRequiredRank(0, 6);
395}
396
Tai Lya4d748b2023-03-28 22:06:56 +0000397template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700398OpCast<Rank, InDtype, OutDtype>::~OpCast()
399{}
400
Tai Lya4d748b2023-03-28 22:06:56 +0000401template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700402int OpCast<Rank, InDtype, OutDtype>::checkTensorAttributes()
403{
Jerry Gea793f462023-04-11 00:05:02 +0000404 // Check Tosa Level
405 auto tosa_level = g_func_config.tosa_level;
406 LEVEL_CHECK(Rank <= tosa_level.MAX_RANK, "Rank should be smaller than or equal to MAX_RANK");
407
Eric Kunzee5e26762020-10-13 16:11:07 -0700408 if (validateRequiredOperands())
409 return 1;
410
411 if (validateRequiredRank(inputs[0]) || validateRequiredRank(outputs[0]))
412 {
413 return 1;
414 }
415
416 // output and input must be the same rank and size
417 if (inputs[0]->matchRankSize(*outputs[0]))
418 {
419 printNodeValidationError("OpCast: input and output rank/size must match");
420 return 1;
421 }
422
423 in = dynamic_cast<TosaReference::TensorTemplate<TIn>*>(inputs[0]);
424 out = dynamic_cast<TosaReference::TensorTemplate<TOut>*>(outputs[0]);
425
426 ASSERT_MEM(in && out);
427
428 return 0;
429}
430
Tai Lya4d748b2023-03-28 22:06:56 +0000431template <int Rank, TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700432int OpCast<Rank, InDtype, OutDtype>::eval()
433{
434 this->out->getTensor() = this->in->getTensor().unaryExpr(cast_helper.get_fcn());
435
436 return GraphNode::eval();
437}
438
Tai Lya4d748b2023-03-28 22:06:56 +0000439template <TOSA_REF_TYPE InDtype, TOSA_REF_TYPE OutDtype>
Eric Kunzee5e26762020-10-13 16:11:07 -0700440CastHelper<InDtype, OutDtype>::CastHelper()
441{
442 fcn = [](InEigenType in) -> OutEigenType {
443 OutEigenType out = (OutEigenType)in; // implicit sign_extend() if sizeof(out_t) >= sizeof(in_t)
Eric Kunzee5e26762020-10-13 16:11:07 -0700444 return out;
445 };
446}
447
Tai Lya4d748b2023-03-28 22:06:56 +0000448template <TOSA_REF_TYPE InDtype>
449CastHelper<InDtype, TOSA_REF_TYPE_BOOL>::CastHelper()
Eric Kunzee5e26762020-10-13 16:11:07 -0700450{
451 fcn = [](InEigenType in) -> bool { return (in != 0) ? true : false; };
452}
453
Tai Lya4d748b2023-03-28 22:06:56 +0000454template <TOSA_REF_TYPE OutDtype>
455CastHelper<TOSA_REF_TYPE_BOOL, OutDtype>::CastHelper()
Eric Kunzee5e26762020-10-13 16:11:07 -0700456{
457 fcn = [](bool in) -> OutEigenType {
458 OutEigenType out = in ? (OutEigenType)1 : (OutEigenType)0;
459 return out;
460 };
461}
462
Tai Lya4d748b2023-03-28 22:06:56 +0000463template <TOSA_REF_TYPE InDtype>
464CastHelper<InDtype, TOSA_REF_TYPE_FP16>::CastHelper()
James Ward8b390432022-08-12 20:48:56 +0100465{
James Ward736fd1a2023-01-23 17:13:37 +0000466 // Integer data converted to fp16 (stored as fp32)
James Ward8b390432022-08-12 20:48:56 +0100467 fcn = [](InEigenType in) -> float {
James Ward736fd1a2023-01-23 17:13:37 +0000468 half_float::half h = half_float::half(in);
Jerry Ge9c9c8da2023-07-19 23:08:16 +0000469 float out = half_float::half_cast<float, half_float::half>(h);
James Ward736fd1a2023-01-23 17:13:37 +0000470 return out;
471 };
472}
473
Tai Lya4d748b2023-03-28 22:06:56 +0000474CastHelper<TOSA_REF_TYPE_FP32, TOSA_REF_TYPE_FP16>::CastHelper()
James Ward736fd1a2023-01-23 17:13:37 +0000475{
476 // fp32 data converted to fp16 (stored as fp32)
477 fcn = [](float in) -> float {
Tai Lya4d748b2023-03-28 22:06:56 +0000478 float out = fpTrunc<TOSA_REF_TYPE_FP16>(in); // truncate required for conversion from higher precision
James Ward736fd1a2023-01-23 17:13:37 +0000479 return out;
480 };
481}
482
Tai Lya4d748b2023-03-28 22:06:56 +0000483template <TOSA_REF_TYPE InDtype>
484CastHelper<InDtype, TOSA_REF_TYPE_BF16>::CastHelper()
James Ward736fd1a2023-01-23 17:13:37 +0000485{
486 // Integer data converted to bf16 (stored as fp32)
487 fcn = [](InEigenType in) -> float {
488 float out = (float)in; // default cast to float is round_to_nearest_float()
489 return out;
490 };
491}
492
Tai Lya4d748b2023-03-28 22:06:56 +0000493CastHelper<TOSA_REF_TYPE_FP32, TOSA_REF_TYPE_BF16>::CastHelper()
James Ward736fd1a2023-01-23 17:13:37 +0000494{
495 // fp32 data converted to bf16 (stored as fp32)
496 fcn = [](float in) -> float {
Tai Lya4d748b2023-03-28 22:06:56 +0000497 return fpTrunc<TOSA_REF_TYPE_BF16>(in); // truncate required for conversions from higher precision
James Ward8b390432022-08-12 20:48:56 +0100498 };
499}
500
Tai Lya4d748b2023-03-28 22:06:56 +0000501template <TOSA_REF_TYPE OutDtype>
502CastHelper<TOSA_REF_TYPE_FP16, OutDtype>::CastHelper()
James Ward8b390432022-08-12 20:48:56 +0100503{
James Ward736fd1a2023-01-23 17:13:37 +0000504 // fp16 data (stored as fp32) converted to integer
James Ward8b390432022-08-12 20:48:56 +0100505 fcn = [](float in) -> OutEigenType {
James Ward736fd1a2023-01-23 17:13:37 +0000506 // Cast from float representation back to half_float before rounding
507 half_float::half h = half_float::half(in);
Jerry Ged6a04612023-12-15 22:45:39 +0000508 if (h >= half_float::half(float(OutMax)))
509 return OutMax;
510
511 if (h <= half_float::half(float(OutMin)))
512 return OutMin;
513
514 h = std::rint(h);
515 OutEigenType out = half_float::half_cast<OutEigenType, half_float::half>(h);
516
James Ward8b390432022-08-12 20:48:56 +0100517 return out;
518 };
519}
520
Tai Lya4d748b2023-03-28 22:06:56 +0000521CastHelper<TOSA_REF_TYPE_FP16, TOSA_REF_TYPE_FP32>::CastHelper()
James Ward736fd1a2023-01-23 17:13:37 +0000522{
523 // No-op since fp16 values treated internally as their fp32 representation
Jerry Ge9c9c8da2023-07-19 23:08:16 +0000524 fcn = [](float in) -> OutEigenType { return in; };
James Ward736fd1a2023-01-23 17:13:37 +0000525}
526
Tai Lya4d748b2023-03-28 22:06:56 +0000527template <TOSA_REF_TYPE OutDtype>
528CastHelper<TOSA_REF_TYPE_BF16, OutDtype>::CastHelper()
James Ward736fd1a2023-01-23 17:13:37 +0000529{
530 // bf16 data (stored as fp32) converted to integer
531 fcn = [](float in) -> OutEigenType {
Jerry Ged6a04612023-12-15 22:45:39 +0000532 if (in >= float(OutMax))
533 return OutMax;
534
535 if (in <= float(OutMin))
536 return OutMin;
537
538 OutEigenType out = std::rint(in);
James Ward736fd1a2023-01-23 17:13:37 +0000539 return out;
540 };
541}
542
Tai Lya4d748b2023-03-28 22:06:56 +0000543CastHelper<TOSA_REF_TYPE_BF16, TOSA_REF_TYPE_FP32>::CastHelper()
James Ward736fd1a2023-01-23 17:13:37 +0000544{
545 // No-op since bf16 values treated as truncated fp32 internally
Jerry Ge9c9c8da2023-07-19 23:08:16 +0000546 fcn = [](InEigenType in) -> OutEigenType { return in; };
James Ward736fd1a2023-01-23 17:13:37 +0000547}
548
Tai Lya4d748b2023-03-28 22:06:56 +0000549template <TOSA_REF_TYPE InDtype>
550CastHelper<InDtype, TOSA_REF_TYPE_FP32>::CastHelper()
Eric Kunzee5e26762020-10-13 16:11:07 -0700551{
James Ward736fd1a2023-01-23 17:13:37 +0000552 // Integer data converted to fp32
Eric Kunzee5e26762020-10-13 16:11:07 -0700553 fcn = [](InEigenType in) -> float {
554 float out = (OutEigenType)in; // default cast to float is round_to_nearest_float()
555 return out;
556 };
557}
558
Tai Lya4d748b2023-03-28 22:06:56 +0000559template <TOSA_REF_TYPE OutDtype>
560CastHelper<TOSA_REF_TYPE_FP32, OutDtype>::CastHelper()
Eric Kunzee5e26762020-10-13 16:11:07 -0700561{
James Ward736fd1a2023-01-23 17:13:37 +0000562 // fp32 data converted to integer
Eric Kunzee5e26762020-10-13 16:11:07 -0700563 fcn = [](float in) -> OutEigenType {
Jerry Ge44827be2023-12-15 00:05:37 +0000564 if (in >= float(OutMax))
565 return OutMax;
566
567 if (in <= float(OutMin))
568 return OutMin;
569
Eric Kunze57bc0792023-01-25 10:05:51 -0800570 OutEigenType out = std::rint(in);
Eric Kunzee5e26762020-10-13 16:11:07 -0700571 return out;
572 };
573}
574
Tai Lya4d748b2023-03-28 22:06:56 +0000575template <TOSA_REF_TYPE OutDtype>
Won Jeon2c34b462024-02-06 18:37:00 +0000576CastHelper<TOSA_REF_TYPE_FP8E4M3, OutDtype>::CastHelper()
577{
578 // fp8e4m3 data (stored as fp32) converted to integer
579 fcn = [](float in) -> OutEigenType {
580 if (in >= float(OutMax))
581 return OutMax;
582 if (in <= float(OutMin))
583 return OutMin;
584
585 OutEigenType out = std::rint(in);
586 return out;
587 };
588}
589
590CastHelper<TOSA_REF_TYPE_FP8E4M3, TOSA_REF_TYPE_FP16>::CastHelper()
591{
592 // fp8e4m3 data (stored as fp32) converted to fp16 (stored as fp32)
593 fcn = [](float in) -> float {
594 half_float::half h = half_float::half(in);
595 float out = half_float::half_cast<half_float::half, float>(h);
596 return out;
597 };
598}
599
600CastHelper<TOSA_REF_TYPE_FP8E4M3, TOSA_REF_TYPE_BF16>::CastHelper()
601{
602 // fp8e4m3 data (stored as fp32) converted to bf16 (stored as fp32)
603 fcn = [](float in) -> float { return (float)in; };
604}
605
606CastHelper<TOSA_REF_TYPE_FP8E4M3, TOSA_REF_TYPE_FP32>::CastHelper()
607{
608 // fp8e4m3 data (stored as fp32) converted to fp32
609 fcn = [](InEigenType in) -> OutEigenType { return in; };
610}
611
612template <TOSA_REF_TYPE OutDtype>
613CastHelper<TOSA_REF_TYPE_FP8E5M2, OutDtype>::CastHelper()
614{
615 // fp8e5m2 data (stored as fp32) converted to integer
616 fcn = [](float in) -> OutEigenType {
617 if (in >= float(OutMax))
618 return OutMax;
619 if (in <= float(OutMin))
620 return OutMin;
621
622 OutEigenType out = std::rint(in);
623 return out;
624 };
625}
626
627CastHelper<TOSA_REF_TYPE_FP8E5M2, TOSA_REF_TYPE_FP16>::CastHelper()
628{
629 // fp8e5m2 data (stored as fp32) converted to fp16 (stored as fp32)
630 fcn = [](float in) -> float {
631 half_float::half h = half_float::half(in);
632 float out = half_float::half_cast<half_float::half, float>(h);
633 return out;
634 };
635}
636
637CastHelper<TOSA_REF_TYPE_FP8E5M2, TOSA_REF_TYPE_BF16>::CastHelper()
638{
639 // fp8e5m2 data (stored as fp32) converted to bf16 (stored as fp32)
640 fcn = [](float in) -> float { return (float)in; };
641}
642
643CastHelper<TOSA_REF_TYPE_FP8E5M2, TOSA_REF_TYPE_FP32>::CastHelper()
644{
645 // fp8e5m2 data (stored as fp32) converted to fp32
646 fcn = [](InEigenType in) -> OutEigenType { return in; };
647}
648
649template <TOSA_REF_TYPE InDtype>
650CastHelper<InDtype, TOSA_REF_TYPE_FP8E4M3>::CastHelper()
651{
652 // Integer data converted to fp8e4m3 (stored as fp32)
653 fcn = [](InEigenType in) -> float {
654 auto f = static_cast<fp32>(static_cast<fp8e4m3>(float(in)));
655 float out = static_cast<float>(f);
656 return out;
657 };
658}
659
660CastHelper<TOSA_REF_TYPE_FP16, TOSA_REF_TYPE_FP8E4M3>::CastHelper()
661{
662 // fp16 data (stored as fp32) converted to fp8e4m3 (stored as fp32)
663 fcn = [](float in) -> float {
664 auto f = static_cast<fp32>(static_cast<fp8e4m3>(in));
665 float out = static_cast<float>(f);
666 return out;
667 };
668}
669
670CastHelper<TOSA_REF_TYPE_BF16, TOSA_REF_TYPE_FP8E4M3>::CastHelper()
671{
672 // bf16 data (stored as fp32) converted to fp8e4m3 (stored as fp32)
673 fcn = [](float in) -> float {
674 auto f = static_cast<fp32>(static_cast<fp8e4m3>(in));
675 float out = static_cast<float>(f);
676 return out;
677 };
678}
679
680CastHelper<TOSA_REF_TYPE_FP32, TOSA_REF_TYPE_FP8E4M3>::CastHelper()
681{
682 // fp32 data converted to fp8e4m3 (stored as fp32)
683 fcn = [](float in) -> float {
684 auto f = static_cast<fp32>(static_cast<fp8e4m3>(in));
685 float out = static_cast<float>(f);
686 return out;
687 };
688}
689
690template <TOSA_REF_TYPE InDtype>
691CastHelper<InDtype, TOSA_REF_TYPE_FP8E5M2>::CastHelper()
692{
693 // Integer data converted to fp8e5m2 (stored as fp32)
694 fcn = [](InEigenType in) -> float {
695 auto f = static_cast<fp32>(static_cast<fp8e5m2>(float(in)));
696 float out = static_cast<float>(f);
697 return out;
698 };
699}
700
701CastHelper<TOSA_REF_TYPE_FP16, TOSA_REF_TYPE_FP8E5M2>::CastHelper()
702{
703 // fp16 data (stored as fp32) converted to fp8e5m2 (stored as fp32)
704 fcn = [](float in) -> float {
705 auto f = static_cast<fp32>(static_cast<fp8e5m2>(in));
706 float out = static_cast<float>(f);
707 return out;
708 };
709}
710
711CastHelper<TOSA_REF_TYPE_BF16, TOSA_REF_TYPE_FP8E5M2>::CastHelper()
712{
713 // bf16 data (stored as fp32) converted to fp8e5m2 (stored as fp32)
714 fcn = [](float in) -> float {
715 auto f = static_cast<fp32>(static_cast<fp8e5m2>(in));
716 float out = static_cast<float>(f);
717 return out;
718 };
719}
720
721CastHelper<TOSA_REF_TYPE_FP32, TOSA_REF_TYPE_FP8E5M2>::CastHelper()
722{
723 // fp32 data converted to fp8e5m2 (stored as fp32)
724 fcn = [](float in) -> float {
725 auto f = static_cast<fp32>(static_cast<fp8e5m2>(in));
726 float out = static_cast<float>(f);
727 return out;
728 };
729}
730
731template <TOSA_REF_TYPE OutDtype>
Tai Lya4d748b2023-03-28 22:06:56 +0000732CastHelper<TOSA_REF_TYPE_FP64, OutDtype>::CastHelper()
733{
734 switch (OutDtype)
735 {
736 case TOSA_REF_TYPE_INT8:
737 case TOSA_REF_TYPE_INT16:
738 case TOSA_REF_TYPE_INT32:
739 // fp64 data converted to integer
740 fcn = [](InEigenType in) -> OutEigenType {
Jerry Ged6a04612023-12-15 22:45:39 +0000741 if (in >= double(OutMax))
742 return OutMax;
743
744 if (in <= double(OutMin))
745 return OutMin;
746
Tai Lya4d748b2023-03-28 22:06:56 +0000747 OutEigenType out = std::rint(in);
Tai Lya4d748b2023-03-28 22:06:56 +0000748 return out;
749 };
750 break;
751 case TOSA_REF_TYPE_FP64:
752 // no op
753 fcn = [](InEigenType in) -> OutEigenType { return in; };
754 break;
755 default:
756 ASSERT_MSG(false, "unsupported TOSA_REF_TYPE %s", EnumNameTOSAREFTYPE(OutDtype));
757 }
758}
759
Eric Kunzee5e26762020-10-13 16:11:07 -0700760// template explicit instantiation
761DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BOOL, INT8);
762DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BOOL, INT16);
763DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BOOL, INT32);
764DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, BOOL);
765DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, INT16);
766DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, INT32);
James Ward8b390432022-08-12 20:48:56 +0100767DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, FP16);
James Ward736fd1a2023-01-23 17:13:37 +0000768DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100769DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700770DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, BOOL);
771DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, INT8);
772DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, INT32);
James Ward8b390432022-08-12 20:48:56 +0100773DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, FP16);
James Ward736fd1a2023-01-23 17:13:37 +0000774DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100775DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, FP32);
Eric Kunzee5e26762020-10-13 16:11:07 -0700776DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, BOOL);
777DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, INT8);
778DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, INT16);
James Ward8b390432022-08-12 20:48:56 +0100779DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, FP16);
James Ward736fd1a2023-01-23 17:13:37 +0000780DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, BF16);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100781DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, FP32);
James Ward8b390432022-08-12 20:48:56 +0100782DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP16, INT8);
783DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP16, INT16);
784DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP16, INT32);
James Ward736fd1a2023-01-23 17:13:37 +0000785DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP16, FP32);
James Ward24dbc422022-10-19 12:20:31 +0100786DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BF16, INT8);
787DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BF16, INT16);
788DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BF16, INT32);
James Ward736fd1a2023-01-23 17:13:37 +0000789DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BF16, FP32);
Jeremy Johnsonbc2a3db2022-09-27 13:50:00 +0100790DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, INT8);
791DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, INT16);
792DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, INT32);
James Ward736fd1a2023-01-23 17:13:37 +0000793DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, FP16);
794DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, BF16);
Tai Lya4d748b2023-03-28 22:06:56 +0000795DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP64, INT8);
796DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP64, INT16);
797DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP64, INT32);
798DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP64, FP64);
799DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT8, FP64);
800DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT16, FP64);
801DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, INT32, FP64);
Won Jeon2c34b462024-02-06 18:37:00 +0000802DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BF16, FP8E4M3);
803DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, BF16, FP8E5M2);
804DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP8E4M3, FP16);
805DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP8E4M3, BF16);
806DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP8E4M3, FP32);
807DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP8E5M2, FP16);
808DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP8E5M2, BF16);
809DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP8E5M2, FP32);
810DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP16, FP8E4M3);
811DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP16, FP8E5M2);
812DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, FP8E4M3);
813DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpCast, FP32, FP8E5M2);
Eric Kunzee5e26762020-10-13 16:11:07 -0700814
Kevin Cheng3a478572021-01-22 17:21:02 -0800815DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT8, INT8);
816DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT8, INT16);
817DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT8, INT32);
818DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT16, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700819DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT16, INT16);
820DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT16, INT32);
Kevin Cheng3a478572021-01-22 17:21:02 -0800821DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT32, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700822DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT32, INT16);
823DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT32, INT32);
Kevin Cheng3a478572021-01-22 17:21:02 -0800824DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT48, INT8);
Eric Kunzee5e26762020-10-13 16:11:07 -0700825DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT48, INT16);
826DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT48, INT32);
Kevin Cheng3a478572021-01-22 17:21:02 -0800827DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, UINT8, INT8);
Jeremy Johnsonf7f78ae2022-05-25 15:26:38 +0100828DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, UINT8, INT16);
829DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, UINT16, INT16);
Kevin Cheng3a478572021-01-22 17:21:02 -0800830DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT8, UINT8);
Jeremy Johnsonf7f78ae2022-05-25 15:26:38 +0100831DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT16, UINT8);
832DEF_INSTANTIATE_RANK0_6_ONE_RANK_TWO_TYPE(OpRescale, INT16, UINT16);