1 // ==++==
2 //
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 //
5 // ==--==
6 /*============================================================
7 **
8 ** Class:  Int64.cs
9 **
10 **
11 ** Purpose: This class will encapsulate a long and provide an
12 **          Object representation of it.
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.Diagnostics.Contracts;
25 
26 [Serializable]
27 [System.Runtime.InteropServices.StructLayout(LayoutKind.Sequential)]
28 [System.Runtime.InteropServices.ComVisible(true)]
29 #if GENERICS_WORK
30     public struct Int64 : IComparable, IFormattable, IConvertible
31         , IComparable<Int64>, IEquatable<Int64>
32 ///     , IArithmetic<Int64>
33 #else
34     public struct Int64 : IComparable, IFormattable, IConvertible
35 #endif
36     {
37         internal long m_value;
38 
39         public const long MaxValue = 0x7fffffffffffffffL;
40         public const long MinValue = unchecked((long)0x8000000000000000L);
41 
42         // Compares this object to another object, returning an integer that
43         // indicates the relationship.
44         // Returns a value less than zero if this  object
45         // null is considered to be less than any instance.
46         // If object is not of type Int64, this method throws an ArgumentException.
47         //
CompareToSystem.Int6448         public int CompareTo(Object value) {
49             if (value == null) {
50                 return 1;
51             }
52             if (value is Int64) {
53                 // Need to use compare because subtraction will wrap
54                 // to positive for very large neg numbers, etc.
55                 long i = (long)value;
56                 if (m_value < i) return -1;
57                 if (m_value > i) return 1;
58                 return 0;
59             }
60             throw new ArgumentException (Environment.GetResourceString("Arg_MustBeInt64"));
61         }
62 
CompareToSystem.Int6463         public int CompareTo(Int64 value) {
64             // Need to use compare because subtraction will wrap
65             // to positive for very large neg numbers, etc.
66             if (m_value < value) return -1;
67             if (m_value > value) return 1;
68             return 0;
69         }
70 
EqualsSystem.Int6471         public override bool Equals(Object obj) {
72             if (!(obj is Int64)) {
73                 return false;
74             }
75             return m_value == ((Int64)obj).m_value;
76         }
77 
78         [System.Runtime.Versioning.NonVersionable]
EqualsSystem.Int6479         public bool Equals(Int64 obj)
80         {
81             return m_value == obj;
82         }
83 
84         // The value of the lower 32 bits XORed with the uppper 32 bits.
GetHashCodeSystem.Int6485         public override int GetHashCode() {
86             return (unchecked((int)((long)m_value)) ^ (int)(m_value >> 32));
87         }
88 
89         [System.Security.SecuritySafeCritical]  // auto-generated
ToStringSystem.Int6490         public override String ToString() {
91             Contract.Ensures(Contract.Result<String>() != null);
92             return Number.FormatInt64(m_value, null, NumberFormatInfo.CurrentInfo);
93         }
94 
95         [System.Security.SecuritySafeCritical]  // auto-generated
ToStringSystem.Int6496         public String ToString(IFormatProvider provider) {
97             Contract.Ensures(Contract.Result<String>() != null);
98             return Number.FormatInt64(m_value, null, NumberFormatInfo.GetInstance(provider));
99         }
100 
101         [System.Security.SecuritySafeCritical]  // auto-generated
ToStringSystem.Int64102         public String ToString(String format) {
103             Contract.Ensures(Contract.Result<String>() != null);
104             return Number.FormatInt64(m_value, format, NumberFormatInfo.CurrentInfo);
105         }
106 
107         [System.Security.SecuritySafeCritical]  // auto-generated
ToStringSystem.Int64108         public String ToString(String format, IFormatProvider provider) {
109             Contract.Ensures(Contract.Result<String>() != null);
110             return Number.FormatInt64(m_value, format, NumberFormatInfo.GetInstance(provider));
111         }
112 
ParseSystem.Int64113         public static long Parse(String s) {
114             return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo);
115         }
116 
ParseSystem.Int64117         public static long Parse(String s, NumberStyles style) {
118             NumberFormatInfo.ValidateParseStyleInteger(style);
119             return Number.ParseInt64(s, style, NumberFormatInfo.CurrentInfo);
120         }
121 
ParseSystem.Int64122         public static long Parse(String s, IFormatProvider provider) {
123             return Number.ParseInt64(s, NumberStyles.Integer, NumberFormatInfo.GetInstance(provider));
124         }
125 
126 
127         // Parses a long from a String in the given style.  If
128         // a NumberFormatInfo isn't specified, the current culture's
129         // NumberFormatInfo is assumed.
130         //
ParseSystem.Int64131         public static long Parse(String s, NumberStyles style, IFormatProvider provider) {
132             NumberFormatInfo.ValidateParseStyleInteger(style);
133             return Number.ParseInt64(s, style, NumberFormatInfo.GetInstance(provider));
134         }
135 
TryParseSystem.Int64136         public static Boolean TryParse(String s, out Int64 result) {
137             return Number.TryParseInt64(s, NumberStyles.Integer, NumberFormatInfo.CurrentInfo, out result);
138         }
139 
TryParseSystem.Int64140         public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Int64 result) {
141             NumberFormatInfo.ValidateParseStyleInteger(style);
142             return Number.TryParseInt64(s, style, NumberFormatInfo.GetInstance(provider), out result);
143         }
144 
145         //
146         // IConvertible implementation
147         //
148 
GetTypeCodeSystem.Int64149         public TypeCode GetTypeCode() {
150             return TypeCode.Int64;
151         }
152 
153         /// <internalonly/>
IConvertible.ToBooleanSystem.Int64154         bool IConvertible.ToBoolean(IFormatProvider provider) {
155             return Convert.ToBoolean(m_value);
156         }
157 
158         /// <internalonly/>
IConvertible.ToCharSystem.Int64159         char IConvertible.ToChar(IFormatProvider provider) {
160             return Convert.ToChar(m_value);
161         }
162 
163         /// <internalonly/>
IConvertible.ToSByteSystem.Int64164         sbyte IConvertible.ToSByte(IFormatProvider provider) {
165             return Convert.ToSByte(m_value);
166         }
167 
168         /// <internalonly/>
IConvertible.ToByteSystem.Int64169         byte IConvertible.ToByte(IFormatProvider provider) {
170             return Convert.ToByte(m_value);
171         }
172 
173         /// <internalonly/>
IConvertible.ToInt16System.Int64174         short IConvertible.ToInt16(IFormatProvider provider) {
175             return Convert.ToInt16(m_value);
176         }
177 
178         /// <internalonly/>
IConvertible.ToUInt16System.Int64179         ushort IConvertible.ToUInt16(IFormatProvider provider) {
180             return Convert.ToUInt16(m_value);
181         }
182 
183         /// <internalonly/>
IConvertible.ToInt32System.Int64184         int IConvertible.ToInt32(IFormatProvider provider) {
185             return Convert.ToInt32(m_value);
186         }
187 
188         /// <internalonly/>
IConvertible.ToUInt32System.Int64189         uint IConvertible.ToUInt32(IFormatProvider provider) {
190             return Convert.ToUInt32(m_value);
191         }
192 
193         /// <internalonly/>
IConvertible.ToInt64System.Int64194         long IConvertible.ToInt64(IFormatProvider provider) {
195             return m_value;
196         }
197 
198         /// <internalonly/>
IConvertible.ToUInt64System.Int64199         ulong IConvertible.ToUInt64(IFormatProvider provider) {
200             return Convert.ToUInt64(m_value);
201         }
202 
203         /// <internalonly/>
IConvertible.ToSingleSystem.Int64204         float IConvertible.ToSingle(IFormatProvider provider) {
205             return Convert.ToSingle(m_value);
206         }
207 
208         /// <internalonly/>
IConvertible.ToDoubleSystem.Int64209         double IConvertible.ToDouble(IFormatProvider provider) {
210             return Convert.ToDouble(m_value);
211         }
212 
213         /// <internalonly/>
IConvertible.ToDecimalSystem.Int64214         Decimal IConvertible.ToDecimal(IFormatProvider provider) {
215             return Convert.ToDecimal(m_value);
216         }
217 
218         /// <internalonly/>
IConvertible.ToDateTimeSystem.Int64219         DateTime IConvertible.ToDateTime(IFormatProvider provider) {
220             throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Int64", "DateTime"));
221         }
222 
223         /// <internalonly/>
IConvertible.ToTypeSystem.Int64224         Object IConvertible.ToType(Type type, IFormatProvider provider) {
225             return Convert.DefaultToType((IConvertible)this, type, provider);
226         }
227 
228 ///#if GENERICS_WORK
229 ///        //
230 ///        // IArithmetic<Int64> implementation
231 ///        //
232 ///
233 ///        /// <internalonly/>
234 ///        Int64 IArithmetic<Int64>.AbsoluteValue(out bool overflowed) {
235 ///            overflowed = (m_value == MinValue);  // -m_value overflows
236 ///            return (m_value < 0 ? -m_value : m_value);
237 ///        }
238 ///
239 ///        /// <internalonly/>
240 ///        Int64 IArithmetic<Int64>.Negate(out bool overflowed) {
241 ///            overflowed = (m_value == MinValue); // Negate(MinValue) overflows
242 ///            return (-m_value);
243 ///        }
244 ///
245 ///        /// <internalonly/>
246 ///        Int64 IArithmetic<Int64>.Sign(out bool overflowed) {
247 ///            overflowed = false;
248 ///            return (m_value >= 0 ? (m_value == 0 ? 0 : 1) : -1);
249 ///        }
250 ///
251 ///        /// <internalonly/>
252 ///        Int64 IArithmetic<Int64>.Add(Int64 addend, out bool overflowed) {
253 ///            //
254 ///            //   true arithmetic range check       =>     re-written for signed int
255 ///            // -------------------------------          -------------------------------
256 ///            // (  ((m_value + addend) > MaxValue)  =>   (  (addend > 0 && m_value > MaxValue - addend)
257 ///            //  ||((m_value + addend) < MinValue))       ||(addend < 0 && m_value < MinValue - addend) )
258 ///
259 ///
260 ///            overflowed = ((addend > 0) && (m_value > (MaxValue - addend))) ||
261 ///                       ((addend < 0) && (m_value < (MinValue - addend)));
262 ///            return unchecked(m_value + addend);
263 ///        }
264 ///
265 ///        /// <internalonly/>
266 ///        Int64 IArithmetic<Int64>.Subtract(Int64 subtrahend, out bool overflowed) {
267 ///            //
268 ///            //   true arithmetic range check           =>    re-written for signed int
269 ///            // -------------------------------             -------------------------------
270 ///            // (  ((m_value - subtrahend) > MaxValue)  =>   (  (subtrahend < 0 && m_value > MaxValue + subtrahend)
271 ///            //  ||((m_value - subtrahend) < MinValue))       ||(subtrahend > 0 && m_value < MinValue + subtrahend) )
272 ///
273 ///            overflowed = ((subtrahend < 0) && (m_value > (MaxValue + subtrahend))) ||
274 ///                       ((subtrahend > 0) && (m_value < (MinValue + subtrahend)));
275 ///            return unchecked(m_value - subtrahend);
276 ///        }
277 ///
278 ///        /// <internalonly/>
279 ///        Int64 IArithmetic<Int64>.Multiply(Int64 multiplier, out bool overflowed) {
280 ///            overflowed = Int64MultiplyOverflowed(m_value, multiplier);
281 ///            return unchecked(m_value * multiplier);
282 ///        }
283 ///
284 ///        //
285 ///        // Please refer to VM\jithelpers.cpp JIT_LMulOvf for more detailed information
286 ///        //
287 ///        // We perform this overflow check here instead of simply using a 'checked' operation
288 ///        // as it is roughly 1,345X faster.
289 ///        //
290 ///        static Boolean Int64MultiplyOverflowed(Int64 val1, Int64 val2) {
291 ///            Int64 ret;
292 ///
293 ///            // Remember the sign of the result
294 ///            Int32 sign = (Int32) (Hi32Bits(val1) ^ Hi32Bits(val2));
295 ///
296 ///            // Convert to unsigned multiplication
297 ///            if (val1 < 0) val1 = -val1;
298 ///            if (val2 < 0) val2 = -val2;
299 ///
300 ///            // Get the upper 32 bits of the numbers
301 ///            UInt32 val1High = Hi32Bits(val1);
302 ///            UInt32 val2High = Hi32Bits(val2);
303 ///
304 ///            UInt64 valMid;
305 ///
306 ///            if (val1High == 0) {
307 ///                // Compute the 'middle' bits of the long multiplication
308 ///                valMid = Mul32x32To64(val2High, (UInt32)val1);
309 ///            }
310 ///            else {
311 ///                if (val2High != 0)
312 ///                    return true;
313 ///                // Compute the 'middle' bits of the long multiplication
314 ///                valMid = Mul32x32To64(val1High, (UInt32)val2);
315 ///            }
316 ///
317 ///                // See if any bits after bit 32 are set
318 ///            if (Hi32Bits((Int64)valMid) != 0)
319 ///                return true;
320 ///
321 ///            ret = (Int64)  (Mul32x32To64((UInt32)val1, (UInt32)val2) + (valMid << 32));
322 ///
323 ///            // check for overflow
324 ///            if (Hi32Bits(ret) < (UInt32)valMid)
325 ///                return true;
326 ///
327 ///            if (sign >= 0) {
328 ///                // have we spilled into the sign bit?
329 ///                if (ret < 0)
330 ///                    return true;
331 ///            }
332 ///            else {
333 ///                ret = -ret;
334 ///                // have we spilled into the sign bit?
335 ///                if (ret > 0)
336 ///                    return true;
337 ///            }
338 ///            return false;
339 ///        }
340 ///
341 ///        //
342 ///        // helper method to get high 32-bit of 64-bit int
343 ///        //
344 ///        static UInt32 Hi32Bits(Int64 x) {
345 ///            return ((UInt32)((UInt64)(x) >> 32));
346 ///        }
347 ///
348 ///        //
349 ///        // helper method to multiply two 32-bit uints
350 ///        //
351 ///        static UInt64 Mul32x32To64(UInt32 x, UInt32 y) {
352 ///            return ((UInt64)(x) * (UInt64)(y));
353 ///        }
354 ///
355 ///        /// <internalonly/>
356 ///        Int64 IArithmetic<Int64>.Divide(Int64 divisor, out bool overflowed) {
357 ///            // signed integer division can overflow.  Consider the following
358 ///            // 8-bit case: -128/-1 = 128.
359 ///            // 128 won't fit into a signed 8-bit integer, instead you will end up
360 ///            // with -128.
361 ///            //
362 ///            // Because of this corner case, we must check if the numerator
363 ///            // is MinValue and if the denominator is -1.
364 ///
365 ///            overflowed = (divisor == -1 && m_value == MinValue);
366 ///
367 ///            if (overflowed) {
368 ///                // we special case (MinValue / (-1)) for Int32 and Int64 as
369 ///                // unchecked still throws OverflowException when variables
370 ///                // are used instead of constants
371 ///                return MinValue;
372 ///            }
373 ///            else {
374 ///                return unchecked(m_value / divisor);
375 ///            }
376 ///        }
377 ///
378 ///        /// <internalonly/>
379 ///        Int64 IArithmetic<Int64>.DivideRemainder(Int64 divisor, out Int64 remainder, out bool overflowed) {
380 ///            overflowed = (divisor == -1 && m_value == MinValue);
381 ///
382 ///            if (overflowed) {
383 ///                // we special case (MinValue / (-1)) for Int32 and Int64 as
384 ///                // unchecked still throws OverflowException when variables
385 ///                // are used instead of constants
386 ///                remainder = 0;
387 ///                return MinValue;
388 ///            }
389 ///            else {
390 ///                remainder = (m_value % divisor);
391 ///                return unchecked(m_value / divisor);
392 ///            }
393 ///        }
394 ///
395 ///        /// <internalonly/>
396 ///        Int64 IArithmetic<Int64>.Remainder(Int64 divisor, out bool overflowed) {
397 ///            overflowed = false;
398 ///
399 ///            if (divisor == -1 && m_value == MinValue) {
400 ///                // we special case (MinValue % (-1)) for Int32 and Int64 as
401 ///                // unchecked still throws OverflowException when variables
402 ///                // are used instead of constants
403 ///                return 0;
404 ///            }
405 ///            else {
406 ///                return (m_value % divisor);
407 ///            }
408 ///        }
409 ///
410 ///        /// <internalonly/>
411 ///        ArithmeticDescriptor<Int64> IArithmetic<Int64>.GetDescriptor() {
412 ///            if (s_descriptor == null) {
413 ///                s_descriptor = new Int64ArithmeticDescriptor( ArithmeticCapabilities.One
414 ///                                                             | ArithmeticCapabilities.Zero
415 ///                                                             | ArithmeticCapabilities.MaxValue
416 ///                                                             | ArithmeticCapabilities.MinValue);
417 ///            }
418 ///            return s_descriptor;
419 ///        }
420 ///
421 ///        private static Int64ArithmeticDescriptor s_descriptor;
422 ///
423 ///        class Int64ArithmeticDescriptor : ArithmeticDescriptor<Int64> {
424 ///            public Int64ArithmeticDescriptor(ArithmeticCapabilities capabilities) : base(capabilities) {}
425 ///
426 ///            public override Int64 One {
427 ///                get {
428 ///                    return (Int64) 1;
429 ///                }
430 ///            }
431 ///
432 ///            public override Int64 Zero {
433 ///                get {
434 ///                    return (Int64) 0;
435 ///                }
436 ///            }
437 ///
438 ///            public override Int64 MinValue {
439 ///                get {
440 ///                    return Int64.MinValue;
441 ///                }
442 ///            }
443 ///
444 ///            public override Int64 MaxValue {
445 ///                get {
446 ///                    return Int64.MaxValue;
447 ///                }
448 ///            }
449 ///        }
450 ///#endif // #if GENERICS_WORK
451 
452     }
453 }
454