| 151 | } |
| 152 | |
| 153 | static inline fp16_t float_to_fp16(float x) { |
| 154 | #if defined(__AVX2__) |
| 155 | // F16C is guaranteed on all AVX2 CPUs; matches CUDA round-to-nearest-even behavior |
| 156 | return fp16_t{ |
| 157 | (uint16_t)_mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(x), _MM_FROUND_TO_NEAREST_INT | _MM_FROUND_NO_EXC), 0) |
| 158 | }; |
| 159 | #else |
| 160 | uint32_t bits; |
| 161 | std::memcpy(&bits, &x, 4); |
| 162 | uint32_t sign = (bits >> 31) & 0x1; |
| 163 | uint32_t exp = (bits >> 23) & 0xFF; |
| 164 | uint32_t mant = bits & 0x7FFFFF; |
| 165 | |
| 166 | uint16_t h; |
| 167 | if (exp == 0xFF) { // Inf / NaN |
| 168 | uint16_t mant16 = mant ? 0x200 : 0; // quiet NaN: set MSB of mantissa |
| 169 | h = (sign << 15) | (0x1F << 10) | mant16; |
| 170 | } else if (exp > 0x70 + 0x1E) { // overflow: exp_f -127 +15 > 30 (exp_f > 142) |
| 171 | h = (sign << 15) | (0x1F << 10); // Inf |
| 172 | } else if (exp < 0x71) { // subnormal or zero (exp_f < 113) |
| 173 | if (exp < 0x67) { // too small -> zero (exp_f < 103) |
| 174 | h = (sign << 15); |
| 175 | } else { |
| 176 | // subnormal: implicit leading 1 |
| 177 | uint32_t shift = 0x71 - exp; |
| 178 | uint32_t mant_with_hidden = mant | 0x800000; |
| 179 | // add rounding bias before shifting (23-10 =13 bits to drop + shift) |
| 180 | uint32_t rounded = (mant_with_hidden + (1u << (shift + 12))) >> (shift + 13); |
| 181 | h = (sign << 15) | (uint16_t)rounded; |
| 182 | } |
| 183 | } else { |
| 184 | // normalized |
| 185 | uint32_t exp_h = exp - 127 + 15; |
| 186 | // round mantissa: add 2^(23-10-1) = 0x1000 |
| 187 | uint32_t mant_rounded = mant + 0x00001000; |
| 188 | if (mant_rounded & 0x00800000) { // mantissa overflow after rounding |
| 189 | mant_rounded = 0; |
| 190 | ++exp_h; |
| 191 | if (exp_h >= 0x1F) { // overflow to Inf |
| 192 | h = (sign << 15) | (0x1F << 10); |
| 193 | return fp16_t{h}; |
| 194 | } |
| 195 | } |
| 196 | h = (sign << 15) | ((uint16_t)exp_h << 10) | ((uint16_t)(mant_rounded >> 13)); |
| 197 | } |
| 198 | return fp16_t{h}; |
| 199 | #endif |
| 200 | } |
| 201 | |
| 202 | static inline float fp16_to_float(uint16_t h) { |
| 203 | #if defined(__AVX2__) |
no outgoing calls
no test coverage detected