math/big: faster Int.Binomial(n, k) for k > n/2

benchmark             old ns/op     new ns/op     delta
BenchmarkBinomial     478664        4410          -99.08%

Fixes #10084.

Change-Id: Ib75034428e32c79c9a660ae9f9bd396afc6a7f11
Reviewed-on: https://go-review.googlesource.com/8351
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/src/math/big/int_test.go b/src/math/big/int_test.go
index 058dd96..a972a72 100644
--- a/src/math/big/int_test.go
+++ b/src/math/big/int_test.go
@@ -219,6 +219,45 @@
 	}
 }
 
+func TestBinomial(t *testing.T) {
+	var z Int
+	for _, test := range []struct {
+		n, k int64
+		want string
+	}{
+		{0, 0, "1"},
+		{0, 1, "0"},
+		{1, 0, "1"},
+		{1, 1, "1"},
+		{1, 10, "0"},
+		{4, 0, "1"},
+		{4, 1, "4"},
+		{4, 2, "6"},
+		{4, 3, "4"},
+		{4, 4, "1"},
+		{10, 1, "10"},
+		{10, 9, "10"},
+		{10, 5, "252"},
+		{11, 5, "462"},
+		{11, 6, "462"},
+		{100, 10, "17310309456440"},
+		{100, 90, "17310309456440"},
+		{1000, 10, "263409560461970212832400"},
+		{1000, 990, "263409560461970212832400"},
+	} {
+		if got := z.Binomial(test.n, test.k).String(); got != test.want {
+			t.Errorf("Binomial(%d, %d) = %s; want %s", test.n, test.k, got, test.want)
+		}
+	}
+}
+
+func BenchmarkBinomial(b *testing.B) {
+	var z Int
+	for i := b.N - 1; i >= 0; i-- {
+		z.Binomial(1000, 990)
+	}
+}
+
 // Examples from the Go Language Spec, section "Arithmetic operators"
 var divisionSignsTests = []struct {
 	x, y int64