// ==++== // // Copyright (c) Microsoft Corporation. All rights reserved. // // ==--== //============================================================ // // Class: Double // // Purpose: A representation of an IEEE double precision // floating point number. // //=========================================================== namespace System { using System; using System.Globalization; using System.Runtime.InteropServices; using System.Runtime.CompilerServices; //| [StructLayout(LayoutKind.Sequential)] public struct Double : IComparable, IFormattable { internal double m_value; // // Public Constants // //| public const double MinValue = -1.7976931348623157E+308; //| public const double MaxValue = 1.7976931348623157E+308; // Real value of Epsilon: 4.9406564584124654e-324 (0x1), but JVC misparses that // number, giving 2*Epsilon (0x2). //| public const double Epsilon = 4.9406564584124650E-324; //| public const double NegativeInfinity = (double)-1.0 / (double)(0.0); //| public const double PositiveInfinity = (double)1.0 / (double)(0.0); //| public const double NaN = (double)0.0 / (double)0.0; // // Private constants // private const ulong PositiveInfinityAsUInt64 = 0x7ff0000000000000; private const ulong NegativeInfinityAsUInt64 = 0xfff0000000000000; private const ulong ExponentAsUInt64 = 0xfff0000000000000; private const ulong MantissaAsUInt64 = 0x000fffffffffffff; // // Native Declarations // //| public static bool IsInfinity(double d) { ulong v = BitConverter.DoubleToUInt64Bits(d); return (v == PositiveInfinityAsUInt64 || v == NegativeInfinityAsUInt64); } //| public static bool IsPositiveInfinity(double d) { ulong v = BitConverter.DoubleToUInt64Bits(d); return (v == PositiveInfinityAsUInt64); } //| public static bool IsNegativeInfinity(double d) { ulong v = BitConverter.DoubleToUInt64Bits(d); return (v == NegativeInfinityAsUInt64); } //| public static bool IsNaN(double d) { // See also Lightning\Src\ClassLibNative\Float\COMFloat::IsNAN ulong v = BitConverter.DoubleToUInt64Bits(d); return (((v & PositiveInfinityAsUInt64) == v) && ((v & MantissaAsUInt64) != 0)); } // Compares this object to another object, returning an instance of System.Relation. // Null is considered less than any instance. // // If object is not of type Double, this method throws an ArgumentException. // // Returns a value less than zero if this object // //| public int CompareTo(Object value) { if (value == null) { return 1; } if (value is Double) { double d = (double)value; if (m_value < d) return -1; if (m_value > d) return 1; if (m_value == d) return 0; // At least one of the values is NaN. // This is busted; NaNs should never compare equal if (IsNaN(m_value)) return (IsNaN(d) ? 0 : -1); else return 1; } throw new ArgumentException("Arg_MustBeDouble"); } // True if obj is another Double with the same value as the current instance. This is // a method of object equality, that only returns true if obj is also a double. //| public override bool Equals(Object obj) { if (!(obj is Double)) { return false; } double temp = ((Double)obj).m_value; // This code below is written this way for performance reasons i.e the != and == check is intentional. if (temp == m_value) { return true; } return IsNaN(temp) && IsNaN(m_value); } //The hashcode for a double is the absolute value of the integer representation //of that double. // //| public override int GetHashCode() { long value = unchecked((long)BitConverter.DoubleToUInt64Bits(m_value)); return ((int)value) ^ ((int)(value >> 32)); } //| public override String ToString() { return ToString(null); } //| public String ToString(String format) { return Number.FormatDouble(m_value, format); } //| public static double Parse(String s) { return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands); } //| public static double Parse(String s, NumberStyles style) { try { return Number.ParseDouble(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; } } //| public static bool TryParse(String s, NumberStyles style, out double result) { if (s == null) { result = 0; return false; } bool success = Number.TryParseDouble(s, style, out result); if (!success) { String sTrim = s.Trim(); if (sTrim.Equals(NumberFormatInfo.positiveInfinitySymbol)) { result = PositiveInfinity; } else if (sTrim.Equals(NumberFormatInfo.negativeInfinitySymbol)) { result = NegativeInfinity; } else if (sTrim.Equals(NumberFormatInfo.nanSymbol)) { result = NaN; } else return false; // We really failed } return true; } // // IValue implementation // //| [NoHeapAllocation] public override TypeCode GetTypeCode() { return TypeCode.Double; } } }