// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //============================================================ // // Class: Single // // Purpose: A wrapper class for the primitive type float. // //=========================================================== namespace System { using System.Globalization; using System; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; //| [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)] public struct Single : IComparable, IFormattable { internal float m_value; // // Public constants // //| public const float MinValue = (float)-3.40282346638528859e+38; //| public const float Epsilon = (float)1.4e-45; //| public const float MaxValue = (float)3.40282346638528859e+38; //| public const float PositiveInfinity = (float)1.0 / (float)0.0; //| public const float NegativeInfinity = (float)-1.0 / (float)0.0; //| public const float NaN = (float)0.0 / (float)0.0; // // Private constants // private const ulong PositiveInfinityAsUInt32 = 0x7f800000; private const ulong NegativeInfinityAsUInt32 = 0xff800000; private const ulong ExponentAsUInt32 = 0xff80000; private const ulong MantissaAsUInt32 = 0x007ffff; // // Native Declarations // //| public static bool IsInfinity(float f) { uint v = BitConverter.SingleToUInt32Bits(f); return (v == PositiveInfinityAsUInt32 || v == NegativeInfinityAsUInt32); } //| public static bool IsPositiveInfinity(float f) { uint v = BitConverter.SingleToUInt32Bits(f); return (v == PositiveInfinityAsUInt32); } //| public static bool IsNegativeInfinity(float f) { uint v = BitConverter.SingleToUInt32Bits(f); return (v == NegativeInfinityAsUInt32); } //| public int CompareTo(Object value) { if (value == null) { return 1; } if (value is Single) { float f = (float)value; if (m_value < f) return -1; if (m_value > f) return 1; if (m_value == f) return 0; // At least one of the values is NaN. if (IsNaN(m_value)) return (IsNaN(f) ? 0 : -1); else // f is NaN. return 1; } throw new ArgumentException ("Arg_MustBeSingle"); } //| public override bool Equals(Object obj) { if (!(obj is Single)) { return false; } float temp = ((Single)obj).m_value; if (temp == m_value) { return true; } return IsNaN(temp) && IsNaN(m_value); } //| public override int GetHashCode() { return unchecked((int)BitConverter.SingleToUInt32Bits(m_value)); } //| public override String ToString() { return ToString(null); } //| public String ToString(String format) { return Number.FormatSingle(m_value, format); } //| public static float Parse(String s) { return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands); } // Parses a float from a String in the given style. If // a NumberFormatInfo isn't specified, the current culture's // NumberFormatInfo is assumed. // // This method will not throw an OverflowException, but will return // PositiveInfinity or NegativeInfinity for a number that is too // large or too small. // //| public static float Parse(String s, NumberStyles style) { try { return Number.ParseSingle(s, style); } catch (FormatException) { //If we caught a FormatException, it may be from one of our special strings. //Check the three with which we're concerned and rethrow if it's not one of //those strings. String sTrim = s.Trim(); if (sTrim.Equals(NumberFormatInfo.positiveInfinitySymbol)) { return PositiveInfinity; } if (sTrim.Equals(NumberFormatInfo.negativeInfinitySymbol)) { return NegativeInfinity; } if (sTrim.Equals(NumberFormatInfo.nanSymbol)) { return NaN; } //Rethrow the previous exception; throw; } } // // IValue implementation // //| [NoHeapAllocation] public override TypeCode GetTypeCode() { return TypeCode.Single; } // // This is just designed to prevent compiler warnings. // This field is used from native, but we need to prevent the compiler warnings. // #if _DEBUG private void DontTouchThis() { m_value = 0; } #endif } }