func (ps *Swing) OddSwing(z *big.Int, k uint) *big.Int { if k < uint(len(SmallOddSwing)) { return z.SetInt64(SmallOddSwing[k]) } rootK := xmath.FloorSqrt(k) ps.factors = ps.factors[:0] // reset length, reusing existing capacity ps.Sieve.Iterate(3, uint64(rootK), func(p uint64) (terminate bool) { q := uint64(k) / p for q > 0 { if q&1 == 1 { ps.factors = append(ps.factors, p) } q /= p } return }) ps.Sieve.Iterate(uint64(rootK+1), uint64(k/3), func(p uint64) (term bool) { if (uint64(k) / p & 1) == 1 { ps.factors = append(ps.factors, p) } return }) ps.Sieve.Iterate(uint64(k/2+1), uint64(k), func(p uint64) (term bool) { ps.factors = append(ps.factors, p) return }) return xmath.Product(z, ps.factors) }
func TestProduct(t *testing.T) { m := new(big.Int) // test empty list if xmath.Product(m, nil).Int64() != 1 { t.Error("Product of empty list should be 1. Got", m) } // compute product with seqential algorithm p := big.NewInt(int64(s[0])) for _, term := range s[1:] { p.Mul(p, m.SetInt64(int64(term))) } // test if _ = xmath.Product(m, s); m.Cmp(p) != 0 { t.Error("Product fail on", len(s), "random numbers") } }
// BinomialS computes the binomial coefficient C(n,k) using prime number // sieve p. BinomialS returns nil if p is too small. Otherwise it leaves // the result in z, replacing the existing value of z, and returning z. func BinomialS(z *big.Int, p *sieve.Sieve, n, k uint) *big.Int { if uint64(n) > p.Lim { return nil } if k > n { return z.SetInt64(0) } if k > n/2 { k = n - k } if k < 3 { switch k { case 0: return z.SetInt64(1) case 1: return z.SetInt64(int64(n)) case 2: var n1 big.Int return z.Rsh(z.Mul(z.SetInt64(int64(n)), n1.SetInt64(int64(n-1))), 1) } } rootN := uint64(xmath.FloorSqrt(n)) var factors []uint64 p.Iterate(2, rootN, func(p uint64) (terminate bool) { var r, nn, kk uint64 = 0, uint64(n), uint64(k) for nn > 0 { if nn%p < kk%p+r { r = 1 factors = append(factors, p) } else { r = 0 } nn /= p kk /= p } return }) p.Iterate(rootN+1, uint64(n/2), func(p uint64) (terminate bool) { if uint64(n)%p < uint64(k)%p { factors = append(factors, p) } return }) p.Iterate(uint64(n-k+1), uint64(n), func(p uint64) (terminate bool) { factors = append(factors, p) return }) return xmath.Product(z, factors) }
func main() { tMin := xmath.ProductSerialThreshold - 10 if tMin < 2 { tMin = 2 } tMax := xmath.ProductSerialThreshold + 10 p := new(big.Int) var st int // close on st f := func(b *testing.B) { t0 := xmath.ProductSerialThreshold xmath.ProductSerialThreshold = st for i := 0; i < b.N; i++ { xmath.Product(p, s) } xmath.ProductSerialThreshold = t0 } for st = tMin; st <= tMax; st++ { fmt.Println("Threshold:", st, testing.Benchmark(f)) } }