move rounder to separate file, gofmt (code unchanged)
diff --git a/dec/dec.go b/dec/dec.go
index e14bf5c..b88370e 100644
--- a/dec/dec.go
+++ b/dec/dec.go
@@ -13,7 +13,7 @@
 // returning a result other than *Dec take one of the operands as the receiver.
 //
 // Quotient (division) operation uses Scalers and Rounders to specify the
-// desired behavior. See Quo, Scaler, and Rounder for details. 
+// desired behavior. See Quo, Scaler, and Rounder for details.
 //
 package dec
 
@@ -71,31 +71,6 @@
 	return s
 }
 
-// Rounder represents a method for rounding the (possibly infinite decimal)
-// result of a division to a finite Dec. It is used by Dec.Round() and
-// Dec.Quo().
-//
-type Rounder interface {
-
-	// When UseRemainder() returns true, the Round() method is passed the
-	// remainder of the division, expressed as the numerator and denominator of
-	// a rational.
-	UseRemainder() bool
-
-	// Round sets the rounded value of a quotient to z, and returns z.
-	// quo is rounded down (truncated towards zero) to the scale obtained from
-	// the Scaler in Quo().
-	//
-	// When the remainder is not used, remNum and remDen are nil.
-	// When used, the remainder is normalized between -1 and 1; that is:
-	// 
-	//  -|remDen| < remNum < |remDen|
-	//
-	// remDen has the same sign as y, and remNum is zero or has the same sign
-	// as x.
-	Round(z, quo *Dec, remNum, remDen *big.Int) *Dec
-}
-
 var bigInt = [...]*big.Int{
 	big.NewInt(0), big.NewInt(1), big.NewInt(2), big.NewInt(3), big.NewInt(4),
 	big.NewInt(5), big.NewInt(6), big.NewInt(7), big.NewInt(8), big.NewInt(9),
@@ -135,7 +110,7 @@
 
 // SetScale sets the scale of x, with the unscaled value unchanged.
 // The mathematical value of the Dec changes as if it was multiplied by
-// 10**(oldscale-scale). 
+// 10**(oldscale-scale).
 func (x *Dec) SetScale(scale Scale) *Dec {
 	x.scale = scale
 	return x
@@ -360,283 +335,6 @@
 	return f
 }
 
-type rounder struct {
-	useRem bool
-	round  func(z, quo *Dec, remNum, remDen *big.Int) *Dec
-}
-
-func (r rounder) UseRemainder() bool {
-	return r.useRem
-}
-
-func (r rounder) Round(z, quo *Dec, remNum, remDen *big.Int) *Dec {
-	return r.round(z, quo, remNum, remDen)
-}
-
-// RoundExact returns quo if rem is zero, or nil otherwise. It is intended to
-// be used with ScaleQuoExact when it is guaranteed that the result can be
-// obtained without rounding. QuoExact is a shorthand for such a quotient
-// operation. 
-// 
-var RoundExact Rounder = roundExact
-
-// RoundDown rounds towards 0; that is, returns the Dec with the greatest
-// absolute value not exceeding that of the result represented by quo and rem.
-//
-// The following table shows examples of the results for
-// Quo(x, y, Scale(scale), RoundDown).
-//
-//      x      y    scale   result
-//  ------------------------------
-//    -1.8    10        1     -0.1
-//    -1.5    10        1     -0.1
-//    -1.2    10        1     -0.1
-//    -1.0    10        1     -0.1
-//    -0.8    10        1     -0.0
-//    -0.5    10        1     -0.0
-//    -0.2    10        1     -0.0
-//     0.0    10        1      0.0
-//     0.2    10        1      0.0
-//     0.5    10        1      0.0
-//     0.8    10        1      0.0
-//     1.0    10        1      0.1
-//     1.2    10        1      0.1
-//     1.5    10        1      0.1
-//     1.8    10        1      0.1
-//
-var RoundDown Rounder = roundDown
-
-// RoundUp rounds away from 0; that is, returns the Dec with the smallest
-// absolute value not smaller than that of the result represented by quo and
-// rem.
-//
-// The following table shows examples of the results for
-// Quo(x, y, Scale(scale), RoundUp).
-//
-//      x      y    scale   result
-//  ------------------------------
-//    -1.8    10        1     -0.2
-//    -1.5    10        1     -0.2
-//    -1.2    10        1     -0.2
-//    -1.0    10        1     -0.1
-//    -0.8    10        1     -0.1
-//    -0.5    10        1     -0.1
-//    -0.2    10        1     -0.1
-//     0.0    10        1      0.0
-//     0.2    10        1      0.1
-//     0.5    10        1      0.1
-//     0.8    10        1      0.1
-//     1.0    10        1      0.1
-//     1.2    10        1      0.2
-//     1.5    10        1      0.2
-//     1.8    10        1      0.2
-//
-var RoundUp Rounder = roundUp
-
-// RoundHalfDown rounds to the nearest Dec, and when the remainder is 1/2, it
-// rounds to the Dec with the lower absolute value.
-//
-// The following table shows examples of the results for
-// Quo(x, y, Scale(scale), RoundHalfDown).
-//
-//      x      y    scale   result
-//  ------------------------------
-//    -1.8    10        1     -0.2
-//    -1.5    10        1     -0.1
-//    -1.2    10        1     -0.1
-//    -1.0    10        1     -0.1
-//    -0.8    10        1     -0.1
-//    -0.5    10        1     -0.0
-//    -0.2    10        1     -0.0
-//     0.0    10        1      0.0
-//     0.2    10        1      0.0
-//     0.5    10        1      0.0
-//     0.8    10        1      0.1
-//     1.0    10        1      0.1
-//     1.2    10        1      0.1
-//     1.5    10        1      0.1
-//     1.8    10        1      0.2
-//
-var RoundHalfDown Rounder = roundHalfDown
-
-// RoundHalfUp rounds to the nearest Dec, and when the remainder is 1/2, it
-// rounds to the Dec with the greater absolute value.
-//
-// The following table shows examples of the results for
-// Quo(x, y, Scale(scale), RoundHalfUp).
-//
-//      x      y    scale   result
-//  ------------------------------
-//    -1.8    10        1     -0.2
-//    -1.5    10        1     -0.2
-//    -1.2    10        1     -0.1
-//    -1.0    10        1     -0.1
-//    -0.8    10        1     -0.1
-//    -0.5    10        1     -0.1
-//    -0.2    10        1     -0.0
-//     0.0    10        1      0.0
-//     0.2    10        1      0.0
-//     0.5    10        1      0.1
-//     0.8    10        1      0.1
-//     1.0    10        1      0.1
-//     1.2    10        1      0.1
-//     1.5    10        1      0.2
-//     1.8    10        1      0.2
-//
-var RoundHalfUp Rounder = roundHalfUp
-
-// RoundFloor rounds towards negative infinity; that is, returns the greatest
-// Dec not exceeding the result represented by quo and rem.
-//
-// The following table shows examples of the results for
-// Quo(x, y, Scale(scale), RoundFloor).
-//
-//      x      y    scale   result
-//  ------------------------------
-//    -1.8    10        1     -0.2
-//    -1.5    10        1     -0.2
-//    -1.2    10        1     -0.2
-//    -1.0    10        1     -0.1
-//    -0.8    10        1     -0.1
-//    -0.5    10        1     -0.1
-//    -0.2    10        1     -0.1
-//     0.0    10        1      0.0
-//     0.2    10        1      0.0
-//     0.5    10        1      0.0
-//     0.8    10        1      0.0
-//     1.0    10        1      0.1
-//     1.2    10        1      0.1
-//     1.5    10        1      0.1
-//     1.8    10        1      0.1
-//
-var RoundFloor Rounder = roundFloor
-
-// RoundCeil rounds towards positive infinity; that is, returns the
-// smallest Dec not smaller than the result represented by quo and rem.
-//
-// The following table shows examples of the results for
-// Quo(x, y, Scale(scale), RoundCeil).
-//
-//      x      y    scale   result
-//  ------------------------------
-//    -1.8    10        1     -0.1
-//    -1.5    10        1     -0.1
-//    -1.2    10        1     -0.1
-//    -1.0    10        1     -0.1
-//    -0.8    10        1     -0.0
-//    -0.5    10        1     -0.0
-//    -0.2    10        1     -0.0
-//     0.0    10        1      0.0
-//     0.2    10        1      0.1
-//     0.5    10        1      0.1
-//     0.8    10        1      0.1
-//     1.0    10        1      0.1
-//     1.2    10        1      0.2
-//     1.5    10        1      0.2
-//     1.8    10        1      0.2
-//
-var RoundCeil Rounder = roundCeil
-
-var intSign = []*big.Int{big.NewInt(-1), big.NewInt(0), big.NewInt(1)}
-
-var roundExact = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		if rA.Sign() != 0 {
-			return nil
-		}
-		return z.move(q)
-	}}
-
-var roundDown = rounder{false,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		return z.move(q)
-	}}
-
-var roundUp = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		z.move(q)
-		if rA.Sign() != 0 {
-			z.Unscaled().Add(z.Unscaled(), intSign[rA.Sign()*rB.Sign()+1])
-		}
-		return z
-	}}
-
-var roundHalfDown = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		z.move(q)
-		brA, brB := rA.BitLen(), rB.BitLen()
-		if brA < brB-1 {
-			// brA < brB-1 => |rA| < |rB/2|
-			return z
-		}
-		adjust := false
-		srA, srB := rA.Sign(), rB.Sign()
-		s := srA * srB
-		if brA == brB-1 {
-			rA2 := new(big.Int).Lsh(rA, 1)
-			if s < 0 {
-				rA2.Neg(rA2)
-			}
-			if rA2.Cmp(rB)*srB > 0 {
-				adjust = true
-			}
-		} else {
-			// brA > brB-1 => |rA| > |rB/2|
-			adjust = true
-		}
-		if adjust {
-			z.Unscaled().Add(z.Unscaled(), intSign[s+1])
-		}
-		return z
-	}}
-
-var roundHalfUp = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		z.move(q)
-		brA, brB := rA.BitLen(), rB.BitLen()
-		if brA < brB-1 {
-			// brA < brB-1 => |rA| < |rB/2|
-			return z
-		}
-		adjust := false
-		srA, srB := rA.Sign(), rB.Sign()
-		s := srA * srB
-		if brA == brB-1 {
-			rA2 := new(big.Int).Lsh(rA, 1)
-			if s < 0 {
-				rA2.Neg(rA2)
-			}
-			if rA2.Cmp(rB)*srB >= 0 {
-				adjust = true
-			}
-		} else {
-			// brA > brB-1 => |rA| > |rB/2|
-			adjust = true
-		}
-		if adjust {
-			z.Unscaled().Add(z.Unscaled(), intSign[s+1])
-		}
-		return z
-	}}
-
-var roundFloor = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		z.move(q)
-		if rA.Sign()*rB.Sign() < 0 {
-			z.Unscaled().Add(z.Unscaled(), intSign[0])
-		}
-		return z
-	}}
-
-var roundCeil = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
-		z.move(q)
-		if rA.Sign()*rB.Sign() > 0 {
-			z.Unscaled().Add(z.Unscaled(), intSign[2])
-		}
-		return z
-	}}
-
 func upscale(a, b *Dec) (*Dec, *Dec) {
 	if a.Scale() == b.Scale() {
 		return a, b
@@ -780,7 +478,7 @@
 
 // SetString sets z to the value of s, interpreted as a decimal (base 10),
 // and returns z and a boolean indicating success. The scale of z is the
-// number of digits after the decimal point (including any trailing 0s), 
+// number of digits after the decimal point (including any trailing 0s),
 // or 0 if there is no decimal point. If SetString fails, the value of z
 // is undefined but the returned value is nil.
 func (z *Dec) SetString(s string) (*Dec, bool) {
@@ -798,7 +496,7 @@
 }
 
 // Scan is a support routine for fmt.Scanner; it sets z to the value of
-// the scanned number. It accepts the decimal formats 'd' and 'f', and 
+// the scanned number. It accepts the decimal formats 'd' and 'f', and
 // handles both equivalently. Bases 2, 8, 16 are not supported.
 // The scale of z is the number of digits after the decimal point
 // (including any trailing 0s), or 0 if there is no decimal point.
diff --git a/dec/dec_test.go b/dec/dec_test.go
index 8d5036d..094d508 100644
--- a/dec/dec_test.go
+++ b/dec/dec_test.go
@@ -132,100 +132,6 @@
 	}
 }
 
-var decRounderInputs = [...]struct {
-	quo    *Dec
-	rA, rB *big.Int
-}{
-	// examples from go language spec
-	{NewDec(big.NewInt(1), 0), big.NewInt(2), big.NewInt(3)},   //  5 /  3
-	{NewDec(big.NewInt(-1), 0), big.NewInt(-2), big.NewInt(3)}, // -5 /  3
-	{NewDec(big.NewInt(-1), 0), big.NewInt(2), big.NewInt(-3)}, //  5 / -3
-	{NewDec(big.NewInt(1), 0), big.NewInt(-2), big.NewInt(-3)}, // -5 / -3
-	// examples from godoc
-	{NewDec(big.NewInt(-1), 1), big.NewInt(-8), big.NewInt(10)},
-	{NewDec(big.NewInt(-1), 1), big.NewInt(-5), big.NewInt(10)},
-	{NewDec(big.NewInt(-1), 1), big.NewInt(-2), big.NewInt(10)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(-8), big.NewInt(10)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(-5), big.NewInt(10)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(-2), big.NewInt(10)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(0), big.NewInt(1)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(2), big.NewInt(10)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(5), big.NewInt(10)},
-	{NewDec(big.NewInt(0), 1), big.NewInt(8), big.NewInt(10)},
-	{NewDec(big.NewInt(1), 1), big.NewInt(2), big.NewInt(10)},
-	{NewDec(big.NewInt(1), 1), big.NewInt(5), big.NewInt(10)},
-	{NewDec(big.NewInt(1), 1), big.NewInt(8), big.NewInt(10)},
-}
-
-var decRounderResults = [...]struct {
-	rounder Rounder
-	results [len(decRounderInputs)]*Dec
-}{
-	{RoundExact, [...]*Dec{nil, nil, nil, nil,
-		nil, nil, nil, nil, nil, nil,
-		NewDec(big.NewInt(0), 1), nil, nil, nil, nil, nil, nil}},
-	{RoundDown, [...]*Dec{
-		NewDecInt64(1), NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(1),
-		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
-		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1)}},
-	{RoundUp, [...]*Dec{
-		NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
-		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1),
-		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
-		NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
-		NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
-	{RoundHalfDown, [...]*Dec{
-		NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
-		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
-		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(1), 1),
-		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 1)}},
-	{RoundHalfUp, [...]*Dec{
-		NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
-		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-1), 1),
-		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
-		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
-	{RoundFloor, [...]*Dec{
-		NewDecInt64(1), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(1),
-		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1),
-		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
-		NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1)}},
-	{RoundCeil, [...]*Dec{
-		NewDecInt64(2), NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(2),
-		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
-		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(0), 1),
-		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
-		NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
-}
-
-func TestDecRounders(t *testing.T) {
-	for i, a := range decRounderResults {
-		for j, input := range decRounderInputs {
-			q := new(Dec).Set(input.quo)
-			rA, rB := new(big.Int).Set(input.rA), new(big.Int).Set(input.rB)
-			res := a.rounder.Round(new(Dec), q, rA, rB)
-			if a.results[j] == nil && res == nil {
-				continue
-			}
-			if (a.results[j] == nil && res != nil) ||
-				(a.results[j] != nil && res == nil) ||
-				a.results[j].Cmp(res) != 0 {
-				t.Errorf("#%d,%d Rounder got %v; expected %v", i, j, res, a.results[j])
-			}
-		}
-	}
-}
-
 var decRoundTests = [...]struct {
 	in  *Dec
 	s   Scale
@@ -275,7 +181,7 @@
 	{"0x", "ignored", 0, 0, false, true},
 	{"0xg", "ignored", 0, 0, false, true},
 	{"0.0g", "ignored", 0, 1, false, true},
-	// examples from godoc for Dec 
+	// examples from godoc for Dec
 	{"0", "0", 0, 0, true, true},
 	{"0.00", "0.00", 0, 2, true, true},
 	{"ignored", "0", 0, -2, true, false},
@@ -464,7 +370,7 @@
 				}
 				var tx Dec
 				tx.SetString(stest)
-				tx.SetScale(k) // test with positive, negative, and zero scale 
+				tx.SetScale(k) // test with positive, negative, and zero scale
 				if err := enc.Encode(&tx); err != nil {
 					t.Errorf("#%d%c: encoding failed: %s", i, 'a'+j, err)
 				}
diff --git a/dec/rounder.go b/dec/rounder.go
new file mode 100644
index 0000000..455d392
--- /dev/null
+++ b/dec/rounder.go
@@ -0,0 +1,309 @@
+package dec
+
+// This file implements signed multi-precision decimals.
+
+import (
+	"math/big"
+)
+
+// Rounder represents a method for rounding the (possibly infinite decimal)
+// result of a division to a finite Dec. It is used by Dec.Round() and
+// Dec.Quo().
+//
+type Rounder interface {
+
+	// When UseRemainder() returns true, the Round() method is passed the
+	// remainder of the division, expressed as the numerator and denominator of
+	// a rational.
+	UseRemainder() bool
+
+	// Round sets the rounded value of a quotient to z, and returns z.
+	// quo is rounded down (truncated towards zero) to the scale obtained from
+	// the Scaler in Quo().
+	//
+	// When the remainder is not used, remNum and remDen are nil.
+	// When used, the remainder is normalized between -1 and 1; that is:
+	//
+	//  -|remDen| < remNum < |remDen|
+	//
+	// remDen has the same sign as y, and remNum is zero or has the same sign
+	// as x.
+	Round(z, quo *Dec, remNum, remDen *big.Int) *Dec
+}
+
+type rounder struct {
+	useRem bool
+	round  func(z, quo *Dec, remNum, remDen *big.Int) *Dec
+}
+
+func (r rounder) UseRemainder() bool {
+	return r.useRem
+}
+
+func (r rounder) Round(z, quo *Dec, remNum, remDen *big.Int) *Dec {
+	return r.round(z, quo, remNum, remDen)
+}
+
+// RoundExact returns quo if rem is zero, or nil otherwise. It is intended to
+// be used with ScaleQuoExact when it is guaranteed that the result can be
+// obtained without rounding. QuoExact is a shorthand for such a quotient
+// operation.
+//
+var RoundExact Rounder = roundExact
+
+// RoundDown rounds towards 0; that is, returns the Dec with the greatest
+// absolute value not exceeding that of the result represented by quo and rem.
+//
+// The following table shows examples of the results for
+// Quo(x, y, Scale(scale), RoundDown).
+//
+//      x      y    scale   result
+//  ------------------------------
+//    -1.8    10        1     -0.1
+//    -1.5    10        1     -0.1
+//    -1.2    10        1     -0.1
+//    -1.0    10        1     -0.1
+//    -0.8    10        1     -0.0
+//    -0.5    10        1     -0.0
+//    -0.2    10        1     -0.0
+//     0.0    10        1      0.0
+//     0.2    10        1      0.0
+//     0.5    10        1      0.0
+//     0.8    10        1      0.0
+//     1.0    10        1      0.1
+//     1.2    10        1      0.1
+//     1.5    10        1      0.1
+//     1.8    10        1      0.1
+//
+var RoundDown Rounder = roundDown
+
+// RoundUp rounds away from 0; that is, returns the Dec with the smallest
+// absolute value not smaller than that of the result represented by quo and
+// rem.
+//
+// The following table shows examples of the results for
+// Quo(x, y, Scale(scale), RoundUp).
+//
+//      x      y    scale   result
+//  ------------------------------
+//    -1.8    10        1     -0.2
+//    -1.5    10        1     -0.2
+//    -1.2    10        1     -0.2
+//    -1.0    10        1     -0.1
+//    -0.8    10        1     -0.1
+//    -0.5    10        1     -0.1
+//    -0.2    10        1     -0.1
+//     0.0    10        1      0.0
+//     0.2    10        1      0.1
+//     0.5    10        1      0.1
+//     0.8    10        1      0.1
+//     1.0    10        1      0.1
+//     1.2    10        1      0.2
+//     1.5    10        1      0.2
+//     1.8    10        1      0.2
+//
+var RoundUp Rounder = roundUp
+
+// RoundHalfDown rounds to the nearest Dec, and when the remainder is 1/2, it
+// rounds to the Dec with the lower absolute value.
+//
+// The following table shows examples of the results for
+// Quo(x, y, Scale(scale), RoundHalfDown).
+//
+//      x      y    scale   result
+//  ------------------------------
+//    -1.8    10        1     -0.2
+//    -1.5    10        1     -0.1
+//    -1.2    10        1     -0.1
+//    -1.0    10        1     -0.1
+//    -0.8    10        1     -0.1
+//    -0.5    10        1     -0.0
+//    -0.2    10        1     -0.0
+//     0.0    10        1      0.0
+//     0.2    10        1      0.0
+//     0.5    10        1      0.0
+//     0.8    10        1      0.1
+//     1.0    10        1      0.1
+//     1.2    10        1      0.1
+//     1.5    10        1      0.1
+//     1.8    10        1      0.2
+//
+var RoundHalfDown Rounder = roundHalfDown
+
+// RoundHalfUp rounds to the nearest Dec, and when the remainder is 1/2, it
+// rounds to the Dec with the greater absolute value.
+//
+// The following table shows examples of the results for
+// Quo(x, y, Scale(scale), RoundHalfUp).
+//
+//      x      y    scale   result
+//  ------------------------------
+//    -1.8    10        1     -0.2
+//    -1.5    10        1     -0.2
+//    -1.2    10        1     -0.1
+//    -1.0    10        1     -0.1
+//    -0.8    10        1     -0.1
+//    -0.5    10        1     -0.1
+//    -0.2    10        1     -0.0
+//     0.0    10        1      0.0
+//     0.2    10        1      0.0
+//     0.5    10        1      0.1
+//     0.8    10        1      0.1
+//     1.0    10        1      0.1
+//     1.2    10        1      0.1
+//     1.5    10        1      0.2
+//     1.8    10        1      0.2
+//
+var RoundHalfUp Rounder = roundHalfUp
+
+// RoundFloor rounds towards negative infinity; that is, returns the greatest
+// Dec not exceeding the result represented by quo and rem.
+//
+// The following table shows examples of the results for
+// Quo(x, y, Scale(scale), RoundFloor).
+//
+//      x      y    scale   result
+//  ------------------------------
+//    -1.8    10        1     -0.2
+//    -1.5    10        1     -0.2
+//    -1.2    10        1     -0.2
+//    -1.0    10        1     -0.1
+//    -0.8    10        1     -0.1
+//    -0.5    10        1     -0.1
+//    -0.2    10        1     -0.1
+//     0.0    10        1      0.0
+//     0.2    10        1      0.0
+//     0.5    10        1      0.0
+//     0.8    10        1      0.0
+//     1.0    10        1      0.1
+//     1.2    10        1      0.1
+//     1.5    10        1      0.1
+//     1.8    10        1      0.1
+//
+var RoundFloor Rounder = roundFloor
+
+// RoundCeil rounds towards positive infinity; that is, returns the
+// smallest Dec not smaller than the result represented by quo and rem.
+//
+// The following table shows examples of the results for
+// Quo(x, y, Scale(scale), RoundCeil).
+//
+//      x      y    scale   result
+//  ------------------------------
+//    -1.8    10        1     -0.1
+//    -1.5    10        1     -0.1
+//    -1.2    10        1     -0.1
+//    -1.0    10        1     -0.1
+//    -0.8    10        1     -0.0
+//    -0.5    10        1     -0.0
+//    -0.2    10        1     -0.0
+//     0.0    10        1      0.0
+//     0.2    10        1      0.1
+//     0.5    10        1      0.1
+//     0.8    10        1      0.1
+//     1.0    10        1      0.1
+//     1.2    10        1      0.2
+//     1.5    10        1      0.2
+//     1.8    10        1      0.2
+//
+var RoundCeil Rounder = roundCeil
+
+var intSign = []*big.Int{big.NewInt(-1), big.NewInt(0), big.NewInt(1)}
+
+var roundExact = rounder{true,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		if rA.Sign() != 0 {
+			return nil
+		}
+		return z.move(q)
+	}}
+
+var roundDown = rounder{false,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		return z.move(q)
+	}}
+
+var roundUp = rounder{true,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		z.move(q)
+		if rA.Sign() != 0 {
+			z.Unscaled().Add(z.Unscaled(), intSign[rA.Sign()*rB.Sign()+1])
+		}
+		return z
+	}}
+
+var roundHalfDown = rounder{true,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		z.move(q)
+		brA, brB := rA.BitLen(), rB.BitLen()
+		if brA < brB-1 {
+			// brA < brB-1 => |rA| < |rB/2|
+			return z
+		}
+		adjust := false
+		srA, srB := rA.Sign(), rB.Sign()
+		s := srA * srB
+		if brA == brB-1 {
+			rA2 := new(big.Int).Lsh(rA, 1)
+			if s < 0 {
+				rA2.Neg(rA2)
+			}
+			if rA2.Cmp(rB)*srB > 0 {
+				adjust = true
+			}
+		} else {
+			// brA > brB-1 => |rA| > |rB/2|
+			adjust = true
+		}
+		if adjust {
+			z.Unscaled().Add(z.Unscaled(), intSign[s+1])
+		}
+		return z
+	}}
+
+var roundHalfUp = rounder{true,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		z.move(q)
+		brA, brB := rA.BitLen(), rB.BitLen()
+		if brA < brB-1 {
+			// brA < brB-1 => |rA| < |rB/2|
+			return z
+		}
+		adjust := false
+		srA, srB := rA.Sign(), rB.Sign()
+		s := srA * srB
+		if brA == brB-1 {
+			rA2 := new(big.Int).Lsh(rA, 1)
+			if s < 0 {
+				rA2.Neg(rA2)
+			}
+			if rA2.Cmp(rB)*srB >= 0 {
+				adjust = true
+			}
+		} else {
+			// brA > brB-1 => |rA| > |rB/2|
+			adjust = true
+		}
+		if adjust {
+			z.Unscaled().Add(z.Unscaled(), intSign[s+1])
+		}
+		return z
+	}}
+
+var roundFloor = rounder{true,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		z.move(q)
+		if rA.Sign()*rB.Sign() < 0 {
+			z.Unscaled().Add(z.Unscaled(), intSign[0])
+		}
+		return z
+	}}
+
+var roundCeil = rounder{true,
+	func(z, q *Dec, rA, rB *big.Int) *Dec {
+		z.move(q)
+		if rA.Sign()*rB.Sign() > 0 {
+			z.Unscaled().Add(z.Unscaled(), intSign[2])
+		}
+		return z
+	}}
diff --git a/dec/rounder_test.go b/dec/rounder_test.go
new file mode 100644
index 0000000..7372808
--- /dev/null
+++ b/dec/rounder_test.go
@@ -0,0 +1,100 @@
+package dec
+
+import (
+	"math/big"
+	"testing"
+)
+
+var decRounderInputs = [...]struct {
+	quo    *Dec
+	rA, rB *big.Int
+}{
+	// examples from go language spec
+	{NewDec(big.NewInt(1), 0), big.NewInt(2), big.NewInt(3)},   //  5 /  3
+	{NewDec(big.NewInt(-1), 0), big.NewInt(-2), big.NewInt(3)}, // -5 /  3
+	{NewDec(big.NewInt(-1), 0), big.NewInt(2), big.NewInt(-3)}, //  5 / -3
+	{NewDec(big.NewInt(1), 0), big.NewInt(-2), big.NewInt(-3)}, // -5 / -3
+	// examples from godoc
+	{NewDec(big.NewInt(-1), 1), big.NewInt(-8), big.NewInt(10)},
+	{NewDec(big.NewInt(-1), 1), big.NewInt(-5), big.NewInt(10)},
+	{NewDec(big.NewInt(-1), 1), big.NewInt(-2), big.NewInt(10)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(-8), big.NewInt(10)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(-5), big.NewInt(10)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(-2), big.NewInt(10)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(0), big.NewInt(1)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(2), big.NewInt(10)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(5), big.NewInt(10)},
+	{NewDec(big.NewInt(0), 1), big.NewInt(8), big.NewInt(10)},
+	{NewDec(big.NewInt(1), 1), big.NewInt(2), big.NewInt(10)},
+	{NewDec(big.NewInt(1), 1), big.NewInt(5), big.NewInt(10)},
+	{NewDec(big.NewInt(1), 1), big.NewInt(8), big.NewInt(10)},
+}
+
+var decRounderResults = [...]struct {
+	rounder Rounder
+	results [len(decRounderInputs)]*Dec
+}{
+	{RoundExact, [...]*Dec{nil, nil, nil, nil,
+		nil, nil, nil, nil, nil, nil,
+		NewDec(big.NewInt(0), 1), nil, nil, nil, nil, nil, nil}},
+	{RoundDown, [...]*Dec{
+		NewDecInt64(1), NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(1),
+		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
+		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1)}},
+	{RoundUp, [...]*Dec{
+		NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
+		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1),
+		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
+		NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
+		NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
+	{RoundHalfDown, [...]*Dec{
+		NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
+		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
+		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(1), 1),
+		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 1)}},
+	{RoundHalfUp, [...]*Dec{
+		NewDecInt64(2), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(2),
+		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-1), 1),
+		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
+		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
+	{RoundFloor, [...]*Dec{
+		NewDecInt64(1), NewDecInt64(-2), NewDecInt64(-2), NewDecInt64(1),
+		NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1), NewDec(big.NewInt(-2), 1),
+		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
+		NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1)}},
+	{RoundCeil, [...]*Dec{
+		NewDecInt64(2), NewDecInt64(-1), NewDecInt64(-1), NewDecInt64(2),
+		NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1), NewDec(big.NewInt(-1), 1),
+		NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1), NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(0), 1),
+		NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1), NewDec(big.NewInt(1), 1),
+		NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1), NewDec(big.NewInt(2), 1)}},
+}
+
+func TestDecRounders(t *testing.T) {
+	for i, a := range decRounderResults {
+		for j, input := range decRounderInputs {
+			q := new(Dec).Set(input.quo)
+			rA, rB := new(big.Int).Set(input.rA), new(big.Int).Set(input.rB)
+			res := a.rounder.Round(new(Dec), q, rA, rB)
+			if a.results[j] == nil && res == nil {
+				continue
+			}
+			if (a.results[j] == nil && res != nil) ||
+				(a.results[j] != nil && res == nil) ||
+				a.results[j].Cmp(res) != 0 {
+				t.Errorf("#%d,%d Rounder got %v; expected %v", i, j, res, a.results[j])
+			}
+		}
+	}
+}