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