diff --git a/roaring/assembly.go b/roaring/assembly.go new file mode 100644 index 000000000..16012be82 --- /dev/null +++ b/roaring/assembly.go @@ -0,0 +1,7 @@ +package roaring + +func hasAsm() bool + +func BSFQ(memory uint64) int + +func POPCNTQ(memory uint64) int diff --git a/roaring/assembly_amd64.s b/roaring/assembly_amd64.s new file mode 100644 index 000000000..a33ade6ab --- /dev/null +++ b/roaring/assembly_amd64.s @@ -0,0 +1,21 @@ +#include "textflag.h" + +TEXT ·hasAsm(SB),4,$0 + MOVQ $1, AX + CPUID + SHRQ $23, CX + ANDQ $1, CX + MOVB CX, ret+0(FP) + RET + +TEXT ·POPCNTQ(SB),NOSPLIT,$0-8 + MOVQ x+0(FP), BP + POPCNTQ BP, BX + MOVQ BX, ret+8(FP) + RET + +TEXT ·BSFQ(SB),NOSPLIT,$0-8 + MOVQ x+0(FP), BP + BSFQ BP, BX + MOVQ BX, ret+8(FP) + RET diff --git a/roaring/assembly_test.go b/roaring/assembly_test.go new file mode 100644 index 000000000..3a3aa2854 --- /dev/null +++ b/roaring/assembly_test.go @@ -0,0 +1,53 @@ +package roaring + +import "testing" + +func TestBSFQ(t *testing.T) { + result := BSFQ(2) + if result != 1 { + t.Fatalf("BSF INCORRECT: %d", result) + } +} + +func TestBSFQ_CompareGo(t *testing.T) { + v := uint64(1) + for i := 0; i < 64; i++ { + if BSFQ(v) != trailingZeroN(v) { + t.Fatalf("BSF INCORRECT: %d %d", BSFQ(v), trailingZeroN(v)) + } + if v == 0 { + v = 1 + } else { + v *= 2 + } + } + /* + if bsfq(0) != trailingZeroN(0) { + fmt.Println(bsfq(0)) + t.Fatalf("BSF INCORRECT") + } + */ +} +func BenchmarkBSF(b *testing.B) { + for i := 0; i < b.N; i++ { + BSFQ(uint64(i)) + } +} + +func BenchmarkTrailingZeroN(b *testing.B) { + for i := 0; i < b.N; i++ { + trailingZeroN(uint64(i)) + } +} + +func BenchmarkPOPCNTQ(b *testing.B) { + for i := 0; i < b.N; i++ { + POPCNTQ(uint64(i)) + } +} + +func BenchmarkPopcount(b *testing.B) { + for i := 0; i < b.N; i++ { + popcount(uint64(i)) + } +}