MCPcopy Create free account
hub / github.com/apache/fory / from_float

Method from_float

cpp/fory/util/float16.cc:30–117  ·  view source on GitHub ↗

Convert float32 to float16 using IEEE 754 round-to-nearest, ties-to-even. Layout of float32: [S|EEEEEEEE|MMMMMMMMMMMMMMMMMMMMMMM] (1+8+23 bits) Layout of float16: [S|EEEEE|MMMMMMMMMM] (1+5+10 bits) Exponent bias: 127 (f32) vs 15 (f16).

Source from the content-addressed store, hash-verified

28// Layout of float16: [S|EEEEE|MMMMMMMMMM] (1+5+10 bits)
29// Exponent bias: 127 (f32) vs 15 (f16).
30float16_t float16_t::from_float(float f) noexcept {
31 uint32_t bits;
32 std::memcpy(&bits, &f, sizeof(bits));
33
34 const uint32_t sign = bits & 0x80000000u;
35 const uint32_t exp = (bits >> 23) & 0xFFu;
36 const uint32_t mantissa = bits & 0x007FFFFFu;
37
38 // NaN or Infinity (f32 exp = 0xFF)
39 if (exp == 255u) {
40 if (mantissa == 0u) {
41 // ±Inf → ±Inf
42 return from_bits(static_cast<uint16_t>((sign >> 16) | 0x7C00u));
43 }
44 // NaN → quiet NaN; map top 9 bits of f32 payload to f16 payload,
45 // force quiet bit (bit 9 of f16 fraction).
46 const uint32_t nan_payload = (mantissa >> 13) & 0x03FFu;
47 const uint32_t quiet_bit = 0x0200u;
48 return from_bits(static_cast<uint16_t>((sign >> 16) | 0x7C00u | quiet_bit |
49 nan_payload));
50 }
51
52 // ±0 (also catches -0.0)
53 if (exp == 0u && mantissa == 0u) {
54 return from_bits(static_cast<uint16_t>(sign >> 16));
55 }
56
57 // Convert exponent bias: 127 → 15
58 const int32_t exp16 = static_cast<int32_t>(exp) - 127 + 15;
59
60 // Overflow → ±Inf
61 if (exp16 >= 31) {
62 return from_bits(static_cast<uint16_t>((sign >> 16) | 0x7C00u));
63 }
64
65 // Underflow: result is a f16 subnormal, or flushes to ±0.
66 if (exp16 <= 0) {
67 // Values with exp16 < -10 are too small even for the smallest f16
68 // subnormal (2^-24); also handles all f32 subnormal inputs (exp==0).
69 if (exp16 < -10) {
70 return from_bits(static_cast<uint16_t>(sign >> 16));
71 }
72 // Assemble f16 subnormal. The f32 normal implicit leading 1 participates
73 // in the f16 mantissa, so include it explicitly.
74 const uint32_t full_mantissa = (1u << 23) | mantissa;
75 // Total right-shift to produce the 10-bit f16 subnormal mantissa:
76 // 13 bits (to drop from 23 to 10) + (1 - exp16) for subnormal scaling.
77 const int32_t shift_total = 13 + (1 - exp16);
78 const uint32_t round_bit = 1u << (shift_total - 1);
79 const uint32_t sticky_mask = round_bit - 1u;
80 const bool sticky = (full_mantissa & sticky_mask) != 0u;
81 const uint32_t mantissa16 = full_mantissa >> shift_total;
82 // Round-to-nearest, ties-to-even
83 const uint32_t result = ((full_mantissa & round_bit) != 0u &&
84 (sticky || (mantissa16 & 1u) != 0u))
85 ? mantissa16 + 1u
86 : mantissa16;
87 // Note: if rounding carries out of the subnormal mantissa the natural

Callers 2

_float_textFunction · 0.45

Calls

no outgoing calls

Tested by

no test coverage detected