well-goknown/vendor/github.com/greatroar/blobloom/setop_64bit.go
2024-10-28 20:11:29 -04:00

149 lines
3.1 KiB
Go

// Copyright 2020-2022 the Blobloom authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//go:build (amd64 || arm64) && !nounsafe
// +build amd64 arm64
// +build !nounsafe
package blobloom
import (
"math/bits"
"sync/atomic"
"unsafe"
)
// Block reinterpreted as array of uint64.
type block64 [BlockBits / 64]uint64
func (f *Filter) intersect(g *Filter) {
a, b := f.b, g.b
for len(a) >= 2 && len(b) >= 2 {
p := (*block64)(unsafe.Pointer(&a[0]))
q := (*block64)(unsafe.Pointer(&b[0]))
p[0] &= q[0]
p[1] &= q[1]
p[2] &= q[2]
p[3] &= q[3]
p[4] &= q[4]
p[5] &= q[5]
p[6] &= q[6]
p[7] &= q[7]
p = (*block64)(unsafe.Pointer(&a[1]))
q = (*block64)(unsafe.Pointer(&b[1]))
p[0] &= q[0]
p[1] &= q[1]
p[2] &= q[2]
p[3] &= q[3]
p[4] &= q[4]
p[5] &= q[5]
p[6] &= q[6]
p[7] &= q[7]
a, b = a[2:], b[2:]
}
if len(a) > 0 && len(b) > 0 {
p := (*block64)(unsafe.Pointer(&a[0]))
q := (*block64)(unsafe.Pointer(&b[0]))
p[0] &= q[0]
p[1] &= q[1]
p[2] &= q[2]
p[3] &= q[3]
p[4] &= q[4]
p[5] &= q[5]
p[6] &= q[6]
p[7] &= q[7]
}
}
func (f *Filter) union(g *Filter) {
a, b := f.b, g.b
for len(a) >= 2 && len(b) >= 2 {
p := (*block64)(unsafe.Pointer(&a[0]))
q := (*block64)(unsafe.Pointer(&b[0]))
p[0] |= q[0]
p[1] |= q[1]
p[2] |= q[2]
p[3] |= q[3]
p[4] |= q[4]
p[5] |= q[5]
p[6] |= q[6]
p[7] |= q[7]
p = (*block64)(unsafe.Pointer(&a[1]))
q = (*block64)(unsafe.Pointer(&b[1]))
p[0] |= q[0]
p[1] |= q[1]
p[2] |= q[2]
p[3] |= q[3]
p[4] |= q[4]
p[5] |= q[5]
p[6] |= q[6]
p[7] |= q[7]
a, b = a[2:], b[2:]
}
if len(a) > 0 && len(b) > 0 {
p := (*block64)(unsafe.Pointer(&a[0]))
q := (*block64)(unsafe.Pointer(&b[0]))
p[0] |= q[0]
p[1] |= q[1]
p[2] |= q[2]
p[3] |= q[3]
p[4] |= q[4]
p[5] |= q[5]
p[6] |= q[6]
p[7] |= q[7]
}
}
func onescount(b *block) (n int) {
p := (*block64)(unsafe.Pointer(&b[0]))
n += bits.OnesCount64(p[0])
n += bits.OnesCount64(p[1])
n += bits.OnesCount64(p[2])
n += bits.OnesCount64(p[3])
n += bits.OnesCount64(p[4])
n += bits.OnesCount64(p[5])
n += bits.OnesCount64(p[6])
n += bits.OnesCount64(p[7])
return n
}
func onescountAtomic(b *block) (n int) {
p := (*block64)(unsafe.Pointer(&b[0]))
n += bits.OnesCount64(atomic.LoadUint64(&p[0]))
n += bits.OnesCount64(atomic.LoadUint64(&p[1]))
n += bits.OnesCount64(atomic.LoadUint64(&p[2]))
n += bits.OnesCount64(atomic.LoadUint64(&p[3]))
n += bits.OnesCount64(atomic.LoadUint64(&p[4]))
n += bits.OnesCount64(atomic.LoadUint64(&p[5]))
n += bits.OnesCount64(atomic.LoadUint64(&p[6]))
n += bits.OnesCount64(atomic.LoadUint64(&p[7]))
return n
}