summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs29
-rw-r--r--src/System.Private.CoreLib/shared/System/Decimal.cs10
-rw-r--r--src/System.Private.CoreLib/shared/System/Math.cs52
-rw-r--r--src/System.Private.CoreLib/shared/System/MathF.cs54
-rw-r--r--src/System.Private.CoreLib/shared/System/MidpointRounding.cs3
-rw-r--r--tests/CoreFX/CoreFX.issues.json4
6 files changed, 106 insertions, 46 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
index 774c5d9a52..51f588e1f5 100644
--- a/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
+++ b/src/System.Private.CoreLib/shared/System/Decimal.DecCalc.cs
@@ -1243,7 +1243,7 @@ ReturnResult:
else
{
if (scale != 0)
- InternalRound(ref pdecIn, (uint)scale, RoundingMode.ToEven);
+ InternalRound(ref pdecIn, (uint)scale, MidpointRounding.ToEven);
if (pdecIn.High != 0)
goto ThrowOverflow;
value = (long)pdecIn.Low64;
@@ -2408,19 +2408,8 @@ ThrowOverflow:
}
}
- internal enum RoundingMode
- {
- ToEven = 0,
- AwayFromZero = 1,
- Truncate = 2,
- Floor = 3,
- Ceiling = 4,
- }
-
- /// <summary>
- /// Does an in-place round by the specified scale
- /// </summary>
- internal static void InternalRound(ref DecCalc d, uint scale, RoundingMode mode)
+ // Does an in-place round by the specified scale
+ internal static void InternalRound(ref DecCalc d, uint scale, MidpointRounding mode)
{
// the scale becomes the desired decimal count
d.uflags -= scale << ScaleShift;
@@ -2473,7 +2462,7 @@ ThrowOverflow:
ulong tmp = d.Low64;
if (tmp == 0)
{
- if (mode <= RoundingMode.Truncate)
+ if (mode <= MidpointRounding.ToZero)
goto done;
remainder = 0;
goto checkRemainder;
@@ -2503,9 +2492,9 @@ ThrowOverflow:
}
checkRemainder:
- if (mode == RoundingMode.Truncate)
+ if (mode == MidpointRounding.ToZero)
goto done;
- else if (mode == RoundingMode.ToEven)
+ else if (mode == MidpointRounding.ToEven)
{
// To do IEEE rounding, we add LSB of result to sticky bits so either causes round up if remainder * 2 == last divisor.
remainder <<= 1;
@@ -2514,14 +2503,14 @@ checkRemainder:
if (power >= remainder)
goto done;
}
- else if (mode == RoundingMode.AwayFromZero)
+ else if (mode == MidpointRounding.AwayFromZero)
{
// Round away from zero at the mid point.
remainder <<= 1;
if (power > remainder)
goto done;
}
- else if (mode == RoundingMode.Floor)
+ else if (mode == MidpointRounding.ToNegativeInfinity)
{
// Round toward -infinity if we have chopped off a non-zero amount from a negative value.
if ((remainder | sticky) == 0 || !d.IsNegative)
@@ -2529,7 +2518,7 @@ checkRemainder:
}
else
{
- Debug.Assert(mode == RoundingMode.Ceiling);
+ Debug.Assert(mode == MidpointRounding.ToPositiveInfinity);
// Round toward infinity if we have chopped off a non-zero amount from a positive value.
if ((remainder | sticky) == 0 || d.IsNegative)
goto done;
diff --git a/src/System.Private.CoreLib/shared/System/Decimal.cs b/src/System.Private.CoreLib/shared/System/Decimal.cs
index c4a76d79bc..cfcb12d5d7 100644
--- a/src/System.Private.CoreLib/shared/System/Decimal.cs
+++ b/src/System.Private.CoreLib/shared/System/Decimal.cs
@@ -327,7 +327,7 @@ namespace System
{
int flags = d.flags;
if ((flags & ScaleMask) != 0)
- DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Ceiling);
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), MidpointRounding.ToPositiveInfinity);
return d;
}
@@ -407,7 +407,7 @@ namespace System
{
int flags = d.flags;
if ((flags & ScaleMask) != 0)
- DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Floor);
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), MidpointRounding.ToNegativeInfinity);
return d;
}
@@ -617,12 +617,12 @@ namespace System
{
if ((uint)decimals > 28)
throw new ArgumentOutOfRangeException(nameof(decimals), SR.ArgumentOutOfRange_DecimalRound);
- if ((uint)mode > (uint)MidpointRounding.AwayFromZero)
+ if ((uint)mode > (uint)MidpointRounding.ToPositiveInfinity)
throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
int scale = d.Scale - decimals;
if (scale > 0)
- DecCalc.InternalRound(ref AsMutable(ref d), (uint)scale, (DecCalc.RoundingMode)mode);
+ DecCalc.InternalRound(ref AsMutable(ref d), (uint)scale, mode);
return d;
}
@@ -829,7 +829,7 @@ namespace System
{
int flags = d.flags;
if ((flags & ScaleMask) != 0)
- DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), DecCalc.RoundingMode.Truncate);
+ DecCalc.InternalRound(ref AsMutable(ref d), (byte)(flags >> ScaleShift), MidpointRounding.ToZero);
}
public static implicit operator decimal(byte value)
diff --git a/src/System.Private.CoreLib/shared/System/Math.cs b/src/System.Private.CoreLib/shared/System/Math.cs
index af74185a88..1c36c9d230 100644
--- a/src/System.Private.CoreLib/shared/System/Math.cs
+++ b/src/System.Private.CoreLib/shared/System/Math.cs
@@ -892,7 +892,7 @@ namespace System
throw new ArgumentOutOfRangeException(nameof(digits), SR.ArgumentOutOfRange_RoundingDigits);
}
- if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero)
+ if (mode < MidpointRounding.ToEven || mode > MidpointRounding.ToPositiveInfinity)
{
throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
}
@@ -903,20 +903,52 @@ namespace System
value *= power10;
- if (mode == MidpointRounding.AwayFromZero)
+ switch (mode)
{
- var fraction = ModF(value, &value);
+ // Rounds to the nearest value; if the number falls midway,
+ // it is rounded to the nearest value with an even least significant digit
+ case MidpointRounding.ToEven:
+ {
+ value = Round(value);
+ break;
+ }
+ // Rounds to the nearest value; if the number falls midway,
+ // it is rounded to the nearest value above (for positive numbers) or below (for negative numbers)
+ case MidpointRounding.AwayFromZero:
+ {
+ double fraction = ModF(value, &value);
+
+ if (Abs(fraction) >= 0.5)
+ {
+ value += Sign(fraction);
+ }
- if (Abs(fraction) >= 0.5)
+ break;
+ }
+ // Directed rounding: Round to the nearest value, toward to zero
+ case MidpointRounding.ToZero:
{
- value += Sign(fraction);
+ value = Truncate(value);
+ break;
+ }
+ // Directed Rounding: Round down to the next value, toward negative infinity
+ case MidpointRounding.ToNegativeInfinity:
+ {
+ value = Floor(value);
+ break;
+ }
+ // Directed rounding: Round up to the next value, toward positive infinity
+ case MidpointRounding.ToPositiveInfinity:
+ {
+ value = Ceiling(value);
+ break;
+ }
+ default:
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
}
}
- else
- {
- value = Round(value);
- }
-
+
value /= power10;
}
diff --git a/src/System.Private.CoreLib/shared/System/MathF.cs b/src/System.Private.CoreLib/shared/System/MathF.cs
index 3bff55daeb..1defa4e40b 100644
--- a/src/System.Private.CoreLib/shared/System/MathF.cs
+++ b/src/System.Private.CoreLib/shared/System/MathF.cs
@@ -306,9 +306,9 @@ namespace System
throw new ArgumentOutOfRangeException(nameof(digits), SR.ArgumentOutOfRange_RoundingDigits);
}
- if (mode < MidpointRounding.ToEven || mode > MidpointRounding.AwayFromZero)
+ if (mode < MidpointRounding.ToEven || mode > MidpointRounding.ToPositiveInfinity)
{
- throw new ArgumentException(SR.Format(SR.Argument_InvalidEnum, mode, nameof(MidpointRounding)), nameof(mode));
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
}
if (Abs(x) < singleRoundLimit)
@@ -317,20 +317,52 @@ namespace System
x *= power10;
- if (mode == MidpointRounding.AwayFromZero)
+ switch (mode)
{
- var fraction = ModF(x, &x);
+ // Rounds to the nearest value; if the number falls midway,
+ // it is rounded to the nearest value with an even least significant digit
+ case MidpointRounding.ToEven:
+ {
+ x = Round(x);
+ break;
+ }
+ // Rounds to the nearest value; if the number falls midway,
+ // it is rounded to the nearest value above (for positive numbers) or below (for negative numbers)
+ case MidpointRounding.AwayFromZero:
+ {
+ float fraction = ModF(x, &x);
+
+ if (Abs(fraction) >= 0.5)
+ {
+ x += Sign(fraction);
+ }
- if (Abs(fraction) >= 0.5f)
+ break;
+ }
+ // Directed rounding: Round to the nearest value, toward to zero
+ case MidpointRounding.ToZero:
{
- x += Sign(fraction);
+ x = Truncate(x);
+ break;
+ }
+ // Directed Rounding: Round down to the next value, toward negative infinity
+ case MidpointRounding.ToNegativeInfinity:
+ {
+ x = Floor(x);
+ break;
+ }
+ // Directed rounding: Round up to the next value, toward positive infinity
+ case MidpointRounding.ToPositiveInfinity:
+ {
+ x = Ceiling(x);
+ break;
+ }
+ default:
+ {
+ throw new ArgumentException(SR.Format(SR.Argument_InvalidEnumValue, mode, nameof(MidpointRounding)), nameof(mode));
}
}
- else
- {
- x = Round(x);
- }
-
+
x /= power10;
}
diff --git a/src/System.Private.CoreLib/shared/System/MidpointRounding.cs b/src/System.Private.CoreLib/shared/System/MidpointRounding.cs
index a75de43e65..835dafe7ee 100644
--- a/src/System.Private.CoreLib/shared/System/MidpointRounding.cs
+++ b/src/System.Private.CoreLib/shared/System/MidpointRounding.cs
@@ -8,5 +8,8 @@ namespace System
{
ToEven = 0,
AwayFromZero = 1,
+ ToZero = 2,
+ ToNegativeInfinity = 3,
+ ToPositiveInfinity = 4
}
}
diff --git a/tests/CoreFX/CoreFX.issues.json b/tests/CoreFX/CoreFX.issues.json
index d35caed1cf..610c35ed4c 100644
--- a/tests/CoreFX/CoreFX.issues.json
+++ b/tests/CoreFX/CoreFX.issues.json
@@ -1051,6 +1051,10 @@
"reason": "https://github.com/dotnet/coreclr/issues/12605"
},
{
+ "name": "System.Tests.DecimalTests.Round_InvalidMidpointRounding_ThrowsArgumentException",
+ "reason": "outdated"
+ },
+ {
"name": "System.Tests.ArrayTests.Copy",
"reason": "Needs updates for XUnit 2.4"
},