57b4b63272173f388a814d03e002fce45b66d500
[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
107         // Compares this object to another object, returning an instance of System.Relation.
108         // Null is considered less than any instance.
109         //
110         // If object is not of type Double, this method throws an ArgumentException.
111         //
112         // Returns a value less than zero if this  object
113         //
114         public int CompareTo(Object value) {
115             if (value == null) {
116                 return 1;
117             }
118             if (value is Double) {
119                 double d = (double)value;
120                 if (m_value < d) return -1;
121                 if (m_value > d) return 1;
122                 if (m_value == d) return 0;
123
124                 // At least one of the values is NaN.
125                 if (IsNaN(m_value))
126                     return (IsNaN(d) ? 0 : -1);
127                 else
128                     return 1;
129             }
130             throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDouble"));
131         }
132
133         public int CompareTo(Double value) {
134             if (m_value < value) return -1;
135             if (m_value > value) return 1;
136             if (m_value == value) return 0;
137
138             // At least one of the values is NaN.
139             if (IsNaN(m_value))
140                 return (IsNaN(value) ? 0 : -1);
141             else
142                 return 1;
143         }
144
145         // True if obj is another Double with the same value as the current instance.  This is
146         // a method of object equality, that only returns true if obj is also a double.
147         public override bool Equals(Object obj) {
148             if (!(obj is Double)) {
149                 return false;
150             }
151             double temp = ((Double)obj).m_value;
152             // This code below is written this way for performance reasons i.e the != and == check is intentional.
153             if (temp == m_value) {
154                 return true;
155             }
156             return IsNaN(temp) && IsNaN(m_value);
157         }
158
159         [System.Runtime.Versioning.NonVersionable]
160         public static bool operator ==(Double left, Double right) {
161             return left == right;
162         }
163
164         [System.Runtime.Versioning.NonVersionable]
165         public static bool operator !=(Double left, Double right) {
166             return left != right;
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         public bool Equals(Double obj)
190         {
191             if (obj == m_value) {
192                 return true;
193             }
194             return IsNaN(obj) && IsNaN(m_value);
195         }
196
197         //The hashcode for a double is the absolute value of the integer representation
198         //of that double.
199         //
200         [System.Security.SecuritySafeCritical]
201         public unsafe override int GetHashCode() {
202             double d = m_value;
203             if (d == 0) {
204                 // Ensure that 0 and -0 have the same hash code
205                 return 0;
206             }
207             long value = *(long*)(&d);
208             return unchecked((int)value) ^ ((int)(value >> 32));
209         }
210
211         [System.Security.SecuritySafeCritical]  // auto-generated
212         public override String ToString() {
213             Contract.Ensures(Contract.Result<String>() != null);
214             return Number.FormatDouble(m_value, null, NumberFormatInfo.CurrentInfo);
215         }
216
217         [System.Security.SecuritySafeCritical]  // auto-generated
218         public String ToString(String format) {
219             Contract.Ensures(Contract.Result<String>() != null);
220             return Number.FormatDouble(m_value, format, NumberFormatInfo.CurrentInfo);
221         }
222         
223         [System.Security.SecuritySafeCritical]  // auto-generated
224         public String ToString(IFormatProvider provider) {
225             Contract.Ensures(Contract.Result<String>() != null);
226             return Number.FormatDouble(m_value, null, NumberFormatInfo.GetInstance(provider));
227         }
228         
229         [System.Security.SecuritySafeCritical]  // auto-generated
230         public String ToString(String format, IFormatProvider provider) {
231             Contract.Ensures(Contract.Result<String>() != null);
232             return Number.FormatDouble(m_value, format, NumberFormatInfo.GetInstance(provider));
233         }
234
235         public static double Parse(String s) {
236             return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo);
237         }
238
239         public static double Parse(String s, NumberStyles style) {
240             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
241             return Parse(s, style, NumberFormatInfo.CurrentInfo);
242         }
243
244         public static double Parse(String s, IFormatProvider provider) {
245             return Parse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.GetInstance(provider));
246         }
247
248         public static double Parse(String s, NumberStyles style, IFormatProvider provider) {
249             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
250             return Parse(s, style, NumberFormatInfo.GetInstance(provider));
251         }
252         
253         // Parses a double from a String in the given style.  If
254         // a NumberFormatInfo isn't specified, the current culture's
255         // NumberFormatInfo is assumed.
256         //
257         // This method will not throw an OverflowException, but will return
258         // PositiveInfinity or NegativeInfinity for a number that is too
259         // large or too small.
260         //
261         private static double Parse(String s, NumberStyles style, NumberFormatInfo info) {
262             return Number.ParseDouble(s, style, info);
263         }
264
265         public static bool TryParse(String s, out double result) {
266             return TryParse(s, NumberStyles.Float| NumberStyles.AllowThousands, NumberFormatInfo.CurrentInfo, out result);
267         }
268
269         public static bool TryParse(String s, NumberStyles style, IFormatProvider provider, out double result) {
270             NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
271             return TryParse(s, style, NumberFormatInfo.GetInstance(provider), out result);
272         }
273         
274         private static bool TryParse(String s, NumberStyles style, NumberFormatInfo info, out double result) {
275             if (s == null) {
276                 result = 0;
277                 return false;
278             }
279             bool success = Number.TryParseDouble(s, style, info, out result);
280             if (!success) {
281                 String sTrim = s.Trim();
282                 if (sTrim.Equals(info.PositiveInfinitySymbol)) {
283                     result = PositiveInfinity;
284                 } else if (sTrim.Equals(info.NegativeInfinitySymbol)) {
285                     result = NegativeInfinity;
286                 } else if (sTrim.Equals(info.NaNSymbol)) {
287                     result = NaN;
288                 } else
289                     return false; // We really failed
290             }
291             return true;
292         }
293
294         //
295         // IConvertible implementation
296         //
297
298         public TypeCode GetTypeCode() {
299             return TypeCode.Double;
300         }
301
302         /// <internalonly/>
303         bool IConvertible.ToBoolean(IFormatProvider provider) {
304             return Convert.ToBoolean(m_value);
305         }
306
307         /// <internalonly/>
308         char IConvertible.ToChar(IFormatProvider provider) {
309             throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Double", "Char"));
310         }
311
312         /// <internalonly/>
313         sbyte IConvertible.ToSByte(IFormatProvider provider) {
314             return Convert.ToSByte(m_value);
315         }
316
317         /// <internalonly/>
318         byte IConvertible.ToByte(IFormatProvider provider) {
319             return Convert.ToByte(m_value);
320         }
321
322         /// <internalonly/>
323         short IConvertible.ToInt16(IFormatProvider provider) {
324             return Convert.ToInt16(m_value);
325         }
326
327         /// <internalonly/>
328         ushort IConvertible.ToUInt16(IFormatProvider provider) {
329             return Convert.ToUInt16(m_value);
330         }
331
332         /// <internalonly/>
333         int IConvertible.ToInt32(IFormatProvider provider) {
334             return Convert.ToInt32(m_value);
335         }
336
337         /// <internalonly/>
338         uint IConvertible.ToUInt32(IFormatProvider provider) {
339             return Convert.ToUInt32(m_value);
340         }
341
342         /// <internalonly/>
343         long IConvertible.ToInt64(IFormatProvider provider) {
344             return Convert.ToInt64(m_value);
345         }
346
347         /// <internalonly/>
348         ulong IConvertible.ToUInt64(IFormatProvider provider) {
349             return Convert.ToUInt64(m_value);
350         }
351
352         /// <internalonly/>
353         float IConvertible.ToSingle(IFormatProvider provider) {
354             return Convert.ToSingle(m_value);
355         }
356
357         /// <internalonly/>
358         double IConvertible.ToDouble(IFormatProvider provider) {
359             return m_value;
360         }
361
362         /// <internalonly/>
363         Decimal IConvertible.ToDecimal(IFormatProvider provider) {
364             return Convert.ToDecimal(m_value);
365         }
366
367         /// <internalonly/>
368         DateTime IConvertible.ToDateTime(IFormatProvider provider) {
369             throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Double", "DateTime"));
370         }
371
372         /// <internalonly/>
373         Object IConvertible.ToType(Type type, IFormatProvider provider) {
374             return Convert.DefaultToType((IConvertible)this, type, provider);
375         }
376
377 ///#if GENERICS_WORK
378 ///        //
379 ///        // IArithmetic<Double> implementation
380 ///        //
381 ///
382 ///        /// <internalonly/>
383 ///        Double IArithmetic<Double>.AbsoluteValue(out bool overflowed) {
384 ///            Double abs = (m_value < 0 ? -m_value : m_value);
385 ///            overflowed = IsInfinity(abs) || IsNaN(abs);
386 ///            return abs;
387 ///        }
388 ///
389 ///        /// <internalonly/>
390 ///        Double IArithmetic<Double>.Negate(out bool overflowed) {
391 ///            Double neg= -m_value;
392 ///            overflowed = IsInfinity(neg) || IsNaN(neg);
393 ///            return neg;
394 ///        }
395 ///
396 ///        /// <internalonly/>
397 ///        Double IArithmetic<Double>.Sign(out bool overflowed) {
398 ///            overflowed = IsNaN(m_value);
399 ///            if (overflowed) {
400 ///                return m_value;
401 ///            }
402 ///            return (m_value >= 0 ? (m_value == 0 ? 0 : 1) : -1);
403 ///        }
404 ///
405 ///        /// <internalonly/>
406 ///        Double IArithmetic<Double>.Add(Double addend, out bool overflowed) {
407 ///            Double s = m_value + addend;
408 ///            overflowed = IsInfinity(s) || IsNaN(s);
409 ///            return s;
410 ///        }
411 ///
412 ///        /// <internalonly/>
413 ///        Double IArithmetic<Double>.Subtract(Double subtrahend, out bool overflowed) {
414 ///            Double s = m_value - subtrahend;
415 ///            overflowed = IsInfinity(s) || IsNaN(s);
416 ///            return s;
417 ///        }
418 ///
419 ///        /// <internalonly/>
420 ///        Double IArithmetic<Double>.Multiply(Double multiplier, out bool overflowed) {
421 ///            Double s = m_value * multiplier;
422 ///            overflowed = IsInfinity(s) || IsNaN(s);
423 ///            return s;
424 ///        }
425 ///
426 ///
427 ///        /// <internalonly/>
428 ///        Double IArithmetic<Double>.Divide(Double divisor, out bool overflowed) {
429 ///            Double s = m_value / divisor;
430 ///            overflowed = IsInfinity(s) || IsNaN(s);
431 ///            return s;
432 ///        }
433 ///
434 ///        /// <internalonly/>
435 ///        Double IArithmetic<Double>.DivideRemainder(Double divisor, out Double remainder, out bool overflowed) {
436 ///            remainder = m_value % divisor;
437 ///            Double s = m_value / divisor;
438 ///            overflowed = IsInfinity(s) || IsInfinity(remainder) || IsNaN(s) || IsNaN(remainder);
439 ///            return s;
440 ///        }
441 ///
442 ///        /// <internalonly/>
443 ///        Double IArithmetic<Double>.Remainder(Double divisor, out bool overflowed) {
444 ///            Double d = m_value % divisor;
445 ///            overflowed = IsInfinity(d) || IsNaN(d);
446 ///            return d;
447 ///        }
448 ///
449 ///        /// <internalonly/>
450 ///        ArithmeticDescriptor<Double> IArithmetic<Double>.GetDescriptor() {
451 ///            if (s_descriptor == null) {
452 ///                s_descriptor = new DoubleArithmeticDescriptor( ArithmeticCapabilities.One
453 ///                                                             | ArithmeticCapabilities.Zero
454 ///                                                             | ArithmeticCapabilities.MaxValue
455 ///                                                             | ArithmeticCapabilities.MinValue
456 ///                                                             | ArithmeticCapabilities.PositiveInfinity
457 ///                                                             | ArithmeticCapabilities.NegativeInfinity);
458 ///            }
459 ///            return s_descriptor;
460 ///        }
461 ///
462 ///        private static DoubleArithmeticDescriptor s_descriptor;
463 /// 
464 ///        class DoubleArithmeticDescriptor : ArithmeticDescriptor<Double> {
465 ///            public DoubleArithmeticDescriptor(ArithmeticCapabilities capabilities) : base(capabilities) {}
466 ///
467 ///            public override Double One {
468 ///                get {
469 ///                    return (Double) 1;
470 ///                }
471 ///            }
472 ///
473 ///            public override Double Zero {
474 ///                get {
475 ///                    return (Double) 0;
476 ///                }
477 ///            }
478 ///
479 ///            public override Double MinValue {
480 ///                get {
481 ///                    return Double.MinValue;
482 ///                }
483 ///            }
484 ///
485 ///            public override Double MaxValue {
486 ///                get {
487 ///                    return Double.MaxValue;
488 ///                }
489 ///            }
490 ///
491 ///            public override Double PositiveInfinity {
492 ///                get {
493 ///                    return Double.PositiveInfinity;
494 ///                }
495 ///            }
496 ///
497 ///            public override Double NegativeInfinity {
498 ///                get {
499 ///                    return Double.NegativeInfinity;
500 ///                }
501 ///            }
502 ///
503 ///        }
504 ///#endif // #if GENERICS_WORK
505
506     }
507 }