├── README.md ├── bench_test.go ├── bitset.go ├── bitset_test.go ├── examples_test.go └── property_test.go /README.md: -------------------------------------------------------------------------------- 1 | # BitSet data structure 2 | *bitset* is a library written in [golang](https://golang.org) implementing a BitSet data structure. 3 | 4 | # Usage 5 | First install the library with 6 | ``` 7 | go get xojoc.pw/bitset 8 | ``` 9 | 10 | ...then run... 11 | 12 | ```` 13 | go test 14 | `````` 15 | 16 | if something fails open an issue. 17 | 18 | As an example let's list all the composite numbers below 10: 19 | ``` 20 | package main 21 | 22 | import ( 23 | "fmt" 24 | "xojoc.pw/bitset" 25 | ) 26 | 27 | func main() { 28 | c := &bitset.BitSet{} 29 | // Set all prime numbers to true. 30 | c.Set(2) 31 | c.Set(3) 32 | c.Set(5) 33 | c.Set(7) 34 | c.ToggleRange(1,10+1) 35 | for i := 1; i < c.Len(); i++ { 36 | if c.Get(i) { 37 | fmt.Printf("%d is composite\n", i) 38 | } 39 | } 40 | } 41 | ``` 42 | Output: 43 | ``` 44 | 1 is composite 45 | 4 is composite 46 | 6 is composite 47 | 8 is composite 48 | 9 is composite 49 | 10 is composite 50 | ``` 51 | see [godoc](https://godoc.org/xojoc.pw/bitset) for the complete documentation. 52 | 53 | # Why? 54 | 55 | * Great and stable API 56 | * Lots of tests, [fuzzing](https://github.com/google/gofuzz) and [quicktesting](https://golang.org/pkg/testing/quick/)! 57 | * [Good documentation](https://godoc.org/xojoc.pw/bitset) with lots of examples. 58 | 59 | Also see [why use xojoc.pw/bitset and not math/big](https://typed.pw/a/29). 60 | 61 | # Who? 62 | *bitset* was written by [Alexandru Cojocaru](https://xojoc.pw). 63 | 64 | # [Donate!](https://xojoc.pw/donate) 65 | 66 | # License 67 | *bitset* is [Free Software](https://www.gnu.org/philosophy/free-sw.html) and in the Public Domain. No warranty. 68 | -------------------------------------------------------------------------------- /bench_test.go: -------------------------------------------------------------------------------- 1 | // Written by http://xojoc.pw. Public Domain. 2 | 3 | package bitset 4 | 5 | import ( 6 | "math/big" 7 | "testing" 8 | ) 9 | 10 | func Benchmark(b *testing.B) { 11 | } 12 | 13 | func BenchmarkClone(b *testing.B) { 14 | s := &BitSet{} 15 | s.Set(1000 * 100 * 1000) 16 | for n := 0; n < b.N; n++ { 17 | n := s.Clone() 18 | n.Get(0) 19 | } 20 | } 21 | func BenchmarkSet(b *testing.B) { 22 | len := 1000 23 | s := &BitSet{} 24 | for n := 0; n < b.N; n++ { 25 | for i := 0; i < len; i++ { 26 | s.Set(i) 27 | } 28 | } 29 | } 30 | func BenchmarkSetBig(b *testing.B) { 31 | len := 1000 32 | s := big.NewInt(0) 33 | for n := 0; n < b.N; n++ { 34 | for i := 0; i < len; i++ { 35 | s.SetBit(s, i, 1) 36 | } 37 | } 38 | } 39 | func BenchmarkSetHigh(b *testing.B) { 40 | s := &BitSet{} 41 | i := 1 42 | for n := 0; n < b.N; n++ { 43 | s.Set(100 * 1000 * 1000 * i) 44 | i++ 45 | } 46 | } 47 | func BenchmarkSetRange(b *testing.B) { 48 | s := &BitSet{} 49 | s.SetRange(0, 100*1000*1000) 50 | } 51 | func BenchmarkClearRange(b *testing.B) { 52 | s := &BitSet{} 53 | s.SetRange(0, 100*1000*1000) 54 | s.ClearRange(0, 100*1000*1000) 55 | } 56 | func BenchmarkToggleRange(b *testing.B) { 57 | s := &BitSet{} 58 | s.SetRange(50*1000*1000, 100*1000*1000) 59 | s.ToggleRange(0, 100*1000*1000) 60 | } 61 | func BenchmarkGetEmpty(b *testing.B) { 62 | s := &BitSet{} 63 | len := 1000 * 1000 64 | for n := 0; n < b.N; n++ { 65 | for i := 0; i < len; i++ { 66 | s.Get(i) 67 | } 68 | } 69 | } 70 | func BenchmarkGetEmptyBig(b *testing.B) { 71 | s := big.NewInt(0) 72 | len := 1000 * 1000 73 | s.SetBit(s, len-1, 1) 74 | for n := 0; n < b.N; n++ { 75 | for i := 0; i < len; i++ { 76 | s.Bit(i) 77 | } 78 | } 79 | } 80 | 81 | /* 82 | func BenchmarkUnion(b *testing.B) { 83 | a := New(1000) 84 | c := New(1000) 85 | for n := 0; n < b.N; n++ { 86 | a.Union(c) 87 | } 88 | } 89 | 90 | func BenchmarkUnionBig(b *testing.B) { 91 | len := 1000 92 | a := big.NewInt(0) 93 | a.SetBit(a, len-1, 1) 94 | c := big.NewInt(0) 95 | c.SetBit(c, len-1, 1) 96 | for n := 0; n < b.N; n++ { 97 | a.Or(a, c) 98 | } 99 | } 100 | 101 | func BenchmarkString(b *testing.B) { 102 | a := New(100000) 103 | for n := 0; n < b.N; n++ { 104 | _ = a.String() 105 | } 106 | } 107 | */ 108 | -------------------------------------------------------------------------------- /bitset.go: -------------------------------------------------------------------------------- 1 | // Written by https://xojoc.pw. Public Domain. 2 | 3 | // Package bitset implements a BitSet data structure. 4 | // 5 | // A BitSet is a mapping between unsigned integers and boolean values. 6 | // You can Set, Clear, Toggle single bits or Union, Intersect, Difference sets. 7 | // 8 | // Indexes start at 0. Ranges have the first index included and the second 9 | // one excluded (like go slices). 10 | // 11 | // BitSets are dynamicaly-sized they grow and shrink automatically. 12 | // 13 | // All methods modify their receiver in place to avoid futile memory usage. 14 | // If you want to keep the original BitSet simply Clone it. 15 | // 16 | // Use Clone when you want to copy a BitSet. Plese note that this will 17 | // *not* work: 18 | // var x BitSet 19 | // x.Add(1) 20 | // y := x // wrong! use Clone 21 | // y.Add(2) 22 | // 23 | // 24 | // If you wonder why you should use this package and not math/big see: 25 | // https://typed.pw/a/29 26 | package bitset // import "xojoc.pw/bitset" 27 | 28 | // TODO: intersects next/prev zero 29 | // TODO: fmt.Formatter 30 | 31 | // Bit tricks: http://graphics.stanford.edu/~seander/bithacks.html 32 | 33 | // Bits per word 34 | const bpw int = 8 << (^uint(0)>>8&1 + ^uint(0)>>16&1 + ^uint(0)>>32&1) 35 | 36 | // BitSet data structure. 37 | type BitSet struct { 38 | // underlying vector 39 | v []uint 40 | } 41 | 42 | // All the functions below assume the bitsets in input 43 | // have no trailing zero bytes. Functions that clear 44 | // bits (Clear, Toggle, Intersect, Difference, SymmetricDifference) 45 | // must call this function, which removes all the trailing zero bytes. 46 | func (s *BitSet) autoShrink() { 47 | for i := len(s.v) - 1; i >= 0; i-- { 48 | if s.v[i] == 0 { 49 | s.v = s.v[:len(s.v)-1] 50 | } else { 51 | break 52 | } 53 | } 54 | s.v = s.v[:len(s.v):len(s.v)] 55 | } 56 | 57 | // Clone makes a copy of s. 58 | func (s BitSet) Clone() *BitSet { 59 | t := &BitSet{} 60 | t.v = append(t.v, s.v...) 61 | return t 62 | } 63 | 64 | // String returns a string representation of s. 65 | func (s BitSet) String() string { 66 | b := make([]byte, s.Len()) 67 | for i := 0; i < s.Len(); i++ { 68 | if s.Get(i) { 69 | b[i] = '1' 70 | } else { 71 | b[i] = '0' 72 | } 73 | } 74 | return string(b) 75 | } 76 | 77 | // Set sets the bit at index i. 78 | func (s *BitSet) Set(i int) { 79 | if i < 0 { 80 | return 81 | } 82 | for i/bpw+1 > len(s.v) { 83 | s.v = append(s.v, 0) 84 | } 85 | s.v[i/bpw] |= 1 << uint(i%bpw) 86 | } 87 | 88 | // SetRange sets the bits between i (included) and j (excluded). 89 | func (s *BitSet) SetRange(i, j int) { 90 | if i < 0 { 91 | i = 0 92 | } 93 | if j < 0 { 94 | j = 0 95 | } 96 | for k := i; k < j; k++ { 97 | s.Set(k) 98 | } 99 | } 100 | 101 | // Clear clears the bit at index i. 102 | func (s *BitSet) Clear(i int) { 103 | if i < 0 { 104 | return 105 | } 106 | if (i/bpw + 1) > len(s.v) { 107 | return 108 | } 109 | s.v[i/bpw] &= ^(1 << uint(i%bpw)) 110 | s.autoShrink() 111 | } 112 | 113 | // ClearRange clears the bits between i (included) and j (excluded). 114 | func (s *BitSet) ClearRange(i, j int) { 115 | for k := i; k < j; k++ { 116 | s.Clear(k) 117 | } 118 | } 119 | 120 | // Toggle inverts the bit at index i. 121 | func (s *BitSet) Toggle(i int) { 122 | if i < 0 { 123 | return 124 | } 125 | if i/bpw+1 > len(s.v) { 126 | s.Set(i) 127 | } else { 128 | s.v[i/bpw] ^= 1 << uint(i%bpw) 129 | s.autoShrink() 130 | } 131 | } 132 | 133 | // ToggleRange inverts the bits between i (included) and j (excluded). 134 | func (s *BitSet) ToggleRange(i, j int) { 135 | for k := i; k < j; k++ { 136 | s.Toggle(k) 137 | } 138 | } 139 | 140 | // Get returns true if the bit at index i is set, false otherwise. 141 | // If i < 0, returns true. 142 | func (s *BitSet) Get(i int) bool { 143 | if i < 0 { 144 | return true 145 | } 146 | if i/bpw+1 > len(s.v) { 147 | return false 148 | } 149 | return (s.v[i/bpw] & (1 << uint(i%bpw))) != 0 150 | } 151 | 152 | // GetRange returns true if the bits between i (included) and j (excluded) are set, false otherwise. 153 | // If i < 0 and j < 0 return true. 154 | func (s *BitSet) GetRange(i, j int) bool { 155 | if i < 0 { 156 | i = 0 157 | } 158 | if j < 0 { 159 | j = 0 160 | } 161 | for k := i; k < j; k++ { 162 | if !s.Get(k) { 163 | return false 164 | } 165 | } 166 | return true 167 | } 168 | 169 | // Len returns the number of bits up to and including the highest bit set. 170 | func (s *BitSet) Len() int { 171 | // NOTE: autoShrink is always called by functions that 172 | // set bits to zero, but just to be sure we call 173 | // it here anyway. 174 | s.autoShrink() 175 | if len(s.v) == 0 { 176 | return 0 177 | } 178 | e := s.v[len(s.v)-1] 179 | c := 0 180 | for e != 0 { 181 | e = e >> 1 182 | c++ 183 | } 184 | return (len(s.v)-1)*bpw + c 185 | } 186 | 187 | // Any returns true if any bit is set, false otherwise. 188 | func (s *BitSet) Any() bool { 189 | for _, e := range s.v { 190 | if e != 0 { 191 | return true 192 | } 193 | } 194 | return false 195 | } 196 | 197 | // AnyRange returns true if any bit between i (included) and j (excluded) is set, false otherwise. 198 | // If i < 0 and j < 0 return true. 199 | func (s *BitSet) AnyRange(i, j int) bool { 200 | if i < 0 { 201 | i = 0 202 | } 203 | if j < 0 { 204 | j = 0 205 | } 206 | for k := i; k < j; k++ { 207 | if s.Get(k) { 208 | return true 209 | } 210 | } 211 | return false 212 | } 213 | 214 | // None returns true if no bit is set, false otherwise. 215 | func (s *BitSet) None() bool { 216 | return !s.Any() 217 | } 218 | 219 | // NoneRange returns true if no bit between i (included) and j (excluded) is set, false otherwise. 220 | // If i < 0 and j < 0 return true. 221 | func (s *BitSet) NoneRange(i, j int) bool { 222 | return !s.AnyRange(i, j) 223 | } 224 | 225 | func countBits(e uint) int { 226 | c := 0 227 | for e != 0 { 228 | c++ 229 | e &= e - 1 230 | } 231 | return c 232 | } 233 | 234 | // Cardinality counts the number of set bits. 235 | func (s *BitSet) Cardinality() int { 236 | c := 0 237 | for _, e := range s.v { 238 | c += countBits(e) 239 | } 240 | return c 241 | } 242 | 243 | // Next returns the index of the next bit set after i. 244 | // If no bit was found returns -1. 245 | func (s *BitSet) Next(i int) int { 246 | if i < 0 { 247 | i = -1 248 | } 249 | for j := i + 1; j < s.Len(); j++ { 250 | if s.Get(j) { 251 | return j 252 | } 253 | } 254 | return -1 255 | } 256 | 257 | // Prev returns the index of the previous bit set before i. 258 | // If no bit was found returns -1. 259 | func (s *BitSet) Prev(i int) int { 260 | for j := i - 1; j >= 0; j-- { 261 | if s.Get(j) { 262 | return j 263 | } 264 | } 265 | return -1 266 | } 267 | 268 | // Equal returns true if s and t have the same bits set, false otherwise. 269 | func (s *BitSet) Equal(t *BitSet) bool { 270 | if len(s.v) != len(t.v) { 271 | return false 272 | } 273 | for i, u := range s.v { 274 | if u != t.v[i] { 275 | return false 276 | } 277 | } 278 | return true 279 | } 280 | 281 | // SuperSet returns true if s is a super set of t, false otherwise. 282 | func (s *BitSet) SuperSet(t *BitSet) bool { 283 | if len(s.v) < len(t.v) { 284 | return false 285 | } 286 | for i := 0; i < len(t.v); i++ { 287 | if t.v[i] & ^s.v[i] != 0 { 288 | return false 289 | } 290 | } 291 | return true 292 | } 293 | 294 | // SubSet returns true if s is a sub set of t, false otherwise. 295 | func (s *BitSet) SubSet(t *BitSet) bool { 296 | return t.SuperSet(s) 297 | } 298 | 299 | // ShiftLeft moves each bit n positions to the left. 300 | func (s *BitSet) ShiftLeft(n int) { 301 | for i := n; i < s.Len(); i++ { 302 | if s.Get(i) { 303 | s.Set(i - n) 304 | } else { 305 | s.Clear(i - n) 306 | } 307 | } 308 | s.ClearRange(s.Len()-n, s.Len()) 309 | } 310 | 311 | // ShiftRight moves each bit n positions to the right. 312 | func (s *BitSet) ShiftRight(n int) { 313 | len := s.Len() 314 | for i := len - 1; i >= 0; i-- { 315 | if s.Get(i) { 316 | s.Set(i + n) 317 | } else { 318 | s.Clear(i + n) 319 | } 320 | } 321 | s.ClearRange(0, n) 322 | } 323 | 324 | // Union stores in a the true bits from either s or t. 325 | func (s *BitSet) Union(t *BitSet) { 326 | for i := 0; i < len(s.v) && i < len(t.v); i++ { 327 | s.v[i] = s.v[i] | t.v[i] 328 | } 329 | if len(t.v) > len(s.v) { 330 | s.v = append(s.v, t.v[len(s.v):]...) 331 | } 332 | } 333 | 334 | // Intersect stores in s the true bits common to both s and t. 335 | func (s *BitSet) Intersect(t *BitSet) { 336 | for i := 0; i < len(s.v) && i < len(t.v); i++ { 337 | s.v[i] = s.v[i] & t.v[i] 338 | } 339 | if len(s.v) > len(t.v) { 340 | // FIXME: probably we should clear a.v 341 | s.v = s.v[:len(t.v)] 342 | } 343 | s.autoShrink() 344 | } 345 | 346 | // Difference stores in s the true bits present in s and not in t. 347 | func (s *BitSet) Difference(t *BitSet) { 348 | for i := 0; i < len(s.v) && i < len(t.v); i++ { 349 | s.v[i] = s.v[i] & ^t.v[i] 350 | } 351 | if len(s.v) <= len(t.v) { 352 | s.autoShrink() 353 | } 354 | } 355 | 356 | // SymmetricDifference stores in s the true bits which are either 357 | // in s or in t, but not in both. 358 | func (s *BitSet) SymmetricDifference(t *BitSet) { 359 | for i := 0; i < len(s.v) && i < len(t.v); i++ { 360 | s.v[i] = s.v[i] ^ t.v[i] 361 | } 362 | if len(s.v) == len(t.v) { 363 | s.autoShrink() 364 | } else if len(s.v) < len(t.v) { 365 | s.v = append(s.v, t.v[len(s.v):]...) 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /bitset_test.go: -------------------------------------------------------------------------------- 1 | // Written by https://xojoc.pw. Public Domain. 2 | 3 | package bitset 4 | 5 | import "testing" 6 | 7 | func TestBitSet_ShiftLeft(t *testing.T) { 8 | s := &BitSet{} 9 | s.ShiftLeft(5) 10 | s.Set(1) 11 | s.Set(3) 12 | s.Set(5) 13 | s.ShiftLeft(2) 14 | if s.String() != "0101" { 15 | t.Errorf("ShiftLeft %q want %q", s.String(), "0101") 16 | } 17 | } 18 | func TestBitSet_ShiftRight(t *testing.T) { 19 | s := &BitSet{} 20 | s.ShiftRight(5) 21 | s.Set(0) 22 | s.Set(2) 23 | s.ShiftRight(1) 24 | if s.String() != "0101" { 25 | t.Errorf("ShiftRight %q want %q", s.String(), "0101") 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /examples_test.go: -------------------------------------------------------------------------------- 1 | // Written by https://xojoc.pw. Public Domain. 2 | 3 | package bitset 4 | 5 | import ( 6 | "fmt" 7 | ) 8 | 9 | func Example() { 10 | // Create new BitSet 11 | s := &BitSet{} 12 | // Bitsets automatically grow 13 | s.Set(2) 14 | s.Set(3) 15 | fmt.Println(s.Get(0)) 16 | fmt.Println(s.Get(2)) 17 | // Out of range Get will return false 18 | fmt.Println(s.Get(1000)) 19 | // Println automatically calls String method 20 | fmt.Println(s) 21 | 22 | t := &BitSet{} 23 | t.Set(2) 24 | t.Set(4) 25 | s.Intersect(t) 26 | fmt.Println(s) 27 | 28 | // Output: 29 | // false 30 | // true 31 | // false 32 | // 0011 33 | // 001 34 | } 35 | 36 | func ExampleBitSet_Union() { 37 | a := &BitSet{} 38 | a.Set(0) 39 | b := &BitSet{} 40 | b.Set(3) 41 | fmt.Println(a) 42 | fmt.Println(b) 43 | a.Union(b) 44 | fmt.Println(a) 45 | 46 | // Output: 47 | // 1 48 | // 0001 49 | // 1001 50 | } 51 | 52 | func ExampleBitSet_Intersect() { 53 | a := &BitSet{} 54 | a.Set(0) 55 | a.Set(3) 56 | b := &BitSet{} 57 | b.Set(0) 58 | b.Set(1) 59 | fmt.Println(a) 60 | fmt.Println(b) 61 | a.Intersect(b) 62 | fmt.Println(a) 63 | 64 | // Output: 65 | // 1001 66 | // 11 67 | // 1 68 | } 69 | 70 | func ExampleBitSet_Difference() { 71 | a := &BitSet{} 72 | a.Set(0) 73 | a.Set(1) 74 | a.Set(2) 75 | b := &BitSet{} 76 | b.Set(1) 77 | fmt.Println(a) 78 | fmt.Println(b) 79 | a.Difference(b) 80 | fmt.Println(a) 81 | 82 | // Output: 83 | // 111 84 | // 01 85 | // 101 86 | } 87 | 88 | func ExampleBitSet_SymmetricDifference() { 89 | a := &BitSet{} 90 | a.Set(0) 91 | a.Set(1) 92 | b := &BitSet{} 93 | b.Set(0) 94 | b.Set(2) 95 | fmt.Println(a) 96 | fmt.Println(b) 97 | a.SymmetricDifference(b) 98 | fmt.Println(a) 99 | 100 | // Output: 101 | // 11 102 | // 101 103 | // 011 104 | } 105 | 106 | func ExampleBitSet_String() { 107 | a := &BitSet{} 108 | a.Set(0) 109 | a.Set(2) 110 | fmt.Println(a) // fmt automatically calls String 111 | 112 | // Output: 113 | // 101 114 | } 115 | -------------------------------------------------------------------------------- /property_test.go: -------------------------------------------------------------------------------- 1 | // Written by https://xojoc.pw. Public Domain. 2 | 3 | package bitset 4 | 5 | import ( 6 | "math/rand" 7 | "reflect" 8 | "testing" 9 | "testing/quick" 10 | "time" 11 | ) 12 | 13 | var cfg = &quick.Config{MaxCount: 1000, Rand: rand.New(rand.NewSource(time.Now().UTC().UnixNano()))} 14 | var limit = 10 * 1000 15 | 16 | func (BitSet) Generate(rand *rand.Rand, size int) reflect.Value { 17 | s := BitSet{} 18 | for i := 0; i < size; i++ { 19 | s.Set(rand.Intn(limit)) 20 | } 21 | return reflect.ValueOf(s) 22 | } 23 | 24 | type index int 25 | 26 | func (index) Generate(rand *rand.Rand, size int) reflect.Value { 27 | return reflect.ValueOf(index(rand.Intn(limit))) 28 | } 29 | 30 | func check(t *testing.T, f interface{}) { 31 | if err := quick.Check(f, cfg); err != nil { 32 | t.Error(err) 33 | } 34 | } 35 | 36 | func TestAny(t *testing.T) { 37 | any := func(i index) bool { 38 | s := &BitSet{} 39 | if s.Any() { 40 | return false 41 | } 42 | s.Set(int(i)) 43 | return s.Any() 44 | } 45 | check(t, any) 46 | } 47 | func TestAnyRange(t *testing.T) { 48 | any := func(i, l, r index) bool { 49 | s := &BitSet{} 50 | if s.AnyRange(int(i-l), int(i+r)+1) { 51 | return false 52 | } 53 | s.Set(int(i)) 54 | return s.AnyRange(int(i-l), int(i+r)+1) 55 | } 56 | check(t, any) 57 | } 58 | func TestCardinality(t *testing.T) { 59 | card := func(is []index) bool { 60 | s := &BitSet{} 61 | if s.Cardinality() != 0 { 62 | return false 63 | } 64 | count := 0 65 | for _, i := range is { 66 | j := int(i) 67 | if s.Get(j) { 68 | continue 69 | } 70 | s.Set(j) 71 | count++ 72 | } 73 | return s.Cardinality() == count 74 | } 75 | check(t, card) 76 | } 77 | func TestClear(t *testing.T) { 78 | c := func(i index) bool { 79 | s := &BitSet{} 80 | j := int(i) 81 | s.Set(j) 82 | s.Clear(j) 83 | return !s.Get(j) 84 | } 85 | check(t, c) 86 | } 87 | func TestClearRange(t *testing.T) { 88 | c := func(i, j index) bool { 89 | s := &BitSet{} 90 | k, t := int(i), int(j) 91 | s.SetRange(k, t) 92 | s.ClearRange(k, t) 93 | return s.None() 94 | } 95 | check(t, c) 96 | } 97 | func TestClone(t *testing.T) { 98 | c := func(s BitSet) bool { 99 | t := s.Clone() 100 | return s.Equal(t) 101 | } 102 | check(t, c) 103 | } 104 | func TestDifference(t *testing.T) { 105 | d := func(a BitSet, b BitSet) bool { 106 | a1 := a.Clone() 107 | b1 := b.Clone() 108 | a1.Difference(b1) 109 | if !a1.SubSet(&a) { 110 | return false 111 | } 112 | a1.Intersect(b1) 113 | if a1.Any() { 114 | return false 115 | } 116 | 117 | a1 = a.Clone() 118 | b1 = b.Clone() 119 | b1.Difference(a1) 120 | if !b1.SubSet(&b) { 121 | return false 122 | } 123 | b1.Intersect(a1) 124 | if b1.Any() { 125 | return false 126 | } 127 | 128 | return true 129 | } 130 | check(t, d) 131 | } 132 | func TestEqual(t *testing.T) { 133 | eq := func(is []index) bool { 134 | s := &BitSet{} 135 | t := &BitSet{} 136 | for _, i := range is { 137 | s.Set(int(i)) 138 | t.Set(int(i)) 139 | } 140 | return s.Equal(t) 141 | } 142 | check(t, eq) 143 | } 144 | func TestGet(t *testing.T) { 145 | g := func(i index) bool { 146 | s := &BitSet{} 147 | j := int(i) 148 | if s.Get(j) { 149 | return false 150 | } 151 | s.Set(j) 152 | return s.Get(j) 153 | } 154 | check(t, g) 155 | } 156 | func TestGetRange(t *testing.T) { 157 | g := func(i, j index) bool { 158 | s := &BitSet{} 159 | k, t := int(i), int(j) 160 | /* 161 | if s.GetRange(k, t) { 162 | return false 163 | } 164 | */ 165 | s.SetRange(k, t) 166 | return s.GetRange(k, t) 167 | } 168 | check(t, g) 169 | } 170 | func TestIntersect(t *testing.T) { 171 | u := func(a, b, c BitSet) bool { 172 | // A ∩ B = B ∩ A 173 | a1 := a.Clone() 174 | a1.Intersect(&b) 175 | b2 := b.Clone() 176 | b2.Intersect(&a) 177 | if !a1.Equal(b2) { 178 | return false 179 | } 180 | 181 | // A ∩ (B ∩ C) = (A ∩ B) ∩ C 182 | a3 := a.Clone() 183 | b3 := b.Clone() 184 | b3.Intersect(&c) 185 | a3.Intersect(b3) 186 | a4 := a.Clone() 187 | a4.Intersect(&b) 188 | a4.Intersect(&c) 189 | if !a3.Equal(a4) { 190 | return false 191 | } 192 | 193 | // A ∩ B ⊆ A 194 | a5 := a.Clone() 195 | a5.Intersect(&b) 196 | if !a5.SubSet(&a) { 197 | return false 198 | } 199 | 200 | // A ∩ A = A 201 | a6 := a.Clone() 202 | a6.Intersect(&a) 203 | if !a.Equal(a6) { 204 | return false 205 | } 206 | 207 | // A ∩ ∅ = ∅ 208 | a7 := &BitSet{} 209 | a7.Intersect(&a) 210 | if !a7.Equal(&BitSet{}) { 211 | return false 212 | } 213 | 214 | // A ⊆ B iff A ∩ B = A 215 | a8 := &BitSet{} 216 | a8.Intersect(&b) 217 | if a.SubSet(&b) && !a8.Equal(&a) { 218 | return false 219 | } 220 | 221 | return true 222 | } 223 | check(t, u) 224 | } 225 | func TestLen(t *testing.T) { 226 | len := func(is []index) bool { 227 | s := &BitSet{} 228 | if s.Len() != 0 { 229 | return false 230 | } 231 | max := 0 232 | for _, i := range is { 233 | j := int(i) 234 | s.Set(j) 235 | if j+1 > max { 236 | max = j + 1 237 | } 238 | if s.Len() != max { 239 | return false 240 | } 241 | } 242 | return true 243 | } 244 | check(t, len) 245 | } 246 | func TestNext(t *testing.T) { 247 | n := func(s BitSet) bool { 248 | i := -1 249 | for { 250 | previ := i 251 | i = s.Next(previ) 252 | if i == -1 { 253 | break 254 | } 255 | for j := previ + 1; j < i; j++ { 256 | if s.Get(j) { 257 | return false 258 | } 259 | } 260 | if !s.Get(i) { 261 | return false 262 | } 263 | } 264 | return true 265 | } 266 | check(t, n) 267 | } 268 | func TestPrev(t *testing.T) { 269 | p := func(s BitSet) bool { 270 | i := s.Len() 271 | for { 272 | previ := i 273 | i = s.Prev(previ) 274 | if i == -1 { 275 | break 276 | } 277 | for j := previ - 1; j > i; j-- { 278 | if s.Get(j) { 279 | return false 280 | } 281 | } 282 | if !s.Get(i) { 283 | return false 284 | } 285 | } 286 | return true 287 | } 288 | check(t, p) 289 | } 290 | 291 | /* 292 | func Test(t *testing.T) { 293 | := func(i index) bool { 294 | } 295 | check(t, ) 296 | } 297 | */ 298 | 299 | func TestUnion(t *testing.T) { 300 | u := func(a, b, c BitSet) bool { 301 | // A ∪ B = B ∪ A 302 | a1 := a.Clone() 303 | a1.Union(&b) 304 | b2 := b.Clone() 305 | b2.Union(&a) 306 | if !a1.Equal(b2) { 307 | return false 308 | } 309 | 310 | // A ∪ (B ∪ C) = (A ∪ B) ∪ C 311 | a3 := a.Clone() 312 | b3 := b.Clone() 313 | b3.Union(&c) 314 | a3.Union(b3) 315 | a4 := a.Clone() 316 | a4.Union(&b) 317 | a4.Union(&c) 318 | if !a3.Equal(a4) { 319 | return false 320 | } 321 | 322 | // A ⊆ (A ∪ B) 323 | a5 := a.Clone() 324 | a5.Union(&b) 325 | if !a.SubSet(a5) { 326 | return false 327 | } 328 | 329 | // A ∪ A = A 330 | a6 := a.Clone() 331 | a6.Union(&a) 332 | if !a.Equal(a6) { 333 | return false 334 | } 335 | 336 | // A ∪ ∅ = A 337 | a7 := &BitSet{} 338 | a7.Union(&a) 339 | if !a.Equal(a7) { 340 | return false 341 | } 342 | 343 | // A ⊆ B iff A ∪ B = B 344 | a8 := &BitSet{} 345 | a8.Union(&b) 346 | if a.SubSet(&b) && !a8.Equal(&b) { 347 | return false 348 | } 349 | 350 | return true 351 | } 352 | check(t, u) 353 | } 354 | 355 | func TestDeMorgan(t *testing.T) { 356 | m := func(a, b BitSet) bool { 357 | max := a.Len() 358 | if b.Len() > max { 359 | max = b.Len() 360 | } 361 | // (A ∪ B)′ = A′ ∩ B′ 362 | a1 := a.Clone() 363 | a1.Union(&b) 364 | a1.ToggleRange(0, max) 365 | a2 := a.Clone() 366 | b2 := b.Clone() 367 | a2.ToggleRange(0, max) 368 | b2.ToggleRange(0, max) 369 | a2.Intersect(b2) 370 | if !a1.Equal(a2) { 371 | return false 372 | } 373 | 374 | // (A ∩ B)′ = A′ ∪ B′ 375 | a3 := a.Clone() 376 | a3.Intersect(&b) 377 | a3.ToggleRange(0, max) 378 | a4 := a.Clone() 379 | b4 := b.Clone() 380 | a4.ToggleRange(0, max) 381 | b4.ToggleRange(0, max) 382 | a4.Union(b4) 383 | return a3.Equal(a4) 384 | } 385 | check(t, m) 386 | } 387 | --------------------------------------------------------------------------------