Commit 2578d583 authored by Kirill Smelkov's avatar Kirill Smelkov

xmath += CeilLog2, FloorLog2

CeilLog2(x)	= min i: 2^i >= x
FloorLog2(x)	= max i: 2^i <= x
parent 8e6e163f
...@@ -34,5 +34,30 @@ func CeilPow2(x uint64) uint64 { ...@@ -34,5 +34,30 @@ func CeilPow2(x uint64) uint64 {
} }
} }
// CeilLog2 returns minimal i: 2^i >= x
func CeilLog2(x uint64) int {
switch bits.OnesCount64(x) {
case 0:
return 0
case 1:
return bits.Len64(x) - 1
default:
return bits.Len64(x)
}
}
// FloorLog2 returns maximal i: 2^i <= x
//
// x=0 gives -> -1.
func FloorLog2(x uint64) int {
switch bits.OnesCount64(x) {
case 0:
return -1
default:
return bits.Len64(x) - 1
}
}
// XXX if needed: NextPow2 (y > x, such that y = 2^i) is // XXX if needed: NextPow2 (y > x, such that y = 2^i) is
// 1 << bits.Len64(x) // 1 << bits.Len64(x)
...@@ -21,38 +21,64 @@ import ( ...@@ -21,38 +21,64 @@ import (
"testing" "testing"
) )
func TestCeilPow2(t *testing.T) { func TestPow2(t *testing.T) {
testv := []struct {in, out uint64} { testv := []struct {x, xcpow2 uint64; xclog2 int} {
{0, 0}, {0, 0, 0},
{1, 1}, {1, 1, 0},
{2, 2}, {2, 2, 1},
{3, 4}, {3, 4, 2},
{4, 4}, {4, 4, 2},
{5, 8}, {5, 8, 3},
{5, 8}, {5, 8, 3},
{6, 8}, {6, 8, 3},
{7, 8}, {7, 8, 3},
{8, 8}, {8, 8, 3},
{9, 16}, {9, 16, 4},
{10, 16}, {10, 16, 4},
{11, 16}, {11, 16, 4},
{12, 16}, {12, 16, 4},
{13, 16}, {13, 16, 4},
{14, 16}, {14, 16, 4},
{15, 16}, {15, 16, 4},
{16, 16}, {16, 16, 4},
{1<<62 - 1, 1<<62}, {1<<62 - 1, 1<<62, 62},
{1<<62, 1<<62}, {1<<62, 1<<62, 62},
{1<<62+1, 1<<63}, {1<<62+1, 1<<63, 63},
{1<<63 - 1, 1<<63}, {1<<63 - 1, 1<<63, 63},
{1<<63, 1<<63}, {1<<63, 1<<63, 63},
} }
for _, tt := range testv { for _, tt := range testv {
out := CeilPow2(tt.in) xcpow2 := CeilPow2(tt.x)
if out != tt.out { if xcpow2 != tt.xcpow2 {
t.Errorf("CeilPow2(%v) -> %v ; want %v", tt.in, out, tt.out) t.Errorf("CeilPow2(%v) -> %v ; want %v", tt.x, xcpow2, tt.xcpow2)
}
xclog2 := CeilLog2(tt.xcpow2)
if xclog2 != tt.xclog2 {
t.Errorf("CeilLog2(%v) -> %v ; want %v", tt.xcpow2, xclog2, tt.xclog2)
} }
}
xclog2 = CeilLog2(tt.x)
if xclog2 != tt.xclog2 {
t.Errorf("CeilLog2(%v) -> %v ; want %v", tt.x, xclog2, tt.xclog2)
}
xflog2 := FloorLog2(tt.xcpow2)
xflog2Ok := tt.xclog2
if tt.x == 0 {
xflog2Ok = -1
}
if xflog2 != xflog2Ok {
t.Errorf("FloorLog2(%v) -> %v ; want %v", tt.xcpow2, xflog2, xflog2Ok)
}
if tt.x != tt.xcpow2 {
xflog2Ok--
}
xflog2 = FloorLog2(tt.x)
if xflog2 != xflog2Ok {
t.Errorf("FloorLog2(%v) -> %v ; want %v", tt.x, xflog2, xflog2Ok)
}
}
} }
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment