Original ISPC reference version; this always rounds ties up.
| 35 | |
| 36 | // Original ISPC reference version; this always rounds ties up. |
| 37 | FP16 float_to_half(FP32 f) |
| 38 | { |
| 39 | FP16 o = { 0 }; |
| 40 | |
| 41 | // Based on ISPC reference code (with minor modifications) |
| 42 | if (f.Exponent == 0) // Signed zero/denormal (which will underflow) |
| 43 | o.Exponent = 0; |
| 44 | else if (f.Exponent == 255) // Inf or NaN (all exponent bits set) |
| 45 | { |
| 46 | o.Exponent = 31; |
| 47 | o.Mantissa = f.Mantissa ? 0x200 : 0; // NaN->qNaN and Inf->Inf |
| 48 | } |
| 49 | else // Normalized number |
| 50 | { |
| 51 | // Exponent unbias the single, then bias the halfp |
| 52 | int newexp = f.Exponent - 127 + 15; |
| 53 | if (newexp >= 31) // Overflow, return signed infinity |
| 54 | o.Exponent = 31; |
| 55 | else if (newexp <= 0) // Underflow |
| 56 | { |
| 57 | if ((14 - newexp) <= 24) // Mantissa might be non-zero |
| 58 | { |
| 59 | uint mant = f.Mantissa | 0x800000; // Hidden 1 bit |
| 60 | o.Mantissa = mant >> (14 - newexp); |
| 61 | if ((mant >> (13 - newexp)) & 1) // Check for rounding |
| 62 | o.u++; // Round, might overflow into exp bit, but this is OK |
| 63 | } |
| 64 | } |
| 65 | else |
| 66 | { |
| 67 | o.Exponent = newexp; |
| 68 | o.Mantissa = f.Mantissa >> 13; |
| 69 | if (f.Mantissa & 0x1000) // Check for rounding |
| 70 | o.u++; // Round, might overflow to inf, this is OK |
| 71 | } |
| 72 | } |
| 73 | |
| 74 | o.Sign = f.Sign; |
| 75 | return o; |
| 76 | } |
| 77 | |
| 78 | FP32 half_to_float(FP16 h) |
| 79 | { |