pax_global_header00006660000000000000000000000064143637770500014526gustar00rootroot0000000000000052 comment=a8d80450b81d8d04749a11f17a102675736783c5 bitset-1.5.0/000077500000000000000000000000001436377705000130235ustar00rootroot00000000000000bitset-1.5.0/.github/000077500000000000000000000000001436377705000143635ustar00rootroot00000000000000bitset-1.5.0/.github/FUNDING.yml000066400000000000000000000004441436377705000162020ustar00rootroot00000000000000# You can add one username per supported platform and one custom link patreon: # Replace with your Patreon username open_collective: # Replace with your Open Collective username ko_fi: # Replace with your Ko-fi username custom: https://donate.mcc.org/ # Replace with your custom donation URL bitset-1.5.0/.github/workflows/000077500000000000000000000000001436377705000164205ustar00rootroot00000000000000bitset-1.5.0/.github/workflows/test.yml000066400000000000000000000006561436377705000201310ustar00rootroot00000000000000on: pull_request name: Test jobs: test: strategy: matrix: go-version: [1.17.x, 1.18.x, 1.19.x] os: [ubuntu-latest, macos-latest, windows-latest] runs-on: ${{ matrix.os }} steps: - name: Install Go uses: actions/setup-go@v2 with: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@master - name: Test run: go test ./... bitset-1.5.0/.gitignore000066400000000000000000000004221436377705000150110ustar00rootroot00000000000000# Compiled Object files, Static and Dynamic libs (Shared Objects) *.o *.a *.so # Folders _obj _test # Architecture specific extensions/prefixes *.[568vq] [568vq].out *.cgo1.go *.cgo2.c _cgo_defun.c _cgo_gotypes.go _cgo_export.* _testmain.go *.exe *.test *.prof target bitset-1.5.0/.travis.yml000066400000000000000000000012271436377705000151360ustar00rootroot00000000000000language: go sudo: false branches: except: - release branches: only: - master - travis go: - "1.11.x" - tip matrix: allow_failures: - go: tip before_install: - if [ -n "$GH_USER" ]; then git config --global github.user ${GH_USER}; fi; - if [ -n "$GH_TOKEN" ]; then git config --global github.token ${GH_TOKEN}; fi; - go get github.com/mattn/goveralls before_script: - make deps script: - make qa after_failure: - cat ./target/test/report.xml after_success: - if [ "$TRAVIS_GO_VERSION" = "1.11.1" ]; then $HOME/gopath/bin/goveralls -covermode=count -coverprofile=target/report/coverage.out -service=travis-ci; fi; bitset-1.5.0/LICENSE000066400000000000000000000027101436377705000140300ustar00rootroot00000000000000Copyright (c) 2014 Will Fitzgerald. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Google Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. bitset-1.5.0/README.md000066400000000000000000000064761436377705000143170ustar00rootroot00000000000000# bitset *Go language library to map between non-negative integers and boolean values* [![Test](https://github.com/bits-and-blooms/bitset/workflows/Test/badge.svg)](https://github.com/willf/bitset/actions?query=workflow%3ATest) [![Go Report Card](https://goreportcard.com/badge/github.com/willf/bitset)](https://goreportcard.com/report/github.com/willf/bitset) [![PkgGoDev](https://pkg.go.dev/badge/github.com/bits-and-blooms/bitset?tab=doc)](https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc) ## Description Package bitset implements bitsets, a mapping between non-negative integers and boolean values. It should be more efficient than map[uint] bool. It provides methods for setting, clearing, flipping, and testing individual integers. But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits. BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used. Many of the methods, including Set, Clear, and Flip, return a BitSet pointer, which allows for chaining. ### Example use: ```go package main import ( "fmt" "math/rand" "github.com/bits-and-blooms/bitset" ) func main() { fmt.Printf("Hello from BitSet!\n") var b bitset.BitSet // play some Go Fish for i := 0; i < 100; i++ { card1 := uint(rand.Intn(52)) card2 := uint(rand.Intn(52)) b.Set(card1) if b.Test(card2) { fmt.Println("Go Fish!") } b.Clear(card1) } // Chaining b.Set(10).Set(11) for i, e := b.NextSet(0); e; i, e = b.NextSet(i + 1) { fmt.Println("The following bit is set:", i) } if b.Intersection(bitset.New(100).Set(10)).Count() == 1 { fmt.Println("Intersection works.") } else { fmt.Println("Intersection doesn't work???") } } ``` As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets. Package documentation is at: https://pkg.go.dev/github.com/bits-and-blooms/bitset?tab=doc ## Memory Usage The memory usage of a bitset using N bits is at least N/8 bytes. The number of bits in a bitset is at least as large as one plus the greatest bit index you have accessed. Thus it is possible to run out of memory while using a bitset. If you have lots of bits, you might prefer compressed bitsets, like the [Roaring bitmaps](http://roaringbitmap.org) and its [Go implementation](https://github.com/RoaringBitmap/roaring). ## Implementation Note Go 1.9 introduced a native `math/bits` library. We provide backward compatibility to Go 1.7, which might be removed. It is possible that a later version will match the `math/bits` return signature for counts (which is `int`, rather than our library's `unit64`). If so, the version will be bumped. ## Installation ```bash go get github.com/bits-and-blooms/bitset ``` ## Contributing If you wish to contribute to this project, please branch and issue a pull request against master ("[GitHub Flow](https://guides.github.com/introduction/flow/)") ## Running all tests Before committing the code, please check if it passes tests, has adequate coverage, etc. ```bash go test go test -cover ``` bitset-1.5.0/azure-pipelines.yml000066400000000000000000000021001436377705000166530ustar00rootroot00000000000000# Go # Build your Go project. # Add steps that test, save build artifacts, deploy, and more: # https://docs.microsoft.com/azure/devops/pipelines/languages/go trigger: - master pool: vmImage: 'Ubuntu-16.04' variables: GOBIN: '$(GOPATH)/bin' # Go binaries path GOROOT: '/usr/local/go1.11' # Go installation path GOPATH: '$(system.defaultWorkingDirectory)/gopath' # Go workspace path modulePath: '$(GOPATH)/src/github.com/$(build.repository.name)' # Path to the module's code steps: - script: | mkdir -p '$(GOBIN)' mkdir -p '$(GOPATH)/pkg' mkdir -p '$(modulePath)' shopt -s extglob shopt -s dotglob mv !(gopath) '$(modulePath)' echo '##vso[task.prependpath]$(GOBIN)' echo '##vso[task.prependpath]$(GOROOT)/bin' displayName: 'Set up the Go workspace' - script: | go version go get -v -t -d ./... if [ -f Gopkg.toml ]; then curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh dep ensure fi go build -v . workingDirectory: '$(modulePath)' displayName: 'Get dependencies, then build' bitset-1.5.0/bitset.go000066400000000000000000000651531436377705000146560ustar00rootroot00000000000000/* Package bitset implements bitsets, a mapping between non-negative integers and boolean values. It should be more efficient than map[uint] bool. It provides methods for setting, clearing, flipping, and testing individual integers. But it also provides set intersection, union, difference, complement, and symmetric operations, as well as tests to check whether any, all, or no bits are set, and querying a bitset's current length and number of positive bits. BitSets are expanded to the size of the largest set bit; the memory allocation is approximately Max bits, where Max is the largest set bit. BitSets are never shrunk. On creation, a hint can be given for the number of bits that will be used. Many of the methods, including Set,Clear, and Flip, return a BitSet pointer, which allows for chaining. Example use: import "bitset" var b BitSet b.Set(10).Set(11) if b.Test(1000) { b.Clear(1000) } if B.Intersection(bitset.New(100).Set(10)).Count() > 1 { fmt.Println("Intersection works.") } As an alternative to BitSets, one should check out the 'big' package, which provides a (less set-theoretical) view of bitsets. */ package bitset import ( "bufio" "bytes" "encoding/base64" "encoding/binary" "encoding/json" "errors" "fmt" "io" "strconv" ) // the wordSize of a bit set const wordSize = uint(64) // log2WordSize is lg(wordSize) const log2WordSize = uint(6) // allBits has every bit set const allBits uint64 = 0xffffffffffffffff // default binary BigEndian var binaryOrder binary.ByteOrder = binary.BigEndian // default json encoding base64.URLEncoding var base64Encoding = base64.URLEncoding // Base64StdEncoding Marshal/Unmarshal BitSet with base64.StdEncoding(Default: base64.URLEncoding) func Base64StdEncoding() { base64Encoding = base64.StdEncoding } // LittleEndian Marshal/Unmarshal Binary as Little Endian(Default: binary.BigEndian) func LittleEndian() { binaryOrder = binary.LittleEndian } // A BitSet is a set of bits. The zero value of a BitSet is an empty set of length 0. type BitSet struct { length uint set []uint64 } // Error is used to distinguish errors (panics) generated in this package. type Error string // safeSet will fixup b.set to be non-nil and return the field value func (b *BitSet) safeSet() []uint64 { if b.set == nil { b.set = make([]uint64, wordsNeeded(0)) } return b.set } // SetBitsetFrom fills the bitset with an array of integers without creating a new BitSet instance func (b *BitSet) SetBitsetFrom(buf []uint64) { b.length = uint(len(buf)) * 64 b.set = buf } // From is a constructor used to create a BitSet from an array of integers func From(buf []uint64) *BitSet { return FromWithLength(uint(len(buf))*64, buf) } // FromWithLength constructs from an array of integers and length. func FromWithLength(len uint, set []uint64) *BitSet { return &BitSet{len, set} } // Bytes returns the bitset as array of integers func (b *BitSet) Bytes() []uint64 { return b.set } // wordsNeeded calculates the number of words needed for i bits func wordsNeeded(i uint) int { if i > (Cap() - wordSize + 1) { return int(Cap() >> log2WordSize) } return int((i + (wordSize - 1)) >> log2WordSize) } // wordsNeededUnbound calculates the number of words needed for i bits, possibly exceeding the capacity. // This function is useful if you know that the capacity cannot be exceeded (e.g., you have an existing bitmap). func wordsNeededUnbound(i uint) int { return int((i + (wordSize - 1)) >> log2WordSize) } // wordsIndex calculates the index of words in a `uint64` func wordsIndex(i uint) uint { return i & (wordSize - 1) } // New creates a new BitSet with a hint that length bits will be required func New(length uint) (bset *BitSet) { defer func() { if r := recover(); r != nil { bset = &BitSet{ 0, make([]uint64, 0), } } }() bset = &BitSet{ length, make([]uint64, wordsNeeded(length)), } return bset } // Cap returns the total possible capacity, or number of bits func Cap() uint { return ^uint(0) } // Len returns the number of bits in the BitSet. // Note the difference to method Count, see example. func (b *BitSet) Len() uint { return b.length } // extendSet adds additional words to incorporate new bits if needed func (b *BitSet) extendSet(i uint) { if i >= Cap() { panic("You are exceeding the capacity") } nsize := wordsNeeded(i + 1) if b.set == nil { b.set = make([]uint64, nsize) } else if cap(b.set) >= nsize { b.set = b.set[:nsize] // fast resize } else if len(b.set) < nsize { newset := make([]uint64, nsize, 2*nsize) // increase capacity 2x copy(newset, b.set) b.set = newset } b.length = i + 1 } // Test whether bit i is set. func (b *BitSet) Test(i uint) bool { if i >= b.length { return false } return b.set[i>>log2WordSize]&(1<= Cap(), this function will panic. // Warning: using a very large value for 'i' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. func (b *BitSet) Set(i uint) *BitSet { if i >= b.length { // if we need more bits, make 'em b.extendSet(i) } b.set[i>>log2WordSize] |= 1 << wordsIndex(i) return b } // Clear bit i to 0 func (b *BitSet) Clear(i uint) *BitSet { if i >= b.length { return b } b.set[i>>log2WordSize] &^= 1 << wordsIndex(i) return b } // SetTo sets bit i to value. // If i>= Cap(), this function will panic. // Warning: using a very large value for 'i' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. func (b *BitSet) SetTo(i uint, value bool) *BitSet { if value { return b.Set(i) } return b.Clear(i) } // Flip bit at i. // If i>= Cap(), this function will panic. // Warning: using a very large value for 'i' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. func (b *BitSet) Flip(i uint) *BitSet { if i >= b.length { return b.Set(i) } b.set[i>>log2WordSize] ^= 1 << wordsIndex(i) return b } // FlipRange bit in [start, end). // If end>= Cap(), this function will panic. // Warning: using a very large value for 'end' // may lead to a memory shortage and a panic: the caller is responsible // for providing sensible parameters in line with their memory capacity. func (b *BitSet) FlipRange(start, end uint) *BitSet { if start >= end { return b } if end-1 >= b.length { // if we need more bits, make 'em b.extendSet(end - 1) } var startWord uint = start >> log2WordSize var endWord uint = end >> log2WordSize b.set[startWord] ^= ^(^uint64(0) << wordsIndex(start)) for i := startWord; i < endWord; i++ { b.set[i] = ^b.set[i] } if end&(wordSize-1) != 0 { b.set[endWord] ^= ^uint64(0) >> wordsIndex(-end) } return b } // Shrink shrinks BitSet so that the provided value is the last possible // set value. It clears all bits > the provided index and reduces the size // and length of the set. // // Note that the parameter value is not the new length in bits: it is the // maximal value that can be stored in the bitset after the function call. // The new length in bits is the parameter value + 1. Thus it is not possible // to use this function to set the length to 0, the minimal value of the length // after this function call is 1. // // A new slice is allocated to store the new bits, so you may see an increase in // memory usage until the GC runs. Normally this should not be a problem, but if you // have an extremely large BitSet its important to understand that the old BitSet will // remain in memory until the GC frees it. func (b *BitSet) Shrink(lastbitindex uint) *BitSet { length := lastbitindex + 1 idx := wordsNeeded(length) if idx > len(b.set) { return b } shrunk := make([]uint64, idx) copy(shrunk, b.set[:idx]) b.set = shrunk b.length = length lastWordUsedBits := length % 64 if lastWordUsedBits != 0 { b.set[idx-1] &= allBits >> uint64(64-wordsIndex(lastWordUsedBits)) } return b } // Compact shrinks BitSet to so that we preserve all set bits, while minimizing // memory usage. Compact calls Shrink. func (b *BitSet) Compact() *BitSet { idx := len(b.set) - 1 for ; idx >= 0 && b.set[idx] == 0; idx-- { } newlength := uint((idx + 1) << log2WordSize) if newlength >= b.length { return b // nothing to do } if newlength > 0 { return b.Shrink(newlength - 1) } // We preserve one word return b.Shrink(63) } // InsertAt takes an index which indicates where a bit should be // inserted. Then it shifts all the bits in the set to the left by 1, starting // from the given index position, and sets the index position to 0. // // Depending on the size of your BitSet, and where you are inserting the new entry, // this method could be extremely slow and in some cases might cause the entire BitSet // to be recopied. func (b *BitSet) InsertAt(idx uint) *BitSet { insertAtElement := idx >> log2WordSize // if length of set is a multiple of wordSize we need to allocate more space first if b.isLenExactMultiple() { b.set = append(b.set, uint64(0)) } var i uint for i = uint(len(b.set) - 1); i > insertAtElement; i-- { // all elements above the position where we want to insert can simply by shifted b.set[i] <<= 1 // we take the most significant bit of the previous element and set it as // the least significant bit of the current element b.set[i] |= (b.set[i-1] & 0x8000000000000000) >> 63 } // generate a mask to extract the data that we need to shift left // within the element where we insert a bit dataMask := uint64(1)< 0x40000 { buffer.WriteString("...") break } buffer.WriteString(strconv.FormatInt(int64(i), 10)) i, e = b.NextSet(i + 1) if e { buffer.WriteString(",") } } buffer.WriteString("}") return buffer.String() } // DeleteAt deletes the bit at the given index position from // within the bitset // All the bits residing on the left of the deleted bit get // shifted right by 1 // The running time of this operation may potentially be // relatively slow, O(length) func (b *BitSet) DeleteAt(i uint) *BitSet { // the index of the slice element where we'll delete a bit deleteAtElement := i >> log2WordSize // generate a mask for the data that needs to be shifted right // within that slice element that gets modified dataMask := ^((uint64(1) << wordsIndex(i)) - 1) // extract the data that we'll shift right from the slice element data := b.set[deleteAtElement] & dataMask // set the masked area to 0 while leaving the rest as it is b.set[deleteAtElement] &= ^dataMask // shift the previously extracted data to the right and then // set it in the previously masked area b.set[deleteAtElement] |= (data >> 1) & dataMask // loop over all the consecutive slice elements to copy each // lowest bit into the highest position of the previous element, // then shift the entire content to the right by 1 for i := int(deleteAtElement) + 1; i < len(b.set); i++ { b.set[i-1] |= (b.set[i] & 1) << 63 b.set[i] >>= 1 } b.length = b.length - 1 return b } // NextSet returns the next bit set from the specified index, // including possibly the current index // along with an error code (true = valid, false = no set bit found) // for i,e := v.NextSet(0); e; i,e = v.NextSet(i + 1) {...} // // Users concerned with performance may want to use NextSetMany to // retrieve several values at once. func (b *BitSet) NextSet(i uint) (uint, bool) { x := int(i >> log2WordSize) if x >= len(b.set) { return 0, false } w := b.set[x] w = w >> wordsIndex(i) if w != 0 { return i + trailingZeroes64(w), true } x = x + 1 for x < len(b.set) { if b.set[x] != 0 { return uint(x)*wordSize + trailingZeroes64(b.set[x]), true } x = x + 1 } return 0, false } // NextSetMany returns many next bit sets from the specified index, // including possibly the current index and up to cap(buffer). // If the returned slice has len zero, then no more set bits were found // // buffer := make([]uint, 256) // this should be reused // j := uint(0) // j, buffer = bitmap.NextSetMany(j, buffer) // for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j,buffer) { // for k := range buffer { // do something with buffer[k] // } // j += 1 // } // // It is possible to retrieve all set bits as follow: // // indices := make([]uint, bitmap.Count()) // bitmap.NextSetMany(0, indices) // // However if bitmap.Count() is large, it might be preferable to // use several calls to NextSetMany, for performance reasons. func (b *BitSet) NextSetMany(i uint, buffer []uint) (uint, []uint) { myanswer := buffer capacity := cap(buffer) x := int(i >> log2WordSize) if x >= len(b.set) || capacity == 0 { return 0, myanswer[:0] } skip := wordsIndex(i) word := b.set[x] >> skip myanswer = myanswer[:capacity] size := int(0) for word != 0 { r := trailingZeroes64(word) t := word & ((^word) + 1) myanswer[size] = r + i size++ if size == capacity { goto End } word = word ^ t } x++ for idx, word := range b.set[x:] { for word != 0 { r := trailingZeroes64(word) t := word & ((^word) + 1) myanswer[size] = r + (uint(x+idx) << 6) size++ if size == capacity { goto End } word = word ^ t } } End: if size > 0 { return myanswer[size-1], myanswer[:size] } return 0, myanswer[:0] } // NextClear returns the next clear bit from the specified index, // including possibly the current index // along with an error code (true = valid, false = no bit found i.e. all bits are set) func (b *BitSet) NextClear(i uint) (uint, bool) { x := int(i >> log2WordSize) if x >= len(b.set) { return 0, false } w := b.set[x] w = w >> wordsIndex(i) wA := allBits >> wordsIndex(i) index := i + trailingZeroes64(^w) if w != wA && index < b.length { return index, true } x++ for x < len(b.set) { index = uint(x)*wordSize + trailingZeroes64(^b.set[x]) if b.set[x] != allBits && index < b.length { return index, true } x++ } return 0, false } // ClearAll clears the entire BitSet func (b *BitSet) ClearAll() *BitSet { if b != nil && b.set != nil { for i := range b.set { b.set[i] = 0 } } return b } // wordCount returns the number of words used in a bit set func (b *BitSet) wordCount() int { return wordsNeededUnbound(b.length) } // Clone this BitSet func (b *BitSet) Clone() *BitSet { c := New(b.length) if b.set != nil { // Clone should not modify current object copy(c.set, b.set) } return c } // Copy into a destination BitSet using the Go array copy semantics: // the number of bits copied is the minimum of the number of bits in the current // BitSet (Len()) and the destination Bitset. // We return the number of bits copied in the destination BitSet. func (b *BitSet) Copy(c *BitSet) (count uint) { if c == nil { return } if b.set != nil { // Copy should not modify current object copy(c.set, b.set) } count = c.length if b.length < c.length { count = b.length } // Cleaning the last word is needed to keep the invariant that other functions, such as Count, require // that any bits in the last word that would exceed the length of the bitmask are set to 0. c.cleanLastWord() return } // CopyFull copies into a destination BitSet such that the destination is // identical to the source after the operation, allocating memory if necessary. func (b *BitSet) CopyFull(c *BitSet) { if c == nil { return } c.length = b.length if len(b.set) == 0 { if c.set != nil { c.set = c.set[:0] } } else { if cap(c.set) < len(b.set) { c.set = make([]uint64, len(b.set)) } else { c.set = c.set[:len(b.set)] } copy(c.set, b.set) } } // Count (number of set bits). // Also known as "popcount" or "population count". func (b *BitSet) Count() uint { if b != nil && b.set != nil { return uint(popcntSlice(b.set)) } return 0 } // Equal tests the equivalence of two BitSets. // False if they are of different sizes, otherwise true // only if all the same bits are set func (b *BitSet) Equal(c *BitSet) bool { if c == nil || b == nil { return c == b } if b.length != c.length { return false } if b.length == 0 { // if they have both length == 0, then could have nil set return true } wn := b.wordCount() for p:= 0; p < wn; p++ { if c.set[p] != b.set[p] { return false } } return true } func panicIfNull(b *BitSet) { if b == nil { panic(Error("BitSet must not be null")) } } // Difference of base set and other set // This is the BitSet equivalent of &^ (and not) func (b *BitSet) Difference(compare *BitSet) (result *BitSet) { panicIfNull(b) panicIfNull(compare) result = b.Clone() // clone b (in case b is bigger than compare) l := int(compare.wordCount()) if l > int(b.wordCount()) { l = int(b.wordCount()) } for i := 0; i < l; i++ { result.set[i] = b.set[i] &^ compare.set[i] } return } // DifferenceCardinality computes the cardinality of the differnce func (b *BitSet) DifferenceCardinality(compare *BitSet) uint { panicIfNull(b) panicIfNull(compare) l := int(compare.wordCount()) if l > int(b.wordCount()) { l = int(b.wordCount()) } cnt := uint64(0) cnt += popcntMaskSlice(b.set[:l], compare.set[:l]) cnt += popcntSlice(b.set[l:]) return uint(cnt) } // InPlaceDifference computes the difference of base set and other set // This is the BitSet equivalent of &^ (and not) func (b *BitSet) InPlaceDifference(compare *BitSet) { panicIfNull(b) panicIfNull(compare) l := int(compare.wordCount()) if l > int(b.wordCount()) { l = int(b.wordCount()) } for i := 0; i < l; i++ { b.set[i] &^= compare.set[i] } } // Convenience function: return two bitsets ordered by // increasing length. Note: neither can be nil func sortByLength(a *BitSet, b *BitSet) (ap *BitSet, bp *BitSet) { if a.length <= b.length { ap, bp = a, b } else { ap, bp = b, a } return } // Intersection of base set and other set // This is the BitSet equivalent of & (and) func (b *BitSet) Intersection(compare *BitSet) (result *BitSet) { panicIfNull(b) panicIfNull(compare) b, compare = sortByLength(b, compare) result = New(b.length) for i, word := range b.set { result.set[i] = word & compare.set[i] } return } // IntersectionCardinality computes the cardinality of the union func (b *BitSet) IntersectionCardinality(compare *BitSet) uint { panicIfNull(b) panicIfNull(compare) b, compare = sortByLength(b, compare) cnt := popcntAndSlice(b.set, compare.set) return uint(cnt) } // InPlaceIntersection destructively computes the intersection of // base set and the compare set. // This is the BitSet equivalent of & (and) func (b *BitSet) InPlaceIntersection(compare *BitSet) { panicIfNull(b) panicIfNull(compare) l := int(compare.wordCount()) if l > int(b.wordCount()) { l = int(b.wordCount()) } for i := 0; i < l; i++ { b.set[i] &= compare.set[i] } for i := l; i < len(b.set); i++ { b.set[i] = 0 } if compare.length > 0 { if compare.length-1 >= b.length { b.extendSet(compare.length - 1) } } } // Union of base set and other set // This is the BitSet equivalent of | (or) func (b *BitSet) Union(compare *BitSet) (result *BitSet) { panicIfNull(b) panicIfNull(compare) b, compare = sortByLength(b, compare) result = compare.Clone() for i, word := range b.set { result.set[i] = word | compare.set[i] } return } // UnionCardinality computes the cardinality of the uniton of the base set // and the compare set. func (b *BitSet) UnionCardinality(compare *BitSet) uint { panicIfNull(b) panicIfNull(compare) b, compare = sortByLength(b, compare) cnt := popcntOrSlice(b.set, compare.set) if len(compare.set) > len(b.set) { cnt += popcntSlice(compare.set[len(b.set):]) } return uint(cnt) } // InPlaceUnion creates the destructive union of base set and compare set. // This is the BitSet equivalent of | (or). func (b *BitSet) InPlaceUnion(compare *BitSet) { panicIfNull(b) panicIfNull(compare) l := int(compare.wordCount()) if l > int(b.wordCount()) { l = int(b.wordCount()) } if compare.length > 0 && compare.length-1 >= b.length { b.extendSet(compare.length - 1) } for i := 0; i < l; i++ { b.set[i] |= compare.set[i] } if len(compare.set) > l { for i := l; i < len(compare.set); i++ { b.set[i] = compare.set[i] } } } // SymmetricDifference of base set and other set // This is the BitSet equivalent of ^ (xor) func (b *BitSet) SymmetricDifference(compare *BitSet) (result *BitSet) { panicIfNull(b) panicIfNull(compare) b, compare = sortByLength(b, compare) // compare is bigger, so clone it result = compare.Clone() for i, word := range b.set { result.set[i] = word ^ compare.set[i] } return } // SymmetricDifferenceCardinality computes the cardinality of the symmetric difference func (b *BitSet) SymmetricDifferenceCardinality(compare *BitSet) uint { panicIfNull(b) panicIfNull(compare) b, compare = sortByLength(b, compare) cnt := popcntXorSlice(b.set, compare.set) if len(compare.set) > len(b.set) { cnt += popcntSlice(compare.set[len(b.set):]) } return uint(cnt) } // InPlaceSymmetricDifference creates the destructive SymmetricDifference of base set and other set // This is the BitSet equivalent of ^ (xor) func (b *BitSet) InPlaceSymmetricDifference(compare *BitSet) { panicIfNull(b) panicIfNull(compare) l := int(compare.wordCount()) if l > int(b.wordCount()) { l = int(b.wordCount()) } if compare.length > 0 && compare.length-1 >= b.length { b.extendSet(compare.length - 1) } for i := 0; i < l; i++ { b.set[i] ^= compare.set[i] } if len(compare.set) > l { for i := l; i < len(compare.set); i++ { b.set[i] = compare.set[i] } } } // Is the length an exact multiple of word sizes? func (b *BitSet) isLenExactMultiple() bool { return wordsIndex(b.length) == 0 } // Clean last word by setting unused bits to 0 func (b *BitSet) cleanLastWord() { if !b.isLenExactMultiple() { b.set[len(b.set)-1] &= allBits >> (wordSize - wordsIndex(b.length)) } } // Complement computes the (local) complement of a bitset (up to length bits) func (b *BitSet) Complement() (result *BitSet) { panicIfNull(b) result = New(b.length) for i, word := range b.set { result.set[i] = ^word } result.cleanLastWord() return } // All returns true if all bits are set, false otherwise. Returns true for // empty sets. func (b *BitSet) All() bool { panicIfNull(b) return b.Count() == b.length } // None returns true if no bit is set, false otherwise. Returns true for // empty sets. func (b *BitSet) None() bool { panicIfNull(b) if b != nil && b.set != nil { for _, word := range b.set { if word > 0 { return false } } } return true } // Any returns true if any bit is set, false otherwise func (b *BitSet) Any() bool { panicIfNull(b) return !b.None() } // IsSuperSet returns true if this is a superset of the other set func (b *BitSet) IsSuperSet(other *BitSet) bool { for i, e := other.NextSet(0); e; i, e = other.NextSet(i + 1) { if !b.Test(i) { return false } } return true } // IsStrictSuperSet returns true if this is a strict superset of the other set func (b *BitSet) IsStrictSuperSet(other *BitSet) bool { return b.Count() > other.Count() && b.IsSuperSet(other) } // DumpAsBits dumps a bit set as a string of bits func (b *BitSet) DumpAsBits() string { if b.set == nil { return "." } buffer := bytes.NewBufferString("") i := len(b.set) - 1 for ; i >= 0; i-- { fmt.Fprintf(buffer, "%064b.", b.set[i]) } return buffer.String() } // BinaryStorageSize returns the binary storage requirements func (b *BitSet) BinaryStorageSize() int { nWords := b.wordCount() return binary.Size(uint64(0)) + binary.Size(b.set[:nWords]) } // WriteTo writes a BitSet to a stream func (b *BitSet) WriteTo(stream io.Writer) (int64, error) { length := uint64(b.length) // Write length err := binary.Write(stream, binaryOrder, length) if err != nil { return 0, err } // Write set // current implementation of bufio.Writer is more memory efficient than // binary.Write for large set writer := bufio.NewWriter(stream) var item = make([]byte, binary.Size(uint64(0))) // for serializing one uint64 nWords := b.wordCount() for i := range b.set[:nWords] { binaryOrder.PutUint64(item, b.set[i]) if nn, err := writer.Write(item); err != nil { return int64(i*binary.Size(uint64(0)) + nn), err } } err = writer.Flush() return int64(b.BinaryStorageSize()), err } // ReadFrom reads a BitSet from a stream written using WriteTo func (b *BitSet) ReadFrom(stream io.Reader) (int64, error) { var length uint64 // Read length first err := binary.Read(stream, binaryOrder, &length) if err != nil { if err == io.EOF { err = io.ErrUnexpectedEOF } return 0, err } newset := New(uint(length)) if uint64(newset.length) != length { return 0, errors.New("unmarshalling error: type mismatch") } var item [8]byte nWords := wordsNeeded(uint(length)) reader := bufio.NewReader(io.LimitReader(stream, 8*int64(nWords))) for i := 0; i < nWords; i++ { if _, err := io.ReadFull(reader, item[:]); err != nil { if err == io.EOF { err = io.ErrUnexpectedEOF } return 0, err } newset.set[i] = binaryOrder.Uint64(item[:]) } *b = *newset return int64(b.BinaryStorageSize()), nil } // MarshalBinary encodes a BitSet into a binary form and returns the result. func (b *BitSet) MarshalBinary() ([]byte, error) { var buf bytes.Buffer _, err := b.WriteTo(&buf) if err != nil { return []byte{}, err } return buf.Bytes(), err } // UnmarshalBinary decodes the binary form generated by MarshalBinary. func (b *BitSet) UnmarshalBinary(data []byte) error { buf := bytes.NewReader(data) _, err := b.ReadFrom(buf) return err } // MarshalJSON marshals a BitSet as a JSON structure func (b *BitSet) MarshalJSON() ([]byte, error) { buffer := bytes.NewBuffer(make([]byte, 0, b.BinaryStorageSize())) _, err := b.WriteTo(buffer) if err != nil { return nil, err } // URLEncode all bytes return json.Marshal(base64Encoding.EncodeToString(buffer.Bytes())) } // UnmarshalJSON unmarshals a BitSet from JSON created using MarshalJSON func (b *BitSet) UnmarshalJSON(data []byte) error { // Unmarshal as string var s string err := json.Unmarshal(data, &s) if err != nil { return err } // URLDecode string buf, err := base64Encoding.DecodeString(s) if err != nil { return err } _, err = b.ReadFrom(bytes.NewReader(buf)) return err } bitset-1.5.0/bitset_benchmark_test.go000066400000000000000000000241721436377705000177230ustar00rootroot00000000000000// Copyright 2014 Will Fitzgerald. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This file tests bit sets package bitset import ( "math/rand" "testing" ) func BenchmarkSet(b *testing.B) { b.StopTimer() r := rand.New(rand.NewSource(0)) sz := 100000 s := New(uint(sz)) b.StartTimer() for i := 0; i < b.N; i++ { s.Set(uint(r.Int31n(int32(sz)))) } } func BenchmarkGetTest(b *testing.B) { b.StopTimer() r := rand.New(rand.NewSource(0)) sz := 100000 s := New(uint(sz)) b.StartTimer() for i := 0; i < b.N; i++ { s.Test(uint(r.Int31n(int32(sz)))) } } func BenchmarkSetExpand(b *testing.B) { b.StopTimer() sz := uint(100000) b.StartTimer() for i := 0; i < b.N; i++ { var s BitSet s.Set(sz) } } // go test -bench=Count func BenchmarkCount(b *testing.B) { b.StopTimer() s := New(100000) for i := 0; i < 100000; i += 100 { s.Set(uint(i)) } b.StartTimer() for i := 0; i < b.N; i++ { s.Count() } } // go test -bench=Iterate func BenchmarkIterate(b *testing.B) { b.StopTimer() s := New(10000) for i := 0; i < 10000; i += 3 { s.Set(uint(i)) } b.StartTimer() for j := 0; j < b.N; j++ { c := uint(0) for i, e := s.NextSet(0); e; i, e = s.NextSet(i + 1) { c++ } } } // go test -bench=SparseIterate func BenchmarkSparseIterate(b *testing.B) { b.StopTimer() s := New(100000) for i := 0; i < 100000; i += 30 { s.Set(uint(i)) } b.StartTimer() for j := 0; j < b.N; j++ { c := uint(0) for i, e := s.NextSet(0); e; i, e = s.NextSet(i + 1) { c++ } } } // go test -bench=LemireCreate // see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/ func BenchmarkLemireCreate(b *testing.B) { for i := 0; i < b.N; i++ { bitmap := New(0) // we force dynamic memory allocation for v := uint(0); v <= 100000000; v += 100 { bitmap.Set(v) } } } // go test -bench=LemireCount // see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/ func BenchmarkLemireCount(b *testing.B) { bitmap := New(100000000) for v := uint(0); v <= 100000000; v += 100 { bitmap.Set(v) } b.ResetTimer() sum := uint(0) for i := 0; i < b.N; i++ { sum += bitmap.Count() } if sum == 0 { // added just to fool ineffassign return } } // go test -bench=LemireIterate // see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/ func BenchmarkLemireIterate(b *testing.B) { bitmap := New(100000000) for v := uint(0); v <= 100000000; v += 100 { bitmap.Set(v) } b.ResetTimer() sum := uint(0) for i := 0; i < b.N; i++ { for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { sum++ } } if sum == 0 { // added just to fool ineffassign return } } // go test -bench=LemireIterateb // see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/ func BenchmarkLemireIterateb(b *testing.B) { bitmap := New(100000000) for v := uint(0); v <= 100000000; v += 100 { bitmap.Set(v) } b.ResetTimer() sum := uint(0) for i := 0; i < b.N; i++ { for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { sum += j } } if sum == 0 { // added just to fool ineffassign return } } // go test -bench=BenchmarkLemireIterateManyb // see http://lemire.me/blog/2016/09/22/swift-versus-java-the-bitset-performance-test/ func BenchmarkLemireIterateManyb(b *testing.B) { bitmap := New(100000000) for v := uint(0); v <= 100000000; v += 100 { bitmap.Set(v) } buffer := make([]uint, 256) b.ResetTimer() sum := uint(0) for i := 0; i < b.N; i++ { j := uint(0) j, buffer = bitmap.NextSetMany(j, buffer) for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) { for k := range buffer { sum += buffer[k] } j++ } } if sum == 0 { // added just to fool ineffassign return } } func setRnd(bits []uint64, halfings int) { var rnd = rand.NewSource(0).(rand.Source64) for i := range bits { bits[i] = 0xFFFFFFFFFFFFFFFF for j := 0; j < halfings; j++ { bits[i] &= rnd.Uint64() } } } // go test -bench=BenchmarkFlorianUekermannIterateMany func BenchmarkFlorianUekermannIterateMany(b *testing.B) { var input = make([]uint64, 68) setRnd(input, 4) var bitmap = From(input) buffer := make([]uint, 256) b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { var last, batch = bitmap.NextSetMany(0, buffer) for len(batch) > 0 { for _, idx := range batch { checksum += idx } last, batch = bitmap.NextSetMany(last+1, batch) } } if checksum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannIterateManyReg(b *testing.B) { var input = make([]uint64, 68) setRnd(input, 4) var bitmap = From(input) b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { checksum += j } } if checksum == 0 { // added just to fool ineffassign return } } // function provided by FlorianUekermann func good(set []uint64) (checksum uint) { for wordIdx, word := range set { var wordIdx = uint(wordIdx * 64) for word != 0 { var bitIdx = uint(trailingZeroes64(word)) word ^= 1 << bitIdx var index = wordIdx + bitIdx checksum += index } } return checksum } func BenchmarkFlorianUekermannIterateManyComp(b *testing.B) { var input = make([]uint64, 68) setRnd(input, 4) b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { checksum += good(input) } if checksum == 0 { // added just to fool ineffassign return } } /////// Mid density // go test -bench=BenchmarkFlorianUekermannLowDensityIterateMany func BenchmarkFlorianUekermannLowDensityIterateMany(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 50000; i++ { input[rnd.Uint64()%1000000] = 1 } var bitmap = From(input) buffer := make([]uint, 256) b.ResetTimer() var sum = uint(0) for i := 0; i < b.N; i++ { j := uint(0) j, buffer = bitmap.NextSetMany(j, buffer) for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) { for k := range buffer { sum += buffer[k] } j++ } } if sum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannLowDensityIterateManyReg(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 50000; i++ { input[rnd.Uint64()%1000000] = 1 } var bitmap = From(input) b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { checksum += j } } if checksum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannLowDensityIterateManyComp(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 50000; i++ { input[rnd.Uint64()%1000000] = 1 } b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { checksum += good(input) } if checksum == 0 { // added just to fool ineffassign return } } /////// Mid density // go test -bench=BenchmarkFlorianUekermannMidDensityIterateMany func BenchmarkFlorianUekermannMidDensityIterateMany(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 3000000; i++ { input[rnd.Uint64()%1000000] |= uint64(1) << (rnd.Uint64() % 64) } var bitmap = From(input) buffer := make([]uint, 256) b.ResetTimer() sum := uint(0) for i := 0; i < b.N; i++ { j := uint(0) j, buffer = bitmap.NextSetMany(j, buffer) for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) { for k := range buffer { sum += buffer[k] } j++ } } if sum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannMidDensityIterateManyReg(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 3000000; i++ { input[rnd.Uint64()%1000000] |= uint64(1) << (rnd.Uint64() % 64) } var bitmap = From(input) b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { checksum += j } } if checksum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannMidDensityIterateManyComp(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 3000000; i++ { input[rnd.Uint64()%1000000] |= uint64(1) << (rnd.Uint64() % 64) } b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { checksum += good(input) } if checksum == 0 { // added just to fool ineffassign return } } ////////// High density func BenchmarkFlorianUekermannMidStrongDensityIterateMany(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 20000000; i++ { input[rnd.Uint64()%1000000] |= uint64(1) << (rnd.Uint64() % 64) } var bitmap = From(input) buffer := make([]uint, 256) b.ResetTimer() sum := uint(0) for i := 0; i < b.N; i++ { j := uint(0) j, buffer = bitmap.NextSetMany(j, buffer) for ; len(buffer) > 0; j, buffer = bitmap.NextSetMany(j, buffer) { for k := range buffer { sum += buffer[k] } j++ } } if sum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannMidStrongDensityIterateManyReg(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 20000000; i++ { input[rnd.Uint64()%1000000] |= uint64(1) << (rnd.Uint64() % 64) } var bitmap = From(input) b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { for j, e := bitmap.NextSet(0); e; j, e = bitmap.NextSet(j + 1) { checksum += j } } if checksum == 0 { // added just to fool ineffassign return } } func BenchmarkFlorianUekermannMidStrongDensityIterateManyComp(b *testing.B) { var input = make([]uint64, 1000000) var rnd = rand.NewSource(0).(rand.Source64) for i := 0; i < 20000000; i++ { input[rnd.Uint64()%1000000] |= uint64(1) << (rnd.Uint64() % 64) } b.ResetTimer() var checksum = uint(0) for i := 0; i < b.N; i++ { checksum += good(input) } if checksum == 0 { // added just to fool ineffassign return } } bitset-1.5.0/bitset_test.go000066400000000000000000001206531436377705000157120ustar00rootroot00000000000000// Copyright 2014 Will Fitzgerald. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // This file tests bit sets package bitset import ( "bytes" "compress/gzip" "encoding" "encoding/base64" "encoding/binary" "encoding/json" "errors" "fmt" "io" "math" "strconv" "testing" ) func TestStringer(t *testing.T) { v := New(0) for i := uint(0); i < 10; i++ { v.Set(i) } if v.String() != "{0,1,2,3,4,5,6,7,8,9}" { t.Error("bad string output") } } func TestStringLong(t *testing.T) { v := New(0) for i := uint(0); i < 262145; i++ { v.Set(i) } str := v.String() if len(str) != 1723903 { t.Error("Unexpected string length: ", len(str)) } } func TestEmptyBitSet(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error("A zero-length bitset should be fine") } }() b := New(0) if b.Len() != 0 { t.Errorf("Empty set should have capacity 0, not %d", b.Len()) } } func TestZeroValueBitSet(t *testing.T) { defer func() { if r := recover(); r != nil { t.Error("A zero-length bitset should be fine") } }() var b BitSet if b.Len() != 0 { t.Errorf("Empty set should have capacity 0, not %d", b.Len()) } } func TestBitSetNew(t *testing.T) { v := New(16) if v.Test(0) { t.Errorf("Unable to make a bit set and read its 0th value.") } } func TestBitSetHuge(t *testing.T) { v := New(uint(math.MaxUint32)) if v.Test(0) { t.Errorf("Unable to make a huge bit set and read its 0th value.") } } func TestLen(t *testing.T) { v := New(1000) if v.Len() != 1000 { t.Errorf("Len should be 1000, but is %d.", v.Len()) } } func TestLenIsNumberOfBitsNotBytes(t *testing.T) { var b BitSet if b.Len() != 0 { t.Errorf("empty bitset should have Len 0, got %v", b.Len()) } b.Set(0) if b.Len() != 1 { t.Errorf("bitset with first bit set should have Len 1, got %v", b.Len()) } b.Set(8) if b.Len() != 9 { t.Errorf("bitset with 0th and 8th bit set should have Len 9, got %v", b.Len()) } b.Set(1) if b.Len() != 9 { t.Errorf("bitset with 0th, 1st and 8th bit set should have Len 9, got %v", b.Len()) } } func ExampleBitSet_Len() { var b BitSet b.Set(8) fmt.Println("len", b.Len()) fmt.Println("count", b.Count()) // Output: // len 9 // count 1 } func TestBitSetIsClear(t *testing.T) { v := New(1000) for i := uint(0); i < 1000; i++ { if v.Test(i) { t.Errorf("Bit %d is set, and it shouldn't be.", i) } } } func TestExendOnBoundary(t *testing.T) { v := New(32) defer func() { if r := recover(); r != nil { t.Error("Border out of index error should not have caused a panic") } }() v.Set(32) } func TestExceedCap(t *testing.T) { defer func() { if r := recover(); r == nil { t.Error("Set to capacity should have caused a panic") } }() NumHosts := uint(32768) bmp := New(NumHosts) bmp.ClearAll() d := Cap() bmp.Set(d) } func TestExpand(t *testing.T) { v := New(0) defer func() { if r := recover(); r != nil { t.Error("Expansion should not have caused a panic") } }() for i := uint(0); i < 1000; i++ { v.Set(i) } } func TestBitSetAndGet(t *testing.T) { v := New(1000) v.Set(100) if !v.Test(100) { t.Errorf("Bit %d is clear, and it shouldn't be.", 100) } } func TestNextClear(t *testing.T) { v := New(1000) v.Set(0).Set(1) next, found := v.NextClear(0) if !found || next != 2 { t.Errorf("Found next clear bit as %d, it should have been 2", next) } v = New(1000) for i := uint(0); i < 66; i++ { v.Set(i) } next, found = v.NextClear(0) if !found || next != 66 { t.Errorf("Found next clear bit as %d, it should have been 66", next) } v = New(1000) for i := uint(0); i < 64; i++ { v.Set(i) } v.Clear(45) v.Clear(52) next, found = v.NextClear(10) if !found || next != 45 { t.Errorf("Found next clear bit as %d, it should have been 45", next) } v = New(1000) for i := uint(0); i < 128; i++ { v.Set(i) } v.Clear(73) v.Clear(99) next, found = v.NextClear(10) if !found || next != 73 { t.Errorf("Found next clear bit as %d, it should have been 73", next) } next, found = v.NextClear(72) if !found || next != 73 { t.Errorf("Found next clear bit as %d, it should have been 73", next) } next, found = v.NextClear(73) if !found || next != 73 { t.Errorf("Found next clear bit as %d, it should have been 73", next) } next, found = v.NextClear(74) if !found || next != 99 { t.Errorf("Found next clear bit as %d, it should have been 73", next) } v = New(128) next, found = v.NextClear(0) if !found || next != 0 { t.Errorf("Found next clear bit as %d, it should have been 0", next) } for i := uint(0); i < 128; i++ { v.Set(i) } _, found = v.NextClear(0) if found { t.Errorf("There are not clear bits") } b := new(BitSet) c, d := b.NextClear(1) if c != 0 || d { t.Error("Unexpected values") return } v = New(100) for i := uint(0); i != 100; i++ { v.Set(i) } next, found = v.NextClear(0) if found || next != 0 { t.Errorf("Found next clear bit as %d, it should have return (0, false)", next) } } func TestIterate(t *testing.T) { v := New(10000) v.Set(0) v.Set(1) v.Set(2) data := make([]uint, 3) c := 0 for i, e := v.NextSet(0); e; i, e = v.NextSet(i + 1) { data[c] = i c++ } if data[0] != 0 { t.Errorf("bug 0") } if data[1] != 1 { t.Errorf("bug 1") } if data[2] != 2 { t.Errorf("bug 2") } v.Set(10) v.Set(2000) data = make([]uint, 5) c = 0 for i, e := v.NextSet(0); e; i, e = v.NextSet(i + 1) { data[c] = i c++ } if data[0] != 0 { t.Errorf("bug 0") } if data[1] != 1 { t.Errorf("bug 1") } if data[2] != 2 { t.Errorf("bug 2") } if data[3] != 10 { t.Errorf("bug 3") } if data[4] != 2000 { t.Errorf("bug 4") } } func TestSetTo(t *testing.T) { v := New(1000) v.SetTo(100, true) if !v.Test(100) { t.Errorf("Bit %d is clear, and it shouldn't be.", 100) } v.SetTo(100, false) if v.Test(100) { t.Errorf("Bit %d is set, and it shouldn't be.", 100) } } func TestChain(t *testing.T) { if !New(1000).Set(100).Set(99).Clear(99).Test(100) { t.Errorf("Bit %d is clear, and it shouldn't be.", 100) } } func TestOutOfBoundsLong(t *testing.T) { v := New(64) defer func() { if r := recover(); r != nil { t.Error("Long distance out of index error should not have caused a panic") } }() v.Set(1000) } func TestOutOfBoundsClose(t *testing.T) { v := New(65) defer func() { if r := recover(); r != nil { t.Error("Local out of index error should not have caused a panic") } }() v.Set(66) } func TestCount(t *testing.T) { tot := uint(64*4 + 11) // just some multi unit64 number v := New(tot) checkLast := true for i := uint(0); i < tot; i++ { sz := uint(v.Count()) if sz != i { t.Errorf("Count reported as %d, but it should be %d", sz, i) checkLast = false break } v.Set(i) } if checkLast { sz := uint(v.Count()) if sz != tot { t.Errorf("After all bits set, size reported as %d, but it should be %d", sz, tot) } } } // test setting every 3rd bit, just in case something odd is happening func TestCount2(t *testing.T) { tot := uint(64*4 + 11) // just some multi unit64 number v := New(tot) for i := uint(0); i < tot; i += 3 { sz := uint(v.Count()) if sz != i/3 { t.Errorf("Count reported as %d, but it should be %d", sz, i) break } v.Set(i) } } // nil tests func TestNullTest(t *testing.T) { var v *BitSet defer func() { if r := recover(); r == nil { t.Error("Checking bit of null reference should have caused a panic") } }() v.Test(66) } func TestNullSet(t *testing.T) { var v *BitSet defer func() { if r := recover(); r == nil { t.Error("Setting bit of null reference should have caused a panic") } }() v.Set(66) } func TestNullClear(t *testing.T) { var v *BitSet defer func() { if r := recover(); r == nil { t.Error("Clearning bit of null reference should have caused a panic") } }() v.Clear(66) } func TestNullCount(t *testing.T) { var v *BitSet defer func() { if r := recover(); r != nil { t.Error("Counting null reference should not have caused a panic") } }() cnt := v.Count() if cnt != 0 { t.Errorf("Count reported as %d, but it should be 0", cnt) } } func TestPanicDifferenceBNil(t *testing.T) { var b *BitSet var compare = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil First should should have caused a panic") } }() b.Difference(compare) } func TestPanicDifferenceCompareNil(t *testing.T) { var compare *BitSet var b = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil Second should should have caused a panic") } }() b.Difference(compare) } func TestPanicUnionBNil(t *testing.T) { var b *BitSet var compare = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil First should should have caused a panic") } }() b.Union(compare) } func TestPanicUnionCompareNil(t *testing.T) { var compare *BitSet var b = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil Second should should have caused a panic") } }() b.Union(compare) } func TestPanicIntersectionBNil(t *testing.T) { var b *BitSet var compare = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil First should should have caused a panic") } }() b.Intersection(compare) } func TestPanicIntersectionCompareNil(t *testing.T) { var compare *BitSet var b = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil Second should should have caused a panic") } }() b.Intersection(compare) } func TestPanicSymmetricDifferenceBNil(t *testing.T) { var b *BitSet var compare = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil First should should have caused a panic") } }() b.SymmetricDifference(compare) } func TestPanicSymmetricDifferenceCompareNil(t *testing.T) { var compare *BitSet var b = New(10) defer func() { if r := recover(); r == nil { t.Error("Nil Second should should have caused a panic") } }() b.SymmetricDifference(compare) } func TestPanicComplementBNil(t *testing.T) { var b *BitSet defer func() { if r := recover(); r == nil { t.Error("Nil should should have caused a panic") } }() b.Complement() } func TestPanicAnytBNil(t *testing.T) { var b *BitSet defer func() { if r := recover(); r == nil { t.Error("Nil should should have caused a panic") } }() b.Any() } func TestPanicNonetBNil(t *testing.T) { var b *BitSet defer func() { if r := recover(); r == nil { t.Error("Nil should should have caused a panic") } }() b.None() } func TestPanicAlltBNil(t *testing.T) { var b *BitSet defer func() { if r := recover(); r == nil { t.Error("Nil should should have caused a panic") } }() b.All() } func TestAll(t *testing.T) { v := New(0) if !v.All() { t.Error("Empty sets should return true on All()") } v = New(2) v.SetTo(0, true) v.SetTo(1, true) if !v.All() { t.Error("Non-empty sets with all bits set should return true on All()") } v = New(2) if v.All() { t.Error("Non-empty sets with no bits set should return false on All()") } v = New(2) v.SetTo(0, true) if v.All() { t.Error("Non-empty sets with some bits set should return false on All()") } } func TestShrink(t *testing.T) { bs := New(10) bs.Set(0) bs.Shrink(63) if !bs.Test(0) { t.Error("0 should be set") return } b := New(0) b.Set(0) b.Set(1) b.Set(2) b.Set(3) b.Set(64) b.Compact() if !b.Test(0) { t.Error("0 should be set") return } if !b.Test(1) { t.Error("1 should be set") return } if !b.Test(2) { t.Error("2 should be set") return } if !b.Test(3) { t.Error("3 should be set") return } if !b.Test(64) { t.Error("64 should be set") return } b.Shrink(2) if !b.Test(0) { t.Error("0 should be set") return } if !b.Test(1) { t.Error("1 should be set") return } if !b.Test(2) { t.Error("2 should be set") return } if b.Test(3) { t.Error("3 should not be set") return } if b.Test(64) { t.Error("64 should not be set") return } b.Set(24) b.Shrink(100) if !b.Test(24) { t.Error("24 should be set") return } b.Set(127) b.Set(128) b.Set(129) b.Compact() if !b.Test(127) { t.Error("127 should be set") return } if !b.Test(128) { t.Error("128 should be set") return } if !b.Test(129) { t.Error("129 be set") return } b.Shrink(128) if !b.Test(127) { t.Error("127 should be set") return } if !b.Test(128) { t.Error("128 should be set") return } if b.Test(129) { t.Error("129 should not be set") return } b.Set(129) b.Shrink(129) if !b.Test(129) { t.Error("129 should be set") return } b.Set(1000) b.Set(2000) b.Set(3000) b.Shrink(3000) if len(b.set) != 3000/64+1 { t.Error("Wrong length of BitSet.set") return } if !b.Test(3000) { t.Error("3000 should be set") return } b.Shrink(2000) if len(b.set) != 2000/64+1 { t.Error("Wrong length of BitSet.set") return } if b.Test(3000) { t.Error("3000 should not be set") return } if !b.Test(2000) { t.Error("2000 should be set") return } if !b.Test(1000) { t.Error("1000 should be set") return } if !b.Test(24) { t.Error("24 should be set") return } b = New(110) b.Set(80) b.Shrink(70) for _, word := range b.set { if (word != 0) { t.Error("word should be 0", word) } } } func TestInsertAtWithSet(t *testing.T) { b := New(0) b.Set(0) b.Set(1) b.Set(63) b.Set(64) b.Set(65) b.InsertAt(3) if !b.Test(0) { t.Error("0 should be set") return } if !b.Test(1) { t.Error("1 should be set") return } if b.Test(3) { t.Error("3 should not be set") return } if !b.Test(64) { t.Error("64 should be set") return } if !b.Test(65) { t.Error("65 should be set") return } if !b.Test(66) { t.Error("66 should be set") return } } func TestInsertAt(t *testing.T) { type testCase struct { input []string insertIdx uint expected []string } testCases := []testCase{ { input: []string{ "1111111111111111111111111111111111111111111111111111111111111111", }, insertIdx: uint(62), expected: []string{ "1011111111111111111111111111111111111111111111111111111111111111", "0000000000000000000000000000000000000000000000000000000000000001", }, }, { input: []string{ "1111111111111111111111111111111111111111111111111111111111111111", }, insertIdx: uint(63), expected: []string{ "0111111111111111111111111111111111111111111111111111111111111111", "0000000000000000000000000000000000000000000000000000000000000001", }, }, { input: []string{ "1111111111111111111111111111111111111111111111111111111111111111", }, insertIdx: uint(0), expected: []string{ "1111111111111111111111111111111111111111111111111111111111111110", "0000000000000000000000000000000000000000000000000000000000000001", }, }, { input: []string{ "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111111111111", }, insertIdx: uint(70), expected: []string{ "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111110111111", "1111111111111111111111111111111111111111111111111111111111111111", "0000000000000000000000000000000000000000000000000000000000000001", }, }, { input: []string{ "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111111110000", }, insertIdx: uint(70), expected: []string{ "1111111111111111111111111111111111111111111111111111111111111111", "1111111111111111111111111111111111111111111111111111111110111111", "1111111111111111111111111111111111111111111111111111111111100001", "0000000000000000000000000000000000000000000000000000000000000001", }, }, { input: []string{ "1111111111111111111111111111111111111111111111111111111111110000", }, insertIdx: uint(10), expected: []string{ "1111111111111111111111111111111111111111111111111111101111110000", "0000000000000000000000000000000000000000000000000000000000000001", }, }, } for _, tc := range testCases { var input []uint64 for _, inputElement := range tc.input { parsed, _ := strconv.ParseUint(inputElement, 2, 64) input = append(input, parsed) } var expected []uint64 for _, expectedElement := range tc.expected { parsed, _ := strconv.ParseUint(expectedElement, 2, 64) expected = append(expected, parsed) } b := From(input) b.InsertAt(tc.insertIdx) if len(b.set) != len(expected) { t.Error("Length of sets should be equal") return } for i := range b.set { if b.set[i] != expected[i] { t.Error("Unexpected results found in set") return } } } } func TestNone(t *testing.T) { v := New(0) if !v.None() { t.Error("Empty sets should return true on None()") } v = New(2) v.SetTo(0, true) v.SetTo(1, true) if v.None() { t.Error("Non-empty sets with all bits set should return false on None()") } v = New(2) if !v.None() { t.Error("Non-empty sets with no bits set should return true on None()") } v = New(2) v.SetTo(0, true) if v.None() { t.Error("Non-empty sets with some bits set should return false on None()") } v = new(BitSet) if !v.None() { t.Error("Empty sets should return true on None()") } } func TestEqual(t *testing.T) { a := New(100) b := New(99) c := New(100) if a.Equal(b) { t.Error("Sets of different sizes should be not be equal") } if !a.Equal(c) { t.Error("Two empty sets of the same size should be equal") } a.Set(99) c.Set(0) if a.Equal(c) { t.Error("Two sets with differences should not be equal") } c.Set(99) a.Set(0) if !a.Equal(c) { t.Error("Two sets with the same bits set should be equal") } if a.Equal(nil) { t.Error("The sets should be different") } a = New(0) b = New(0) if !a.Equal(b) { t.Error("Two empty set should be equal") } var x *BitSet var y *BitSet z := New(0) if !x.Equal(y) { t.Error("Two nil bitsets should be equal") } if x.Equal(z) { t.Error("Nil receiver bitset should not be equal to non-nil bitset") } } func TestUnion(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) b.Set(i - 1) } for i := uint(100); i < 200; i++ { b.Set(i) } if a.UnionCardinality(b) != 200 { t.Errorf("Union should have 200 bits set, but had %d", a.UnionCardinality(b)) } if a.UnionCardinality(b) != b.UnionCardinality(a) { t.Errorf("Union should be symmetric") } c := a.Union(b) d := b.Union(a) if c.Count() != 200 { t.Errorf("Union should have 200 bits set, but had %d", c.Count()) } if !c.Equal(d) { t.Errorf("Union should be symmetric") } } func TestInPlaceUnion(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) b.Set(i - 1) } for i := uint(100); i < 200; i++ { b.Set(i) } c := a.Clone() c.InPlaceUnion(b) d := b.Clone() d.InPlaceUnion(a) if c.Count() != 200 { t.Errorf("Union should have 200 bits set, but had %d", c.Count()) } if d.Count() != 200 { t.Errorf("Union should have 200 bits set, but had %d", d.Count()) } if !c.Equal(d) { t.Errorf("Union should be symmetric") } } func TestIntersection(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) b.Set(i - 1).Set(i) } for i := uint(100); i < 200; i++ { b.Set(i) } if a.IntersectionCardinality(b) != 50 { t.Errorf("Intersection should have 50 bits set, but had %d", a.IntersectionCardinality(b)) } if a.IntersectionCardinality(b) != b.IntersectionCardinality(a) { t.Errorf("Intersection should be symmetric") } c := a.Intersection(b) d := b.Intersection(a) if c.Count() != 50 { t.Errorf("Intersection should have 50 bits set, but had %d", c.Count()) } if !c.Equal(d) { t.Errorf("Intersection should be symmetric") } } func TestInplaceIntersection(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) b.Set(i - 1).Set(i) } for i := uint(100); i < 200; i++ { b.Set(i) } c := a.Clone() c.InPlaceIntersection(b) d := b.Clone() d.InPlaceIntersection(a) if c.Count() != 50 { t.Errorf("Intersection should have 50 bits set, but had %d", c.Count()) } if d.Count() != 50 { t.Errorf("Intersection should have 50 bits set, but had %d", d.Count()) } if !c.Equal(d) { t.Errorf("Intersection should be symmetric") } } func TestDifference(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) b.Set(i - 1) } for i := uint(100); i < 200; i++ { b.Set(i) } if a.DifferenceCardinality(b) != 50 { t.Errorf("a-b Difference should have 50 bits set, but had %d", a.DifferenceCardinality(b)) } if b.DifferenceCardinality(a) != 150 { t.Errorf("b-a Difference should have 150 bits set, but had %d", b.DifferenceCardinality(a)) } c := a.Difference(b) d := b.Difference(a) if c.Count() != 50 { t.Errorf("a-b Difference should have 50 bits set, but had %d", c.Count()) } if d.Count() != 150 { t.Errorf("b-a Difference should have 150 bits set, but had %d", d.Count()) } if c.Equal(d) { t.Errorf("Difference, here, should not be symmetric") } } func TestInPlaceDifference(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) b.Set(i - 1) } for i := uint(100); i < 200; i++ { b.Set(i) } c := a.Clone() c.InPlaceDifference(b) d := b.Clone() d.InPlaceDifference(a) if c.Count() != 50 { t.Errorf("a-b Difference should have 50 bits set, but had %d", c.Count()) } if d.Count() != 150 { t.Errorf("b-a Difference should have 150 bits set, but had %d", d.Count()) } if c.Equal(d) { t.Errorf("Difference, here, should not be symmetric") } } func TestSymmetricDifference(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) // 01010101010 ... 0000000 b.Set(i - 1).Set(i) // 11111111111111111000000 } for i := uint(100); i < 200; i++ { b.Set(i) } if a.SymmetricDifferenceCardinality(b) != 150 { t.Errorf("a^b Difference should have 150 bits set, but had %d", a.SymmetricDifferenceCardinality(b)) } if b.SymmetricDifferenceCardinality(a) != 150 { t.Errorf("b^a Difference should have 150 bits set, but had %d", b.SymmetricDifferenceCardinality(a)) } c := a.SymmetricDifference(b) d := b.SymmetricDifference(a) if c.Count() != 150 { t.Errorf("a^b Difference should have 150 bits set, but had %d", c.Count()) } if d.Count() != 150 { t.Errorf("b^a Difference should have 150 bits set, but had %d", d.Count()) } if !c.Equal(d) { t.Errorf("SymmetricDifference should be symmetric") } } func TestInPlaceSymmetricDifference(t *testing.T) { a := New(100) b := New(200) for i := uint(1); i < 100; i += 2 { a.Set(i) // 01010101010 ... 0000000 b.Set(i - 1).Set(i) // 11111111111111111000000 } for i := uint(100); i < 200; i++ { b.Set(i) } c := a.Clone() c.InPlaceSymmetricDifference(b) d := b.Clone() d.InPlaceSymmetricDifference(a) if c.Count() != 150 { t.Errorf("a^b Difference should have 150 bits set, but had %d", c.Count()) } if d.Count() != 150 { t.Errorf("b^a Difference should have 150 bits set, but had %d", d.Count()) } if !c.Equal(d) { t.Errorf("SymmetricDifference should be symmetric") } } func TestComplement(t *testing.T) { a := New(50) b := a.Complement() if b.Count() != 50 { t.Errorf("Complement failed, size should be 50, but was %d", b.Count()) } a = New(50) a.Set(10).Set(20).Set(42) b = a.Complement() if b.Count() != 47 { t.Errorf("Complement failed, size should be 47, but was %d", b.Count()) } } func TestIsSuperSet(t *testing.T) { a := New(500) b := New(300) c := New(200) // Setup bitsets // a and b overlap // only c is (strict) super set for i := uint(0); i < 100; i++ { a.Set(i) } for i := uint(50); i < 150; i++ { b.Set(i) } for i := uint(0); i < 200; i++ { c.Set(i) } if a.IsSuperSet(b) { t.Errorf("IsSuperSet fails") } if a.IsSuperSet(c) { t.Errorf("IsSuperSet fails") } if b.IsSuperSet(a) { t.Errorf("IsSuperSet fails") } if b.IsSuperSet(c) { t.Errorf("IsSuperSet fails") } if !c.IsSuperSet(a) { t.Errorf("IsSuperSet fails") } if !c.IsSuperSet(b) { t.Errorf("IsSuperSet fails") } if a.IsStrictSuperSet(b) { t.Errorf("IsStrictSuperSet fails") } if a.IsStrictSuperSet(c) { t.Errorf("IsStrictSuperSet fails") } if b.IsStrictSuperSet(a) { t.Errorf("IsStrictSuperSet fails") } if b.IsStrictSuperSet(c) { t.Errorf("IsStrictSuperSet fails") } if !c.IsStrictSuperSet(a) { t.Errorf("IsStrictSuperSet fails") } if !c.IsStrictSuperSet(b) { t.Errorf("IsStrictSuperSet fails") } } func TestDumpAsBits(t *testing.T) { a := New(10).Set(10) astr := "0000000000000000000000000000000000000000000000000000010000000000." if a.DumpAsBits() != astr { t.Errorf("DumpAsBits failed, output should be \"%s\" but was \"%s\"", astr, a.DumpAsBits()) } var b BitSet // zero value (b.set == nil) bstr := "." if b.DumpAsBits() != bstr { t.Errorf("DumpAsBits failed, output should be \"%s\" but was \"%s\"", bstr, b.DumpAsBits()) } } func TestMarshalUnmarshalBinary(t *testing.T) { a := New(1010).Set(10).Set(1001) b := new(BitSet) copyBinary(t, a, b) // BitSets must be equal after marshalling and unmarshalling if !a.Equal(b) { t.Error("Bitsets are not equal:\n\t", a.DumpAsBits(), "\n\t", b.DumpAsBits()) return } aSetBit := uint(128) a = New(256).Set(aSetBit) aExpectedMarshaledSize := 8 /* length: uint64 */ + 4 * 8 /* set : [4]uint64 */ aMarshaled, err := a.MarshalBinary() if err != nil || aExpectedMarshaledSize != len(aMarshaled) || aExpectedMarshaledSize != a.BinaryStorageSize() { t.Error("MarshalBinary failed to produce expected (", aExpectedMarshaledSize , ") number of bytes") return } shiftAmount := uint(72) // https://github.com/bits-and-blooms/bitset/issues/114 for i := uint(0) ; i < shiftAmount; i++ { a.DeleteAt(0) } aExpectedMarshaledSize = 8 /* length: uint64 */ + 3 * 8 /* set : [3]uint64 */ aMarshaled, err = a.MarshalBinary() if err != nil || aExpectedMarshaledSize != len(aMarshaled) || aExpectedMarshaledSize != a.BinaryStorageSize() { t.Error("MarshalBinary failed to produce expected (", aExpectedMarshaledSize , ") number of bytes") return } copyBinary(t, a, b) if b.Len() != 256 - shiftAmount || !b.Test(aSetBit - shiftAmount) { t.Error("Shifted bitset is not copied correctly") } } func TestMarshalUnmarshalBinaryByLittleEndian(t *testing.T) { LittleEndian() defer func() { // Revert when done. binaryOrder = binary.BigEndian }() a := New(1010).Set(10).Set(1001) b := new(BitSet) copyBinary(t, a, b) // BitSets must be equal after marshalling and unmarshalling if !a.Equal(b) { t.Error("Bitsets are not equal:\n\t", a.DumpAsBits(), "\n\t", b.DumpAsBits()) return } } func copyBinary(t *testing.T, from encoding.BinaryMarshaler, to encoding.BinaryUnmarshaler) { data, err := from.MarshalBinary() if err != nil { t.Errorf(err.Error()) return } err = to.UnmarshalBinary(data) if err != nil { t.Errorf(err.Error()) return } } func TestMarshalUnmarshalJSON(t *testing.T) { a := New(1010).Set(10).Set(1001) data, err := json.Marshal(a) if err != nil { t.Errorf(err.Error()) return } b := new(BitSet) err = json.Unmarshal(data, b) if err != nil { t.Errorf(err.Error()) return } // Bitsets must be equal after marshalling and unmarshalling if !a.Equal(b) { t.Error("Bitsets are not equal:\n\t", a.DumpAsBits(), "\n\t", b.DumpAsBits()) return } } func TestMarshalUnmarshalJSONWithTrailingData(t *testing.T) { a := New(1010).Set(10).Set(1001) data, err := json.Marshal(a) if err != nil { t.Errorf(err.Error()) return } // appending some noise data = data[:len(data)-3] // remove " data = append(data, []byte(`AAAAAAAAAA"`)...) b := new(BitSet) err = json.Unmarshal(data, b) if err != nil { t.Errorf(err.Error()) return } // Bitsets must be equal after marshalling and unmarshalling // Do not over-reading when unmarshalling if !a.Equal(b) { t.Error("Bitsets are not equal:\n\t", a.DumpAsBits(), "\n\t", b.DumpAsBits()) return } } func TestMarshalUnmarshalJSONByStdEncoding(t *testing.T) { Base64StdEncoding() a := New(1010).Set(10).Set(1001) data, err := json.Marshal(a) if err != nil { t.Errorf(err.Error()) return } b := new(BitSet) err = json.Unmarshal(data, b) if err != nil { t.Errorf(err.Error()) return } // Bitsets must be equal after marshalling and unmarshalling if !a.Equal(b) { t.Error("Bitsets are not equal:\n\t", a.DumpAsBits(), "\n\t", b.DumpAsBits()) return } } func TestSafeSet(t *testing.T) { b := new(BitSet) c := b.safeSet() outType := fmt.Sprintf("%T", c) expType := "[]uint64" if outType != expType { t.Error("Expecting type: ", expType, ", gotf:", outType) return } if len(c) != 0 { t.Error("The slice should be empty") return } } func TestSetBitsetFrom(t *testing.T) { u := []uint64{2, 3, 5, 7, 11} b := new(BitSet) b.SetBitsetFrom(u) outType := fmt.Sprintf("%T", b) expType := "*bitset.BitSet" if outType != expType { t.Error("Expecting type: ", expType, ", gotf:", outType) return } } func TestIssue116(t *testing.T) { a := []uint64{2, 3, 5, 7, 11} b := []uint64{2, 3, 5, 7, 11, 0, 1} bitset1 := FromWithLength(320, a) bitset2 := FromWithLength(320, b) if !bitset1.Equal(bitset2) || !bitset2.Equal(bitset1) { t.Error("Bitsets should be equal irrespective of the underlying capacity") } } func TestFrom(t *testing.T) { u := []uint64{2, 3, 5, 7, 11} b := From(u) outType := fmt.Sprintf("%T", b) expType := "*bitset.BitSet" if outType != expType { t.Error("Expecting type: ", expType, ", gotf:", outType) return } } func TestBytes(t *testing.T) { b := new(BitSet) c := b.Bytes() outType := fmt.Sprintf("%T", c) expType := "[]uint64" if outType != expType { t.Error("Expecting type: ", expType, ", gotf:", outType) return } if len(c) != 0 { t.Error("The slice should be empty") return } } func TestCap(t *testing.T) { c := Cap() if c <= 0 { t.Error("The uint capacity should be >= 0") return } } func TestWordsNeededLong(t *testing.T) { i := Cap() out := wordsNeeded(i) if out <= 0 { t.Error("Unexpected value: ", out) return } } func TestTestTooLong(t *testing.T) { b := new(BitSet) if b.Test(1) { t.Error("Unexpected value: true") return } } func TestClearTooLong(t *testing.T) { b := new(BitSet) c := b.Clear(1) if b != c { t.Error("Unexpected value") return } } func TestClearAll(t *testing.T) { u := []uint64{2, 3, 5, 7, 11} b := From(u) c := b.ClearAll() if c.length != 320 { t.Error("Unexpected length: ", b.length) return } if c.Test(0) || c.Test(1) || c.Test(2) || c.Test(3) || c.Test(4) || c.Test(5) { t.Error("All bits should be unset") return } } func TestFlip(t *testing.T) { b := new(BitSet) c := b.Flip(11) if c.length != 12 { t.Error("Unexpected value: ", c.length) return } d := c.Flip(7) if d.length != 12 { t.Error("Unexpected value: ", d.length) return } } func TestFlipRange(t *testing.T) { b := new(BitSet) b.Set(1).Set(3).Set(5).Set(7).Set(9).Set(11).Set(13).Set(15) c := b.FlipRange(4, 25) if c.length != 25 { t.Error("Unexpected value: ", c.length) return } d := c.FlipRange(8, 24) if d.length != 25 { t.Error("Unexpected value: ", d.length) return } // for i := uint(0); i < 256; i++ { for j := uint(0); j <= i; j++ { bits := New(i) bits.FlipRange(0, j) c := bits.Count() if c != j { t.Error("Unexpected value: ", c, " expected: ", j) return } } } } func TestCopy(t *testing.T) { a := New(10) if a.Copy(nil) != 0 { t.Error("No values should be copied") return } a = New(10) b := New(20) if a.Copy(b) != 10 { t.Error("Unexpected value") return } } func TestCopyUnaligned(t *testing.T) { a := New(16) a.FlipRange(0, 16) b := New(1) a.Copy(b) if b.Count() > b.Len() { t.Errorf("targets copied set count (%d) should never be larger than target's length (%d)", b.Count(), b.Len()) } if !b.Test(0) { t.Errorf("first bit should still be set in copy: %+v", b) } // Test a more complex scenario with a mix of bits set in the unaligned space to verify no bits are lost. a = New(32) a.Set(0).Set(3).Set(4).Set(16).Set(17).Set(29).Set(31) b = New(19) a.Copy(b) const expectedCount = 5 if b.Count() != expectedCount { t.Errorf("targets copied set count: %d, want %d", b.Count(), expectedCount) } if !(b.Test(0) && b.Test(3) && b.Test(4) && b.Test(16) && b.Test(17)) { t.Errorf("expected set bits are not set: %+v", b) } } func TestCopyFull(t *testing.T) { a := New(10) b := &BitSet{} a.CopyFull(b) if b.length != a.length || len(b.set) != len(a.set) { t.Error("Expected full length copy") return } for i, v := range a.set { if v != b.set[i] { t.Error("Unexpected value") return } } } func TestNextSetError(t *testing.T) { b := new(BitSet) c, d := b.NextSet(1) if c != 0 || d { t.Error("Unexpected values") return } } func TestDeleteWithBitStrings(t *testing.T) { type testCase struct { input []string deleteIdx uint expected []string } testCases := []testCase{ { input: []string{ "1110000000000000000000000000000000000000000000000000000000000001", }, deleteIdx: uint(63), expected: []string{ "0110000000000000000000000000000000000000000000000000000000000001", }, }, { input: []string{ "1000000000000000000000000000000000000000000000000000000000010101", }, deleteIdx: uint(0), expected: []string{ "0100000000000000000000000000000000000000000000000000000000001010", }, }, { input: []string{ "0000000000000000000000000000000000000000000000000000000000111000", }, deleteIdx: uint(4), expected: []string{ "0000000000000000000000000000000000000000000000000000000000011000", }, }, { input: []string{ "1000000000000000000000000000000000000000000000000000000000000001", "1010000000000000000000000000000000000000000000000000000000000001", }, deleteIdx: uint(63), expected: []string{ "1000000000000000000000000000000000000000000000000000000000000001", "0101000000000000000000000000000000000000000000000000000000000000", }, }, { input: []string{ "1000000000000000000000000000000000000000000000000000000000000000", "1000000000000000000000000000000000000000000000000000000000000001", "1000000000000000000000000000000000000000000000000000000000000001", }, deleteIdx: uint(64), expected: []string{ "1000000000000000000000000000000000000000000000000000000000000000", "1100000000000000000000000000000000000000000000000000000000000000", "0100000000000000000000000000000000000000000000000000000000000000", }, }, { input: []string{ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", }, deleteIdx: uint(256), expected: []string{ "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000001", "0000000000000000000000000000000000000000000000000000000000000000", }, }, } for _, tc := range testCases { var input []uint64 for _, inputElement := range tc.input { parsed, _ := strconv.ParseUint(inputElement, 2, 64) input = append(input, parsed) } var expected []uint64 for _, expectedElement := range tc.expected { parsed, _ := strconv.ParseUint(expectedElement, 2, 64) expected = append(expected, parsed) } b := From(input) b.DeleteAt(tc.deleteIdx) if len(b.set) != len(expected) { t.Errorf("Length of sets expected to be %d, but was %d", len(expected), len(b.set)) return } for i := range b.set { if b.set[i] != expected[i] { t.Errorf("Unexpected output\nExpected: %b\nGot: %b", expected[i], b.set[i]) return } } } } func TestDeleteWithBitSetInstance(t *testing.T) { length := uint(256) bitSet := New(length) // the indexes that get set in the bit set indexesToSet := []uint{0, 1, 126, 127, 128, 129, 170, 171, 200, 201, 202, 203, 255} // the position we delete from the bitset deleteAt := uint(127) // the indexes that we expect to be set after the delete expectedToBeSet := []uint{0, 1, 126, 127, 128, 169, 170, 199, 200, 201, 202, 254} expected := make(map[uint]struct{}) for _, index := range expectedToBeSet { expected[index] = struct{}{} } for _, index := range indexesToSet { bitSet.Set(index) } bitSet.DeleteAt(deleteAt) for i := uint(0); i < length; i++ { if _, ok := expected[i]; ok { if !bitSet.Test(i) { t.Errorf("Expected index %d to be set, but wasn't", i) } } else { if bitSet.Test(i) { t.Errorf("Expected index %d to not be set, but was", i) } } } } func TestWriteTo(t *testing.T) { const length = 9585 const oneEvery = 97 addBuf := []byte(`12345678`) bs := New(length) // Add some bits for i := uint(0); i < length; i += oneEvery { bs = bs.Set(i) } var buf bytes.Buffer n, err := bs.WriteTo(&buf) if err != nil { t.Fatal(err) } wantSz := buf.Len() // Size of the serialized data in bytes. if n != int64(wantSz) { t.Errorf("want write size to be %d, got %d", wantSz, n) } buf.Write(addBuf) // Add additional data on stream. // Generate test input for regression tests: if false { gzout := bytes.NewBuffer(nil) gz, err := gzip.NewWriterLevel(gzout, 9) if err != nil { t.Fatal(err) } gz.Write(buf.Bytes()) gz.Close() t.Log("Encoded:", base64.StdEncoding.EncodeToString(gzout.Bytes())) } // Read back. bs = New(length) n, err = bs.ReadFrom(&buf) if err != nil { t.Fatal(err) } if n != int64(wantSz) { t.Errorf("want read size to be %d, got %d", wantSz, n) } // Check bits for i := uint(0); i < length; i += oneEvery { if !bs.Test(i) { t.Errorf("bit %d was not set", i) } } more, err := io.ReadAll(&buf) if err != nil { t.Fatal(err) } if !bytes.Equal(more, addBuf) { t.Fatalf("extra mismatch. got %v, want %v", more, addBuf) } } type inCompleteRetBufReader struct { returnEvery int64 reader io.Reader offset int64 } func (ir *inCompleteRetBufReader) Read(b []byte) (n int, err error) { if ir.returnEvery > 0 { maxRead := ir.returnEvery - (ir.offset % ir.returnEvery) if len(b) > int(maxRead) { b = b[:maxRead] } } n, err = ir.reader.Read(b) ir.offset += int64(n) return } func TestReadFrom(t *testing.T) { addBuf := []byte(`12345678`) // Bytes after stream tests := []struct { length uint oneEvery uint input string // base64+gzipped wantErr error returnEvery int64 }{ { length: 9585, oneEvery: 97, input: "H4sIAAAAAAAC/2IAA9VCCM3AyMDAwMSACVgYGBg4sIgLMDAwKGARd2BgYGjAFB41noDx6IAJajw64IAajw4UoMajg4ZR4/EaP5pQh1g+MDQyNjE1M7cABAAA//9W5OoOwAQAAA==", returnEvery: 127, }, { length: 1337, oneEvery: 42, input: "H4sIAAAAAAAC/2IAA1ZLBgYWEIPRAUQKgJkMcCZYisEBzkSSYkSTYqCxAYZGxiamZuYWgAAAAP//D0wyWbgAAAA=", }, { length: 1337, // Truncated input. oneEvery: 42, input: "H4sIAAAAAAAC/2IAA9VCCM3AyMDAwARmAQIAAP//vR3xdRkAAAA=", wantErr: io.ErrUnexpectedEOF, }, { length: 1337, // Empty input. oneEvery: 42, input: "H4sIAAAAAAAC/wEAAP//AAAAAAAAAAA=", wantErr: io.ErrUnexpectedEOF, }, } for i, test := range tests { t.Run(fmt.Sprint(i), func(t *testing.T) { fatalErr := func(err error) { t.Helper() if err != nil { t.Fatal(err) } } var buf bytes.Buffer b, err := base64.StdEncoding.DecodeString(test.input) fatalErr(err) gz, err := gzip.NewReader(bytes.NewBuffer(b)) fatalErr(err) _, err = io.Copy(&buf, gz) fatalErr(err) fatalErr(gz.Close()) bs := New(test.length) _, err = bs.ReadFrom(&inCompleteRetBufReader{returnEvery: test.returnEvery, reader: &buf}) if err != nil { if errors.Is(err, test.wantErr) { // Correct, nothing more we can test. return } t.Fatalf("did not get expected error %v, got %v", test.wantErr, err) } else { if test.wantErr != nil { t.Fatalf("did not get expected error %v", test.wantErr) } } fatalErr(err) // Test if correct bits are set. for i := uint(0); i < test.length; i++ { want := i%test.oneEvery == 0 got := bs.Test(i) if want != got { t.Errorf("bit %d was %v, should be %v", i, got, want) } } more, err := io.ReadAll(&buf) fatalErr(err) if !bytes.Equal(more, addBuf) { t.Errorf("extra mismatch. got %v, want %v", more, addBuf) } }) } } bitset-1.5.0/go.mod000066400000000000000000000000621436377705000141270ustar00rootroot00000000000000module github.com/bits-and-blooms/bitset go 1.14 bitset-1.5.0/go.sum000066400000000000000000000000001436377705000141440ustar00rootroot00000000000000bitset-1.5.0/popcnt.go000066400000000000000000000017741436377705000146660ustar00rootroot00000000000000package bitset // bit population count, take from // https://code.google.com/p/go/issues/detail?id=4988#c11 // credit: https://code.google.com/u/arnehormann/ func popcount(x uint64) (n uint64) { x -= (x >> 1) & 0x5555555555555555 x = (x>>2)&0x3333333333333333 + x&0x3333333333333333 x += x >> 4 x &= 0x0f0f0f0f0f0f0f0f x *= 0x0101010101010101 return x >> 56 } func popcntSliceGo(s []uint64) uint64 { cnt := uint64(0) for _, x := range s { cnt += popcount(x) } return cnt } func popcntMaskSliceGo(s, m []uint64) uint64 { cnt := uint64(0) for i := range s { cnt += popcount(s[i] &^ m[i]) } return cnt } func popcntAndSliceGo(s, m []uint64) uint64 { cnt := uint64(0) for i := range s { cnt += popcount(s[i] & m[i]) } return cnt } func popcntOrSliceGo(s, m []uint64) uint64 { cnt := uint64(0) for i := range s { cnt += popcount(s[i] | m[i]) } return cnt } func popcntXorSliceGo(s, m []uint64) uint64 { cnt := uint64(0) for i := range s { cnt += popcount(s[i] ^ m[i]) } return cnt } bitset-1.5.0/popcnt_19.go000066400000000000000000000013561436377705000151730ustar00rootroot00000000000000// +build go1.9 package bitset import "math/bits" func popcntSlice(s []uint64) uint64 { var cnt int for _, x := range s { cnt += bits.OnesCount64(x) } return uint64(cnt) } func popcntMaskSlice(s, m []uint64) uint64 { var cnt int for i := range s { cnt += bits.OnesCount64(s[i] &^ m[i]) } return uint64(cnt) } func popcntAndSlice(s, m []uint64) uint64 { var cnt int for i := range s { cnt += bits.OnesCount64(s[i] & m[i]) } return uint64(cnt) } func popcntOrSlice(s, m []uint64) uint64 { var cnt int for i := range s { cnt += bits.OnesCount64(s[i] | m[i]) } return uint64(cnt) } func popcntXorSlice(s, m []uint64) uint64 { var cnt int for i := range s { cnt += bits.OnesCount64(s[i] ^ m[i]) } return uint64(cnt) } bitset-1.5.0/popcnt_amd64.go000066400000000000000000000022371436377705000156540ustar00rootroot00000000000000// +build !go1.9 // +build amd64,!appengine package bitset // *** the following functions are defined in popcnt_amd64.s //go:noescape func hasAsm() bool // useAsm is a flag used to select the GO or ASM implementation of the popcnt function var useAsm = hasAsm() //go:noescape func popcntSliceAsm(s []uint64) uint64 //go:noescape func popcntMaskSliceAsm(s, m []uint64) uint64 //go:noescape func popcntAndSliceAsm(s, m []uint64) uint64 //go:noescape func popcntOrSliceAsm(s, m []uint64) uint64 //go:noescape func popcntXorSliceAsm(s, m []uint64) uint64 func popcntSlice(s []uint64) uint64 { if useAsm { return popcntSliceAsm(s) } return popcntSliceGo(s) } func popcntMaskSlice(s, m []uint64) uint64 { if useAsm { return popcntMaskSliceAsm(s, m) } return popcntMaskSliceGo(s, m) } func popcntAndSlice(s, m []uint64) uint64 { if useAsm { return popcntAndSliceAsm(s, m) } return popcntAndSliceGo(s, m) } func popcntOrSlice(s, m []uint64) uint64 { if useAsm { return popcntOrSliceAsm(s, m) } return popcntOrSliceGo(s, m) } func popcntXorSlice(s, m []uint64) uint64 { if useAsm { return popcntXorSliceAsm(s, m) } return popcntXorSliceGo(s, m) } bitset-1.5.0/popcnt_amd64.s000066400000000000000000000033241436377705000155070ustar00rootroot00000000000000// +build !go1.9 // +build amd64,!appengine TEXT ·hasAsm(SB),4,$0-1 MOVQ $1, AX CPUID SHRQ $23, CX ANDQ $1, CX MOVB CX, ret+0(FP) RET #define POPCNTQ_DX_DX BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0xd2 TEXT ·popcntSliceAsm(SB),4,$0-32 XORQ AX, AX MOVQ s+0(FP), SI MOVQ s_len+8(FP), CX TESTQ CX, CX JZ popcntSliceEnd popcntSliceLoop: BYTE $0xf3; BYTE $0x48; BYTE $0x0f; BYTE $0xb8; BYTE $0x16 // POPCNTQ (SI), DX ADDQ DX, AX ADDQ $8, SI LOOP popcntSliceLoop popcntSliceEnd: MOVQ AX, ret+24(FP) RET TEXT ·popcntMaskSliceAsm(SB),4,$0-56 XORQ AX, AX MOVQ s+0(FP), SI MOVQ s_len+8(FP), CX TESTQ CX, CX JZ popcntMaskSliceEnd MOVQ m+24(FP), DI popcntMaskSliceLoop: MOVQ (DI), DX NOTQ DX ANDQ (SI), DX POPCNTQ_DX_DX ADDQ DX, AX ADDQ $8, SI ADDQ $8, DI LOOP popcntMaskSliceLoop popcntMaskSliceEnd: MOVQ AX, ret+48(FP) RET TEXT ·popcntAndSliceAsm(SB),4,$0-56 XORQ AX, AX MOVQ s+0(FP), SI MOVQ s_len+8(FP), CX TESTQ CX, CX JZ popcntAndSliceEnd MOVQ m+24(FP), DI popcntAndSliceLoop: MOVQ (DI), DX ANDQ (SI), DX POPCNTQ_DX_DX ADDQ DX, AX ADDQ $8, SI ADDQ $8, DI LOOP popcntAndSliceLoop popcntAndSliceEnd: MOVQ AX, ret+48(FP) RET TEXT ·popcntOrSliceAsm(SB),4,$0-56 XORQ AX, AX MOVQ s+0(FP), SI MOVQ s_len+8(FP), CX TESTQ CX, CX JZ popcntOrSliceEnd MOVQ m+24(FP), DI popcntOrSliceLoop: MOVQ (DI), DX ORQ (SI), DX POPCNTQ_DX_DX ADDQ DX, AX ADDQ $8, SI ADDQ $8, DI LOOP popcntOrSliceLoop popcntOrSliceEnd: MOVQ AX, ret+48(FP) RET TEXT ·popcntXorSliceAsm(SB),4,$0-56 XORQ AX, AX MOVQ s+0(FP), SI MOVQ s_len+8(FP), CX TESTQ CX, CX JZ popcntXorSliceEnd MOVQ m+24(FP), DI popcntXorSliceLoop: MOVQ (DI), DX XORQ (SI), DX POPCNTQ_DX_DX ADDQ DX, AX ADDQ $8, SI ADDQ $8, DI LOOP popcntXorSliceLoop popcntXorSliceEnd: MOVQ AX, ret+48(FP) RET bitset-1.5.0/popcnt_amd64_test.go000066400000000000000000000042141436377705000167100ustar00rootroot00000000000000// +build !go1.9 // +build amd64,!appengine // This file tests the popcnt funtions package bitset import ( "testing" ) func TestPopcntSliceCond(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} oldUseAsm := useAsm defer func() { useAsm = oldUseAsm }() useAsm = false resGo := popcntSlice(s) useAsm = (true && oldUseAsm) resAsm := popcntSlice(s) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestPopcntMaskSliceCond(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} oldUseAsm := useAsm defer func() { useAsm = oldUseAsm }() useAsm = false resGo := popcntMaskSlice(s, m) useAsm = (true && oldUseAsm) resAsm := popcntMaskSlice(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestPopcntAndSliceCond(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} oldUseAsm := useAsm defer func() { useAsm = oldUseAsm }() useAsm = false resGo := popcntAndSlice(s, m) useAsm = (true && oldUseAsm) resAsm := popcntAndSlice(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestPopcntOrSliceCond(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} oldUseAsm := useAsm defer func() { useAsm = oldUseAsm }() useAsm = false resGo := popcntOrSlice(s, m) useAsm = (true && oldUseAsm) resAsm := popcntOrSlice(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestPopcntXorSliceCond(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} oldUseAsm := useAsm defer func() { useAsm = oldUseAsm }() useAsm = false resGo := popcntXorSlice(s, m) useAsm = (true && oldUseAsm) resAsm := popcntXorSlice(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } bitset-1.5.0/popcnt_cmp_test.go000066400000000000000000000032421436377705000165540ustar00rootroot00000000000000// +build !go1.9 // +build amd64,!appengine // This file tests the popcnt funtions package bitset import ( "testing" ) func TestComparePopcntSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} resGo := popcntSliceGo(s) resAsm := popcntSliceAsm(s) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestComparePopcntMaskSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} resGo := popcntMaskSliceGo(s, m) resAsm := popcntMaskSliceAsm(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestComparePopcntAndSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} resGo := popcntAndSliceGo(s, m) resAsm := popcntAndSliceAsm(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestComparePopcntOrSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} resGo := popcntOrSliceGo(s, m) resAsm := popcntOrSliceAsm(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } func TestComparePopcntXorSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} resGo := popcntXorSliceGo(s, m) resAsm := popcntXorSliceAsm(s, m) if resGo != resAsm { t.Errorf("The implementations are different: GO %d != ASM %d", resGo, resAsm) } } bitset-1.5.0/popcnt_generic.go000066400000000000000000000006661436377705000163610ustar00rootroot00000000000000// +build !go1.9 // +build !amd64 appengine package bitset func popcntSlice(s []uint64) uint64 { return popcntSliceGo(s) } func popcntMaskSlice(s, m []uint64) uint64 { return popcntMaskSliceGo(s, m) } func popcntAndSlice(s, m []uint64) uint64 { return popcntAndSliceGo(s, m) } func popcntOrSlice(s, m []uint64) uint64 { return popcntOrSliceGo(s, m) } func popcntXorSlice(s, m []uint64) uint64 { return popcntXorSliceGo(s, m) } bitset-1.5.0/popcnt_go18_test.go000066400000000000000000000024631436377705000165570ustar00rootroot00000000000000// This file tests the popcnt funtions package bitset import ( "testing" ) func TestPopcntSliceGo(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} res := popcntSliceGo(s) const l uint64 = 27 if res != l { t.Errorf("Wrong popcount %d != %d", res, l) } } func TestPopcntMaskSliceGo(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntMaskSliceGo(s, m) const l uint64 = 9 if res != l { t.Errorf("Wrong mask %d != %d", res, l) } } func TestPopcntAndSliceGo(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntAndSliceGo(s, m) const l uint64 = 18 if res != l { t.Errorf("Wrong And %d != %d", res, l) } } func TestPopcntOrSliceGo(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntOrSliceGo(s, m) const l uint64 = 50 if res != l { t.Errorf("Wrong OR %d != %d", res, l) } } func TestPopcntXorSliceGo(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntXorSliceGo(s, m) const l uint64 = 32 if res != l { t.Errorf("Wrong OR %d != %d", res, l) } } bitset-1.5.0/popcnt_test.go000066400000000000000000000024371436377705000157220ustar00rootroot00000000000000// This file tests the popcnt funtions package bitset import ( "testing" ) func TestPopcntSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} res := popcntSlice(s) const l uint64 = 27 if res != l { t.Errorf("Wrong popcount %d != %d", res, l) } } func TestPopcntMaskSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntMaskSlice(s, m) const l uint64 = 9 if res != l { t.Errorf("Wrong mask %d != %d", res, l) } } func TestPopcntAndSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntAndSlice(s, m) const l uint64 = 18 if res != l { t.Errorf("Wrong And %d != %d", res, l) } } func TestPopcntOrSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntOrSlice(s, m) const l uint64 = 50 if res != l { t.Errorf("Wrong OR %d != %d", res, l) } } func TestPopcntXorSlice(t *testing.T) { s := []uint64{2, 3, 5, 7, 11, 13, 17, 19, 23, 29} m := []uint64{31, 37, 41, 43, 47, 53, 59, 61, 67, 71} res := popcntXorSlice(s, m) const l uint64 = 32 if res != l { t.Errorf("Wrong OR %d != %d", res, l) } } bitset-1.5.0/trailing_zeros_18.go000066400000000000000000000006321436377705000167160ustar00rootroot00000000000000// +build !go1.9 package bitset var deBruijn = [...]byte{ 0, 1, 56, 2, 57, 49, 28, 3, 61, 58, 42, 50, 38, 29, 17, 4, 62, 47, 59, 36, 45, 43, 51, 22, 53, 39, 33, 30, 24, 18, 12, 5, 63, 55, 48, 27, 60, 41, 37, 16, 46, 35, 44, 21, 52, 32, 23, 11, 54, 26, 40, 15, 34, 20, 31, 10, 25, 14, 19, 9, 13, 8, 7, 6, } func trailingZeroes64(v uint64) uint { return uint(deBruijn[((v&-v)*0x03f79d71b4ca8b09)>>58]) } bitset-1.5.0/trailing_zeros_19.go000066400000000000000000000002041436377705000167120ustar00rootroot00000000000000// +build go1.9 package bitset import "math/bits" func trailingZeroes64(v uint64) uint { return uint(bits.TrailingZeros64(v)) }