main
hpp 104 lines 2.44 KB
Raw
1 #pragma once
2
3 #include <bit>
4 #include <cstdint>
5
6 inline float bf16_to_float(uint16_t bf16) {
7 uint32_t bits = static_cast<uint32_t>(bf16) << 16;
8 return std::bit_cast<float>(bits);
9 }
10
11 inline uint16_t float_to_bf16(float fp32) {
12 uint32_t bits = std::bit_cast<uint32_t>(fp32);
13 return static_cast<uint16_t>(bits >> 16);
14 }
15
16 /************************************************
17 * Copyright (c) 2015 Princeton Vision Group
18 * Licensed under the MIT license.
19 * Codes below copied from
20 * https://github.com/PrincetonVision/marvin/tree/master/tools/tensorIO_matlab
21 *************************************************/
22 inline uint16_t float_to_fp16(float fp32) {
23 uint16_t fp16;
24
25 unsigned u, remainder, shift, lsb, lsb_s1, lsb_m1;
26 unsigned sign, exponent, mantissa;
27
28 uint32_t x = std::bit_cast<uint32_t>(fp32);
29 u = (x & 0x7fffffff);
30
31 // Get rid of +NaN/-NaN case first.
32 if (u > 0x7f800000) {
33 fp16 = 0x7fffU;
34 return fp16;
35 }
36
37 sign = ((x >> 16) & 0x8000);
38
39 // Get rid of +Inf/-Inf, +0/-0.
40 if (u > 0x477fefff) {
41 fp16 = sign | 0x7c00U;
42 return fp16;
43 }
44 if (u < 0x33000001) {
45 fp16 = (sign | 0x0000);
46 return fp16;
47 }
48
49 exponent = ((u >> 23) & 0xff);
50 mantissa = (u & 0x7fffff);
51
52 if (exponent > 0x70) {
53 shift = 13;
54 exponent -= 0x70;
55 } else {
56 shift = 0x7e - exponent;
57 exponent = 0;
58 mantissa |= 0x800000;
59 }
60 lsb = (1 << shift);
61 lsb_s1 = (lsb >> 1);
62 lsb_m1 = (lsb - 1);
63
64 // Round to nearest even.
65 remainder = (mantissa & lsb_m1);
66 mantissa >>= shift;
67 if (remainder > lsb_s1 || (remainder == lsb_s1 && (mantissa & 0x1))) {
68 ++mantissa;
69 if (!(mantissa & 0x3ff)) {
70 ++exponent;
71 mantissa = 0;
72 }
73 }
74
75 fp16 = (sign | (exponent << 10) | mantissa);
76
77 return fp16;
78 }
79
80 inline float fp16_to_float(uint16_t fp16) {
81 unsigned sign = ((fp16 >> 15) & 1);
82 unsigned exponent = ((fp16 >> 10) & 0x1f);
83 unsigned mantissa = ((fp16 & 0x3ff) << 13);
84 uint32_t temp;
85 if (exponent == 0x1f) { /* NaN or Inf */
86 mantissa = (mantissa ? (sign = 0, 0x7fffff) : 0);
87 exponent = 0xff;
88 } else if (!exponent) { /* Denorm or Zero */
89 if (mantissa) {
90 unsigned int msb;
91 exponent = 0x71;
92 do {
93 msb = (mantissa & 0x400000);
94 mantissa <<= 1; /* normalize */
95 --exponent;
96 } while (!msb);
97 mantissa &= 0x7fffff; /* 1.mantissa is implicit */
98 }
99 } else {
100 exponent += 0x70;
101 }
102 temp = ((sign << 31) | (exponent << 23) | mantissa);
103 return std::bit_cast<float>(temp);
104 }