(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / corlib / System / Double.cs
blob3fbe769ca181c830ccd53ba63262ad8fa30f2bdf
1 //
2 // System.Double.cs
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Bob Smith (bob@thestuff.net)
7 //
8 // (C) Ximian, Inc. http://www.ximian.com
9 // (C) Bob Smith. http://www.thestuff.net
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Globalization;
36 using System.Runtime.CompilerServices;
38 namespace System {
40 [Serializable]
41 public struct Double : IComparable, IFormattable, IConvertible {
42 public const double Epsilon = 4.9406564584124650e-324;
43 public const double MaxValue = 1.7976931348623157e308;
44 public const double MinValue = -1.7976931348623157e308;
45 public const double NaN = 0.0d / 0.0d;
46 public const double NegativeInfinity = -1.0d / 0.0d;
47 public const double PositiveInfinity = 1.0d / 0.0d;
49 internal double m_value;
51 [MethodImplAttribute(MethodImplOptions.InternalCall)]
52 extern internal static void AssertEndianity (out double value);
54 public int CompareTo (object v)
56 if (v == null)
57 return 1;
59 if (!(v is System.Double))
60 throw new ArgumentException (Locale.GetText ("Value is not a System.Double"));
62 double dv = (double)v;
64 if (IsPositiveInfinity(m_value) && IsPositiveInfinity(dv))
65 return 0;
67 if (IsNegativeInfinity(m_value) && IsNegativeInfinity(dv))
68 return 0;
70 if (IsNaN(dv))
71 if (IsNaN(m_value))
72 return 0;
73 else
74 return 1;
76 if (IsNaN(m_value))
77 if (IsNaN(dv))
78 return 0;
79 else
80 return -1;
82 if (m_value > dv) return 1;
83 else if (m_value < dv) return -1;
84 else return 0;
87 public override bool Equals (object o)
89 if (!(o is System.Double))
90 return false;
92 if (IsNaN ((double)o)) {
93 if (IsNaN(m_value))
94 return true;
95 else
96 return false;
99 return ((double) o) == m_value;
102 public override unsafe int GetHashCode ()
104 double d = m_value;
105 return (*((long*)&d)).GetHashCode ();
108 public static bool IsInfinity (double d)
110 return (d == PositiveInfinity || d == NegativeInfinity);
113 public static bool IsNaN (double d)
115 return (d != d);
118 public static bool IsNegativeInfinity (double d)
120 return (d < 0.0d && (d == NegativeInfinity || d == PositiveInfinity));
123 public static bool IsPositiveInfinity (double d)
125 return (d > 0.0d && (d == NegativeInfinity || d == PositiveInfinity));
128 public static double Parse (string s)
130 return Parse (s, (NumberStyles.Float | NumberStyles.AllowThousands), null);
133 public static double Parse (string s, IFormatProvider fp)
135 return Parse (s, (NumberStyles.Float | NumberStyles.AllowThousands), fp);
138 public static double Parse (string s, NumberStyles style)
140 return Parse (s, style, null);
143 // We're intentionally using constants here to avoid some bigger headaches in mcs.
144 // This struct must be compiled before System.Enum so we can't use enums here.
145 private const int State_AllowSign = 1;
146 private const int State_Digits = 2;
147 private const int State_Decimal = 3;
148 private const int State_ExponentSign = 4;
149 private const int State_Exponent = 5;
150 private const int State_ConsumeWhiteSpace = 6;
152 [MonoTODO("check if digits are group in correct numbers between the group separators")]
153 public static double Parse (string s, NumberStyles style, IFormatProvider provider)
155 if (s == null) throw new ArgumentNullException();
156 if (style > NumberStyles.Any)
158 throw new ArgumentException();
160 NumberFormatInfo format = NumberFormatInfo.GetInstance(provider);
161 if (format == null) throw new Exception("How did this happen?");
162 if (s == format.NaNSymbol) return Double.NaN;
163 if (s == format.PositiveInfinitySymbol) return Double.PositiveInfinity;
164 if (s == format.NegativeInfinitySymbol) return Double.NegativeInfinity;
167 // validate and prepare string for C
169 int len = s.Length;
170 byte [] b = new byte [len + 1];
171 int didx = 0;
172 int sidx = 0;
173 char c;
175 if ((style & NumberStyles.AllowLeadingWhite) != 0){
176 while (sidx < len && Char.IsWhiteSpace (c = s [sidx]))
177 sidx++;
179 if (sidx == len)
180 throw new FormatException();
183 bool allow_trailing_white = ((style & NumberStyles.AllowTrailingWhite) != 0);
186 // Machine state
188 int state = State_AllowSign;
191 // Setup
193 string decimal_separator = null;
194 string group_separator = null;
195 int decimal_separator_len = 0;
196 int group_separator_len = 0;
197 if ((style & NumberStyles.AllowDecimalPoint) != 0){
198 decimal_separator = format.NumberDecimalSeparator;
199 decimal_separator_len = decimal_separator.Length;
201 if ((style & NumberStyles.AllowThousands) != 0){
202 group_separator = format.NumberGroupSeparator;
203 group_separator_len = group_separator.Length;
205 string positive = format.PositiveSign;
206 string negative = format.NegativeSign;
208 for (; sidx < len; sidx++){
209 c = s [sidx];
211 if (c == '\0') {
212 sidx = len;
213 continue;
215 switch (state){
216 case State_AllowSign:
217 if ((style & NumberStyles.AllowLeadingSign) != 0){
218 if (c == positive [0] &&
219 s.Substring (sidx, positive.Length) == positive){
220 state = State_Digits;
221 sidx += positive.Length-1;
222 continue;
225 if (c == negative [0] &&
226 s.Substring (sidx, negative.Length) == negative){
227 state = State_Digits;
228 b [didx++] = (byte) '-';
229 sidx += negative.Length-1;
230 continue;
233 state = State_Digits;
234 goto case State_Digits;
236 case State_Digits:
237 if (Char.IsDigit (c)){
238 b [didx++] = (byte) c;
239 break;
241 if (c == 'e' || c == 'E')
242 goto case State_Decimal;
244 if (decimal_separator != null &&
245 decimal_separator [0] == c){
246 if (s.Substring (sidx, decimal_separator_len) ==
247 decimal_separator){
248 b [didx++] = (byte) '.';
249 sidx += decimal_separator_len-1;
250 state = State_Decimal;
251 break;
254 if (group_separator != null &&
255 group_separator [0] == c){
256 if (s.Substring (sidx, group_separator_len) ==
257 group_separator){
258 sidx += group_separator_len-1;
259 state = State_Digits;
260 break;
264 if (Char.IsWhiteSpace (c))
265 goto case State_ConsumeWhiteSpace;
267 throw new FormatException ("Unknown char: " + c);
269 case State_Decimal:
270 if (Char.IsDigit (c)){
271 b [didx++] = (byte) c;
272 break;
275 if (c == 'e' || c == 'E'){
276 if ((style & NumberStyles.AllowExponent) == 0)
277 throw new FormatException ("Unknown char: " + c);
278 b [didx++] = (byte) c;
279 state = State_ExponentSign;
280 break;
283 if (Char.IsWhiteSpace (c))
284 goto case State_ConsumeWhiteSpace;
285 throw new FormatException ("Unknown char: " + c);
287 case State_ExponentSign:
288 if (Char.IsDigit (c)){
289 state = State_Exponent;
290 goto case State_Exponent;
293 if (c == positive [0] &&
294 s.Substring (sidx, positive.Length) == positive){
295 state = State_Digits;
296 sidx += positive.Length-1;
297 continue;
300 if (c == negative [0] &&
301 s.Substring (sidx, negative.Length) == negative){
302 state = State_Digits;
303 b [didx++] = (byte) '-';
304 sidx += negative.Length-1;
305 continue;
308 if (Char.IsWhiteSpace (c))
309 goto case State_ConsumeWhiteSpace;
311 throw new FormatException ("Unknown char: " + c);
313 case State_Exponent:
314 if (Char.IsDigit (c)){
315 b [didx++] = (byte) c;
316 break;
319 if (Char.IsWhiteSpace (c))
320 goto case State_ConsumeWhiteSpace;
321 throw new FormatException ("Unknown char: " + c);
323 case State_ConsumeWhiteSpace:
324 if (allow_trailing_white && Char.IsWhiteSpace (c))
325 break;
326 throw new FormatException ("Unknown char");
330 b [didx] = 0;
331 unsafe {
332 fixed (byte *p = &b [0]){
333 double retVal = ParseImpl (p);
334 if (IsPositiveInfinity(retVal) || IsNegativeInfinity(retVal))
335 throw new OverflowException();
337 return retVal;
342 [MethodImplAttribute(MethodImplOptions.InternalCall)]
343 unsafe private static extern double ParseImpl (byte *byte_ptr);
345 public static bool TryParse (string s,
346 NumberStyles style,
347 IFormatProvider provider,
348 out double result)
350 try {
351 result = Parse (s, style, provider);
352 return true;
353 } catch {
354 result = 0;
355 return false;
359 public override string ToString ()
361 return ToString (null, null);
364 public string ToString (IFormatProvider fp)
366 return ToString (null, fp);
369 public string ToString (string format)
371 return ToString (format, null);
374 public string ToString (string format, IFormatProvider fp)
376 NumberFormatInfo nfi = fp != null ? fp.GetFormat (typeof (NumberFormatInfo)) as NumberFormatInfo : null;
377 return DoubleFormatter.NumberToString (format, nfi, m_value);
380 // =========== IConvertible Methods =========== //
382 public TypeCode GetTypeCode ()
384 return TypeCode.Double;
387 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
389 return System.Convert.ToType(m_value, conversionType, provider);
392 bool IConvertible.ToBoolean (IFormatProvider provider)
394 return System.Convert.ToBoolean(m_value);
397 byte IConvertible.ToByte (IFormatProvider provider)
399 return System.Convert.ToByte(m_value);
402 char IConvertible.ToChar (IFormatProvider provider)
404 throw new InvalidCastException();
407 DateTime IConvertible.ToDateTime (IFormatProvider provider)
409 throw new InvalidCastException();
412 decimal IConvertible.ToDecimal (IFormatProvider provider)
414 return System.Convert.ToDecimal(m_value);
417 double IConvertible.ToDouble (IFormatProvider provider)
419 return System.Convert.ToDouble(m_value);
422 short IConvertible.ToInt16 (IFormatProvider provider)
424 return System.Convert.ToInt16(m_value);
427 int IConvertible.ToInt32 (IFormatProvider provider)
429 return System.Convert.ToInt32(m_value);
432 long IConvertible.ToInt64 (IFormatProvider provider)
434 return System.Convert.ToInt64(m_value);
437 sbyte IConvertible.ToSByte (IFormatProvider provider)
439 return System.Convert.ToSByte(m_value);
442 float IConvertible.ToSingle (IFormatProvider provider)
444 return System.Convert.ToSingle(m_value);
448 string IConvertible.ToString (IFormatProvider provider)
450 return ToString(provider);
454 ushort IConvertible.ToUInt16 (IFormatProvider provider)
456 return System.Convert.ToUInt16(m_value);
459 uint IConvertible.ToUInt32 (IFormatProvider provider)
461 return System.Convert.ToUInt32(m_value);
464 ulong IConvertible.ToUInt64 (IFormatProvider provider)
466 return System.Convert.ToUInt64(m_value);