// Package bitset is a minimal []uint64-backed bit vector: the engine's // stand-in for Rust's bitvec, backing dense bool columns and the presence // bitmaps of rank/select columns. Deliberately tiny -- no dependency.
package bitset import ( ) // Bits is a fixed-length bit vector. type Bits struct { words []uint64 n int } // New returns an all-false bit vector of n bits. func ( int) *Bits { return &Bits{words: make([]uint64, (+63)/64), n: } } // FromPackedLSB builds a bit vector from n bits packed LSB-first within each // byte -- the RCPG dense-bool on-disk layout. func ( []byte, int) *Bits { := New() for := range { if [/8]&(1<<(%8)) != 0 { .words[/64] |= 1 << ( % 64) } } return } // ToPackedLSB returns the bits packed LSB-first within each byte, ceil(n/8) // bytes -- the RCPG dense-bool on-disk layout. func ( *Bits) () []byte { := make([]byte, (.n+7)/8) for := range .n { if .Get() { [/8] |= 1 << ( % 8) } } return } // Len is the number of bits. func ( *Bits) () int { return .n } // Get reports bit i; false when out of range. func ( *Bits) ( int) bool { if < 0 || >= .n { return false } return .words[/64]&(1<<(%64)) != 0 } // Set sets bit i to v; i must be in [0, Len). func ( *Bits) ( int, bool) { if { .words[/64] |= 1 << ( % 64) } else { .words[/64] &^= 1 << ( % 64) } } // Count is the number of set bits. func ( *Bits) () int { := 0 for , := range .words { += bits.OnesCount64() } return } // CountRange is the number of set bits in [lo, hi) -- the popcount behind // rank queries. Out-of-range bounds are clamped. func ( *Bits) (, int) int { = max(, 0) = min(, .n) if >= { return 0 } , := /64, (-1)/64 := ^uint64(0) << ( % 64) := ^uint64(0) >> (63 - (-1)%64) if == { return bits.OnesCount64(.words[] & & ) } := bits.OnesCount64(.words[] & ) for := + 1; < ; ++ { += bits.OnesCount64(.words[]) } return + bits.OnesCount64(.words[]&) } // Ones iterates the set bit positions in ascending order. func ( *Bits) () iter.Seq[int] { return func( func(int) bool) { for , := range .words { for != 0 { := *64 + bits.TrailingZeros64() if >= .n || !() { return } &= - 1 } } } }