5 // Miguel de Icaza (miguel@ximian.com)
6 // Bob Smith (bob@thestuff.net)
8 // (C) Ximian, Inc. http://www.ximian.com
9 // (C) Bob Smith. http://www.thestuff.net
12 using System.Globalization;
13 using System.Runtime.CompilerServices;
18 public struct Double : IComparable, IFormattable, IConvertible {
19 public const double Epsilon = 4.9406564584124650e-324;
20 public const double MaxValue = 1.7976931348623157e308;
21 public const double MinValue = -1.7976931348623157e308;
22 public const double NaN = 0.0d / 0.0d;
23 public const double NegativeInfinity = -1.0d / 0.0d;
24 public const double PositiveInfinity = 1.0d / 0.0d;
26 // VES needs to know about value. public is workaround
27 // so source will compile
30 public int CompareTo (object v)
35 if (!(v is System.Double))
36 throw new ArgumentException (Locale.GetText ("Value is not a System.Double"));
38 if (IsPositiveInfinity(value) && IsPositiveInfinity((double) v)){
42 if (IsNegativeInfinity(value) && IsNegativeInfinity((double) v)){
46 if (IsNaN((double) v)) {
53 return (int) (value - ((double) v));
56 public override bool Equals (object o)
58 if (!(o is System.Double))
61 if (IsNaN ((double)o)) {
68 return ((double) o) == value;
71 public override int GetHashCode ()
76 public static bool IsInfinity (double d)
78 return (d == PositiveInfinity || d == NegativeInfinity);
81 public static bool IsNaN (double d)
86 public static bool IsNegativeInfinity (double d)
88 return (d < 0.0d && (d == NegativeInfinity || d == PositiveInfinity));
91 public static bool IsPositiveInfinity (double d)
93 return (d > 0.0d && (d == NegativeInfinity || d == PositiveInfinity));
96 public static double Parse (string s)
98 return Parse (s, (NumberStyles.Float | NumberStyles.AllowThousands), null);
101 public static double Parse (string s, IFormatProvider fp)
103 return Parse (s, (NumberStyles.Float | NumberStyles.AllowThousands), fp);
106 public static double Parse (string s, NumberStyles style)
108 return Parse (s, style, null);
112 AllowSign, Digits, Decimal, ExponentSign, Exponent, ConsumeWhiteSpace
115 [MonoTODO("check if digits are group in correct numbers between the group separators")]
116 public static double Parse (string s, NumberStyles style, IFormatProvider provider)
118 if (s == null) throw new ArgumentNullException();
119 if (style > NumberStyles.Any)
121 throw new ArgumentException();
123 NumberFormatInfo format = NumberFormatInfo.GetInstance(provider);
124 if (format == null) throw new Exception("How did this happen?");
125 if (s == format.NaNSymbol) return Double.NaN;
126 if (s == format.PositiveInfinitySymbol) return Double.PositiveInfinity;
127 if (s == format.NegativeInfinitySymbol) return Double.NegativeInfinity;
130 // validate and prepare string for C
133 byte [] b = new byte [len + 1];
138 if ((style & NumberStyles.AllowLeadingWhite) != 0){
139 while (sidx < len && Char.IsWhiteSpace (c = s [sidx]))
143 throw new FormatException();
146 bool allow_trailing_white = ((style & NumberStyles.AllowTrailingWhite) != 0);
151 State state = State.AllowSign;
156 string decimal_separator = null;
157 string group_separator = null;
158 int decimal_separator_len = 0;
159 int group_separator_len = 0;
160 if ((style & NumberStyles.AllowDecimalPoint) != 0){
161 decimal_separator = format.NumberDecimalSeparator;
162 decimal_separator_len = decimal_separator.Length;
164 if ((style & NumberStyles.AllowThousands) != 0){
165 group_separator = format.NumberGroupSeparator;
166 group_separator_len = group_separator.Length;
168 string positive = format.PositiveSign;
169 string negative = format.NegativeSign;
171 for (; sidx < len; sidx++){
175 case State.AllowSign:
176 if ((style & NumberStyles.AllowLeadingSign) != 0){
177 if (c == positive [0] &&
178 s.Substring (sidx, positive.Length) == positive){
179 state = State.Digits;
180 sidx += positive.Length-1;
184 if (c == negative [0] &&
185 s.Substring (sidx, negative.Length) == negative){
186 state = State.Digits;
187 b [didx++] = (byte) '-';
188 sidx += negative.Length-1;
192 state = State.Digits;
193 goto case State.Digits;
196 if (Char.IsDigit (c)){
197 b [didx++] = (byte) c;
200 if (c == 'e' || c == 'E')
201 goto case State.Decimal;
203 if (decimal_separator != null &&
204 decimal_separator [0] == c){
205 if (s.Substring (sidx, decimal_separator_len) ==
207 b [didx++] = (byte) '.';
208 sidx += decimal_separator_len-1;
209 state = State.Decimal;
213 if (group_separator != null &&
214 group_separator [0] == c){
215 if (s.Substring (sidx, group_separator_len) ==
217 sidx += group_separator_len-1;
218 state = State.Digits;
223 if (Char.IsWhiteSpace (c))
224 goto case State.ConsumeWhiteSpace;
226 throw new FormatException ("Unknown char: " + c);
229 if (Char.IsDigit (c)){
230 b [didx++] = (byte) c;
234 if (c == 'e' || c == 'E'){
235 if ((style & NumberStyles.AllowExponent) == 0)
236 throw new FormatException ("Unknown char: " + c);
237 b [didx++] = (byte) c;
238 state = State.ExponentSign;
242 if (Char.IsWhiteSpace (c))
243 goto case State.ConsumeWhiteSpace;
244 throw new FormatException ("Unknown char: " + c);
246 case State.ExponentSign:
247 if (Char.IsDigit (c)){
248 state = State.Exponent;
249 goto case State.Exponent;
252 if (c == positive [0] &&
253 s.Substring (sidx, positive.Length) == positive){
254 state = State.Digits;
255 sidx += positive.Length-1;
259 if (c == negative [0] &&
260 s.Substring (sidx, negative.Length) == negative){
261 state = State.Digits;
262 b [didx++] = (byte) '-';
263 sidx += negative.Length-1;
267 if (Char.IsWhiteSpace (c))
268 goto case State.ConsumeWhiteSpace;
270 throw new FormatException ("Unknown char: " + c);
273 if (Char.IsDigit (c)){
274 b [didx++] = (byte) c;
278 if (Char.IsWhiteSpace (c))
279 goto case State.ConsumeWhiteSpace;
280 throw new FormatException ("Unknown char: " + c);
282 case State.ConsumeWhiteSpace:
283 if (allow_trailing_white && Char.IsWhiteSpace (c))
285 throw new FormatException ("Unknown char");
291 fixed (byte *p = &b [0]){
292 double retVal = ParseImpl (p);
293 if (IsPositiveInfinity(retVal) || IsNegativeInfinity(retVal))
294 throw new OverflowException();
301 [MethodImplAttribute(MethodImplOptions.InternalCall)]
302 unsafe private static extern double ParseImpl (byte *byte_ptr);
304 public override string ToString ()
306 return ToString (null, null);
309 public string ToString (IFormatProvider fp)
311 return ToString (null, fp);
314 public string ToString (string format)
316 return ToString (format, null);
320 public string ToString (string format, IFormatProvider fp)
322 // FIXME: Need to pass format and provider info to this call too.
323 return ToStringImpl(value);
326 [MethodImplAttribute(MethodImplOptions.InternalCall)]
327 private static extern string ToStringImpl (double value);
329 // =========== IConvertible Methods =========== //
331 public TypeCode GetTypeCode ()
333 return TypeCode.Double;
336 object IConvertible.ToType (Type conversionType, IFormatProvider provider)
338 return System.Convert.ToType(value, conversionType, provider);
341 bool IConvertible.ToBoolean (IFormatProvider provider)
343 return System.Convert.ToBoolean(value);
346 byte IConvertible.ToByte (IFormatProvider provider)
348 return System.Convert.ToByte(value);
351 char IConvertible.ToChar (IFormatProvider provider)
353 throw new InvalidCastException();
356 [CLSCompliant(false)]
357 DateTime IConvertible.ToDateTime (IFormatProvider provider)
359 throw new InvalidCastException();
362 decimal IConvertible.ToDecimal (IFormatProvider provider)
364 return System.Convert.ToDecimal(value);
367 double IConvertible.ToDouble (IFormatProvider provider)
369 return System.Convert.ToDouble(value);
372 short IConvertible.ToInt16 (IFormatProvider provider)
374 return System.Convert.ToInt16(value);
377 int IConvertible.ToInt32 (IFormatProvider provider)
379 return System.Convert.ToInt32(value);
382 long IConvertible.ToInt64 (IFormatProvider provider)
384 return System.Convert.ToInt64(value);
387 [CLSCompliant(false)]
388 sbyte IConvertible.ToSByte (IFormatProvider provider)
390 return System.Convert.ToSByte(value);
393 float IConvertible.ToSingle (IFormatProvider provider)
395 return System.Convert.ToSingle(value);
399 string IConvertible.ToString (IFormatProvider provider)
401 return ToString(provider);
405 [CLSCompliant(false)]
406 ushort IConvertible.ToUInt16 (IFormatProvider provider)
408 return System.Convert.ToUInt16(value);
411 [CLSCompliant(false)]
412 uint IConvertible.ToUInt32 (IFormatProvider provider)
414 return System.Convert.ToUInt32(value);
417 [CLSCompliant(false)]
418 ulong IConvertible.ToUInt64 (IFormatProvider provider)
420 return System.Convert.ToUInt64(value);