mirror of
https://github.com/golang/go
synced 2024-11-19 13:04:45 -07:00
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>
This commit is contained in:
parent
3ed9e4ca3c
commit
919a6fbeab
@ -184,6 +184,10 @@ func (z *Int) MulRange(a, b int64) *Int {
|
|||||||
|
|
||||||
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
|
// Binomial sets z to the binomial coefficient of (n, k) and returns z.
|
||||||
func (z *Int) Binomial(n, k int64) *Int {
|
func (z *Int) Binomial(n, k int64) *Int {
|
||||||
|
// reduce the number of multiplications by reducing k
|
||||||
|
if n/2 < k && k <= n {
|
||||||
|
k = n - k // Binomial(n, k) == Binomial(n, n-k)
|
||||||
|
}
|
||||||
var a, b Int
|
var a, b Int
|
||||||
a.MulRange(n-k+1, n)
|
a.MulRange(n-k+1, n)
|
||||||
b.MulRange(1, k)
|
b.MulRange(1, k)
|
||||||
|
@ -219,6 +219,45 @@ func TestMulRangeZ(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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"
|
// Examples from the Go Language Spec, section "Arithmetic operators"
|
||||||
var divisionSignsTests = []struct {
|
var divisionSignsTests = []struct {
|
||||||
x, y int64
|
x, y int64
|
||||||
|
Loading…
Reference in New Issue
Block a user