Bump corefx
[mono.git] / mcs / class / referencesource / mscorlib / system / double.cs
1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 ** Class:  Double
9 **
10 **
11 ** Purpose: A representation of an IEEE double precision
12 **          floating point number.
13 **
14 **
15 ===========================================================*/
16 namespace System {
17
18     using System;
19     using System.Globalization;
20 ///#if GENERICS_WORK
21 ///    using System.Numerics;
22 ///#endif
23     using System.Runtime.InteropServices;
24     using System.Runtime.CompilerServices;
25     using System.Runtime.ConstrainedExecution;
26     using System.Diagnostics.Contracts;
27
28 [Serializable]
29 [StructLayout(LayoutKind.Sequential)]
30 [System.Runtime.InteropServices.ComVisible(true)]
31 #if GENERICS_WORK
32     public struct Double : IComparable, IFormattable, IConvertible
33         , IComparable<Double>, IEquatable<Double>
34 ///     , IArithmetic<Double>
35 #else
36     public struct Double : IComparable, IFormattable, IConvertible
37 #endif
38     {
39         internal double m_value;
40
41         //
42         // Public Constants
43         //
44         public const double MinValue = -1.7976931348623157E+308;
45         public const double MaxValue = 1.7976931348623157E+308;
46
47         // Note Epsilon should be a double whose hex representation is 0x1
48         // on little endian machines.
49         public const double Epsilon  = 4.9406564584124654E-324;
50         public const double NegativeInfinity = (double)-1.0 / (double)(0.0);
51         public const double PositiveInfinity = (double)1.0 / (double)(0.0);
52         public const double NaN = (double)0.0 / (double)0.0;
53         
54         internal static double NegativeZero = BitConverter.Int64BitsToDouble(unchecked((long)0x8000000000000000));
55
56         [Pure]
57         [System.Security.SecuritySafeCritical]  // auto-generated
58         [System.Runtime.Versioning.NonVersionable]
59         public unsafe static bool IsInfinity(double d) {
60             return (*(long*)(&d) & 0x7FFFFFFFFFFFFFFF) == 0x7FF0000000000000;
61         }
62
63         [Pure]
64         [System.Runtime.Versioning.NonVersionable]
65         public static bool IsPositiveInfinity(double d) {
66             //Jit will generate inlineable code with this
67             if (d == double.PositiveInfinity)
68             {
69                 return true;
70             }
71             else
72             {
73                 return false;
74             }
75         }
76
77         [Pure]
78         [System.Runtime.Versioning.NonVersionable]
79         public static bool IsNegativeInfinity(double d) {
80             //Jit will generate inlineable code with this
81             if (d == double.NegativeInfinity)
82             {
83                 return true;
84             }
85             else
86             {
87                 return false;
88             }
89         }
90
91         [Pure]
92         [System.Security.SecuritySafeCritical]  // auto-generated
93         internal unsafe static bool IsNegative(double d) {
94             return (*(UInt64*)(&d) & 0x8000000000000000) == 0x8000000000000000;
95         }
96
97         [Pure]
98         [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
99         [System.Security.SecuritySafeCritical]
100         [System.Runtime.Versioning.NonVersionable]
101         public unsafe static bool IsNaN(double d)
102         {
103             return (*(UInt64*)(&d) & 0x7FFFFFFFFFFFFFFFL) > 0x7FF0000000000000L;
104         }
105
106 #if MONO
107         [Pure]
108         [System.Runtime.Versioning.NonVersionable]
109         [MethodImpl(MethodImplOptions.AggressiveInlining)]
110         public unsafe static bool IsFinite(double d)
111         {
112             var bits = BitConverter.DoubleToInt64Bits(d);
113             return (bits & 0x7FFFFFFFFFFFFFFF) < 0x7FF0000000000000;
114         }
115 #endif
116
117         // Compares this object to another object, returning an instance of System.Relation.
118         // Null is considered less than any instance.
119         //
120         // If object is not of type Double, this method throws an ArgumentException.
121         //
122         // Returns a value less than zero if this  object
123         //
124         public int CompareTo(Object value) {
125             if (value == null) {
126                 return 1;
127             }
128             if (value is Double) {
129                 double d = (double)value;
130                 if (m_value < d) return -1;
131                 if (m_value > d) return 1;
132                 if (m_value == d) return 0;
133
134                 // At least one of the values is NaN.
135                 if (IsNaN(m_value))
136                     return (IsNaN(d) ? 0 : -1);
137                 else
138                     return 1;
139             }
140             throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDouble"));
141         }
142
143         public int CompareTo(Double value) {
144             if (m_value < value) return -1;
145             if (m_value > value) return 1;
146             if (m_value == value) return 0;
147
148             // At least one of the values is NaN.
149             if (IsNaN(m_value))
150                 return (IsNaN(value) ? 0 : -1);
151             else
152                 return 1;
153         }
154
155         // True if obj is another Double with the same value as the current instance.  This is
156         // a method of object equality, that only returns true if obj is also a double.
157         public override bool Equals(Object obj) {
158             if (!(obj is Double)) {
159                 return false;
160             }
161             double temp = ((Double)obj).m_value;
162             // This code below is written this way for performance reasons i.e the != and == check is intentional.
163             if (temp == m_value) {
164                 return true;
165             }
166             return IsNaN(temp) && IsNaN(m_value);
167         }
168
169         [System.Runtime.Versioning.NonVersionable]
170         public static bool operator ==(Double left, Double right) {
171             return left == right;
172         }
173
174         [System.Runtime.Versioning.NonVersionable]
175         public static bool operator !=(Double left, Double right) {
176             return left != right;
177         }
178
179         [System.Runtime.Versioning.NonVersionable]
180         public static bool operator <(Double left, Double right) {
181             return left < right;
182         }
183
184         [System.Runtime.Versioning.NonVersionable]
185         public static bool operator >(Double left, Double right) {
186             return left > right;
187         }
188
189         [System.Runtime.Versioning.NonVersionable]
190         public static bool operator <=(Double left, Double right) {
191             return left <= right;
192         }
193
194         [System.Runtime.Versioning.NonVersionable]
195         public static bool operator >=(Double left, Double right) {
196             return left >= right;
197         }
198
199         public bool Equals(Double obj)
200         {
201             if (obj == m_value) {
202                 return true;
203             }
204             return IsNaN(obj) && IsNaN(m_value);
205         }
206
207         //The hashcode for a double is the absolute value of the integer representation
208         //of that double.
209         //
210         [System.Security.SecuritySafeCritical]
211         public unsafe override int GetHashCode() {
212             double d = m_value;
213             if (d == 0) {
214                 // Ensure that 0 and -0 have the same hash code
215                 return 0;
216             }
217             long value = *(long*)(&d);
218             return unchecked((int)value) ^ ((int)(value >> 32));
219         }
220
221         [System.Security.SecuritySafeCritical]  // auto-generated
222         public override String ToString() {
223             Contract.Ensures(Contract.Result<String>() != null);
224             return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
225         }
226
227         [System.Security.SecuritySafeCritical]  // auto-generated
228         public String ToString(String format) {
229             Contract.Ensures(Contract.Result<String>() != null);
230             return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
231         }
232         
233         [System.Security.SecuritySafeCritical]  // auto-generated
234         public String ToString(IFormatProvider provider) {
235             Contract.Ensures(Contract.Result<String>() != null);
236             return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
237         }
238         
239         [System.Security.SecuritySafeCritical]  // auto-generated
240         public String ToString(String format, IFormatProvider provider) {
241             Contract.Ensures(Contract.Result<String>() != null);
242             return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
243         }
244
245         public static double Parse(String s) {
246             return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
247         }
248
249         public static double Parse(String s, NumberStyles style) {
250             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
251             return Parse(s, style, NumberFormatInfo.CurrentInfo);
252         }
253
254         public static double Parse(String s, IFormatProvider provider) {
255             return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
256         }
257
258         public static double Parse(String s, NumberStyles style, IFormatProvider provider) {
259             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
260             return Parse(s, style, NumberFormatInfo.GetInstance(provider));
261         }
262         
263         // Parses a double from a String in the given style.  If
264         // a NumberFormatInfo isn't specified, the current culture's
265         // NumberFormatInfo is assumed.
266         //
267         // This method will not throw an OverflowException, but will return
268         // PositiveInfinity or NegativeInfinity for a number that is too
269         // large or too small.
270         //
271         private static double Parse(String s, NumberStyles style, NumberFormatInfo info) {
272             return Number.ParseDouble(s, style, info);
273         }
274
275         public static bool TryParse(String s, out double result) {
276             return TryParse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
277         }
278
279         public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result) {
280             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
281             return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
282         }
283         
284         private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out double result) {
285             if (s == null) {
286                 result = 0;
287                 return false;
288             }
289             bool success = Number.TryParseDouble(s, style, info, out result);
290             if (!success) {
291                 String sTrim = s.Trim();
292                 if (sTrim.Equals(info.PositiveInfinitySymbol)) {
293                     result = PositiveInfinity;
294                 } else if (sTrim.Equals(info.NegativeInfinitySymbol)) {
295                     result = NegativeInfinity;
296                 } else if (sTrim.Equals(info.NaNSymbol)) {
297                     result = NaN;
298                 } else
299                     return false; // We really failed
300             }
301             return true;
302         }
303
304         //
305         // IConvertible implementation
306         //
307
308         public TypeCode GetTypeCode() {
309             return TypeCode.Double;
310         }
311
312         /// <internalonly/>
313         bool IConvertible.ToBoolean(IFormatProvider provider) {
314             return Convert.ToBoolean(m_value);
315         }
316
317         /// <internalonly/>
318         char IConvertible.ToChar(IFormatProvider provider) {
319             throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Double", "Char"));
320         }
321
322         /// <internalonly/>
323         sbyte IConvertible.ToSByte(IFormatProvider provider) {
324             return Convert.ToSByte(m_value);
325         }
326
327         /// <internalonly/>
328         byte IConvertible.ToByte(IFormatProvider provider) {
329             return Convert.ToByte(m_value);
330         }
331
332         /// <internalonly/>
333         short IConvertible.ToInt16(IFormatProvider provider) {
334             return Convert.ToInt16(m_value);
335         }
336
337         /// <internalonly/>
338         ushort IConvertible.ToUInt16(IFormatProvider provider) {
339             return Convert.ToUInt16(m_value);
340         }
341
342         /// <internalonly/>
343         int IConvertible.ToInt32(IFormatProvider provider) {
344             return Convert.ToInt32(m_value);
345         }
346
347         /// <internalonly/>
348         uint IConvertible.ToUInt32(IFormatProvider provider) {
349             return Convert.ToUInt32(m_value);
350         }
351
352         /// <internalonly/>
353         long IConvertible.ToInt64(IFormatProvider provider) {
354             return Convert.ToInt64(m_value);
355         }
356
357         /// <internalonly/>
358         ulong IConvertible.ToUInt64(IFormatProvider provider) {
359             return Convert.ToUInt64(m_value);
360         }
361
362         /// <internalonly/>
363         float IConvertible.ToSingle(IFormatProvider provider) {
364             return Convert.ToSingle(m_value);
365         }
366
367         /// <internalonly/>
368         double IConvertible.ToDouble(IFormatProvider provider) {
369             return m_value;
370         }
371
372         /// <internalonly/>
373         Decimal IConvertible.ToDecimal(IFormatProvider provider) {
374             return Convert.ToDecimal(m_value);
375         }
376
377         /// <internalonly/>
378         DateTime IConvertible.ToDateTime(IFormatProvider provider) {
379             throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Double", "DateTime"));
380         }
381
382         /// <internalonly/>
383         Object IConvertible.ToType(Type type, IFormatProvider provider) {
384             return Convert.DefaultToType((IConvertible)this, type, provider);
385         }
386
387 ///#if GENERICS_WORK
388 ///        //
389 ///        // IArithmetic<Double> implementation
390 ///        //
391 ///
392 ///        /// <internalonly/>
393 ///        Double IArithmetic<Double>.AbsoluteValue(out bool overflowed) {
394 ///            Double abs = (m_value < 0 ? -m_value : m_value);
395 ///            overflowed = IsInfinity(abs) || IsNaN(abs);
396 ///            return abs;
397 ///        }
398 ///
399 ///        /// <internalonly/>
400 ///        Double IArithmetic<Double>.Negate(out bool overflowed) {
401 ///            Double neg= -m_value;
402 ///            overflowed = IsInfinity(neg) || IsNaN(neg);
403 ///            return neg;
404 ///        }
405 ///
406 ///        /// <internalonly/>
407 ///        Double IArithmetic<Double>.Sign(out bool overflowed) {
408 ///            overflowed = IsNaN(m_value);
409 ///            if (overflowed) {
410 ///                return m_value;
411 ///            }
412 ///            return (m_value >= 0 ? (m_value == 0 ? 0 : 1) : -1);
413 ///        }
414 ///
415 ///        /// <internalonly/>
416 ///        Double IArithmetic<Double>.Add(Double addend, out bool overflowed) {
417 ///            Double s = m_value + addend;
418 ///            overflowed = IsInfinity(s) || IsNaN(s);
419 ///            return s;
420 ///        }
421 ///
422 ///        /// <internalonly/>
423 ///        Double IArithmetic<Double>.Subtract(Double subtrahend, out bool overflowed) {
424 ///            Double s = m_value - subtrahend;
425 ///            overflowed = IsInfinity(s) || IsNaN(s);
426 ///            return s;
427 ///        }
428 ///
429 ///        /// <internalonly/>
430 ///        Double IArithmetic<Double>.Multiply(Double multiplier, out bool overflowed) {
431 ///            Double s = m_value * multiplier;
432 ///            overflowed = IsInfinity(s) || IsNaN(s);
433 ///            return s;
434 ///        }
435 ///
436 ///
437 ///        /// <internalonly/>
438 ///        Double IArithmetic<Double>.Divide(Double divisor, out bool overflowed) {
439 ///            Double s = m_value / divisor;
440 ///            overflowed = IsInfinity(s) || IsNaN(s);
441 ///            return s;
442 ///        }
443 ///
444 ///        /// <internalonly/>
445 ///        Double IArithmetic<Double>.DivideRemainder(Double divisor, out Double remainder, out bool overflowed) {
446 ///            remainder = m_value % divisor;
447 ///            Double s = m_value / divisor;
448 ///            overflowed = IsInfinity(s) || IsInfinity(remainder) || IsNaN(s) || IsNaN(remainder);
449 ///            return s;
450 ///        }
451 ///
452 ///        /// <internalonly/>
453 ///        Double IArithmetic<Double>.Remainder(Double divisor, out bool overflowed) {
454 ///            Double d = m_value % divisor;
455 ///            overflowed = IsInfinity(d) || IsNaN(d);
456 ///            return d;
457 ///        }
458 ///
459 ///        /// <internalonly/>
460 ///        ArithmeticDescriptor<Double> IArithmetic<Double>.GetDescriptor() {
461 ///            if (s_descriptor == null) {
462 ///                s_descriptor = new DoubleArithmeticDescriptor( ArithmeticCapabilities.One
463 ///                                                             | ArithmeticCapabilities.Zero
464 ///                                                             | ArithmeticCapabilities.MaxValue
465 ///                                                             | ArithmeticCapabilities.MinValue
466 ///                                                             | ArithmeticCapabilities.PositiveInfinity
467 ///                                                             | ArithmeticCapabilities.NegativeInfinity);
468 ///            }
469 ///            return s_descriptor;
470 ///        }
471 ///
472 ///        private static DoubleArithmeticDescriptor s_descriptor;
473 /// 
474 ///        class DoubleArithmeticDescriptor : ArithmeticDescriptor<Double> {
475 ///            public DoubleArithmeticDescriptor(ArithmeticCapabilities capabilities) : base(capabilities) {}
476 ///
477 ///            public override Double One {
478 ///                get {
479 ///                    return (Double) 1;
480 ///                }
481 ///            }
482 ///
483 ///            public override Double Zero {
484 ///                get {
485 ///                    return (Double) 0;
486 ///                }
487 ///            }
488 ///
489 ///            public override Double MinValue {
490 ///                get {
491 ///                    return Double.MinValue;
492 ///                }
493 ///            }
494 ///
495 ///            public override Double MaxValue {
496 ///                get {
497 ///                    return Double.MaxValue;
498 ///                }
499 ///            }
500 ///
501 ///            public override Double PositiveInfinity {
502 ///                get {
503 ///                    return Double.PositiveInfinity;
504 ///                }
505 ///            }
506 ///
507 ///            public override Double NegativeInfinity {
508 ///                get {
509 ///                    return Double.NegativeInfinity;
510 ///                }
511 ///            }
512 ///
513 ///        }
514 ///#endif // #if GENERICS_WORK
515
516     }
517 }