The Labs \ Source Viewer \ SSCLI \ System \ Double

  1. // ==++==
  2. //
  3. //
  4. // Copyright (c) 2006 Microsoft Corporation. All rights reserved.
  5. //
  6. // The use and distribution terms for this software are contained in the file
  7. // named license.txt, which can be found in the root of this distribution.
  8. // By using this software in any fashion, you are agreeing to be bound by the
  9. // terms of this license.
  10. //
  11. // You must not remove this notice, or any other, from this software.
  12. //
  13. //
  14. // ==--==
  15. /*============================================================
  16. **
  17. ** Class:  Double
  18. **
  19. **
  20. ** Purpose: A representation of an IEEE double precision
  21. **          floating point number.
  22. **
  23. **
  24. ===========================================================*/
  25. namespace System
  26. {
  27.    
  28.     using System;
  29.     using System.Globalization;
  30.     using System.Runtime.InteropServices;
  31.     using System.Runtime.CompilerServices;
  32.     using System.Runtime.ConstrainedExecution;
  33.    
  34.     [Serializable(), StructLayout(LayoutKind.Sequential)]
  35.     [System.Runtime.InteropServices.ComVisible(true)]
  36.     public struct Double : IComparable, IFormattable, IConvertible, IComparable<double>, IEquatable<double>
  37.     {
  38.         internal double m_value;
  39.        
  40.         //
  41.         // Public Constants
  42.         //
  43.         public const double MinValue = -1.79769313486232E+308;
  44.         public const double MaxValue = 1.79769313486232E+308;
  45.        
  46.         // Note Epsilon should be a double whose hex representation is 0x1
  47.         // on little endian machines.
  48.         public const double Epsilon = 4.94065645841247E-324;
  49.         public const double NegativeInfinity = (double)-1.0 / (double)(0.0);
  50.         public const double PositiveInfinity = (double)1.0 / (double)(0.0);
  51.         public const double NaN = (double)0.0 / (double)0.0;
  52.        
  53.         static internal double NegativeZero = BitConverter.Int64BitsToDouble(unchecked((long)9223372036854775808ul));
  54.        
  55.         unsafe public static bool IsInfinity(double d)
  56.         {
  57.             return (*(long*)(&d) & 9223372036854775807l) == 9218868437227405312l;
  58.         }
  59.         public static bool IsPositiveInfinity(double d)
  60.         {
  61.             //Jit will generate inlineable code with this
  62.             if (d == double.PositiveInfinity) {
  63.                 return true;
  64.             }
  65.             else {
  66.                 return false;
  67.             }
  68.         }
  69.         public static bool IsNegativeInfinity(double d)
  70.         {
  71.             //Jit will generate inlineable code with this
  72.             if (d == double.NegativeInfinity) {
  73.                 return true;
  74.             }
  75.             else {
  76.                 return false;
  77.             }
  78.         }
  79.        
  80.         unsafe static internal bool IsNegative(double d)
  81.         {
  82.             return (*(UInt64*)(&d) & 9223372036854775808ul) == 9223372036854775808ul;
  83.         }
  84.        
  85.         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
  86.         public static bool IsNaN(double d)
  87.         {
  88.             //Jit will generate inlineable code with this
  89.             // warning CS1718: comparison to same variable
  90.             #pragma warning disable 1718
  91.             if (d != d) {
  92.                 return true;
  93.             }
  94.             else {
  95.                 return false;
  96.             }
  97.             #pragma warning restore 1718
  98.         }
  99.        
  100.        
  101.         // Compares this object to another object, returning an instance of System.Relation.
  102.         // Null is considered less than any instance.
  103.         //
  104.         // If object is not of type Double, this method throws an ArgumentException.
  105.         //
  106.         // Returns a value less than zero if this object
  107.         //
  108.         public int CompareTo(object value)
  109.         {
  110.             if (value == null) {
  111.                 return 1;
  112.             }
  113.             if (value is double) {
  114.                 double d = (double)value;
  115.                 if (m_value < d)
  116.                     return -1;
  117.                 if (m_value > d)
  118.                     return 1;
  119.                 if (m_value == d)
  120.                     return 0;
  121.                
  122.                 // At least one of the values is NaN.
  123.                 if (IsNaN(m_value))
  124.                     return (IsNaN(d) ? 0 : -1);
  125.                 else
  126.                     return 1;
  127.             }
  128.             throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDouble"));
  129.         }
  130.        
  131.         public int CompareTo(double value)
  132.         {
  133.             if (m_value < value)
  134.                 return -1;
  135.             if (m_value > value)
  136.                 return 1;
  137.             if (m_value == value)
  138.                 return 0;
  139.            
  140.             // At least one of the values is NaN.
  141.             if (IsNaN(m_value))
  142.                 return (IsNaN(value) ? 0 : -1);
  143.             else
  144.                 return 1;
  145.         }
  146.        
  147.         // True if obj is another Double with the same value as the current instance. This is
  148.         // a method of object equality, that only returns true if obj is also a double.
  149.         public override bool Equals(object obj)
  150.         {
  151.             if (!(obj is double)) {
  152.                 return false;
  153.             }
  154.             double temp = ((double)obj).m_value;
  155.             // This code below is written this way for performance reasons i.e the != and == check is intentional.
  156.             if (temp == m_value) {
  157.                 return true;
  158.             }
  159.             return IsNaN(temp) && IsNaN(m_value);
  160.         }
  161.        
  162.         public bool Equals(double obj)
  163.         {
  164.             if (obj == m_value) {
  165.                 return true;
  166.             }
  167.             return IsNaN(obj) && IsNaN(m_value);
  168.         }
  169.        
  170.         //The hashcode for a double is the absolute value of the integer representation
  171.         //of that double.
  172.         //
  173.         unsafe public override int GetHashCode()
  174.         {
  175.             double d = m_value;
  176.             if (d == 0) {
  177.                 // Ensure that 0 and -0 have the same hash code
  178.                 return 0;
  179.             }
  180.             long value = *(long*)(&d);
  181.             return unchecked((int)value) ^ ((int)(value >> 32));
  182.         }
  183.        
  184.         public override string ToString()
  185.         {
  186.             return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
  187.         }
  188.        
  189.         public string ToString(string format)
  190.         {
  191.             return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
  192.         }
  193.        
  194.         public string ToString(IFormatProvider provider)
  195.         {
  196.             return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
  197.         }
  198.        
  199.         public string ToString(string format, IFormatProvider provider)
  200.         {
  201.             return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
  202.         }
  203.        
  204.         public static double Parse(string s)
  205.         {
  206.             return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
  207.         }
  208.        
  209.         public static double Parse(string s, NumberStyles style)
  210.         {
  211.             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
  212.             return Parse(s, style, NumberFormatInfo.CurrentInfo);
  213.         }
  214.        
  215.         public static double Parse(string s, IFormatProvider provider)
  216.         {
  217.             return Parse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
  218.         }
  219.        
  220.         public static double Parse(string s, NumberStyles style, IFormatProvider provider)
  221.         {
  222.             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
  223.             return Parse(s, style, NumberFormatInfo.GetInstance(provider));
  224.         }
  225.        
  226.         // Parses a double from a String in the given style. If
  227.         // a NumberFormatInfo isn't specified, the current culture's
  228.         // NumberFormatInfo is assumed.
  229.         //
  230.         // This method will not throw an OverflowException, but will return
  231.         // PositiveInfinity or NegativeInfinity for a number that is too
  232.         // large or too small.
  233.         //
  234.         private static double Parse(string s, NumberStyles style, NumberFormatInfo info)
  235.         {
  236.             try {
  237.                 return Number.ParseDouble(s, style, info);
  238.             }
  239.             catch (FormatException) {
  240.                 //If we caught a FormatException, it may be from one of our special strings.
  241.                 //Check the three with which we're concerned and rethrow if it's not one of
  242.                 //those strings.
  243.                 string sTrim = s.Trim();
  244.                 if (sTrim.Equals(info.PositiveInfinitySymbol)) {
  245.                     return PositiveInfinity;
  246.                 }
  247.                 if (sTrim.Equals(info.NegativeInfinitySymbol)) {
  248.                     return NegativeInfinity;
  249.                 }
  250.                 if (sTrim.Equals(info.NaNSymbol)) {
  251.                     return NaN;
  252.                 }
  253.                 //Rethrow the previous exception;
  254.                 throw;
  255.             }
  256.         }
  257.        
  258.         public static bool TryParse(string s, out double result)
  259.         {
  260.             return TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
  261.         }
  262.        
  263.         public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out double result)
  264.         {
  265.             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
  266.             return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
  267.         }
  268.        
  269.         private static bool TryParse(string s, NumberStyles style, NumberFormatInfo info, out double result)
  270.         {
  271.             if (s == null) {
  272.                 result = 0;
  273.                 return false;
  274.             }
  275.             bool success = Number.TryParseDouble(s, style, info, out result);
  276.             if (!success) {
  277.                 string sTrim = s.Trim();
  278.                 if (sTrim.Equals(info.PositiveInfinitySymbol)) {
  279.                     result = PositiveInfinity;
  280.                 }
  281.                 else if (sTrim.Equals(info.NegativeInfinitySymbol)) {
  282.                     result = NegativeInfinity;
  283.                 }
  284.                 else if (sTrim.Equals(info.NaNSymbol)) {
  285.                     result = NaN;
  286.                 }
  287.                 else
  288.                     return false;
  289.                 // We really failed
  290.             }
  291.             return true;
  292.         }
  293.        
  294.         //
  295.         // IValue implementation
  296.         //
  297.        
  298.         public TypeCode GetTypeCode()
  299.         {
  300.             return TypeCode.Double;
  301.         }
  302.        
  303.         /// <internalonly/>
  304.         bool IConvertible.ToBoolean(IFormatProvider provider)
  305.         {
  306.             return Convert.ToBoolean(m_value);
  307.         }
  308.        
  309.         /// <internalonly/>
  310.         char IConvertible.ToChar(IFormatProvider provider)
  311.         {
  312.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Double", "Char"));
  313.         }
  314.        
  315.         /// <internalonly/>
  316.         sbyte IConvertible.ToSByte(IFormatProvider provider)
  317.         {
  318.             return Convert.ToSByte(m_value);
  319.         }
  320.        
  321.         /// <internalonly/>
  322.         byte IConvertible.ToByte(IFormatProvider provider)
  323.         {
  324.             return Convert.ToByte(m_value);
  325.         }
  326.        
  327.         /// <internalonly/>
  328.         short IConvertible.ToInt16(IFormatProvider provider)
  329.         {
  330.             return Convert.ToInt16(m_value);
  331.         }
  332.        
  333.         /// <internalonly/>
  334.         ushort IConvertible.ToUInt16(IFormatProvider provider)
  335.         {
  336.             return Convert.ToUInt16(m_value);
  337.         }
  338.        
  339.         /// <internalonly/>
  340.         int IConvertible.ToInt32(IFormatProvider provider)
  341.         {
  342.             return Convert.ToInt32(m_value);
  343.         }
  344.        
  345.         /// <internalonly/>
  346.         uint IConvertible.ToUInt32(IFormatProvider provider)
  347.         {
  348.             return Convert.ToUInt32(m_value);
  349.         }
  350.        
  351.         /// <internalonly/>
  352.         long IConvertible.ToInt64(IFormatProvider provider)
  353.         {
  354.             return Convert.ToInt64(m_value);
  355.         }
  356.        
  357.         /// <internalonly/>
  358.         ulong IConvertible.ToUInt64(IFormatProvider provider)
  359.         {
  360.             return Convert.ToUInt64(m_value);
  361.         }
  362.        
  363.         /// <internalonly/>
  364.         float IConvertible.ToSingle(IFormatProvider provider)
  365.         {
  366.             return Convert.ToSingle(m_value);
  367.         }
  368.        
  369.         /// <internalonly/>
  370.         double IConvertible.ToDouble(IFormatProvider provider)
  371.         {
  372.             return m_value;
  373.         }
  374.        
  375.         /// <internalonly/>
  376.         decimal IConvertible.ToDecimal(IFormatProvider provider)
  377.         {
  378.             return Convert.ToDecimal(m_value);
  379.         }
  380.        
  381.         /// <internalonly/>
  382.         DateTime IConvertible.ToDateTime(IFormatProvider provider)
  383.         {
  384.             throw new InvalidCastException(String.Format(CultureInfo.CurrentCulture, Environment.GetResourceString("InvalidCast_FromTo"), "Double", "DateTime"));
  385.         }
  386.        
  387.         /// <internalonly/>
  388.         object IConvertible.ToType(Type type, IFormatProvider provider)
  389.         {
  390.             return Convert.DefaultToType((IConvertible)this, type, provider);
  391.         }
  392.     }
  393. }

Developer Fusion