7 // Rounder represents a method for rounding the (possibly infinite decimal)
8 // result of a division to a finite Dec. It is used by Dec.Round() and
11 // See the Example for results of using each Rounder with some sample values.
15 // See http://speleotrove.com/decimal/damodel.html#refround for more detailed
16 // definitions of these rounding modes.
18 RoundDown Rounder // towards 0
19 RoundUp Rounder // away from 0
20 RoundFloor Rounder // towards -infinity
21 RoundCeil Rounder // towards +infinity
22 RoundHalfDown Rounder // to nearest; towards 0 if same distance
23 RoundHalfUp Rounder // to nearest; away from 0 if same distance
24 RoundHalfEven Rounder // to nearest; even last digit if same distance
27 // RoundExact is to be used in the case when rounding is not necessary.
28 // When used with Quo or Round, it returns the result verbatim when it can be
29 // expressed exactly with the given precision, and it returns nil otherwise.
30 // QuoExact is a shorthand for using Quo with RoundExact.
31 var RoundExact Rounder
33 type rounder interface {
35 // When UseRemainder() returns true, the Round() method is passed the
36 // remainder of the division, expressed as the numerator and denominator of
40 // Round sets the rounded value of a quotient to z, and returns z.
41 // quo is rounded down (truncated towards zero) to the scale obtained from
42 // the Scaler in Quo().
44 // When the remainder is not used, remNum and remDen are nil.
45 // When used, the remainder is normalized between -1 and 1; that is:
47 // -|remDen| < remNum < |remDen|
49 // remDen has the same sign as y, and remNum is zero or has the same sign
51 Round(z, quo *Dec, remNum, remDen *big.Int) *Dec
56 round func(z, quo *Dec, remNum, remDen *big.Int) *Dec
59 func (r rndr) UseRemainder() bool {
63 func (r rndr) Round(z, quo *Dec, remNum, remDen *big.Int) *Dec {
64 return r.round(z, quo, remNum, remDen)
67 var intSign = []*big.Int{big.NewInt(-1), big.NewInt(0), big.NewInt(1)}
69 func roundHalf(f func(c int, odd uint) (roundUp bool)) func(z, q *Dec, rA, rB *big.Int) *Dec {
70 return func(z, q *Dec, rA, rB *big.Int) *Dec {
72 brA, brB := rA.BitLen(), rB.BitLen()
74 // brA < brB-1 => |rA| < |rB/2|
78 srA, srB := rA.Sign(), rB.Sign()
81 rA2 := new(big.Int).Lsh(rA, 1)
85 roundUp = f(rA2.Cmp(rB)*srB, z.UnscaledBig().Bit(0))
87 // brA > brB-1 => |rA| > |rB/2|
91 z.UnscaledBig().Add(z.UnscaledBig(), intSign[s+1])
98 RoundExact = rndr{true,
99 func(z, q *Dec, rA, rB *big.Int) *Dec {
105 RoundDown = rndr{false,
106 func(z, q *Dec, rA, rB *big.Int) *Dec {
110 func(z, q *Dec, rA, rB *big.Int) *Dec {
113 z.UnscaledBig().Add(z.UnscaledBig(), intSign[rA.Sign()*rB.Sign()+1])
117 RoundFloor = rndr{true,
118 func(z, q *Dec, rA, rB *big.Int) *Dec {
120 if rA.Sign()*rB.Sign() < 0 {
121 z.UnscaledBig().Add(z.UnscaledBig(), intSign[0])
125 RoundCeil = rndr{true,
126 func(z, q *Dec, rA, rB *big.Int) *Dec {
128 if rA.Sign()*rB.Sign() > 0 {
129 z.UnscaledBig().Add(z.UnscaledBig(), intSign[2])
133 RoundHalfDown = rndr{true, roundHalf(
134 func(c int, odd uint) bool {
137 RoundHalfUp = rndr{true, roundHalf(
138 func(c int, odd uint) bool {
141 RoundHalfEven = rndr{true, roundHalf(
142 func(c int, odd uint) bool {
143 return c > 0 || c == 0 && odd == 1