* @brief Converts a 32-bit float to a 16-bit half-precision float. * * Based on Mike Acton's half.c implementation. */
| 104 | * Based on Mike Acton's half.c implementation. |
| 105 | */ |
| 106 | half halfFromFloat(float f) |
| 107 | { |
| 108 | union |
| 109 | { |
| 110 | float f; |
| 111 | uint32_t u; |
| 112 | } floatUnion = {f}; |
| 113 | |
| 114 | uint32_t float32 = floatUnion.u; |
| 115 | |
| 116 | // Constants for bit masks, shifts, and biases |
| 117 | const uint16_t ONE = 0x0001; |
| 118 | const uint32_t FLOAT_SIGN_MASK = 0x80000000; |
| 119 | const uint32_t FLOAT_EXP_MASK = 0x7f800000; |
| 120 | const uint32_t FLOAT_MANTISSA_MASK = 0x007fffff; |
| 121 | const uint32_t FLOAT_HIDDEN_BIT = 0x00800000; |
| 122 | const uint32_t FLOAT_ROUND_BIT = 0x00001000; |
| 123 | const uint16_t FLOAT_EXP_BIAS = 0x007f; |
| 124 | const uint16_t HALF_EXP_BIAS = 0x000f; |
| 125 | const uint16_t FLOAT_SIGN_POS = 0x001f; |
| 126 | const uint16_t HALF_SIGN_POS = 0x000f; |
| 127 | const uint16_t FLOAT_EXP_POS = 0x0017; |
| 128 | const uint16_t HALF_EXP_POS = 0x000a; |
| 129 | const uint16_t HALF_EXP_MASK = 0x7c00; |
| 130 | const uint16_t FLOAT_EXP_FLAGGED_VALUE = 0x00ff; |
| 131 | const uint16_t HALF_EXP_MASK_VALUE = HALF_EXP_MASK >> HALF_EXP_POS; |
| 132 | const uint16_t HALF_EXP_MAX_VALUE = HALF_EXP_MASK_VALUE - ONE; |
| 133 | const uint16_t FLOAT_HALF_SIGN_POS_OFFSET = FLOAT_SIGN_POS - HALF_SIGN_POS; |
| 134 | const uint16_t FLOAT_HALF_BIAS_OFFSET = FLOAT_EXP_BIAS - HALF_EXP_BIAS; |
| 135 | const uint16_t FLOAT_HALF_MANTISSA_POS_OFFSET = FLOAT_EXP_POS - HALF_EXP_POS; |
| 136 | const uint16_t HALF_NAN_MIN = HALF_EXP_MASK | ONE; |
| 137 | |
| 138 | // Extracting the sign, exponent, and mantissa from the 32-bit float |
| 139 | const uint32_t floatSignMasked = float32 & FLOAT_SIGN_MASK; |
| 140 | const uint32_t floatExpMasked = float32 & FLOAT_EXP_MASK; |
| 141 | const uint16_t halfSign = |
| 142 | static_cast<uint16_t>(floatSignMasked >> FLOAT_HALF_SIGN_POS_OFFSET); |
| 143 | const uint16_t floatExp = |
| 144 | static_cast<uint16_t>(floatExpMasked >> FLOAT_EXP_POS); |
| 145 | const uint32_t floatMantissa = float32 & FLOAT_MANTISSA_MASK; |
| 146 | |
| 147 | // Check for NaN |
| 148 | if ((floatExpMasked == FLOAT_EXP_MASK) && (floatMantissa != 0)) |
| 149 | { |
| 150 | half result; |
| 151 | result.data = |
| 152 | HALF_EXP_MASK | (floatMantissa >> FLOAT_HALF_MANTISSA_POS_OFFSET); |
| 153 | return result; |
| 154 | } |
| 155 | |
| 156 | // Adjusting the exponent and rounding the mantissa |
| 157 | const uint16_t floatExpHalfBias = floatExp - FLOAT_HALF_BIAS_OFFSET; |
| 158 | const uint32_t floatMantissaRoundMask = floatMantissa & FLOAT_ROUND_BIT; |
| 159 | const uint32_t floatMantissaRoundOffset = floatMantissaRoundMask << ONE; |
| 160 | const uint32_t floatMantissaRounded = |
| 161 | floatMantissa + floatMantissaRoundOffset; |
| 162 | |
| 163 | // Handling denormalized numbers |
no outgoing calls
no test coverage detected