Line data Source code
1 : /**
2 : * Copyright (c) 2025 Huawei Technologies Co., Ltd.
3 : * This program is free software, you can redistribute it and/or modify it under the terms and conditions of
4 : * CANN Open Software License Agreement Version 2.0 (the "License").
5 : * Please refer to the License for details. You may not use this file except in compliance with the License.
6 : * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR IMPLIED,
7 : * INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY, OR FITNESS FOR A PARTICULAR PURPOSE.
8 : * See LICENSE in the root of the software repository for the full text of the License.
9 : */
10 :
11 : /*!
12 : * \file kernel_fp16.h
13 : * \brief
14 : */
15 : #ifndef ASCENDC_FP16_H
16 : #define ASCENDC_FP16_H
17 : #include <algorithm>
18 : #include <cmath>
19 : #include <cstdint>
20 :
21 : enum class DimIndex {
22 : K_DIM0 = 0,
23 : K_DIM1,
24 : K_DIM2,
25 : K_DIM3,
26 : K_DIM4,
27 : K_DIM5,
28 : K_DIM6,
29 : K_DIM7,
30 : K_DIM8,
31 : K_DIM9,
32 : K_DIM10,
33 : K_DIM11,
34 : K_DIM12,
35 : K_DIM13,
36 : K_DIM14,
37 : K_DIM15,
38 : K_DIM16,
39 : };
40 :
41 : enum class BitShift {
42 : K_BIT_SHIFT2 = 2,
43 : K_BIT_SHIFT3 = 3,
44 : K_BIT_SHIFT4 = 4,
45 : K_BIT_SHIFT5 = 5,
46 : K_BIT_SHIFT6 = 6,
47 : K_BIT_SHIFT7 = 7,
48 : K_BIT_SHIFT8 = 8,
49 : K_BIT_SHIFT9 = 9,
50 : K_BIT_SHIFT10 = 10,
51 : K_BIT_SHIFT11 = 11,
52 : K_BIT_SHIFT12 = 12,
53 : K_BIT_SHIFT13 = 13,
54 : K_BIT_SHIFT14 = 14,
55 : K_BIT_SHIFT15 = 15,
56 : K_BIT_SHIFT16 = 16,
57 : K_BIT_SHIFT20 = 20,
58 : K_BIT_SHIFT24 = 24,
59 : K_BIT_SHIFT27 = 27,
60 : K_BIT_SHIFT28 = 28,
61 : K_BIT_SHIFT31 = 31,
62 : K_BIT_SHIFT32 = 32,
63 : K_BIT_SHIFT36 = 36,
64 : K_BIT_SHIFT40 = 40,
65 : K_BIT_SHIFT44 = 44,
66 : K_BIT_SHIFT48 = 48,
67 : K_BIT_SHIFT52 = 52,
68 : K_BIT_SHIFT56 = 56,
69 : K_BIT_SHIFT59 = 59,
70 : K_BIT_SHIFT60 = 60,
71 : K_BIT_SHIFT63 = 63,
72 : K_BIT_SHIFT64 = 64,
73 : K_BIT_SHIFT128 = 128,
74 : K_BIT_SHIFT255 = 255,
75 : K_BIT_SHIFT256 = 256,
76 : K_BIT_SHIFT512 = 512,
77 : K_BIT_SHIFT768 = 768,
78 : K_BIT_SHIFT784 = 784,
79 : K_BIT_SHIFT1020 = 1020,
80 : K_BIT_SHIFT1024 = 1024,
81 : K_BIT_SHIFT3136 = 3136,
82 : K_BIT_SHIFT4096 = 4096,
83 : K_BIT_SHIFT6144 = 6144,
84 : K_BIT_SHIFT10240 = 10240,
85 : K_BIT_SHIFT65536 = 65536
86 : };
87 :
88 : enum class Fp16BasicParam {
89 : K_FP16_EXP_BIAS = 15, // fp16 exponent bias
90 : K_FP16_EXP_LEN = 5, // the exponent bit length of fp16 is 5
91 : K_FP16_MAN_LEN = 10, // the mantissa bit length of fp16 is 10
92 : K_FP16_SIGN_INDEX = 15, // bit index of sign in fp16
93 : K_FP16_SIGN_MASK = 0x8000, // sign mask of fp16 (1 00000 00000 00000)
94 : K_FP16_EXP_MASK = 0x7C00, // exponent mask of fp16 ( 11111 00000 00000)
95 : K_FP16_MAN_MASK = 0x03FF, // mantissa mask of fp16 ( 11111 11111)
96 : K_FP16_MAN_HIDE_BIT = 0x0400, // hide_bit of mantissa of fp16( 1 00000 00000)
97 : K_FP16_MAX = 0x7BFF, // maximum value (0111 1011 1111 1111)
98 : K_FP16_MIN = 0xFBFF, // minimum value (1111 1011 1111 1111)
99 : K_FP16_ABS_MAX = 0x7FFF, // absolute maximum value (0111 1111 1111 1111)
100 : K_FP16_MAX_EXP = 0x001F, // maximum exponent value of fp16 is 15(11111)
101 : K_FP16_MAX_VALID_EXP = 0x001E, // maximum valid exponent value of fp16 is 14(11110)
102 : K_FP16_MAX_MAN = 0x03FF, // maximum mantissa value of fp16(11111 11111)
103 : };
104 :
105 : // / @ingroup fp16 basic operator
106 : // / @brief get sign of fp16
107 70 : inline uint16_t FP16_EXTRAC_SIGN(uint16_t x)
108 : {
109 70 : return (((x) >> static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_INDEX)) & 1);
110 : }
111 : // / @ingroup fp16 basic operator
112 : // / @brief get exponent of fp16
113 70 : inline int16_t FP16_EXTRAC_EXP(uint16_t x)
114 : {
115 : return (
116 70 : ((x) >> static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN)) &
117 70 : static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_EXP));
118 : }
119 : // / @ingroup fp16 basic operator
120 : // / @brief get mantissa of fp16
121 70 : inline uint16_t FP16_EXTRAC_MAN(uint16_t x)
122 : {
123 : return (
124 70 : (((x) >> 0) & 0x3FF) |
125 140 : (((((x) >> static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN)) & 0x1F) > 0 ? 1 : 0) * 0x400));
126 : }
127 : // / @ingroup fp16 basic operator
128 : // / @brief constructor of fp16 from sign exponent and mantissa
129 62 : inline uint16_t FP16_CONSTRUCTOR(uint16_t s, uint16_t e, uint16_t m)
130 : {
131 : return (
132 62 : ((s) << (static_cast<uint16_t>(Fp16BasicParam::K_FP16_SIGN_INDEX))) |
133 62 : ((e) << static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAN_LEN)) |
134 62 : ((m) & (static_cast<uint16_t>(Fp16BasicParam::K_FP16_MAX_MAN))));
135 : }
136 : // / @ingroup fp16 special value judgment
137 : // / @brief whether a fp16 is zero
138 8 : inline bool FP16_IS_ZERO(uint16_t x) { return (x & (static_cast<uint16_t>(Fp16BasicParam::K_FP16_ABS_MAX))) == 0; }
139 : // / @ingroup fp16 special value judgment
140 : // / @brief whether a fp16 is a denormalized value
141 22 : inline bool FP16_IS_DENORM(uint16_t x) { return (x & (static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_MASK))) == 0; }
142 : // / @ingroup fp16 special value judgment
143 : // / @brief whether a fp16 is invalid
144 52 : inline bool FP16_IS_INVALID(uint16_t x)
145 : {
146 : return (
147 52 : (x & static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_MASK)) ==
148 52 : static_cast<uint16_t>(Fp16BasicParam::K_FP16_EXP_MASK));
149 : }
150 :
151 : enum class Fp32BasicParam : uint32_t {
152 : K_FP32_EXP_BIAS = 127, // fp32 exponent bias
153 : K_FP32_EXP_LEN = 8, // the exponent bit length of float/fp32 is 8
154 : K_FP32_MAN_LEN = 23, // the mantissa bit length of float/fp32 is 23
155 : K_FP32_SIGN_INDEX = 31, // bit index of sign in float/fp32
156 : K_FP32_SIGN_MASK = 0x80000000u, // sign mask of fp32 (1 0000 0000 0000 0000 0000 0000 000)
157 : K_FP32_EXP_MASK = 0x7F800000u, // exponent mask of fp32 ( 1111 1111 0000 0000 0000 0000 000)
158 : K_FP32_MAN_MASK = 0x007FFFFFu, // mantissa mask of fp32 (1111 1111 1111 1111 111)
159 : K_FP32_MAN_HIDE_BIT = 0x00800000u, // hide_bit of mantissa of fp32 ( 1 0000 0000 0000 0000 000)
160 : K_FP32_ABS_MAX = 0x7FFFFFFFu, // absolute maximum value (0 1111 1111 1111 1111 1111 1111 111)
161 : K_FP32_MAX_EXP = 0xFF, // maximum exponent value of fp32 is 255(1111 1111)
162 : K_FP32_MAX_MAN = 0x7FFFFF // maximum mantissa value of fp32 (1111 1111 1111 1111 1111 111)
163 : };
164 :
165 : // / @ingroup fp32 basic operator
166 : // / @brief constructor of fp32 from sign exponent and mantissa
167 18 : inline uint32_t FP32_CONSTRUCTOR(uint32_t s, uint32_t e, uint32_t m)
168 : {
169 : return (
170 18 : ((s) << static_cast<uint16_t>(Fp32BasicParam::K_FP32_SIGN_INDEX)) |
171 18 : ((e) << static_cast<uint16_t>(Fp32BasicParam::K_FP32_MAN_LEN)) |
172 18 : ((m) & static_cast<uint32_t>(Fp32BasicParam::K_FP32_MAX_MAN)));
173 : }
174 :
175 : enum class Fp64BasicParam : uint64_t {
176 : K_FP64_EXP_BIAS = 1023, // fp64 exponent bias
177 : K_FP64_EXP_LEN = 11, // the exponent bit length of double/fp64 is 11
178 : K_FP64_MAN_LEN = 52, // the mantissa bit length of double/fp64 is 52
179 : K_FP64_SIGN_INDEX = 63, // bit index of sign in double/fp64 is 63
180 : K_FP64_SIGN_MASK = 0x8000000000000000LLu, // sign mask of fp64 (1 000 (total 63bits 0))
181 : K_FP64_EXP_MASK = 0x7FF0000000000000LLu, // exponent mask of fp64 (0 1 11111 11111 0000?-?-(total 52bits 0))
182 : K_FP64_MAN_MASK = 0x000FFFFFFFFFFFFFLLu, // mantissa mask of fp64 ( 1111?-?-(total 52bits 1))
183 : K_FP64_MAN_HIDE_BIT = 0x0010000000000000LLu, // hide_bit of mantissa of fp64 ( 1 0000?-?-(total 52bits 0))
184 : K_FP64_ABS_MAX = 0x7FFFFFFFFFFFFFFFLLu, // absolute maximum value (0 111?-?-(total 63bits 1))
185 : K_FP64_MAX_EXP = 0x07FF, // maximum exponent value of fp64 is 2047(1 11111 11111)
186 : K_FP64_MAX_MAN = 0xFFFFFFFFFFFLLu // maximum mantissa value of fp64 (111?-?-(total 52bits 1))
187 : };
188 :
189 : enum class NumBitMax : uint64_t {
190 : K_INT8_MAX = 0x7F, // maximum positive value of int8_t (0111 1111)
191 : K_BIT_LEN8_MAX = 0xFF, // maximum value of a data with 8 bits length (1111 111)
192 : K_INT16_MAX = 0x7FFF, // maximum positive value of int16_t (0111 1111 1111 1111)
193 : K_BIT_LEN16_MAX = 0xFFFF, // maximum value of a data with 16 bits length (1111 1111 1111 1111)
194 : K_INT32_MAX = 0x7FFFFFFFu, // maximum positive value of int32_t (0111 1111 1111 1111 1111 1111 1111 1111)
195 : // maximum value of uint32_t(1111 1111 1111 1111 1111 1111 1111 1111)
196 : K_BIT_LEN32_MAX = 0xFFFFFFFFu,
197 : // maximum value of int64_t (0111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111)
198 : K_INT64_MAX = 0x7FFFFFFFFFFFFFFFu,
199 : // maximum value of uint64_t (1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111)
200 : K_BIT_LEN64_MAX = 0xFFFFFFFFFFFFFFFFu
201 : };
202 :
203 : // / @ingroup half enum
204 : // / @brief round mode of last valid digital
205 : enum class TagFp16RoundMode {
206 : K_ROUND_TO_NEAREST = 0, // < round to nearest even
207 : K_ROUND_BY_TRUNCATED, // < round by truncated
208 : K_ROUND_MODE_RESERVED,
209 : };
210 :
211 : #ifndef __TIK_CC
212 : #define __ai_core__
213 : #define __ai_host__
214 : #endif
215 :
216 : /**
217 : * @ingroup half
218 : * @brief Half precision float
219 : * bit15: 1 bit SIGN +---+-----+------------+
220 : * bit14-10: 5 bit EXP | S |EEEEE|MM MMMM MMMM|
221 : * bit0-9: 10bit MAN +---+-----+------------+
222 : */
223 : #define TIK_ALIGN(n) alignas(n)
224 : struct half {
225 : uint16_t val;
226 :
227 : public:
228 : /* *
229 : * @ingroup half constructor
230 : * @brief Default constructor
231 : */
232 : __ai_host__ __ai_core__ half() = default;
233 : /* *
234 : * @ingroup half copy constructor
235 : * @brief Constructor with a half object(copy constructor)
236 : */
237 20 : __ai_host__ __ai_core__ half(const half& fp) : val(fp.val) {}
238 : /* *
239 : * @ingroup half constructor
240 : * @brief Constructor with an float value
241 : */
242 16 : __ai_host__ __ai_core__ half(const float& fVal) : val(FloatToFp16(fVal)) {}
243 : /* *
244 : * @ingroup half constructor
245 : * @brief Constructor with an double value
246 : */
247 4 : __ai_host__ __ai_core__ half(const double& dVal) : val(DoubleToFp16(dVal)) {}
248 : /* *
249 : * @ingroup half constructor
250 : * @brief Constructor with an int8_t value
251 : */
252 : __ai_host__ __ai_core__ half(const int8_t& iVal) : val(Int8ToFp16(iVal)) {}
253 : /* *
254 : * @ingroup half constructor
255 : * @brief Constructor with an uint8_t value
256 : */
257 : __ai_host__ __ai_core__ half(const uint8_t& uiVal) : val(UInt8ToFp16(uiVal)) {}
258 : /* *
259 : * @ingroup half constructor
260 : * @brief Constructor with an int16_t value
261 : */
262 : __ai_host__ __ai_core__ half(const int16_t& iVal) : val(Int16ToFp16(iVal)) {}
263 : /* *
264 : * @ingroup half constructor
265 : * @brief Constructor with an uint16_t value
266 : */
267 40 : __ai_host__ __ai_core__ half(const uint16_t& uiVal) : val(UInt16ToFp16(uiVal)) {}
268 : /* *
269 : * @ingroup half constructor
270 : * @brief Constructor with an int32_t value
271 : */
272 : __ai_host__ __ai_core__ half(const int32_t& iVal) : val(Int32ToFp16(iVal)) {}
273 : /* *
274 : * @ingroup half constructor
275 : * @brief Constructor with an uint32_t value
276 : */
277 : __ai_host__ __ai_core__ half(const uint32_t& uiVal) : val(UInt32ToFp16(uiVal)) {}
278 :
279 : uint16_t FloatToFp16(const float& fVal) const;
280 : uint16_t DoubleToFp16(const double& dVal);
281 : uint16_t Int8ToFp16(const int8_t& iVal) const;
282 : uint16_t UInt8ToFp16(const uint8_t& uiVal) const;
283 : uint16_t Int16ToFp16(const int16_t& iVal) const;
284 : uint16_t UInt16ToFp16(const uint16_t& uiVal);
285 : uint16_t Int32ToFp16(const int32_t& iVal) const;
286 : uint16_t UInt32ToFp16(const uint32_t& uiVal) const;
287 :
288 : /* *
289 : * @ingroup half math operator
290 : * @param [in] fp half object to be added
291 : * @brief Override addition operator to performing half addition
292 : * @return Return half result of adding this and fp
293 : */
294 : half operator+(const half fp) const;
295 : /* *
296 : * @ingroup half math operator
297 : * @param [in] fp half object to be subtracted
298 : * @brief Override addition operator to performing half subtraction
299 : * @return Return half result of subtraction fp from this
300 : */
301 : half operator-(const half fp) const;
302 : /* *
303 : * @ingroup half math operator
304 : * @param [in] fp half object to be multiplied
305 : * @brief Override multiplication operator to performing half
306 : * multiplication
307 : * @return Return half result of multiplying this and fp
308 : */
309 : half operator*(const half fp) const;
310 : /* *
311 : * @ingroup half math operator divided
312 : * @param [in] fp half object to be divided
313 : * @brief Override division operator to performing half division
314 : * @return Return half result of division this by fp
315 : */
316 : half operator/(const half fp) const;
317 : /* *
318 : * @ingroup half math operator
319 : * @param [in] fp half object to be added
320 : * @brief Override addition operator to performing half addition
321 : * @return Return half result of adding this and fp
322 : */
323 : half operator+=(const half fp);
324 : /* *
325 : * @ingroup half math operator
326 : * @param [in] fp half object to be subtracted
327 : * @brief Override addition operator to performing half subtraction
328 : * @return Return half result of subtraction fp from this
329 : */
330 : half operator-=(const half fp);
331 : /* *
332 : * @ingroup half math operator
333 : * @param [in] fp half object to be multiplied
334 : * @brief Override multiplication operator to performing half
335 : * multiplication
336 : * @return Return half result of multiplying this and fp
337 : */
338 : half operator*=(const half fp);
339 : /* *
340 : * @ingroup half math operator divided
341 : * @param [in] fp half object to be divided
342 : * @brief Override division operator to performing half division
343 : * @return Return half result of division this by fp
344 : */
345 : half operator/=(const half fp);
346 : /*
347 : * @ingroup half math operator auto-increment
348 : * @param [in] fp half object to be Front auto-increment
349 : * @brief Override Front auto-increment operator to performing half Front auto-increment
350 : * @return Return half result of Front auto-increment this and fp
351 : */
352 : half operator++();
353 : /*
354 : * @ingroup half math operator auto-increment
355 : * @param [in] fp half object to be Back auto-increment
356 : * @brief Override Front Back auto-increment operator to performing half Back auto-increment
357 : * @return Return half result of Back auto-increment this and fp
358 : */
359 : half operator++(int);
360 : /*
361 : * @ingroup half math operator auto-decrement
362 : * @param [in] fp half object to be Front auto-decrement
363 : * @brief Override Front auto-decrement operator to performing half Front auto-decrement
364 : * @return Return half result of Front auto-decrement this and fp
365 : */
366 : half operator--();
367 : /*
368 : * @ingroup half math operator auto-decrement
369 : * @param [in] fp half object to be Back auto-decrement
370 : * @brief Override Back auto-decrement operator to performing half Back auto-decrement
371 : * @return Return half result of Back auto-decrement this and fp
372 : */
373 : half operator--(int);
374 : /*
375 : * @ingroup half math operator AND
376 : * @param [in] fp half object to be AND
377 : * @brief Override AND operator to performing half Front AND
378 : * @return Return half result of AND this and fp
379 : */
380 : bool operator&&(const half fp) const;
381 : /*
382 : * @ingroup half math operator OR
383 : * @param [in] fp half object to be OR
384 : * @brief Override OR operator to performing half OR
385 : * @return Return half result of OR this and fp
386 : */
387 : bool operator||(const half fp) const;
388 :
389 : /* *
390 : * @ingroup half math compare operator
391 : * @param [in] fp half object to be compared
392 : * @brief Override basic comparison operator to performing half if-equal
393 : * comparison
394 : * @return Return boolean result of if-equal comparison of this and fp.
395 : */
396 : bool operator==(const half& fp) const;
397 : /* *
398 : * @ingroup half math compare operator
399 : * @param [in] fp half object to be compared
400 : * @brief Override basic comparison operator to performing half not-equal
401 : * comparison
402 : * @return Return boolean result of not-equal comparison of this and fp.
403 : */
404 : bool operator!=(const half& fp) const;
405 : /* *
406 : * @ingroup half math compare operator
407 : * @param [in] fp half object to be compared
408 : * @brief Override basic comparison operator to performing half
409 : * greater-than comparison
410 : * @return Return boolean result of greater-than comparison of this and fp.
411 : */
412 : bool operator>(const half& fp) const;
413 : /* *
414 : * @ingroup half math compare operator
415 : * @param [in] fp half object to be compared
416 : * @brief Override basic comparison operator to performing half
417 : * greater-equal comparison
418 : * @return Return boolean result of greater-equal comparison of this and fp.
419 : */
420 : bool operator>=(const half& fp) const;
421 : /* *
422 : * @ingroup half math compare operator
423 : * @param [in] fp half object to be compared
424 : * @brief Override basic comparison operator to performing half less-than
425 : * comparison
426 : * @return Return boolean result of less-than comparison of this and fp.
427 : */
428 : bool operator<(const half& fp) const;
429 : /* *
430 : * @ingroup half math compare operator
431 : * @param [in] fp half object to be compared
432 : * @brief Override basic comparison operator to performing half less-equal
433 : * comparison
434 : * @return Return boolean result of less-equal comparison of this and fp.
435 : */
436 : bool operator<=(const half& fp) const;
437 :
438 : /* *
439 : * @ingroup half math evaluation operator
440 : * @param [in] fp half object to be copy to half
441 : * @brief Override basic evaluation operator to copy half to a new half
442 : * @return Return half result from fp
443 : */
444 : half& operator=(const half& fp);
445 :
446 : /* *
447 : * @ingroup half math evaluation operator
448 : * @param [in] fVal float object to be converted to half
449 : * @brief Override basic evaluation operator to convert float to half
450 : * @return Return half result from fVal
451 : */
452 : half& operator=(const float& fVal);
453 : /* *
454 : * @ingroup half math evaluation operator
455 : * @param [in] dVal double object to be converted to half
456 : * @brief Override basic evaluation operator to convert double to half
457 : * @return Return half result from dVal
458 : */
459 : half& operator=(const double& dVal);
460 : /* *
461 : * @ingroup half math evaluation operator
462 : * @param [in] iVal float object to be converted to half
463 : * @brief Override basic evaluation operator to convert float to half
464 : * @return Return half result from iVal
465 : */
466 : half& operator=(const int8_t& iVal);
467 : /* *
468 : * @ingroup half math evaluation operator
469 : * @param [in] uiVal uint8_t object to be converted to half
470 : * @brief Override basic evaluation operator to convert uint8_t to half
471 : * @return Return half result from uiVal
472 : */
473 : half& operator=(const uint8_t& uiVal);
474 : /* *
475 : * @ingroup half math evaluation operator
476 : * @param [in] iVal int16_t object to be converted to half
477 : * @brief Override basic evaluation operator to convert int16_t to half
478 : * @return Return half result from iVal
479 : */
480 : half& operator=(const int16_t& iVal);
481 : /* *
482 : * @ingroup half math evaluation operator
483 : * @param [in] uiVal uint16_t object to be converted to half
484 : * @brief Override basic evaluation operator to convert uint16_t to half
485 : * @return Return half result from uiVal
486 : */
487 : half& operator=(const uint16_t& uiVal);
488 : /* *
489 : * @ingroup half math evaluation operator
490 : * @param [in] iVal int32_t object to be converted to half
491 : * @brief Override basic evaluation operator to convert int32_t to half
492 : * @return Return half result from iVal
493 : */
494 : half& operator=(const int32_t& iVal);
495 : /* *
496 : * @ingroup half math evaluation operator
497 : * @param [in] uiVal uint32_t object to be converted to half
498 : * @brief Override basic evaluation operator to convert uint32_t to half
499 : * @return Return half result from uiVal
500 : */
501 : half& operator=(const uint32_t& uiVal);
502 : /* *
503 : * @ingroup half math conversion
504 : * @brief Override convert operator to convert half to float/fp32
505 : * @return Return float/fp32 value of half
506 : */
507 : operator float() const;
508 : /* *
509 : * @ingroup half math conversion
510 : * @brief Override convert operator to convert half to double/fp64
511 : * @return Return double/fp64 value of half
512 : */
513 : operator double() const;
514 : /* *
515 : * @ingroup half math conversion
516 : * @brief Override convert operator to convert half to int8_t
517 : * @return Return int8_t value of half
518 : */
519 : operator int8_t() const;
520 : /* *
521 : * @ingroup half math conversion
522 : * @brief Override convert operator to convert half to uint8_t
523 : * @return Return uint8_t value of half
524 : */
525 : operator uint8_t() const;
526 : /* *
527 : * @ingroup half conversion
528 : * @brief Override convert operator to convert half to int16_t
529 : * @return Return int16_t value of half
530 : */
531 : operator int16_t() const;
532 : /* *
533 : * @ingroup half math conversion
534 : * @brief Override convert operator to convert half to uint16_t
535 : * @return Return uint16_t value of half
536 : */
537 : operator uint16_t() const;
538 : /* *
539 : * @ingroup half math conversion
540 : * @brief Override convert operator to convert half to int32_t
541 : * @return Return int32_t value of half
542 : */
543 : operator int32_t() const;
544 : /* *
545 : * @ingroup half math conversion
546 : * @brief Override convert operator to convert half to int64_t
547 : * @return Return int64_t value of half
548 : */
549 : operator uint32_t() const;
550 : /* *
551 : * @ingroup half judgment method
552 : * @param [in] fp half object to be judgement
553 : * @brief whether a half is inifinite
554 : * @return Returns 1:+INF -1:-INF 0:not INF
555 : */
556 : int32_t IsInf() const;
557 : /* *
558 : * @ingroup half math conversion
559 : * @brief Convert half to float/fp32
560 : * @return Return float/fp32 value of half
561 : */
562 : float ToFloat() const;
563 : /* *
564 : * @ingroup half math conversion
565 : * @brief Convert half to double/fp64
566 : * @return Return double/fp64 value of half
567 : */
568 : double ToDouble() const;
569 : /* *
570 : * @ingroup half math conversion
571 : * @brief Convert half to int8_t
572 : * @return Return int8_t value of half
573 : */
574 : int8_t ToInt8() const;
575 : /* *
576 : * @ingroup half math conversion
577 : * @brief Convert half to uint8_t
578 : * @return Return uint8_t value of half
579 : */
580 : uint8_t ToUInt8() const;
581 : /* *
582 : * @ingroup half conversion
583 : * @brief Convert half to int16_t
584 : * @return Return int16_t value of half
585 : */
586 : int16_t ToInt16() const;
587 : /* *
588 : * @ingroup half math conversion
589 : * @brief Convert half to uint16_t
590 : * @return Return uint16_t value of half
591 : */
592 : uint16_t ToUInt16() const;
593 : /* *
594 : * @ingroup half math conversion
595 : * @brief Convert half to int32_t
596 : * @return Return int32_t value of half
597 : */
598 : int32_t ToInt32() const;
599 : /* *
600 : * @ingroup half math conversion
601 : * @brief Convert half to int64_t
602 : * @return Return int64_t value of half
603 : */
604 : uint32_t ToUInt32() const;
605 : };
606 :
607 : /**
608 : * @ingroup half public method
609 : * @param [in] val signature is negative
610 : * @param [in|out] s sign of half object
611 : * @param [in|out] e exponent of half object
612 : * @param [in|out] m mantissa of half object
613 : * @brief Extract the sign, exponent and mantissa of a half object
614 : */
615 : void ExtractFp16(const uint16_t& val, uint16_t& s, int16_t& e, uint16_t& m);
616 : /**
617 : * @ingroup half public method
618 : * @param [in] negative sign is negative
619 : * @param [in|out] man mantissa to be reverse
620 : * @brief Calculate a mantissa's complement (add ont to it's radix-minus-one
621 : * complement)
622 : * @return Return complement of man
623 : */
624 : template <typename T>
625 0 : void ReverseMan(bool negative, T& man)
626 : {
627 0 : if (negative) {
628 0 : man = (~(man)) + 1;
629 : }
630 0 : }
631 : /**
632 : * @ingroup half public method
633 : * @param [in] ea exponent of one half/float number
634 : * @param [in] ma mantissa of one half/float number
635 : * @param [in] eb exponent of another half/float number
636 : * @param [in] mb mantissa of another half/float number
637 : * @brief choose mantissa to be shift right whoes exponent is less than another
638 : * one
639 : * @return Return mantissawhoes exponent is less than another one
640 : */
641 : template <typename T>
642 : T MinMan(const int16_t& ea, T& ma, const int16_t& eb, T& mb)
643 : {
644 : return (ea > eb) ? mb : ma;
645 : }
646 :
647 : /**
648 : * @ingroup half public method
649 : * @param [in] man mantissa to be operate
650 : * @param [in] shift right shift bits
651 : * @brief right shift a mantissa
652 : * @return Return right-shift mantissa
653 : */
654 : template <typename T>
655 0 : T RightShift(T man, int16_t shift)
656 : {
657 0 : int32_t bits = sizeof(T) * 8; // one byte have 8 bits
658 0 : T mask = ((static_cast<T>(1u)) << (static_cast<uint32_t>(bits - 1)));
659 0 : for (int32_t i = 0; i < shift; i++) {
660 0 : man = ((man & mask) | (man >> 1));
661 : }
662 0 : return man;
663 : }
664 :
665 : /**
666 : * @ingroup half public method
667 : * @param [in] ea exponent of one temp half number
668 : * @param [in] ma mantissa of one temp half number
669 : * @param [in] eb exponent of another temp half number
670 : * @param [in] mb mantissa of another temp half number
671 : * @brief Get mantissa sum of two temp half numbers, T support types:
672 : * uint16_t/uint32_t/uint64_t
673 : * @return Return mantissa sum
674 : */
675 : template <typename T>
676 0 : T GetManSum(int16_t ea, const T& ma, int16_t eb, const T& mb)
677 : {
678 : T sum;
679 0 : if (ea != eb) {
680 : T mTmp;
681 0 : int16_t eTmp = static_cast<int16_t>(std::abs(ea - eb));
682 0 : if (ea > eb) {
683 0 : mTmp = mb;
684 0 : mTmp = RightShift(mTmp, eTmp);
685 0 : sum = ma + mTmp;
686 : } else {
687 0 : mTmp = ma;
688 0 : mTmp = RightShift(mTmp, eTmp);
689 0 : sum = mTmp + mb;
690 : }
691 : } else {
692 0 : sum = mb + ma;
693 : }
694 0 : return sum;
695 : }
696 :
697 : /**
698 : * @ingroup half public method
699 : * @param [in] bit0 whether the last preserved bit is 1 before round
700 : * @param [in] bit1 whether the abbreviation's highest bit is 1
701 : * @param [in] bitLeft whether the abbreviation's bits which not contain highest
702 : * bit grater than 0
703 : * @param [in] man mantissa of a half or float number, support types:
704 : * uint16_t/uint32_t/uint64_t
705 : * @param [in] shift abbreviation bits
706 : * @brief Round half or float mantissa to nearest value
707 : * @return Returns true if round 1,otherwise false;
708 : */
709 : template <typename T>
710 26 : T ManRoundToNearest(bool bit0, bool bit1, bool bitLeft, T man, uint16_t shift = 0)
711 : {
712 26 : man = ((bit1 && (bit0 || bitLeft)) ? 1 : 0) + (man >> shift);
713 26 : return man;
714 : }
715 :
716 : /**
717 : * @ingroup half public method
718 : * @param [in] man mantissa of a float number, support types: uint16_t/uint32_t/uint64_t
719 : * @brief Get bit length of a uint32_t number
720 : * @return Return bit length of man
721 : */
722 : template <typename T>
723 36 : int16_t GetManBitLength(T man)
724 : {
725 36 : int16_t lenRet = 0;
726 450 : while (man) {
727 414 : lenRet++;
728 414 : man >>= 1;
729 : }
730 36 : return lenRet;
731 : }
732 :
733 : /**
734 : * \brief half datatype
735 : *
736 : * \details This structure implements the datatype for storing half-precision floating-point numbers.
737 : * The structure implements assignment operators and type conversions.
738 : * 16 bits are being used in total: 1 sign bit, 5 bits for the exponent, and the significand is
739 : * being stored in 10 bits.
740 : * The total precision is 11 bits. There are 15361 representable numbers within theinterval [0.0, 1.0],
741 : * endpoints included.
742 : * On average we have log10(2**11) ≈ 3.311 decimal digits.
743 : */
744 : namespace float16 {
745 : using Fp16T = half;
746 : } // namespace float16
747 : #endif // ASCENDC_FP16_H
|