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 : #ifndef FP16_T_H
11 : #define FP16_T_H
12 :
13 : #include <algorithm>
14 : #include <cmath>
15 : #include <math.h>
16 : #include <stdint.h>
17 :
18 : namespace Adx {
19 :
20 : const uint16_t DIM_1 = 1;
21 : const uint16_t DIM_2 = 2;
22 : const uint16_t DIM_7 = 7;
23 : const uint16_t DIM_11 = 11;
24 :
25 : const uint16_t BitShift_15 = 15;
26 : const uint16_t BitShift_31 = 31;
27 : const uint16_t BitShift_32 = 32;
28 :
29 : /**
30 : * @ingroup fp16 basic parameter
31 : * @brief fp16 exponent bias
32 : */
33 : #define FP16_EXP_BIAS (15)
34 : /**
35 : * @ingroup fp16 basic parameter
36 : * @brief the mantissa bit length of fp16 is 10
37 : */
38 : #define FP16_MAN_LEN (10)
39 : /**
40 : * @ingroup fp16 basic parameter
41 : * @brief bit index of sign in fp16
42 : */
43 : #define FP16_SIGN_INDEX (15)
44 : /**
45 : * @ingroup fp16 basic parameter
46 : * @brief sign mask of fp16 (1 00000 00000 00000)
47 : */
48 : #define FP16_SIGN_MASK (0x8000)
49 : /**
50 : * @ingroup fp16 basic parameter
51 : * @brief exponent mask of fp16 ( 11111 00000 00000)
52 : */
53 : #define FP16_EXP_MASK (0x7C00)
54 : /**
55 : * @ingroup fp16 basic parameter
56 : * @brief mantissa mask of fp16 ( 11111 11111)
57 : */
58 : #define FP16_MAN_MASK (0x03FF)
59 : /**
60 : * @ingroup fp16 basic parameter
61 : * @brief conceal bit of mantissa of fp16( 1 00000 00000)
62 : */
63 : #define FP16_MAN_HIDE_BIT (0x0400)
64 : /**
65 : * @ingroup fp16 basic parameter
66 : * @brief maximum value (0111 1011 1111 1111)
67 : */
68 : #define FP16_MAX (0x7BFF)
69 : /**
70 : * @ingroup fp16 basic parameter
71 : * @brief minimum value (1111 1011 1111 1111)
72 : */
73 : #define FP16_MIN (0xFBFF)
74 : /**
75 : * @ingroup fp16 basic parameter
76 : * @brief absolute maximum value (0111 1111 1111 1111)
77 : */
78 : #define FP16_ABS_MAX (0x7FFF)
79 : /**
80 : * @ingroup fp16 basic parameter
81 : * @brief maximum exponent value of fp16 is 15(11111)
82 : */
83 : #define FP16_MAX_EXP (0x001F)
84 : /**
85 : * @ingroup fp16 basic parameter
86 : * @brief maximum valid exponent value of fp16 is 14(11110)
87 : */
88 : #define FP16_MAX_VALID_EXP (0x001E)
89 : /**
90 : * @ingroup fp16 basic parameter
91 : * @brief maximum mantissa value of fp16(11111 11111)
92 : */
93 : #define FP16_MAX_MAN (0x03FF)
94 : /**
95 : * @ingroup fp16 basic parameter
96 : * @brief absolute minimum normal value of fp16
97 : * (E=1,M=0 D=2^(-14)=0.00006103515625)
98 : */
99 : #define FP16_MIN_NORMAL ((1.0f / (2 << 14)))
100 :
101 : /**
102 : * @ingroup fp16 basic operator
103 : * @brief get sign of fp16
104 : */
105 : #define FP16_EXTRAC_SIGN(x) (((x) >> 15) & 1)
106 : /**
107 : * @ingroup fp16 basic operator
108 : * @brief get exponent of fp16
109 : */
110 : #define FP16_EXTRAC_EXP(x) (((x) >> 10) & FP16_MAX_EXP)
111 : /**
112 : * @ingroup fp16 basic operator
113 : * @brief get mantissa of fp16
114 : */
115 : #define FP16_EXTRAC_MAN(x) ((((x) >> 0) & 0x3FF) | (((((x) >> 10) & 0x1F) > 0 ? 1 : 0) * 0x400))
116 : /**
117 : * @ingroup fp16 basic operator
118 : * @brief constructor of fp16 from sign exponent and mantissa
119 : */
120 : #define FP16_CONSTRUCTOR(s, e, m) \
121 : (static_cast<uint16_t>(((s) << FP16_SIGN_INDEX) | ((e) << FP16_MAN_LEN) | ((m) &FP16_MAX_MAN)))
122 :
123 : /**
124 : * @ingroup fp16 special value judgment
125 : * @brief whether a fp16 is zero
126 : */
127 : #define FP16_IS_ZERO(x) (((x) &FP16_ABS_MAX) == 0)
128 : /**
129 : * @ingroup fp16 special value judgment
130 : * @brief whether a fp16 is a denormalized value
131 : */
132 : #define FP16_IS_DENORM(x) ((((x) &FP16_EXP_MASK) == 0))
133 : /**
134 : * @ingroup fp16 special value judgment
135 : * @brief whether a fp16 is infinite
136 : */
137 : #define FP16_IS_INF(x) (((x) &FP16_ABS_MAX) == FP16_ABS_MAX)
138 : /**
139 : * @ingroup fp16 special value judgment
140 : * @brief whether a fp16 is NaN
141 : */
142 : #define FP16_IS_NAN(x) (((x & FP16_EXP_MASK) == FP16_EXP_MASK) && (x & FP16_MAN_MASK))
143 : /**
144 : * @ingroup fp16 special value judgment
145 : * @brief whether a fp16 is invalid
146 : */
147 : #define FP16_IS_INVALID(x) ((x & FP16_EXP_MASK) == FP16_EXP_MASK)
148 : /**
149 : * @ingroup fp32 basic parameter
150 : * @brief fp32 exponent bias
151 : */
152 : #define FP32_EXP_BIAS (127)
153 : /**
154 : * @ingroup fp32 basic parameter
155 : * @brief the exponent bit length of float/fp32 is 8
156 : */
157 : #define FP32_EXP_LEN (8)
158 : /**
159 : * @ingroup fp32 basic parameter
160 : * @brief the mantissa bit length of float/fp32 is 23
161 : */
162 : #define FP32_MAN_LEN (23)
163 : /**
164 : * @ingroup fp32 basic parameter
165 : * @brief bit index of sign in float/fp32
166 : */
167 : #define FP32_SIGN_INDEX (31)
168 : /**
169 : * @ingroup fp32 basic parameter
170 : * @brief sign mask of fp32 (1 0000 0000 0000 0000 0000 0000 000)
171 : */
172 : #define FP32_SIGN_MASK (0x80000000u)
173 : /**
174 : * @ingroup fp32 basic parameter
175 : * @brief exponent mask of fp32 ( 1111 1111 0000 0000 0000 0000 000)
176 : */
177 : #define FP32_EXP_MASK (0x7F800000u)
178 : /**
179 : * @ingroup fp32 basic parameter
180 : * @brief mantissa mask of fp32 ( 1111 1111 1111 1111 111)
181 : */
182 : #define FP32_MAN_MASK (0x007FFFFFu)
183 : /**
184 : * @ingroup fp32 basic parameter
185 : * @brief conceal bit of mantissa of fp32 ( 1 0000 0000 0000 0000 000)
186 : */
187 : #define FP32_MAN_HIDE_BIT (0x00800000u)
188 : /**
189 : * @ingroup fp32 basic parameter
190 : * @brief absolute maximum value (0 1111 1111 1111 1111 1111 1111 111)
191 : */
192 : #define FP32_ABS_MAX (0x7FFFFFFFu)
193 : /**
194 : * @ingroup fp32 basic parameter
195 : * @brief maximum exponent value of fp32 is 255(1111 1111)
196 : */
197 : #define FP32_MAX_EXP (0xFF)
198 : /**
199 : * @ingroup fp32 basic parameter
200 : * @brief maximum mantissa value of fp32 (1111 1111 1111 1111 1111 111)
201 : */
202 : #define FP32_MAX_MAN (0x7FFFFF)
203 : /**
204 : * @ingroup fp32 special value judgment
205 : * @brief whether a fp32 is NaN
206 : */
207 : #define FP32_IS_NAN(x) (((x & FP32_EXP_MASK) == FP32_EXP_MASK) && (x & FP32_MAN_MASK))
208 : /**
209 : * @ingroup fp32 special value judgment
210 : * @brief whether a fp32 is infinite
211 : */
212 : #define FP32_IS_INF(x) (((x & FP32_EXP_MASK) == FP32_EXP_MASK) && (!(x & FP32_MAN_MASK)))
213 : /**
214 : * @ingroup fp32 special value judgment
215 : * @brief whether a fp32 is a denormalized value
216 : */
217 : #define FP32_IS_DENORM(x) ((((x) &FP32_EXP_MASK) == 0))
218 : /**
219 : * @ingroup fp32 basic operator
220 : * @brief get sign of fp32
221 : */
222 : #define FP32_EXTRAC_SIGN(x) (((x) >> FP32_SIGN_INDEX) & 1)
223 : /**
224 : * @ingroup fp32 basic operator
225 : * @brief get exponent of fp16
226 : */
227 : #define FP32_EXTRAC_EXP(x) (((x) &FP32_EXP_MASK) >> FP32_MAN_LEN)
228 : /**
229 : * @ingroup fp32 basic operator
230 : * @brief get mantissa of fp16
231 : */
232 : #define FP32_EXTRAC_MAN(x) \
233 : (((x) &FP32_MAN_MASK) | (((((x) >> FP32_MAN_LEN) & FP32_MAX_EXP) > 0 ? 1 : 0) * FP32_MAN_HIDE_BIT))
234 : /**
235 : * @ingroup fp32 basic operator
236 : * @brief constructor of fp32 from sign exponent and mantissa
237 : */
238 : #define FP32_CONSTRUCTOR(s, e, m) (((s) << FP32_SIGN_INDEX) | ((e) << FP32_MAN_LEN) | ((m) &FP32_MAX_MAN))
239 :
240 : /**
241 : * @ingroup fp64 basic parameter
242 : * @brief fp64 exponent bias
243 : */
244 : #define FP64_EXP_BIAS (1023)
245 : /**
246 : * @ingroup fp64 basic parameter
247 : * @brief the exponent bit length of double/fp64 is 11
248 : */
249 : #define FP64_EXP_LEN (11)
250 : /**
251 : * @ingroup fp64 basic parameter
252 : * @brief the mantissa bit length of double/fp64 is 52
253 : */
254 : #define FP64_MAN_LEN (52)
255 : /**
256 : * @ingroup fp64 basic parameter
257 : * @brief bit index of sign in double/fp64 is 63
258 : */
259 : #define FP64_SIGN_INDEX (63)
260 : /**
261 : * @ingroup fp64 basic parameter
262 : * @brief sign mask of fp64 (1 000 (total 63bits 0))
263 : */
264 : #define FP64_SIGN_MASK (0x8000000000000000LLu)
265 : /**
266 : * @ingroup fp64 basic parameter
267 : * @brief exponent mask of fp64 (0 1 11111 11111 0000?-?-(total 52bits 0))
268 : */
269 : #define FP64_EXP_MASK (0x7FF0000000000000LLu)
270 : /**
271 : * @ingroup fp64 basic parameter
272 : * @brief mantissa mask of fp64 ( 1111?-?-(total 52bits 1))
273 : */
274 : #define FP64_MAN_MASK (0x000FFFFFFFFFFFFFLLu)
275 : /**
276 : * @ingroup fp64 basic parameter
277 : * @brief conceal bit of mantissa of fp64 ( 1 0000?-?-(total 52bits 0))
278 : */
279 : #define FP64_MAN_HIDE_BIT (0x0010000000000000LLu)
280 : /**
281 : * @ingroup fp64 basic parameter
282 : * @brief absolute maximum value (0 111?-?-(total 63bits 1))
283 : */
284 : #define FP64_ABS_MAX (0x7FFFFFFFFFFFFFFFLLu)
285 : /**
286 : * @ingroup fp64 basic parameter
287 : * @brief maximum exponent value of fp64 is 2047(1 11111 11111)
288 : */
289 : #define FP64_MAX_EXP (0x07FF)
290 : /**
291 : * @ingroup fp64 basic parameter
292 : * @brief maximum mantissa value of fp64 (111?-?-(total 52bits 1))
293 : */
294 : #define FP64_MAX_MAN (0xFFFFFFFFFFFLLu)
295 : /**
296 : * @ingroup fp64 special value judgment
297 : * @brief whether a fp64 is NaN
298 : */
299 : #define FP64_IS_NAN(x) (((x & FP64_EXP_MASK) == FP64_EXP_MASK) && (x & FP64_MAN_MASK))
300 : /**
301 : * @ingroup fp64 special value judgment
302 : * @brief whether a fp64 is infinite
303 : */
304 : #define FP64_IS_INF(x) (((x & FP64_EXP_MASK) == FP64_EXP_MASK) && (!(x & FP64_MAN_MASK)))
305 :
306 : /**
307 : * @ingroup integer special value judgment
308 : * @brief maximum positive value of int8_t (0111 1111)
309 : */
310 : #define INT8_T_MAX (0x7F)
311 : /**
312 : * @ingroup integer special value judgment
313 : * @brief maximum value of a data with 8 bits length (1111 111)
314 : */
315 : #define BIT_LEN8_MAX (0xFF)
316 : /**
317 : * @ingroup integer special value judgment
318 : * @brief maximum positive value of int16_t (0111 1111 1111 1111)
319 : */
320 : #define INT16_T_MAX (0x7FFF)
321 : /**
322 : * @ingroup integer special value judgment
323 : * @brief maximum value of a data with 16 bits length (1111 1111 1111 1111)
324 : */
325 : #define BIT_LEN16_MAX (0xFFFF)
326 : /**
327 : * @ingroup integer special value judgment
328 : * @brief maximum positive value of int32_t (0111 1111 1111 1111 1111 1111 1111 1111)
329 : */
330 : #define INT32_T_MAX (0x7FFFFFFFu)
331 : /**
332 : * @ingroup integer special value judgment
333 : * @brief maximum value of a data with 32 bits length (1111 1111 1111 1111 1111 1111 1111 1111)
334 : */
335 : #define BIT_LEN32_MAX (0xFFFFFFFFu)
336 : /**
337 : * @ingroup print switch
338 : * @brief print an error if input fp16 is overflow
339 : */
340 :
341 : /**
342 : * @ingroup fp16_t enum
343 : * @brief round mode of last valid digital
344 : */
345 : typedef enum tagFp16RoundMode {
346 : ROUND_TO_NEAREST = 0, /**< round to nearest even */
347 : ROUND_BY_TRUNCATED, /**< round by truncated */
348 : ROUND_MODE_RESERVED,
349 : } fp16RoundMode_t;
350 :
351 : /**
352 : * @ingroup fp16_t
353 : * @brief Half precision float
354 : * bit15: 1 bit SIGN +---+-----+------------+
355 : * bit14-10: 5 bit EXP | S |EEEEE|MM MMMM MMMM|
356 : * bit0-9: 10bit MAN +---+-----+------------+
357 : *
358 : */
359 : typedef struct tagFp16 {
360 : uint16_t val;
361 :
362 : public:
363 : /**
364 : * @ingroup fp16_t constructor
365 : * @brief Constructor without any param(default constructor)
366 : */
367 53 : tagFp16(void)
368 53 : {
369 53 : val = 0x0u;
370 53 : }
371 : /**
372 : * @ingroup all type constructor
373 : * @brief Constructor with all type
374 : */
375 : template<typename T>
376 52 : tagFp16(const T &value)
377 : {
378 52 : *this = value;
379 52 : }
380 : /**
381 : * @ingroup fp16_t constructor
382 : * @brief Constructor with an uint16_t value
383 : */
384 3 : constexpr tagFp16(const uint16_t &uiVal) : val(uiVal)
385 : {
386 3 : }
387 : /**
388 : * @ingroup fp16_t constructor
389 : * @brief Constructor with a fp16_t object(copy constructor)
390 : */
391 4 : tagFp16(const tagFp16 &fp) : val(fp.val)
392 : {
393 4 : }
394 : /**
395 : * @ingroup fp16_t math evaluation operator
396 : * @param [in] fp fp16_t object to be copy to fp16_t
397 : * @brief Override basic evaluation operator to copy fp16_t to a new fp16_t
398 : * @return Return fp16_t result from fp
399 : */
400 : tagFp16 &operator=(const tagFp16 &fp);
401 : /**
402 : * @ingroup fp16_t math evaluation operator
403 : * @param [in] fVal float object to be converted to fp16_t
404 : * @brief Override basic evaluation operator to convert float to fp16_t
405 : * @return Return fp16_t result from fVal
406 : */
407 : tagFp16 &operator=(const float &fVal);
408 : /**
409 : * @ingroup fp16_t math evaluation operator
410 : * @param [in] dVal double object to be converted to fp16_t
411 : * @brief Override basic evaluation operator to convert double to fp16_t
412 : * @return Return fp16_t result from dVal
413 : */
414 : tagFp16 &operator=(const double &dVal);
415 : /**
416 : * @ingroup fp16_t math evaluation operator
417 : * @param [in] iVal float object to be converted to fp16_t
418 : * @brief Override basic evaluation operator to convert float to fp16_t
419 : * @return Return fp16_t result from iVal
420 : */
421 : tagFp16 &operator=(const int8_t &iVal);
422 : /**
423 : * @ingroup fp16_t math evaluation operator
424 : * @param [in] uiVal uint8_t object to be converted to fp16_t
425 : * @brief Override basic evaluation operator to convert uint8_t to fp16_t
426 : * @return Return fp16_t result from uiVal
427 : */
428 : tagFp16 &operator=(const uint8_t &uiVal);
429 : /**
430 : * @ingroup fp16_t math evaluation operator
431 : * @param [in] iVal int16_t object to be converted to fp16_t
432 : * @brief Override basic evaluation operator to convert int16_t to fp16_t
433 : * @return Return fp16_t result from iVal
434 : */
435 : tagFp16 &operator=(const int16_t &iVal);
436 : /**
437 : * @ingroup fp16_t math evaluation operator
438 : * @param [in] uiVal uint16_t object to be converted to fp16_t
439 : * @brief Override basic evaluation operator to convert uint16_t to fp16_t
440 : * @return Return fp16_t result from uiVal
441 : */
442 : tagFp16 &operator=(const uint16_t &uiVal);
443 : /**
444 : * @ingroup fp16_t math evaluation operator
445 : * @param [in] iVal int32_t object to be converted to fp16_t
446 : * @brief Override basic evaluation operator to convert int32_t to fp16_t
447 : * @return Return fp16_t result from iVal
448 : */
449 : tagFp16 &operator=(const int32_t &iVal);
450 : /**
451 : * @ingroup fp16_t math evaluation operator
452 : * @param [in] uiVal uint32_t object to be converted to fp16_t
453 : * @brief Override basic evaluation operator to convert uint32_t to fp16_t
454 : * @return Return fp16_t result from uiVal
455 : */
456 : tagFp16 &operator=(const uint32_t &uiVal);
457 : tagFp16 &operator=(const int64_t &iVal);
458 : tagFp16 &operator=(const uint64_t &uiVal);
459 : /**
460 : * @ingroup fp16_t math conversion
461 : * @brief Convert fp16_t to float/fp32
462 : * @return Return float/fp32 value of fp16_t
463 : */
464 : float toFloat();
465 : } fp16_t;
466 :
467 : /**
468 : * @ingroup fp16_t public method
469 : * @param [in] val signature is negative
470 : * @param [in|out] s sign of fp16_t object
471 : * @param [in|out] e exponent of fp16_t object
472 : * @param [in|out] m mantissa of fp16_t object
473 : * @brief Extract the sign, exponent and mantissa of a fp16_t object
474 : */
475 : void ExtractFP16(const uint16_t &val, uint16_t *s, int16_t *e, uint16_t *m);
476 : /*lint +e1573*/
477 : /**
478 : * @ingroup fp16_t public method
479 : * @param [in] bit0 whether the last preserved bit is 1 before round
480 : * @param [in] bit1 whether the abbreviation's highest bit is 1
481 : * @param [in] bitLeft whether the abbreviation's bits which not contain highest bit grater than 0
482 : * @param [in] man mantissa of a fp16_t or float number, support types: uint16_t/uint32_t/uint64_t
483 : * @param [in] shift abbreviation bits
484 : * @brief Round fp16_t or float mantissa to nearest value
485 : * @return Returns true if round 1,otherwise false;
486 : */
487 : /*lint -e1573*/
488 : template<typename T>
489 18 : T ManRoundToNearest(bool bit0, bool bit1, bool bitLeft, T man, uint16_t shift = 0)
490 : {
491 18 : man = (man >> shift) + ((bit1 && (bitLeft || bit0)) ? 1 : 0);
492 18 : return man;
493 : }
494 : /*lint +e1573*/
495 : /**
496 : * @ingroup fp16_t public method
497 : * @param [in] man mantissa of a float number, support types: uint16_t/uint32_t/uint64_t
498 : * @brief Get bit length of a uint32_t number
499 : * @return Return bit length of man
500 : */
501 : /*lint -e1573*/
502 : template<typename T>
503 35 : int16_t GetManBitLength(T man)
504 : {
505 35 : int16_t len = 0;
506 412 : while (man) {
507 377 : man >>= 1;
508 377 : len++;
509 : }
510 35 : return len;
511 : }
512 :
513 : /*lint +e1573*/
514 : }; // namespace op
515 :
516 : #endif /*_FP16_T_HPP_*/
|