* @brief Converts a 16-bit half-precision float to a 32-bit float. * * Based on Mike Acton's half.c implementation. */
| 227 | * Based on Mike Acton's half.c implementation. |
| 228 | */ |
| 229 | float halfToFloat(half h) |
| 230 | { |
| 231 | // Constants for bit masks, shifts, and biases |
| 232 | const uint16_t ONE = 0x0001; |
| 233 | const uint16_t TWO = 0x0002; |
| 234 | const uint32_t FLOAT_EXP_MASK = 0x7f800000; |
| 235 | const uint32_t FLOAT_MANTISSA_MASK = 0x007fffff; |
| 236 | const uint16_t FLOAT_EXP_BIAS = 0x007f; |
| 237 | const uint16_t HALF_EXP_BIAS = 0x000f; |
| 238 | const uint16_t HALF_SIGN_MASK = 0x8000; |
| 239 | const uint16_t HALF_EXP_MASK = 0x7c00; |
| 240 | const uint16_t HALF_MANTISSA_MASK = 0x03ff; |
| 241 | const uint16_t HALF_EXP_POS = 0x000a; |
| 242 | const uint16_t FLOAT_EXP_POS = 0x0017; |
| 243 | const uint16_t FLOAT_SIGN_POS = 0x001f; |
| 244 | const uint16_t HALF_SIGN_POS = 0x000f; |
| 245 | const uint16_t HALF_FLOAT_DENORM_SA_OFFSET = 0x000a; |
| 246 | const uint32_t HALF_FLOAT_BIAS_OFFSET = HALF_EXP_BIAS - FLOAT_EXP_BIAS; |
| 247 | const uint16_t HALF_FLOAT_SIGN_POS_OFFSET = FLOAT_SIGN_POS - HALF_SIGN_POS; |
| 248 | const uint16_t HALF_FLOAT_MANTISSA_POS_OFFSET = FLOAT_EXP_POS - HALF_EXP_POS; |
| 249 | |
| 250 | // Extracting the sign, exponent, and mantissa from the 16-bit float |
| 251 | const uint32_t halfSignMasked = h.data & HALF_SIGN_MASK; |
| 252 | const uint32_t halfExpMasked = h.data & HALF_EXP_MASK; |
| 253 | const uint16_t halfMantissa = h.data & HALF_MANTISSA_MASK; |
| 254 | |
| 255 | // Shifting the sign bit to the correct position for the 32-bit float |
| 256 | const uint32_t floatSign = halfSignMasked << HALF_FLOAT_SIGN_POS_OFFSET; |
| 257 | |
| 258 | // Adjusting the exponent |
| 259 | const uint16_t halfExpHalfBias = halfExpMasked >> HALF_EXP_POS; |
| 260 | const uint32_t floatExp = halfExpHalfBias - HALF_FLOAT_BIAS_OFFSET; |
| 261 | |
| 262 | // Shifting the mantissa to the correct position for the 32-bit float |
| 263 | const uint32_t floatMantissa = halfMantissa << HALF_FLOAT_MANTISSA_POS_OFFSET; |
| 264 | |
| 265 | // Checking conditions for zero, denormalized, infinity, and NaN |
| 266 | const uint32_t isExpNonZero = halfExpMasked != 0; |
| 267 | const uint32_t isMantissaNonZero = halfMantissa != 0; |
| 268 | const uint32_t isZero = !(isExpNonZero || isMantissaNonZero); |
| 269 | const uint32_t isDenorm = !isZero && !isExpNonZero; |
| 270 | const uint32_t isExpFlagged = halfExpMasked == HALF_EXP_MASK; |
| 271 | const uint32_t isInf = isExpFlagged && !isMantissaNonZero; |
| 272 | const uint32_t isNan = isExpFlagged && isMantissaNonZero; |
| 273 | |
| 274 | // Handling denormalized numbers |
| 275 | const uint16_t halfMantissaLeadingZeros = __builtin_clz(halfMantissa) - 16; |
| 276 | const uint16_t halfDenormShiftAmount = |
| 277 | halfMantissaLeadingZeros + HALF_FLOAT_DENORM_SA_OFFSET; |
| 278 | const uint32_t halfFloatDenormMantissaShiftAmount = |
| 279 | halfDenormShiftAmount - TWO; |
| 280 | const uint32_t halfFloatDenormMantissa = |
| 281 | halfMantissa << halfFloatDenormMantissaShiftAmount; |
| 282 | const uint32_t floatDenormMantissa = |
| 283 | halfFloatDenormMantissa & FLOAT_MANTISSA_MASK; |
| 284 | const uint32_t halfFloatDenormShiftAmount = ONE - halfDenormShiftAmount; |
| 285 | const uint32_t floatDenormExp = halfFloatDenormShiftAmount + FLOAT_EXP_BIAS; |
| 286 | const uint32_t floatDenormExpPacked = floatDenormExp << FLOAT_EXP_POS; |
no test coverage detected