/// <summary> /// Constructs an instance of this class with the value of the argument. /// </summary> /// <param name="value">A <b>float</b> value.</param> public glFloat16(float value) { #if !SLOW_BUT_PLATTFORM_INDEPENDENT_FLOAT_CONVERSION // Get bits as uint SingleUInt32Union union = new SingleUInt32Union(); union.single = value; uint ivalue = union.uint32; // Signed zero? if ((ivalue & 0x7FFFFFFF) == 0) { Value = (ushort)(ivalue >> 16); // Set signed zero return; } uint maskedSign = ivalue & 0x80000000; uint maskedExpo = ivalue & 0x7F800000; // Denormalized number? (this would underflow anyway) if (maskedExpo == 0) { Value = (ushort)(maskedSign >> 16); // Set signed zero return; } uint maskedMant = ivalue & 0x007FFFFF; // Infinity or NaN? (all exponent bits set) if (maskedExpo == 0x7F800000) { // NaN? if (maskedMant != 0) { Value = NaN; } else { Value = (ushort)((maskedSign >> 16) | ExponentMask); // Set signed infinity } return; } // Normalized number Value = (ushort)(maskedSign >> 16); int iExponent = ((int)maskedExpo >> 23) - 127 + 15; // Convert exponent from float range to 16-bit float range // Overflow? (exponent out of range) if (iExponent >= 0x1F) { Value |= ExponentMask; // Set signed infinity return; } // Underflow? (exponent out of range) if (iExponent <= 0) { // No mantissa bits left if ((14 - iExponent) > 24) { return; } // Make denormalized number maskedMant |= 0x00800000; // Add the leading one digit ushort denormMantissa = (ushort)(maskedMant >> (14 - iExponent)); // Check for rounding if (((maskedMant >> (13 - iExponent)) & 1) != 0) { denormMantissa++; } Value |= denormMantissa; return; } Value |= (ushort)(iExponent << 10); Value |= (ushort)(maskedMant >> 13); // Check for rounding if ((maskedMant & 0x00001000) != 0) { Value++; } #else if (float.IsNaN(value)) { Value = NaN; return; } if (float.IsPositiveInfinity(value)) { Value = PositiveInfinity; return; } if (float.IsNegativeInfinity(value)) { Value = NegativeInfinity; return; } if (value < MinValue) { value = MinValue; } else if (value > MaxValue) { value = MaxValue; } Value = 0; if (value < 0) { value = Math.Abs(value); Value = SignMask; } int exp = (int)(Math.Log(value, 2) + 15); if (exp <= 0) { Value |= (ushort)(value * (1 << 24) + 0.5f); } else if (exp > 25) { Value |= (ushort)((exp << 10) + (int)(value / (1 << (exp - 25)) - 1023.5f)); } else { Value |= (ushort)((exp << 10) + (int)(value * (1 << (25 - exp)) - 1023.5f)); } #endif }
/// <summary> /// Constructs an instance of this class with the value of the argument. /// </summary> /// <param name="value">A <b>float</b> value.</param> public glUFloat10(float value) { #if !SLOW_BUT_PLATTFORM_INDEPENDENT_FLOAT_CONVERSION // Get bits as uint SingleUInt32Union union = new SingleUInt32Union(); union.single = value; uint ivalue = union.uint32; Value = 0; // Zero? if ((ivalue & 0x7FFFFFFF) == 0) { return; } uint maskedExpo = ivalue & 0x7F800000; // Denormalized number? (this would underflow anyway) if (maskedExpo == 0) { return; } uint maskedMant = ivalue & 0x007FFFFF; // Infinity or NaN? (all exponent bits set) if (maskedExpo == 0x7F800000) { // NaN? if (maskedMant != 0) { Value = NaN; } else if ((ivalue & 0x80000000) == 0) { Value = Infinity; // Negative infinity => 0 } return; } // Negative? if ((ivalue & 0x80000000) != 0) { return; } // Normalized number int iExponent = ((int)maskedExpo >> 23) - 127 + 15; // Convert exponent from float range to 16-bit float range // Overflow? (exponent out of range) if (iExponent >= 0x1F) { Value = Infinity; return; } // Underflow? (exponent out of range) if (iExponent <= 0) { // No mantissa bits left if ((19 - iExponent) > 24) { return; } // Make denormalized number maskedMant |= 0x00800000; // Add the leading one digit ushort denormMantissa = (ushort)(maskedMant >> (19 - iExponent)); // Check for rounding if (((maskedMant >> (18 - iExponent)) & 1) != 0) { denormMantissa++; } Value |= denormMantissa; return; } Value |= (ushort)(iExponent << 5); Value |= (ushort)(maskedMant >> 18); // Check for rounding if ((maskedMant & 0x00020000) != 0) { Value++; } #else if (float.IsNaN(value)) { Value = NaN; return; } if (float.IsInfinity(value)) { Value = Infinity; return; } if (value < MinValue) { value = MinValue; } else if (value > MaxValue) { value = MaxValue; } int exp = (int)(Math.Log(value, 2) + 15); if (exp <= 0) { Value = (ushort)(value * (1 << 19) + 0.5f); } else if (exp > 20) { Value = (ushort)((exp << 5) + (int)(value / (1 << (exp - 20)) - 31.5f)); } else { Value = (ushort)((exp << 5) + (int)(value * (1 << (20 - exp)) - 31.5f)); } #endif }