| 3134 | exp = 1; |
| 3135 | while ((mant & 0x0400) == 0) { |
| 3136 | mant <<= 1; |
| 3137 | exp--; |
| 3138 | } |
| 3139 | mant &= 0x03ff; |
| 3140 | bits = sign | ((exp + 127 - 15) << 23) | (mant << 13); |
| 3141 | } |
| 3142 | } else if (exp == 31) { |
| 3143 | bits = sign | 0x7f800000u | (mant << 13); |
| 3144 | } else { |
| 3145 | bits = sign | ((exp + 127 - 15) << 23) | (mant << 13); |
| 3146 | } |
| 3147 | |
| 3148 | float f; |
| 3149 | memcpy(&f, &bits, sizeof(f)); |
| 3150 | return f; |
| 3151 | #endif |
| 3152 | } |
| 3153 | |
| 3154 | static inline uint16_t f32_to_f16(float f) { |
| 3155 | #if defined(__ARM_NEON) |
| 3156 | const float32x4_t fv = vdupq_n_f32(f); |
| 3157 | const float16x4_t hv = vcvt_f16_f32(fv); |
| 3158 | return vget_lane_u16(vreinterpret_u16_f16(hv), 0); |
| 3159 | #else |
| 3160 | uint32_t bits; |
| 3161 | memcpy(&bits, &f, sizeof(bits)); |
| 3162 | |
| 3163 | const uint32_t sign = (bits >> 16) & 0x8000u; |
| 3164 | int32_t exp = (int32_t)((bits >> 23) & 0xffu) - 127 + 15; |
| 3165 | uint32_t mant = bits & 0x7fffffu; |
| 3166 | |
| 3167 | if (exp <= 0) { |
| 3168 | if (exp < -10) return (uint16_t)sign; |
| 3169 | mant |= 0x800000u; |
| 3170 | const uint32_t shift = (uint32_t)(14 - exp); |
| 3171 | uint32_t half_mant = mant >> shift; |
| 3172 | const uint32_t round_bit = (mant >> (shift - 1)) & 1u; |
| 3173 | const uint32_t sticky = mant & ((1u << (shift - 1)) - 1u); |
| 3174 | if (round_bit && (sticky || (half_mant & 1u))) half_mant++; |
| 3175 | return (uint16_t)(sign | half_mant); |
| 3176 | } |
| 3177 | |
| 3178 | if (exp >= 31) { |
no test coverage detected