Пример #1
0
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)
}
Пример #2
0
// 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)
}
Пример #3
0
func TestFloorSqrt(t *testing.T) {
	tcs := []struct {
		n, s uint
	}{
		{0, 0},
		{1, 1},
		{2, 1},
		{3, 1},
		{4, 2},
		{5, 2},
		{7, 2},
		{1<<20 - 1, 1<<10 - 1},
		{1 << 20, 1 << 10},
		{1<<20 + 1, 1 << 10},
		{math.MaxUint32 - 1, math.MaxUint16},
	}
	for _, tc := range tcs {
		if s := xmath.FloorSqrt(tc.n); s != tc.s {
			t.Errorf("FloorSqrt(%d) expected to be %d.  got %d", tc.n, tc.s, s)
		}
	}
}