From c9bb3d880d8bf18c1fbe6f9c93ac9d9564a7f9ce Mon Sep 17 00:00:00 2001 From: Alexey Kiselev Date: Thu, 12 Sep 2019 17:35:00 +0300 Subject: [PATCH] "Half Down" rounding mode was added under name ToNearestTowardZero. (#136) --- context.go | 15 +++++++++------ context_test.go | 39 +++++++++++++++++++++++++++++++++++++++ dectest/test.go | 1 + format.go | 4 ++++ roundingmode_string.go | 7 ++++--- util.go | 2 +- 6 files changed, 58 insertions(+), 10 deletions(-) diff --git a/context.go b/context.go index e89fc9c..707e807 100644 --- a/context.go +++ b/context.go @@ -152,12 +152,13 @@ type RoundingMode uint8 // The following rounding modes are supported. const ( - ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven - ToNearestAway // == IEEE 754-2008 roundTiesToAway - ToZero // == IEEE 754-2008 roundTowardZero - AwayFromZero // no IEEE 754-2008 equivalent - ToNegativeInf // == IEEE 754-2008 roundTowardNegative - ToPositiveInf // == IEEE 754-2008 roundTowardPositive + ToNearestEven RoundingMode = iota // == IEEE 754-2008 roundTiesToEven + ToNearestAway // == IEEE 754-2008 roundTiesToAway + ToZero // == IEEE 754-2008 roundTowardZero + AwayFromZero // no IEEE 754-2008 equivalent + ToNegativeInf // == IEEE 754-2008 roundTowardNegative + ToPositiveInf // == IEEE 754-2008 roundTowardPositive + ToNearestTowardZero // no IEEE 754-2008 equivalent unnecessary // placeholder for x / y with UnlimitedPrecision. ) @@ -185,6 +186,8 @@ func (m RoundingMode) needsInc(odd bool, r int, pos bool) bool { return odd case ToNearestAway: return r >= 0 + case ToNearestTowardZero: + return r > 0 default: return false } diff --git a/context_test.go b/context_test.go index e62c90c..27772ee 100644 --- a/context_test.go +++ b/context_test.go @@ -18,3 +18,42 @@ func TestCondition_String(t *testing.T) { } } } + +func TestNonStandardRoundingModes(t *testing.T) { + for i, test := range [...]struct { + value int64 + mode RoundingMode + expected int64 + }{ + {55, ToNearestTowardZero, 5}, + {25, ToNearestTowardZero, 2}, + {16, ToNearestTowardZero, 2}, + {11, ToNearestTowardZero, 1}, + {10, ToNearestTowardZero, 1}, + {-10, ToNearestTowardZero, -1}, + {-11, ToNearestTowardZero, -1}, + {-16, ToNearestTowardZero, -2}, + {-25, ToNearestTowardZero, -2}, + {-55, ToNearestTowardZero, -5}, + {55, AwayFromZero, 6}, + {25, AwayFromZero, 3}, + {16, AwayFromZero, 2}, + {11, AwayFromZero, 2}, + {10, AwayFromZero, 1}, + {-10, AwayFromZero, -1}, + {-11, AwayFromZero, -2}, + {-16, AwayFromZero, -2}, + {-25, AwayFromZero, -3}, + {-55, AwayFromZero, -6}, + } { + v := New(test.value, 1) + v.Context.RoundingMode = test.mode + r, ok := v.RoundToInt().Int64() + if !ok { + t.Fatalf("#%d: failed to convert result to int64", i) + } + if test.expected != r { + t.Fatalf("#%d: wanted %d, got %d", i, test.expected, r) + } + } +} diff --git a/dectest/test.go b/dectest/test.go index 36a9843..7658ac9 100644 --- a/dectest/test.go +++ b/dectest/test.go @@ -81,6 +81,7 @@ var decRoundingModes = map[RoundingMode]decimal.RoundingMode{ Floor: decimal.ToNegativeInf, HalfEven: decimal.ToNearestEven, HalfUp: decimal.ToNearestAway, + HalfDown: decimal.ToNearestTowardZero, } var decConditions = map[Condition]decimal.Condition{ diff --git a/format.go b/format.go index dc0b7f0..8a34100 100644 --- a/format.go +++ b/format.go @@ -57,6 +57,10 @@ func roundString(b []byte, mode RoundingMode, pos bool, prec int) []byte { if b[i+1] >= '5' { b[i]++ } + case ToNearestTowardZero: + if b[i+1] > '5' { + b[i]++ + } } if b[i] != '9'+1 { diff --git a/roundingmode_string.go b/roundingmode_string.go index e6378e2..9bf09b5 100644 --- a/roundingmode_string.go +++ b/roundingmode_string.go @@ -14,12 +14,13 @@ func _() { _ = x[AwayFromZero-3] _ = x[ToNegativeInf-4] _ = x[ToPositiveInf-5] - _ = x[unnecessary-6] + _ = x[ToNearestTowardZero-6] + _ = x[unnecessary-7] } -const _RoundingMode_name = "ToNearestEvenToNearestAwayToZeroAwayFromZeroToNegativeInfToPositiveInfunnecessary" +const _RoundingMode_name = "ToNearestEvenToNearestAwayToZeroAwayFromZeroToNegativeInfToPositiveInfToNearestTowardZerounnecessary" -var _RoundingMode_index = [...]uint8{0, 13, 26, 32, 44, 57, 70, 81} +var _RoundingMode_index = [...]uint8{0, 13, 26, 32, 44, 57, 70, 89, 100} func (i RoundingMode) String() string { if i >= RoundingMode(len(_RoundingMode_index)-1) { diff --git a/util.go b/util.go index 3ea7111..13b4cd7 100644 --- a/util.go +++ b/util.go @@ -33,7 +33,7 @@ func (c Context) fix(z *Big) *Big { } switch m := c.RoundingMode; m { - case ToNearestAway, ToNearestEven: + case ToNearestAway, ToNearestEven, ToNearestTowardZero: z.SetInf(z.Signbit()) case AwayFromZero: // OK