diff options
Diffstat (limited to 'src/mscorlib/src/System/Decimal.cs')
-rw-r--r-- | src/mscorlib/src/System/Decimal.cs | 883 |
1 files changed, 507 insertions, 376 deletions
diff --git a/src/mscorlib/src/System/Decimal.cs b/src/mscorlib/src/System/Decimal.cs index a01ed19753..ce59a99334 100644 --- a/src/mscorlib/src/System/Decimal.cs +++ b/src/mscorlib/src/System/Decimal.cs @@ -2,17 +2,18 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -namespace System { - - using System; - using System.Globalization; - using System.Runtime.InteropServices; - using System.Runtime.CompilerServices; - using System.Runtime.ConstrainedExecution; - using System.Runtime.Versioning; - using System.Runtime.Serialization; - using System.Diagnostics.Contracts; +using System; +using System.Globalization; +using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; +using System.Runtime.ConstrainedExecution; +using System.Runtime.Versioning; +using System.Runtime.Serialization; +using System.Diagnostics.Contracts; + +namespace System +{ // Implements the Decimal data type. The Decimal data type can // represent values ranging from -79,228,162,514,264,337,593,543,950,335 to // 79,228,162,514,264,337,593,543,950,335 with 28 significant digits. The @@ -60,31 +61,30 @@ namespace System { [System.Runtime.Versioning.NonVersionable] // This only applies to field layout public struct Decimal : IFormattable, IComparable, IConvertible, IComparable<Decimal>, IEquatable<Decimal>, IDeserializationCallback { - // Sign mask for the flags field. A value of zero in this bit indicates a // positive Decimal value, and a value of one in this bit indicates a // negative Decimal value. // // Look at OleAut's DECIMAL_NEG constant to check for negative values // in native code. - private const int SignMask = unchecked((int)0x80000000); + private const int SignMask = unchecked((int)0x80000000); private const byte DECIMAL_NEG = 0x80; private const byte DECIMAL_ADD = 0x00; - + // Scale mask for the flags field. This byte in the flags field contains // the power of 10 to divide the Decimal value by. The scale byte must // contain a value between 0 and 28 inclusive. private const int ScaleMask = 0x00FF0000; - + // Number of bits scale is shifted by. private const int ScaleShift = 16; - + // The maximum power of 10 that a 32 bit integer can store private const Int32 MaxInt32Scale = 9; // Fast access for 10^n where n is 0-9 private static UInt32[] Powers10 = new UInt32[] { - 1, + 1, 10, 100, 1000, @@ -94,21 +94,21 @@ namespace System { 10000000, 100000000, 1000000000 - }; - + }; + // Constant representing the Decimal value 0. public const Decimal Zero = 0m; - + // Constant representing the Decimal value 1. public const Decimal One = 1m; - + // Constant representing the Decimal value -1. public const Decimal MinusOne = -1m; - + // Constant representing the largest possible Decimal value. The value of // this constant is 79,228,162,514,264,337,593,543,950,335. public const Decimal MaxValue = 79228162514264337593543950335m; - + // Constant representing the smallest possible Decimal value. The value of // this constant is -79,228,162,514,264,337,593,543,950,335. public const Decimal MinValue = -79228162514264337593543950335m; @@ -120,8 +120,8 @@ namespace System { // Constant representing the positive number that is the closest possible // Decimal value to +0m. - private const Decimal NearPositiveZero = +0.000000000000000000000000001m; - + private const Decimal NearPositiveZero = +0.000000000000000000000000001m; + // The lo, mid, hi, and flags fields contain the representation of the // Decimal value. The lo, mid, and hi fields contain the 96-bit integer // part of the Decimal. Bits 0-15 (the lower word) of the flags field are @@ -137,8 +137,8 @@ namespace System { private int hi; private int lo; private int mid; - - + + // Constructs a zero Decimal. //public Decimal() { // lo = 0; @@ -146,17 +146,20 @@ namespace System { // hi = 0; // flags = 0; //} - + // Constructs a Decimal from an integer value. // - public Decimal(int value) { + public Decimal(int value) + { // JIT today can't inline methods that contains "starg" opcode. // For more details, see DevDiv Bugs 81184: x86 JIT CQ: Removing the inline striction of "starg". - int value_copy = value; - if (value_copy >= 0) { + int value_copy = value; + if (value_copy >= 0) + { flags = 0; } - else { + else + { flags = SignMask; value_copy = -value_copy; } @@ -164,27 +167,31 @@ namespace System { mid = 0; hi = 0; } - + // Constructs a Decimal from an unsigned integer value. // [CLSCompliant(false)] - public Decimal(uint value) { + public Decimal(uint value) + { flags = 0; - lo = (int) value; + lo = (int)value; mid = 0; hi = 0; } - + // Constructs a Decimal from a long value. // - public Decimal(long value) { + public Decimal(long value) + { // JIT today can't inline methods that contains "starg" opcode. // For more details, see DevDiv Bugs 81184: x86 JIT CQ: Removing the inline striction of "starg". long value_copy = value; - if (value_copy >= 0) { + if (value_copy >= 0) + { flags = 0; } - else { + else + { flags = SignMask; value_copy = -value_copy; } @@ -192,30 +199,32 @@ namespace System { mid = (int)(value_copy >> 32); hi = 0; } - + // Constructs a Decimal from an unsigned long value. // - [CLSCompliant(false)] - public Decimal(ulong value) { + [CLSCompliant(false)] + public Decimal(ulong value) + { flags = 0; lo = (int)value; mid = (int)(value >> 32); hi = 0; } - + // Constructs a Decimal from a float value. // [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern Decimal(float value); - + // Constructs a Decimal from a double value. // [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern Decimal(double value); - + // Constructs a Decimal from a Currency value. // - internal Decimal(Currency value) { + internal Decimal(Currency value) + { this = Currency.ToDecimal(value); } @@ -225,13 +234,13 @@ namespace System { { return new Currency(value).ToOACurrency(); } - + public static Decimal FromOACurrency(long cy) { return Currency.ToDecimal(Currency.FromOACurrency(cy)); } - + // Constructs a Decimal from an integer array containing a binary // representation. The bits argument must be a non-null integer // array with four elements. bits[0], bits[1], and @@ -251,21 +260,25 @@ namespace System { // The possible binary representations of a particular value are all // equally valid, and all are numerically equivalent. // - public Decimal(int[] bits) { - this.lo = 0; - this.mid = 0; - this.hi = 0; - this.flags = 0; + public Decimal(int[] bits) + { + lo = 0; + mid = 0; + hi = 0; + flags = 0; SetBits(bits); } - private void SetBits(int[] bits) { - if (bits==null) + private void SetBits(int[] bits) + { + if (bits == null) throw new ArgumentNullException(nameof(bits)); Contract.EndContractBlock(); - if (bits.Length == 4) { + if (bits.Length == 4) + { int f = bits[3]; - if ((f & ~(SignMask | ScaleMask)) == 0 && (f & ScaleMask) <= (28 << 16)) { + if ((f & ~(SignMask | ScaleMask)) == 0 && (f & ScaleMask) <= (28 << 16)) + { lo = bits[0]; mid = bits[1]; hi = bits[2]; @@ -273,94 +286,108 @@ namespace System { return; } } - throw new ArgumentException(Environment.GetResourceString("Arg_DecBitCtor")); + throw new ArgumentException(SR.Arg_DecBitCtor); } - + // Constructs a Decimal from its constituent parts. // - public Decimal(int lo, int mid, int hi, bool isNegative, byte scale) { + public Decimal(int lo, int mid, int hi, bool isNegative, byte scale) + { if (scale > 28) - throw new ArgumentOutOfRangeException(nameof(scale), Environment.GetResourceString("ArgumentOutOfRange_DecimalScale")); + throw new ArgumentOutOfRangeException(nameof(scale), SR.ArgumentOutOfRange_DecimalScale); Contract.EndContractBlock(); this.lo = lo; this.mid = mid; this.hi = hi; - this.flags = ((int)scale) << 16; + flags = ((int)scale) << 16; if (isNegative) - this.flags |= SignMask; + flags |= SignMask; } [OnSerializing] - void OnSerializing(StreamingContext ctx) { + private void OnSerializing(StreamingContext ctx) + { // OnSerializing is called before serialization of an object - try { - SetBits( GetBits(this) ); - } catch (ArgumentException e) { - throw new SerializationException(Environment.GetResourceString("Overflow_Decimal"), e); - } + try + { + SetBits(GetBits(this)); + } + catch (ArgumentException e) + { + throw new SerializationException(SR.Overflow_Decimal, e); + } } - void IDeserializationCallback.OnDeserialization(Object sender) { + void IDeserializationCallback.OnDeserialization(Object sender) + { // OnDeserialization is called after each instance of this class is deserialized. // This callback method performs decimal validation after being deserialized. - try { - SetBits( GetBits(this) ); - } catch (ArgumentException e) { - throw new SerializationException(Environment.GetResourceString("Overflow_Decimal"), e); - } + try + { + SetBits(GetBits(this)); + } + catch (ArgumentException e) + { + throw new SerializationException(SR.Overflow_Decimal, e); + } } - + // Constructs a Decimal from its constituent parts. - private Decimal(int lo, int mid, int hi, int flags) { - if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) { + private Decimal(int lo, int mid, int hi, int flags) + { + if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) + { this.lo = lo; this.mid = mid; this.hi = hi; this.flags = flags; return; } - throw new ArgumentException(Environment.GetResourceString("Arg_DecBitCtor")); + throw new ArgumentException(SR.Arg_DecBitCtor); } - + // Returns the absolute value of the given Decimal. If d is // positive, the result is d. If d is negative, the result // is -d. // - internal static Decimal Abs(Decimal d) { + internal static Decimal Abs(Decimal d) + { return new Decimal(d.lo, d.mid, d.hi, d.flags & ~SignMask); } - + // Adds two Decimal values. // public static Decimal Add(Decimal d1, Decimal d2) { - FCallAddSub (ref d1, ref d2, DECIMAL_ADD); + FCallAddSub(ref d1, ref d2, DECIMAL_ADD); return d1; } - + // FCallAddSub adds or subtracts two decimal values. On return, d1 contains the result // of the operation. Passing in DECIMAL_ADD or DECIMAL_NEG for bSign indicates // addition or subtraction, respectively. // [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallAddSub(ref Decimal d1, ref Decimal d2, byte bSign); - + // Rounds a Decimal to an integer value. The Decimal argument is rounded // towards positive infinity. - public static Decimal Ceiling(Decimal d) { + public static Decimal Ceiling(Decimal d) + { return (-(Decimal.Floor(-d))); - } - + } + // Compares two Decimal values, returning an integer that indicates their // relationship. // - public static int Compare(Decimal d1, Decimal d2) { + public static int Compare(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2); } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern int FCallCompare(ref Decimal d1, ref Decimal d2); - + // Compares this object to another object, returning an integer that // indicates the relationship. // Returns a value less than zero if this object @@ -372,9 +399,9 @@ namespace System { if (value == null) return 1; if (!(value is Decimal)) - throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDecimal")); - - Decimal other = (Decimal)value; + throw new ArgumentException(SR.Arg_MustBeDecimal); + + Decimal other = (Decimal)value; return FCallCompare(ref this, ref other); } @@ -382,12 +409,12 @@ namespace System { { return FCallCompare(ref this, ref value); } - + // Divides two Decimal values. // public static Decimal Divide(Decimal d1, Decimal d2) { - FCallDivide (ref d1, ref d2); + FCallDivide(ref d1, ref d2); return d1; } @@ -397,13 +424,15 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallDivide(ref Decimal d1, ref Decimal d2); - + // Checks if this Decimal is equal to a given object. Returns true // if the given object is a boxed Decimal and its value is equal to the // value of this Decimal. Returns false otherwise. // - public override bool Equals(Object value) { - if (value is Decimal) { + public override bool Equals(Object value) + { + if (value is Decimal) + { Decimal other = (Decimal)value; return FCallCompare(ref this, ref other) == 0; } @@ -419,52 +448,57 @@ namespace System { // [MethodImplAttribute(MethodImplOptions.InternalCall)] public extern override int GetHashCode(); - + // Compares two Decimal values for equality. Returns true if the two // Decimal values are equal, or false if they are not equal. // - public static bool Equals(Decimal d1, Decimal d2) { + public static bool Equals(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) == 0; } - + // Rounds a Decimal to an integer value. The Decimal argument is rounded // towards negative infinity. // public static Decimal Floor(Decimal d) { - FCallFloor (ref d); + FCallFloor(ref d); return d; } [MethodImplAttribute(MethodImplOptions.InternalCall)] - private static extern void FCallFloor(ref Decimal d); + private static extern void FCallFloor(ref Decimal d); // Converts this Decimal to a string. The resulting string consists of an // optional minus sign ("-") followed to a sequence of digits ("0" - "9"), // optionally followed by a decimal point (".") and another sequence of // digits. // - public override String ToString() { + public override String ToString() + { Contract.Ensures(Contract.Result<String>() != null); return Number.FormatDecimal(this, null, NumberFormatInfo.CurrentInfo); } - public String ToString(String format) { + public String ToString(String format) + { Contract.Ensures(Contract.Result<String>() != null); return Number.FormatDecimal(this, format, NumberFormatInfo.CurrentInfo); } - public String ToString(IFormatProvider provider) { + public String ToString(IFormatProvider provider) + { Contract.Ensures(Contract.Result<String>() != null); return Number.FormatDecimal(this, null, NumberFormatInfo.GetInstance(provider)); - } + } - public String ToString(String format, IFormatProvider provider) { + public String ToString(String format, IFormatProvider provider) + { Contract.Ensures(Contract.Result<String>() != null); return Number.FormatDecimal(this, format, NumberFormatInfo.GetInstance(provider)); } - + // Converts a string to a Decimal. The string must consist of an optional // minus sign ("-") followed by a sequence of digits ("0" - "9"). The // sequence of digits may optionally contain a single decimal point (".") @@ -472,29 +506,35 @@ namespace System { // Parse also allows a currency symbol, a trailing negative sign, and // parentheses in the number. // - public static Decimal Parse(String s) { + public static Decimal Parse(String s) + { return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo); } - - public static Decimal Parse(String s, NumberStyles style) { + + public static Decimal Parse(String s, NumberStyles style) + { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); return Number.ParseDecimal(s, style, NumberFormatInfo.CurrentInfo); } - public static Decimal Parse(String s, IFormatProvider provider) { + public static Decimal Parse(String s, IFormatProvider provider) + { return Number.ParseDecimal(s, NumberStyles.Number, NumberFormatInfo.GetInstance(provider)); } - - public static Decimal Parse(String s, NumberStyles style, IFormatProvider provider) { + + public static Decimal Parse(String s, NumberStyles style, IFormatProvider provider) + { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider)); } - - public static Boolean TryParse(String s, out Decimal result) { + + public static Boolean TryParse(String s, out Decimal result) + { return Number.TryParseDecimal(s, NumberStyles.Number, NumberFormatInfo.CurrentInfo, out result); } - public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Decimal result) { + public static Boolean TryParse(String s, NumberStyles style, IFormatProvider provider, out Decimal result) + { NumberFormatInfo.ValidateParseStyleFloatingPoint(style); return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result); } @@ -509,160 +549,181 @@ namespace System { // indicates the sign of the Decimal value, 0 meaning positive and 1 // meaning negative. // - public static int[] GetBits(Decimal d) { - return new int[] {d.lo, d.mid, d.hi, d.flags}; + public static int[] GetBits(Decimal d) + { + return new int[] { d.lo, d.mid, d.hi, d.flags }; } - internal static void GetBytes(Decimal d, byte [] buffer) { + internal static void GetBytes(Decimal d, byte[] buffer) + { Contract.Requires((buffer != null && buffer.Length >= 16), "[GetBytes]buffer != null && buffer.Length >= 16"); - buffer[0] = (byte) d.lo; - buffer[1] = (byte) (d.lo >> 8); - buffer[2] = (byte) (d.lo >> 16); - buffer[3] = (byte) (d.lo >> 24); - - buffer[4] = (byte) d.mid; - buffer[5] = (byte) (d.mid >> 8); - buffer[6] = (byte) (d.mid >> 16); - buffer[7] = (byte) (d.mid >> 24); - - buffer[8] = (byte) d.hi; - buffer[9] = (byte) (d.hi >> 8); - buffer[10] = (byte) (d.hi >> 16); - buffer[11] = (byte) (d.hi >> 24); - - buffer[12] = (byte) d.flags; - buffer[13] = (byte) (d.flags >> 8); - buffer[14] = (byte) (d.flags >> 16); - buffer[15] = (byte) (d.flags >> 24); - } - - internal static decimal ToDecimal(byte [] buffer) { + buffer[0] = (byte)d.lo; + buffer[1] = (byte)(d.lo >> 8); + buffer[2] = (byte)(d.lo >> 16); + buffer[3] = (byte)(d.lo >> 24); + + buffer[4] = (byte)d.mid; + buffer[5] = (byte)(d.mid >> 8); + buffer[6] = (byte)(d.mid >> 16); + buffer[7] = (byte)(d.mid >> 24); + + buffer[8] = (byte)d.hi; + buffer[9] = (byte)(d.hi >> 8); + buffer[10] = (byte)(d.hi >> 16); + buffer[11] = (byte)(d.hi >> 24); + + buffer[12] = (byte)d.flags; + buffer[13] = (byte)(d.flags >> 8); + buffer[14] = (byte)(d.flags >> 16); + buffer[15] = (byte)(d.flags >> 24); + } + + internal static decimal ToDecimal(byte[] buffer) + { Contract.Requires((buffer != null && buffer.Length >= 16), "[ToDecimal]buffer != null && buffer.Length >= 16"); int lo = ((int)buffer[0]) | ((int)buffer[1] << 8) | ((int)buffer[2] << 16) | ((int)buffer[3] << 24); int mid = ((int)buffer[4]) | ((int)buffer[5] << 8) | ((int)buffer[6] << 16) | ((int)buffer[7] << 24); int hi = ((int)buffer[8]) | ((int)buffer[9] << 8) | ((int)buffer[10] << 16) | ((int)buffer[11] << 24); int flags = ((int)buffer[12]) | ((int)buffer[13] << 8) | ((int)buffer[14] << 16) | ((int)buffer[15] << 24); - return new Decimal(lo,mid,hi,flags); + return new Decimal(lo, mid, hi, flags); } - + // This method does a 'raw' and 'unchecked' addition of a UInt32 to a Decimal in place. // 'raw' means that it operates on the internal 96-bit unsigned integer value and // ingores the sign and scale. This means that it is not equivalent to just adding // that number, as the sign and scale are effectively applied to the UInt32 value also. // 'unchecked' means that it does not fail if you overflow the 96 bit value. - private static void InternalAddUInt32RawUnchecked(ref Decimal value, UInt32 i) { - UInt32 v; + private static void InternalAddUInt32RawUnchecked(ref Decimal value, UInt32 i) + { + UInt32 v; UInt32 sum; v = (UInt32)value.lo; sum = v + i; value.lo = (Int32)sum; - if (sum < v || sum < i) { + if (sum < v || sum < i) + { v = (UInt32)value.mid; sum = v + 1; value.mid = (Int32)sum; - if (sum < v || sum < 1) { - value.hi = (Int32) ((UInt32)value.hi + 1); - } + if (sum < v || sum < 1) + { + value.hi = (Int32)((UInt32)value.hi + 1); + } } - } + } // This method does an in-place division of a decimal by a UInt32, returning the remainder. // Although it does not operate on the sign or scale, this does not result in any // caveat for the result. It is equivalent to dividing by that number. - private static UInt32 InternalDivRemUInt32(ref Decimal value, UInt32 divisor) { + private static UInt32 InternalDivRemUInt32(ref Decimal value, UInt32 divisor) + { UInt32 remainder = 0; UInt64 n; - if (value.hi != 0) { - n = ((UInt32) value.hi); + if (value.hi != 0) + { + n = ((UInt32)value.hi); value.hi = (Int32)((UInt32)(n / divisor)); remainder = (UInt32)(n % divisor); } - if (value.mid != 0 || remainder != 0) { - n = ((UInt64)remainder << 32) | (UInt32) value.mid; + if (value.mid != 0 || remainder != 0) + { + n = ((UInt64)remainder << 32) | (UInt32)value.mid; value.mid = (Int32)((UInt32)(n / divisor)); - remainder = (UInt32)(n % divisor); + remainder = (UInt32)(n % divisor); } - if (value.lo != 0 || remainder != 0) { - n = ((UInt64)remainder << 32) | (UInt32) value.lo; + if (value.lo != 0 || remainder != 0) + { + n = ((UInt64)remainder << 32) | (UInt32)value.lo; value.lo = (Int32)((UInt32)(n / divisor)); - remainder = (UInt32)(n % divisor); + remainder = (UInt32)(n % divisor); } return remainder; } - + // Does an in-place round the specified number of digits, rounding mid-point values // away from zero - private static void InternalRoundFromZero(ref Decimal d, int decimalCount) { + private static void InternalRoundFromZero(ref Decimal d, int decimalCount) + { Int32 scale = (d.flags & ScaleMask) >> ScaleShift; Int32 scaleDifference = scale - decimalCount; - if (scaleDifference <= 0) { + if (scaleDifference <= 0) + { return; } // Divide the value by 10^scaleDifference UInt32 lastRemainder; UInt32 lastDivisor; - do { + do + { Int32 diffChunk = (scaleDifference > MaxInt32Scale) ? MaxInt32Scale : scaleDifference; lastDivisor = Powers10[diffChunk]; lastRemainder = InternalDivRemUInt32(ref d, lastDivisor); scaleDifference -= diffChunk; } while (scaleDifference > 0); - + // Round away from zero at the mid point - if (lastRemainder >= (lastDivisor >> 1)) { + if (lastRemainder >= (lastDivisor >> 1)) + { InternalAddUInt32RawUnchecked(ref d, 1); } - + // the scale becomes the desired decimal count d.flags = ((decimalCount << ScaleShift) & ScaleMask) | (d.flags & SignMask); } - + // Returns the larger of two Decimal values. // - internal static Decimal Max(Decimal d1, Decimal d2) { - return FCallCompare(ref d1, ref d2) >= 0? d1: d2; + internal static Decimal Max(Decimal d1, Decimal d2) + { + return FCallCompare(ref d1, ref d2) >= 0 ? d1 : d2; } - + // Returns the smaller of two Decimal values. // - internal static Decimal Min(Decimal d1, Decimal d2) { - return FCallCompare(ref d1, ref d2) < 0? d1: d2; + internal static Decimal Min(Decimal d1, Decimal d2) + { + return FCallCompare(ref d1, ref d2) < 0 ? d1 : d2; } - - public static Decimal Remainder(Decimal d1, Decimal d2) { + + public static Decimal Remainder(Decimal d1, Decimal d2) + { // OleAut doesn't provide a VarDecMod. - + // In the operation x % y the sign of y does not matter. Result will have the sign of x. - d2.flags = (d2.flags & ~SignMask) | (d1.flags & SignMask); + d2.flags = (d2.flags & ~SignMask) | (d1.flags & SignMask); // This piece of code is to work around the fact that Dividing a decimal with 28 digits number by decimal which causes // causes the result to be 28 digits, can cause to be incorrectly rounded up. // eg. Decimal.MaxValue / 2 * Decimal.MaxValue will overflow since the division by 2 was rounded instead of being truncked. - if (Abs(d1) < Abs(d2)) { + if (Abs(d1) < Abs(d2)) + { return d1; } d1 -= d2; - if (d1 == 0) { + if (d1 == 0) + { // The sign of D1 will be wrong here. Fall through so that we still get a DivideByZeroException d1.flags = (d1.flags & ~SignMask) | (d2.flags & SignMask); } - + // Formula: d1 - (RoundTowardsZero(d1 / d2) * d2) - Decimal dividedResult = Truncate(d1/d2); + Decimal dividedResult = Truncate(d1 / d2); Decimal multipliedResult = dividedResult * d2; Decimal result = d1 - multipliedResult; // See if the result has crossed 0 - if ((d1.flags & SignMask) != (result.flags & SignMask)) { - - if (NearNegativeZero <= result && result <= NearPositiveZero) { + if ((d1.flags & SignMask) != (result.flags & SignMask)) + { + if (NearNegativeZero <= result && result <= NearPositiveZero) + { // Certain Remainder operations on decimals with 28 significant digits round // to [+-]0.000000000000000000000000001m instead of [+-]0m during the intermediate calculations. // 'zero' results just need their sign corrected. result.flags = (result.flags & ~SignMask) | (d1.flags & SignMask); } - else { + else + { // If the division rounds up because it runs out of digits, the multiplied result can end up with a larger // absolute value and the result of the formula crosses 0. To correct it can add the divisor back. result += d2; @@ -671,12 +732,12 @@ namespace System { return result; } - + // Multiplies two Decimal values. // public static Decimal Multiply(Decimal d1, Decimal d2) { - FCallMultiply (ref d1, ref d2); + FCallMultiply(ref d1, ref d2); return d1; } @@ -685,11 +746,12 @@ namespace System { // [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallMultiply(ref Decimal d1, ref Decimal d2); - + // Returns the negated value of the given Decimal. If d is non-zero, // the result is -d. If d is zero, the result is zero. // - public static Decimal Negate(Decimal d) { + public static Decimal Negate(Decimal d) + { return new Decimal(d.lo, d.mid, d.hi, d.flags ^ SignMask); } @@ -700,33 +762,39 @@ namespace System { // // By default a mid-point value is rounded to the nearest even number. If the mode is // passed in, it can also round away from zero. - - public static Decimal Round(Decimal d) { + + public static Decimal Round(Decimal d) + { return Round(d, 0); } - + public static Decimal Round(Decimal d, int decimals) { - FCallRound (ref d, decimals); + FCallRound(ref d, decimals); return d; } - public static Decimal Round(Decimal d, MidpointRounding mode) { + public static Decimal Round(Decimal d, MidpointRounding mode) + { return Round(d, 0, mode); } - public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) { + public static Decimal Round(Decimal d, int decimals, MidpointRounding mode) + { if ((decimals < 0) || (decimals > 28)) - throw new ArgumentOutOfRangeException(nameof(decimals), Environment.GetResourceString("ArgumentOutOfRange_DecimalRound")); - if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) { - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidEnumValue", mode, nameof(MidpointRounding)), nameof(mode)); + throw new ArgumentOutOfRangeException(nameof(decimals), SR.ArgumentOutOfRange_DecimalRound); + if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero) + { + throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode)); } Contract.EndContractBlock(); - if (mode == MidpointRounding.ToEven) { - FCallRound (ref d, decimals); + if (mode == MidpointRounding.ToEven) + { + FCallRound(ref d, decimals); } - else { + else + { InternalRoundFromZero(ref d, decimals); } return d; @@ -734,7 +802,7 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallRound(ref Decimal d, int decimals); - + // Subtracts two Decimal values. // public static Decimal Subtract(Decimal d1, Decimal d2) @@ -747,67 +815,75 @@ namespace System { // towards zero to the nearest integer value, and the result of this // operation is returned as a byte. // - public static byte ToByte(Decimal value) { + public static byte ToByte(Decimal value) + { uint temp; - try { - temp = ToUInt32(value); + try + { + temp = ToUInt32(value); } - catch (OverflowException e) { - throw new OverflowException(Environment.GetResourceString("Overflow_Byte"), e); + catch (OverflowException e) + { + throw new OverflowException(SR.Overflow_Byte, e); } - if (temp < Byte.MinValue || temp > Byte.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Byte")); + if (temp < Byte.MinValue || temp > Byte.MaxValue) throw new OverflowException(SR.Overflow_Byte); return (byte)temp; - } - + // Converts a Decimal to a signed byte. The Decimal value is rounded // towards zero to the nearest integer value, and the result of this // operation is returned as a byte. // - [CLSCompliant(false)] - public static sbyte ToSByte(Decimal value) { + [CLSCompliant(false)] + public static sbyte ToSByte(Decimal value) + { int temp; - try { - temp = ToInt32(value); + try + { + temp = ToInt32(value); } - catch (OverflowException e) { - throw new OverflowException(Environment.GetResourceString("Overflow_SByte"), e); + catch (OverflowException e) + { + throw new OverflowException(SR.Overflow_SByte, e); } - if (temp < SByte.MinValue || temp > SByte.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_SByte")); + if (temp < SByte.MinValue || temp > SByte.MaxValue) throw new OverflowException(SR.Overflow_SByte); return (sbyte)temp; } - + // Converts a Decimal to a short. The Decimal value is // rounded towards zero to the nearest integer value, and the result of // this operation is returned as a short. // - public static short ToInt16(Decimal value) { + public static short ToInt16(Decimal value) + { int temp; - try { - temp = ToInt32(value); + try + { + temp = ToInt32(value); } - catch (OverflowException e) { - throw new OverflowException(Environment.GetResourceString("Overflow_Int16"), e); + catch (OverflowException e) + { + throw new OverflowException(SR.Overflow_Int16, e); } - if (temp < Int16.MinValue || temp > Int16.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_Int16")); + if (temp < Int16.MinValue || temp > Int16.MaxValue) throw new OverflowException(SR.Overflow_Int16); return (short)temp; } - - + + // Converts a Decimal to a Currency. Since a Currency // has fewer significant digits than a Decimal, this operation may // produce round-off errors. // internal static Currency ToCurrency(Decimal d) { - Currency result = new Currency (); - FCallToCurrency (ref result, d); + Currency result = new Currency(); + FCallToCurrency(ref result, d); return result; } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallToCurrency(ref Currency result, Decimal d); - + // Converts a Decimal to a double. Since a double has fewer significant // digits than a Decimal, this operation may produce round-off errors. // @@ -816,92 +892,107 @@ namespace System { [MethodImplAttribute(MethodImplOptions.InternalCall)] internal static extern int FCallToInt32(Decimal d); - + // Converts a Decimal to an integer. The Decimal value is rounded towards // zero to the nearest integer value, and the result of this operation is // returned as an integer. // - public static int ToInt32(Decimal d) { - if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); - if (d.hi == 0 && d.mid == 0) { + public static int ToInt32(Decimal d) + { + if ((d.flags & ScaleMask) != 0) FCallTruncate(ref d); + if (d.hi == 0 && d.mid == 0) + { int i = d.lo; - if (d.flags >= 0) { + if (d.flags >= 0) + { if (i >= 0) return i; } - else { + else + { i = -i; if (i <= 0) return i; } } - throw new OverflowException(Environment.GetResourceString("Overflow_Int32")); + throw new OverflowException(SR.Overflow_Int32); } - + // Converts a Decimal to a long. The Decimal value is rounded towards zero // to the nearest integer value, and the result of this operation is // returned as a long. // - public static long ToInt64(Decimal d) { - if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); - if (d.hi == 0) { + public static long ToInt64(Decimal d) + { + if ((d.flags & ScaleMask) != 0) FCallTruncate(ref d); + if (d.hi == 0) + { long l = d.lo & 0xFFFFFFFFL | (long)d.mid << 32; - if (d.flags >= 0) { + if (d.flags >= 0) + { if (l >= 0) return l; } - else { + else + { l = -l; if (l <= 0) return l; } } - throw new OverflowException(Environment.GetResourceString("Overflow_Int64")); + throw new OverflowException(SR.Overflow_Int64); } - + // Converts a Decimal to an ushort. The Decimal // value is rounded towards zero to the nearest integer value, and the // result of this operation is returned as an ushort. // - [CLSCompliant(false)] - public static ushort ToUInt16(Decimal value) { + [CLSCompliant(false)] + public static ushort ToUInt16(Decimal value) + { uint temp; - try { - temp = ToUInt32(value); + try + { + temp = ToUInt32(value); } - catch (OverflowException e) { - throw new OverflowException(Environment.GetResourceString("Overflow_UInt16"), e); + catch (OverflowException e) + { + throw new OverflowException(SR.Overflow_UInt16, e); } - if (temp < UInt16.MinValue || temp > UInt16.MaxValue) throw new OverflowException(Environment.GetResourceString("Overflow_UInt16")); + if (temp < UInt16.MinValue || temp > UInt16.MaxValue) throw new OverflowException(SR.Overflow_UInt16); return (ushort)temp; } - + // Converts a Decimal to an unsigned integer. The Decimal // value is rounded towards zero to the nearest integer value, and the // result of this operation is returned as an unsigned integer. // - [CLSCompliant(false)] - public static uint ToUInt32(Decimal d) { - if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); - if (d.hi == 0 && d.mid == 0) { - uint i = (uint) d.lo; - if (d.flags >= 0 || i == 0) + [CLSCompliant(false)] + public static uint ToUInt32(Decimal d) + { + if ((d.flags & ScaleMask) != 0) FCallTruncate(ref d); + if (d.hi == 0 && d.mid == 0) + { + uint i = (uint)d.lo; + if (d.flags >= 0 || i == 0) return i; } - throw new OverflowException(Environment.GetResourceString("Overflow_UInt32")); + throw new OverflowException(SR.Overflow_UInt32); } - + // Converts a Decimal to an unsigned long. The Decimal // value is rounded towards zero to the nearest integer value, and the // result of this operation is returned as a long. // - [CLSCompliant(false)] - public static ulong ToUInt64(Decimal d) { - if ((d.flags & ScaleMask) != 0) FCallTruncate (ref d); - if (d.hi == 0) { + [CLSCompliant(false)] + public static ulong ToUInt64(Decimal d) + { + if ((d.flags & ScaleMask) != 0) FCallTruncate(ref d); + if (d.hi == 0) + { ulong l = ((ulong)(uint)d.lo) | ((ulong)(uint)d.mid << 32); if (d.flags >= 0 || l == 0) return l; } - throw new OverflowException(Environment.GetResourceString("Overflow_UInt64")); + throw new OverflowException(SR.Overflow_UInt64); } - + // Converts a Decimal to a float. Since a float has fewer significant // digits than a Decimal, this operation may produce round-off errors. // @@ -914,180 +1005,219 @@ namespace System { // public static Decimal Truncate(Decimal d) { - FCallTruncate (ref d); + FCallTruncate(ref d); return d; } [MethodImplAttribute(MethodImplOptions.InternalCall)] private static extern void FCallTruncate(ref Decimal d); - - - public static implicit operator Decimal(byte value) { + + + public static implicit operator Decimal(byte value) + { return new Decimal(value); } - + [CLSCompliant(false)] - public static implicit operator Decimal(sbyte value) { + public static implicit operator Decimal(sbyte value) + { return new Decimal(value); } - - public static implicit operator Decimal(short value) { + + public static implicit operator Decimal(short value) + { return new Decimal(value); } - + [CLSCompliant(false)] - public static implicit operator Decimal(ushort value) { + public static implicit operator Decimal(ushort value) + { return new Decimal(value); } - public static implicit operator Decimal(char value) { + public static implicit operator Decimal(char value) + { return new Decimal(value); } - - public static implicit operator Decimal(int value) { + + public static implicit operator Decimal(int value) + { return new Decimal(value); } - + [CLSCompliant(false)] - public static implicit operator Decimal(uint value) { + public static implicit operator Decimal(uint value) + { return new Decimal(value); } - - public static implicit operator Decimal(long value) { + + public static implicit operator Decimal(long value) + { return new Decimal(value); } - + [CLSCompliant(false)] - public static implicit operator Decimal(ulong value) { + public static implicit operator Decimal(ulong value) + { return new Decimal(value); } - - - public static explicit operator Decimal(float value) { + + + public static explicit operator Decimal(float value) + { return new Decimal(value); } - - public static explicit operator Decimal(double value) { + + public static explicit operator Decimal(double value) + { return new Decimal(value); } - - public static explicit operator byte(Decimal value) { + + public static explicit operator byte(Decimal value) + { return ToByte(value); } - + [CLSCompliant(false)] - public static explicit operator sbyte(Decimal value) { + public static explicit operator sbyte(Decimal value) + { return ToSByte(value); } - - public static explicit operator char(Decimal value) { + + public static explicit operator char(Decimal value) + { UInt16 temp; - try { + try + { temp = ToUInt16(value); - } - catch (OverflowException e) { - throw new OverflowException(Environment.GetResourceString("Overflow_Char"), e); + } + catch (OverflowException e) + { + throw new OverflowException(SR.Overflow_Char, e); } return (char)temp; } - public static explicit operator short(Decimal value) { + public static explicit operator short(Decimal value) + { return ToInt16(value); } - + [CLSCompliant(false)] - public static explicit operator ushort(Decimal value) { + public static explicit operator ushort(Decimal value) + { return ToUInt16(value); } - - public static explicit operator int(Decimal value) { + + public static explicit operator int(Decimal value) + { return ToInt32(value); } - + [CLSCompliant(false)] - public static explicit operator uint(Decimal value) { + public static explicit operator uint(Decimal value) + { return ToUInt32(value); } - - public static explicit operator long(Decimal value) { + + public static explicit operator long(Decimal value) + { return ToInt64(value); } - + [CLSCompliant(false)] - public static explicit operator ulong(Decimal value) { + public static explicit operator ulong(Decimal value) + { return ToUInt64(value); } - - public static explicit operator float(Decimal value) { + + public static explicit operator float(Decimal value) + { return ToSingle(value); } - - public static explicit operator double(Decimal value) { + + public static explicit operator double(Decimal value) + { return ToDouble(value); } - - public static Decimal operator +(Decimal d) { + + public static Decimal operator +(Decimal d) + { return d; } - - public static Decimal operator -(Decimal d) { + + public static Decimal operator -(Decimal d) + { return Negate(d); } - - public static Decimal operator ++(Decimal d) { + + public static Decimal operator ++(Decimal d) + { return Add(d, One); } - - public static Decimal operator --(Decimal d) { + + public static Decimal operator --(Decimal d) + { return Subtract(d, One); } - - public static Decimal operator +(Decimal d1, Decimal d2) { + + public static Decimal operator +(Decimal d1, Decimal d2) + { FCallAddSub(ref d1, ref d2, DECIMAL_ADD); return d1; } - - public static Decimal operator -(Decimal d1, Decimal d2) { + + public static Decimal operator -(Decimal d1, Decimal d2) + { FCallAddSub(ref d1, ref d2, DECIMAL_NEG); return d1; } - - public static Decimal operator *(Decimal d1, Decimal d2) { - FCallMultiply (ref d1, ref d2); + + public static Decimal operator *(Decimal d1, Decimal d2) + { + FCallMultiply(ref d1, ref d2); return d1; } - - public static Decimal operator /(Decimal d1, Decimal d2) { - FCallDivide (ref d1, ref d2); + + public static Decimal operator /(Decimal d1, Decimal d2) + { + FCallDivide(ref d1, ref d2); return d1; } - - public static Decimal operator %(Decimal d1, Decimal d2) { + + public static Decimal operator %(Decimal d1, Decimal d2) + { return Remainder(d1, d2); } - - public static bool operator ==(Decimal d1, Decimal d2) { + + public static bool operator ==(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) == 0; } - public static bool operator !=(Decimal d1, Decimal d2) { + public static bool operator !=(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) != 0; } - public static bool operator <(Decimal d1, Decimal d2) { + public static bool operator <(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) < 0; } - public static bool operator <=(Decimal d1, Decimal d2) { + public static bool operator <=(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) <= 0; } - public static bool operator >(Decimal d1, Decimal d2) { + public static bool operator >(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) > 0; } - public static bool operator >=(Decimal d1, Decimal d2) { + public static bool operator >=(Decimal d1, Decimal d2) + { return FCallCompare(ref d1, ref d2) >= 0; } @@ -1095,83 +1225,84 @@ namespace System { // IConvertible implementation // - public TypeCode GetTypeCode() { + public TypeCode GetTypeCode() + { return TypeCode.Decimal; } - /// <internalonly/> - bool IConvertible.ToBoolean(IFormatProvider provider) { - return Convert.ToBoolean(this); + bool IConvertible.ToBoolean(IFormatProvider provider) + { + return Convert.ToBoolean(this); } - /// <internalonly/> - char IConvertible.ToChar(IFormatProvider provider) { - throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Decimal", "Char")); + char IConvertible.ToChar(IFormatProvider provider) + { + throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "Char")); } - /// <internalonly/> - sbyte IConvertible.ToSByte(IFormatProvider provider) { + sbyte IConvertible.ToSByte(IFormatProvider provider) + { return Convert.ToSByte(this); } - /// <internalonly/> - byte IConvertible.ToByte(IFormatProvider provider) { + byte IConvertible.ToByte(IFormatProvider provider) + { return Convert.ToByte(this); } - /// <internalonly/> - short IConvertible.ToInt16(IFormatProvider provider) { + short IConvertible.ToInt16(IFormatProvider provider) + { return Convert.ToInt16(this); } - /// <internalonly/> - ushort IConvertible.ToUInt16(IFormatProvider provider) { + ushort IConvertible.ToUInt16(IFormatProvider provider) + { return Convert.ToUInt16(this); } - /// <internalonly/> - int IConvertible.ToInt32(IFormatProvider provider) { + int IConvertible.ToInt32(IFormatProvider provider) + { return Convert.ToInt32(this); } - /// <internalonly/> - uint IConvertible.ToUInt32(IFormatProvider provider) { + uint IConvertible.ToUInt32(IFormatProvider provider) + { return Convert.ToUInt32(this); } - /// <internalonly/> - long IConvertible.ToInt64(IFormatProvider provider) { + long IConvertible.ToInt64(IFormatProvider provider) + { return Convert.ToInt64(this); } - /// <internalonly/> - ulong IConvertible.ToUInt64(IFormatProvider provider) { + ulong IConvertible.ToUInt64(IFormatProvider provider) + { return Convert.ToUInt64(this); } - /// <internalonly/> - float IConvertible.ToSingle(IFormatProvider provider) { + float IConvertible.ToSingle(IFormatProvider provider) + { return Convert.ToSingle(this); } - /// <internalonly/> - double IConvertible.ToDouble(IFormatProvider provider) { + double IConvertible.ToDouble(IFormatProvider provider) + { return Convert.ToDouble(this); } - /// <internalonly/> - Decimal IConvertible.ToDecimal(IFormatProvider provider) { + Decimal IConvertible.ToDecimal(IFormatProvider provider) + { return this; } - /// <internalonly/> - DateTime IConvertible.ToDateTime(IFormatProvider provider) { - throw new InvalidCastException(Environment.GetResourceString("InvalidCast_FromTo", "Decimal", "DateTime")); + DateTime IConvertible.ToDateTime(IFormatProvider provider) + { + throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Decimal", "DateTime")); } - /// <internalonly/> - Object IConvertible.ToType(Type type, IFormatProvider provider) { + Object IConvertible.ToType(Type type, IFormatProvider provider) + { return Convert.DefaultToType((IConvertible)this, type, provider); } } |