public static ushort Float32ToUInt16(float value) { var f32infty = new Float32IntegerUnion { I = 255 << 23 }; var f16infty = new Float32IntegerUnion { I = 31 << 23 }; var magic = new Float32IntegerUnion { I = 15 << 23 }; var inval = new Float32IntegerUnion { F = value }; var sign_mask = 0x80000000; var round_mask = ~0xFFFU; var sign = inval.I & sign_mask; inval.I ^= sign; ushort @out; if (inval.I >= f32infty.I) // Inf or NaN (all exponent bits set) { @out = (ushort)(inval.I > f32infty.I ? 0x7FFFu : 0x7C00u); } else { inval.I &= round_mask; inval.F *= magic.F; inval.I -= round_mask; if (inval.I > f16infty.I) { inval.I = f16infty.I; // Clamp to signed infinity if overflowed } @out = (ushort)((inval.I >> 13) & 0xFFFF); // Take the bits! } return((ushort)(@out | (sign >> 16) & 0xFFFF)); }
public static float UInt16ToFloat32(ushort value) { var magic = new Float32IntegerUnion { I = (254 - 15) << 23 }; var was_inf_nan = new Float32IntegerUnion { I = (127 + 16) << 23 }; var union = new Float32IntegerUnion { I = ((uint)value & 0x7FFF) << 13 }; // exponent/mantissa bits union.F *= magic.F; // exponent adjust if (union.F >= was_inf_nan.F) // make sure Inf/NaN survive { union.I |= 255 << 23; } union.I |= ((uint)value & 0x8000) << 16; // sign bit return(union.F); }