Example #1
0
func TestLog2(t *testing.T) {
	for _, tc := range s {
		u := uint(tc)
		u >>= u & 0x1f
		if u == 0 {
			continue // not interesting
		}
		l := xmath.Log2(u)
		s := u >> l
		if s != 1 {
			t.Fatalf("Log2(%d) returned %x", u, l)
		}
	}
}
Example #2
0
func init() {
	// singletons
	Binary = func(n uint) uint {
		return n / 2
	}
	CoBinary = func(n uint) uint {
		return (n + 1) / 2
	}
	Dichotomic = func(n uint) uint {
		return n / (1 << ((xmath.Log2(n) + 1) / 2))
	}
	// non-singletons
	Total = func(n uint) []uint {
		s := make([]uint, n-2)
		for i := range s {
			s[i] = uint(i + 2)
		}
		// fmt.Printf(indent+" Total(%d) = %v\n", n, s)
		return s
	}
	Dyadic = func(n uint) []uint {
		s := make([]uint, xmath.Log2(n)-1)
		for i := range s {
			s[i] = n / (uint(1) << uint(len(s)-i))
		}
		// fmt.Printf(indent+" Dyadic(%d) = %v\n", n, s)
		return s
	}
	Fermat = func(n uint) []uint {
		s := make([]uint, 1+xmath.Log2(xmath.Log2(n)-1))
		for i := range s {
			s[i] = n / (uint(1) << (uint(1) << uint(len(s)-1-i)))
		}
		//	fmt.Printf(indent+" Fermat(%d) = %v\n", n, s)
		return s
	}
}
Example #3
0
// Chain computes an addition chain, returning it in StarChain form.
func (γ SingletonStrategy) Chain(n uint) StarChain {
	// This is the function minChain as described in the paper.
	switch a := xmath.Log2(n); {
	case n == 1<<a:
		r := make(StarChain, a)
		for i := range r {
			r[i] = i
		}
		return r
	case n == 3:
		return StarChain{0, 0}
	}
	s, _ := γ.chain1(n, γ(n))
	return s
}
Example #4
0
// Factorial computes n!, leaving result in z and returning z.
func Factorial(z *big.Int, n uint) *big.Int {
	currentN := int64(1)
	var product func(*big.Int, uint) *big.Int
	product = func(z *big.Int, n uint) *big.Int {
		switch n {
		case 1:
			currentN += 2
			return z.SetInt64(currentN)
		case 2:
			currentN += 2
			r := currentN
			currentN += 2
			r *= currentN
			return z.SetInt64(r)
		}
		m := n / 2
		var r big.Int
		return z.Mul(product(z, m), product(&r, n-m))
	}

	var p, pr big.Int
	p.SetInt64(1)
	z.SetInt64(1)

	var h, shift uint
	var high uint = 1
	log2n := xmath.Log2(n)

	for h != n {
		shift += h
		h = n >> log2n
		log2n--
		length := high
		high = (h - 1) | 1
		length = (high - length) / 2

		if length > 0 {
			z.Mul(z, p.Mul(&p, product(&pr, length)))
		}
	}

	return z.Lsh(z, shift)
}
Example #5
0
// minChain returns a chain that is stored in the map.
func (cc *cm) minChain(n uint) StarChain {
	// fmt.Println(indent, "minChain(", n, ")")
	ns := indent
	indent += "  "
	defer func() { indent = ns }()
	if s, ok := cc.m[n]; ok {
		// fmt.Println(indent, "memoized")
		return s
	}
	// This is the function minChain as described in the paper.
	switch a := xmath.Log2(n); {
	case n == 1<<a:
		r := make(StarChain, a)
		for i := range r {
			r[i] = i
		}
		cc.m[n] = r
		// fmt.Println(indent, "It's a power of 2.  Returning", r.AddChain())
		return r
		//	case n == 3:
		//		// fmt.Println(indent, "It's 3.  Returning", StarChain{0, 0}.AddChain())
		//		return StarChain{0, 0}
	}
	min := int(n)
	var minS StarChain
	// var bestk uint
	// fmt.Println(indent, "Considering some possibilities...")
	for _, k := range cc.γ(n) {
		s, _ := cc.chain1(n, k)
		if len(s) < min {
			// fmt.Println(indent, "oh,", k, "was a good one")
			// bestk = k
			min = len(s)
			minS = s
		}
	}
	cc.m[n] = minS
	// fmt.Println(indent, "yeah,", bestk, "was best.  Returning", minS.AddChain())
	return minS
}