refactor roundHalf*
diff --git a/dec/rounder.go b/dec/rounder.go
index 5810b8b..18dfdca 100644
--- a/dec/rounder.go
+++ b/dec/rounder.go
@@ -258,15 +258,15 @@
 		return z
 	}}
 
-var roundHalfDown = rounder{true,
-	func(z, q *Dec, rA, rB *big.Int) *Dec {
+func roundHalf(f func(c int, odd uint) (roundUp bool)) func(z, q *Dec, rA, rB *big.Int) *Dec {
+	return 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
+		roundUp := false
 		srA, srB := rA.Sign(), rB.Sign()
 		s := srA * srB
 		if brA == brB-1 {
@@ -274,77 +274,32 @@
 			if s < 0 {
 				rA2.Neg(rA2)
 			}
-			if rA2.Cmp(rB)*srB > 0 {
-				adjust = true
-			}
+			roundUp = f(rA2.Cmp(rB)*srB, z.Unscaled().Bit(0))
 		} else {
 			// brA > brB-1 => |rA| > |rB/2|
-			adjust = true
+			roundUp = true
 		}
-		if adjust {
+		if roundUp {
 			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 roundHalfDown = rounder{true, roundHalf(
+	func(c int, odd uint) bool {
+		return c > 0
+	})}
 
-var roundHalfEven = 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)
-			}
-			c := rA2.Cmp(rB) * srB
-			if c > 0 || c == 0 && z.Unscaled().Bit(0) == 1 {
-				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, roundHalf(
+	func(c int, odd uint) bool {
+		return c >= 0
+	})}
+
+var roundHalfEven = rounder{true, roundHalf(
+	func(c int, odd uint) bool {
+		return c > 0 || c == 0 && odd == 1
+	})}
 
 var roundFloor = rounder{true,
 	func(z, q *Dec, rA, rB *big.Int) *Dec {