github.com/qioalice/ekago/v3@v3.3.2-0.20221202205325-5c262d586ee4/ekamath/bitset.go (about) 1 // Copyright © 2021. All rights reserved. 2 // Author: Ilya Stroy. 3 // Contacts: iyuryevich@pm.me, https://github.com/qioalice 4 // License: https://opensource.org/licenses/MIT 5 6 // This package is re-write of 7 // https://github.com/bits-and-blooms/bitset 8 // that is distributed (for now: 2021 Sep 12) by BSD 3-Clause "New" or "Revised" License. 9 // 10 // Here's some small changes, like introducing PrevUp(), PrevDown() methods, 11 // using `uint` instead of `uint64` (thus it can be uint32 on 32bit platforms) 12 // and some other improvements and changes. 13 14 package ekamath 15 16 import ( 17 "encoding/base64" 18 "errors" 19 ) 20 21 type ( 22 // BitSet is a bitset with variate capacity. 23 // It can be grown, depends on your cases. 24 // 25 // The index of BitSet is starts from 1. 26 // In almost all cases it's prohibited to use 0 as index. 27 // NextUp(), NextDown() an their unsafe methods are exceptions. 28 // 29 // It's strongly recommend to instantiate BitSet using NewBitSet() constructor, 30 // but just creating a BitSet is also possible and ready-to-use 31 // (it will be with 0 capacity and will grow when you will try to set any bit). 32 BitSet struct { 33 bs []uint 34 } 35 ) 36 37 var ( 38 ErrBitSetInvalid = errors.New("invalid BitSet") 39 ErrBitSetInvalidDataToDecode = errors.New("invalid data to decode to BitSet") 40 ) 41 42 // ---------------------------------------------------------------------------- // 43 44 // IsValid reports whether current BitSet is valid. 45 func (bs *BitSet) IsValid() bool { 46 return bs != nil 47 } 48 49 // IsEmpty reports whether current BitSet is empty bitset or not. 50 // Empty bitset is a bitset with all downed (zeroed) bits. 51 // Returns true if BitSet is invalid. 52 func (bs *BitSet) IsEmpty() bool { 53 if !bs.IsValid() { 54 return true 55 } 56 for i, n := 0, len(bs.bs); i < n; i++ { 57 if bs.bs[i] != 0 { 58 return false 59 } 60 } 61 return true 62 } 63 64 // ---------------------------------------------------------------------------- // 65 66 // Capacity returns the number of values (starting from 1) that can be stored 67 // inside current BitSet. 68 // Returns 0 if current BitSet is invalid. 69 func (bs *BitSet) Capacity() uint { 70 if !bs.IsValid() { 71 return 0 72 } 73 return uint(len(bs.bs)) * _BITSET_BITS_PER_CHUNK 74 } 75 76 // Count returns number of bits that are upped (set to 1). 77 // Returns 0 if current BitSet is invalid. 78 func (bs *BitSet) Count() uint { 79 80 if !bs.IsValid() { 81 return 0 82 } 83 84 var c uint 85 for i, n := uint(0), bs.chunkSize(); i < n; i++ { 86 c += bsCountOnes(bs.bs[i]) 87 } 88 89 return c 90 } 91 92 // CountBetween returns number of bits that are upped (set to 1), 93 // between range [a..b]. Note: `b` IS IN the range. 94 // Returns 0 if either current BitSet is invalid, `a` >= `b` 95 // or any part of that range is out of bound of the BitSet. 96 func (bs *BitSet) CountBetween(a, b uint) uint { 97 98 if !bs.IsValid() || a >= b { 99 return 0 100 } 101 102 c1, off1 := bsFromIdx(a - 1) 103 c2, off2 := bsFromIdx(b - 1) 104 105 if bs1size := bs.chunkSize(); c1 > bs1size || c2 > bs1size { 106 return 0 107 } 108 109 // The case when chunk is the same. 110 if c1 == c2 { 111 mask := (_BITSET_MASK_FULL >> (_BITSET_BITS_PER_CHUNK - off2 + off1 - 1)) << off1 112 return bsCountOnes(bs.bs[c1] & mask) 113 } 114 115 // There are 3 parts of counting: 116 // 1. Discard unnecessary bits and count remains of the chunk of `A` bound, 117 // 2. Discard unnecessary bits and count remains of the chunk of `B` bound, 118 // 3. Count all in the chunks between those that belongs either `A` or `B` bound. 119 var c uint 120 121 // Part 1. 122 mask := _BITSET_MASK_FULL << off1 123 c += bsCountOnes(bs.bs[c1] & mask) 124 125 // Part 2. 126 mask = _BITSET_MASK_FULL >> (_BITSET_BITS_PER_CHUNK - off2 - 1) 127 c += bsCountOnes(bs.bs[c2] & mask) 128 129 // Part 3. 130 for c1++; c1 < c2; c1++ { 131 c += bsCountOnes(bs.bs[c1]) 132 } 133 134 return c 135 } 136 137 // ---------------------------------------------------------------------------- // 138 139 // Clear downs (zeroes) ALL bits in the current BitSet. 140 // Does nothing if BitSet is invalid. 141 func (bs *BitSet) Clear() *BitSet { 142 if bs.IsValid() { 143 for i, n := 0, len(bs.bs); i < n; i++ { 144 bs.bs[i] = 0 145 } 146 } 147 return bs 148 } 149 150 // Clone makes a copy of BitSet and returns it. 151 // If BitSet is invalid, NewBitSet() is called instead. 152 func (bs *BitSet) Clone() *BitSet { 153 154 if !bs.IsValid() { 155 return NewBitSet(0) // make BitSet with default capacity 156 } 157 158 cloned := make([]uint, len(bs.bs)) 159 copy(cloned, bs.bs) 160 161 return &BitSet{ 162 bs: cloned, 163 } 164 } 165 166 // GrowUnsafeUpTo grows current BitSet to be able operate with bits 167 // up to requested index. 168 // Panics if BitSet is invalid. 169 func (bs *BitSet) GrowUnsafeUpTo(idx uint) *BitSet { 170 171 n := bsChunksForBits(idx) 172 173 if l, c := bs.chunkSize(), bs.chunkCapacity(); c == 0 { 174 bs.bs = make([]uint, n) 175 176 } else if l <= n { 177 if c >= n { 178 bs.bs = bs.bs[:n] 179 180 } else { 181 old := bs.bs 182 bs.bs = make([]uint, n) 183 copy(bs.bs, old) 184 } 185 } 186 187 return bs 188 } 189 190 // ShrinkUpTo shrinks current BitSet to be able operate with bits 191 // up to requested index. 192 // Does nothing if current BitSet is less than the requested index. 193 // Panics if BitSet is invalid. 194 func (bs *BitSet) ShrinkUpTo(idx uint) *BitSet { 195 196 chunk, offset := bsFromIdx(idx - 1) 197 198 if bs1size := bs.chunkSize(); chunk <= bs1size { 199 200 for i := chunk + 1; i < bs1size; i++ { 201 bs.bs[i] = 0 202 } 203 204 bs.bs[chunk] &= _BITSET_MASK_FULL >> (_BITSET_BITS_PER_CHUNK - offset - 1) 205 bs.bs = bs.bs[:chunk+1] 206 } 207 208 return bs 209 } 210 211 // ---------------------------------------------------------------------------- // 212 213 // Up sets bit to 1 with requested index checking bounds, 214 // growing bitset if it's too small. Does nothing if BitSet is invalid. 215 func (bs *BitSet) Up(idx uint) *BitSet { 216 if bs.isValidIdx(idx, 1, true) { 217 bs.GrowUnsafeUpTo(idx).UpUnsafe(idx) 218 } 219 return bs 220 } 221 222 // UpUnsafe sets bit to 1 with requested index without any check. 223 // Panics if BitSet is invalid or if an index is out of bounds. 224 func (bs *BitSet) UpUnsafe(idx uint) *BitSet { 225 chunk, offset := bsFromIdx(idx - 1) 226 bs.bs[chunk] |= 1 << offset 227 return bs 228 } 229 230 // Down sets bit to 0 with requested index checking bounds, 231 // growing bitset if it's too small. Does nothing if BitSet is invalid. 232 func (bs *BitSet) Down(idx uint) *BitSet { 233 if bs.isValidIdx(idx, 1, true) { 234 bs.GrowUnsafeUpTo(idx).DownUnsafe(idx) 235 } 236 return bs 237 } 238 239 // DownUnsafe sets bit to 0 with requested index without any check. 240 // Panics if BitSet is invalid or if an index is out of bounds. 241 func (bs *BitSet) DownUnsafe(idx uint) *BitSet { 242 chunk, offset := bsFromIdx(idx - 1) 243 bs.bs[chunk] &^= 1 << offset 244 return bs 245 } 246 247 // Set calls Up() or Down() with provided index depends on `b`. 248 func (bs *BitSet) Set(idx uint, b bool) *BitSet { 249 if bs.isValidIdx(idx, 1, true) { 250 bs.GrowUnsafeUpTo(idx).SetUnsafe(idx, b) 251 } 252 return bs 253 } 254 255 // SetUnsafe calls UpUnsafe() or DownUnsafe() with provided index 256 // depends on `b`. 257 func (bs *BitSet) SetUnsafe(idx uint, b bool) *BitSet { 258 if b { 259 return bs.UpUnsafe(idx) 260 } else { 261 return bs.DownUnsafe(idx) 262 } 263 } 264 265 // Invert changes bit to against value with requested index checking bounds, 266 // growing bitset if it's too small. Does nothing if BitSet is invalid. 267 func (bs *BitSet) Invert(idx uint) *BitSet { 268 if bs.isValidIdx(idx, 1, true) { 269 bs.GrowUnsafeUpTo(idx).InvertUnsafe(idx) 270 } 271 return bs 272 } 273 274 // InvertUnsafe changes bit to against value with requested index without any check. 275 // Panics if BitSet is invalid or if an index is out of bounds. 276 func (bs *BitSet) InvertUnsafe(idx uint) *BitSet { 277 chunk, offset := bsFromIdx(idx - 1) 278 bs.bs[chunk] ^= 1 << offset 279 return bs 280 } 281 282 // IsSet reports whether a bit with requested index is set or not. 283 // Returns false either if bit isn't set, BitSet is invalid or index is out of bound. 284 func (bs *BitSet) IsSet(idx uint) bool { 285 return bs.isValidIdx(idx, 1, false) && bs.IsSetUnsafe(idx) 286 } 287 288 // IsSetUnsafe reports whether a bit with requested index is set or not. 289 // Panics if BitSet is invalid or if an index is out of bound. 290 func (bs *BitSet) IsSetUnsafe(idx uint) bool { 291 chunk, offset := bsFromIdx(idx - 1) 292 return bs.bs[chunk]&(1<<offset) != 0 293 } 294 295 // ---------------------------------------------------------------------------- // 296 297 // NextUp returns an index of next upped (set to 1) bit. 298 // It's safe to use 0 as index because this is the only way to get 1st bit. 299 // 300 // You can use this method (and the similar methods, like NextDown(), PrevUp(), PrevDown()) 301 // to iterate over BitSet: 302 // 303 // for v, e := bs.NextUp(0); e; v, e = bs.NextUp(v) { 304 // fmt.Printf("Elem: %d\n", v) 305 // } 306 func (bs *BitSet) NextUp(idx uint) (uint, bool) { 307 if bs.isValidIdx(idx, 0, false) { 308 return bs.NextUpUnsafe(idx) 309 } 310 return idx, false 311 } 312 313 // NextUpUnsafe is the same as NextUp but without any bound checks. 314 // It will lead to UB or panic if you will use an incorrect index. 315 func (bs *BitSet) NextUpUnsafe(idx uint) (uint, bool) { 316 return bs.nextGeneric(idx, false) 317 } 318 319 // NextDown returns an index of next downed (set to 0) bit. 320 // It's safe to use 0 as index because this is the only way to get 1st bit. 321 // See NextUp() method to get to know how to use that method to iterate over BitSet. 322 func (bs *BitSet) NextDown(idx uint) (uint, bool) { 323 if bs.isValidIdx(idx, 0, false) { 324 return bs.NextDownUnsafe(idx) 325 } 326 return idx, false 327 } 328 329 // NextDownUnsafe is the same as NextDown but without any bound checks. 330 // It will lead to UB or panic if you will use an incorrect index. 331 func (bs *BitSet) NextDownUnsafe(idx uint) (uint, bool) { 332 return bs.nextGeneric(idx, true) 333 } 334 335 // PrevUp returns an index of prev upped (set to 1) bit. 336 // The minimum index you should use to get not false 2nd return argument is 2 337 // (the minimum index of BitSet is 1 and there's no upped bits before 1 or 0). 338 // See NextUp() method to get to know how to use that method to iterate over BitSet. 339 func (bs *BitSet) PrevUp(idx uint) (uint, bool) { 340 if bs.isValidIdx(idx, 2, false) { 341 return bs.PrevUpUnsafe(idx) 342 } 343 return idx, false 344 } 345 346 // PrevUpUnsafe is the same as PrevUp but without any bound checks. 347 // It will lead to UB or panic if you will use an incorrect index. 348 func (bs *BitSet) PrevUpUnsafe(idx uint) (uint, bool) { 349 return bs.prevGeneric(idx, false) 350 } 351 352 // PrevDown returns an index of prev downed (set to 0) bit. 353 // The minimum index you should use to get not false 2nd return argument is 2 354 // (the minimum index of BitSet is 1 and there's no downed bits before 1 or 0). 355 // See NextUp() method to get to know how to use that method to iterate over BitSet. 356 func (bs *BitSet) PrevDown(idx uint) (uint, bool) { 357 if bs.isValidIdx(idx, 2, false) { 358 return bs.PrevDownUnsafe(idx) 359 } 360 return idx, false 361 } 362 363 // PrevDownUnsafe is the same as PrevDown but without any bound checks. 364 // It will lead to UB or panic if you will use an incorrect index. 365 func (bs *BitSet) PrevDownUnsafe(idx uint) (uint, bool) { 366 return bs.prevGeneric(idx, true) 367 } 368 369 // ---------------------------------------------------------------------------- // 370 371 // Complement makes a complement operation (invert all bits), 372 // saving result to the current BitSet and returns it. 373 // If you want to use current BitSet after this operation, just make a copy before. 374 // Read more: https://en.wikipedia.org/wiki/Complement_(set_theory) 375 // 376 // Does nothing if either current BitSet is invalid or has 0 capacity. 377 func (bs *BitSet) Complement() *BitSet { 378 379 if bs.IsValid() { 380 for i, n := uint(0), bs.chunkSize(); i < n; i++ { 381 bs.bs[i] ^= _BITSET_MASK_FULL 382 } 383 } 384 385 return bs 386 } 387 388 // Union makes a union operation, saving result to the current BitSet and returns it. 389 // If you want to use current BitSet after this operation, just make a copy before. 390 // Read more: https://en.wikipedia.org/wiki/Union_(set_theory) 391 // 392 // If `bs2` BitSet's capacity > current's one, 393 // the current BitSet will be grown up to that BitSet capacity. 394 // 395 // Does nothing if either current BitSet or provided one is invalid. 396 func (bs *BitSet) Union(bs2 *BitSet) *BitSet { 397 398 // Capacity() includes IsValid() call 399 if bs2cap := bs2.Capacity(); bs.IsValid() && bs2cap > 0 { 400 401 bs.GrowUnsafeUpTo(bs2cap) 402 for i, n := uint(0), bs2.chunkSize(); i < n; i++ { 403 bs.bs[i] |= bs2.bs[i] 404 } 405 } 406 407 return bs 408 } 409 410 // Intersection makes an intersection operation, saving result to the current BitSet 411 // and returns it. 412 // If you want to use current BitSet after this operation, just make a copy before. 413 // Read more: https://en.wikipedia.org/wiki/Intersection_(set_theory) 414 // 415 // If `bs2` BitSet has bits out of the upper bound of the current BitSet, 416 // they will be ignored. 417 // If current BitSet has bits out of the upper bound of `bs2` BitSet, 418 // they will be zeroed. 419 // 420 // Does nothing if either current BitSet or provided one is invalid. 421 func (bs *BitSet) Intersection(bs2 *BitSet) *BitSet { 422 423 if bs.IsValid() && bs2.IsValid() { 424 425 bs1size := bs.chunkSize() 426 427 i := uint(0) 428 for n := Min(bs1size, bs2.chunkSize()); i < n; i++ { 429 bs.bs[i] &= bs2.bs[i] 430 } 431 432 for ; i < bs1size; i++ { 433 bs.bs[i] = 0 434 } 435 } 436 437 return bs 438 } 439 440 // Difference performs a difference operation, saving result to the current BitSet 441 // and returns it. 442 // If you want to use current BitSet after this operation, just make a copy before. 443 // Read more: https://en.wikipedia.org/wiki/Complement_(set_theory)#Relative_complement 444 // 445 // If either `bs2` BitSet or current BitSet has bits out of the upper bound 446 // of the other BitSet, they will be ignored. 447 // 448 // Does nothing if either current BitSet or provided one is invalid. 449 func (bs *BitSet) Difference(bs2 *BitSet) *BitSet { 450 451 if bs.IsValid() && bs2.IsValid() { 452 453 for i, n := uint(0), Min(bs.chunkSize(), bs2.chunkSize()); i < n; i++ { 454 bs.bs[i] &^= bs2.bs[i] 455 } 456 } 457 458 return bs 459 } 460 461 // SymmetricDifference performs a symmetric difference (XOR) operation, 462 // saving result to the current BitSet and returns it. 463 // If you want to use current BitSet after this operation, just make a copy before. 464 // Read more: https://en.wikipedia.org/wiki/Symmetric_difference 465 // 466 // If `bs2` BitSet's capacity > current's one, 467 // the current BitSet will be grown up to that BitSet capacity. 468 // 469 // Does nothing if either current BitSet or provided one is invalid. 470 func (bs *BitSet) SymmetricDifference(bs2 *BitSet) *BitSet { 471 472 // Capacity() includes IsValid() call 473 if bs2cap := bs2.Capacity(); bs.IsValid() && bs2cap != 0 { 474 475 bs1size := bs.chunkSize() 476 bs2size := bs2.chunkSize() 477 478 bs.GrowUnsafeUpTo(bs2cap) 479 480 i := uint(0) 481 for n := Min(bs1size, bs2size); i < n; i++ { 482 bs.bs[i] ^= bs2.bs[i] 483 } 484 485 for ; i < bs2size; i++ { 486 bs.bs[i] |= bs2.bs[i] 487 } 488 } 489 490 return bs 491 } 492 493 // ---------------------------------------------------------------------------- // 494 495 // MarshalBinary implements BinaryMarshaler interface encoding current BitSet 496 // in binary form. 497 // 498 // It guarantees that if BitSet is valid, the MarshalBinary() cannot fail. 499 // There's no guarantees about algorithm that will be used to encode/decode. 500 // Returns nil if BitSet doesn't have any presented underlying chunks. 501 // 502 // WARNING! 503 // User MUST NOT modify returned data. If you need it, clone it firstly. 504 // 505 // Despite of warnings and restrictions, this method has O(1) complexity. 506 func (bs *BitSet) MarshalBinary() ([]byte, error) { 507 508 if !bs.IsValid() { 509 return nil, ErrBitSetInvalid 510 } 511 512 return bsUnsafeToBytesSlice(bs.bs), nil 513 } 514 515 // UnmarshalBinary implements BinaryUnmarshaler interface decoding provided `data` 516 // from binary form. 517 // 518 // The current BitSet's data will be overwritten by the decoded one 519 // if decoding operation has been completed successfully. 520 // 521 // Provided `data` MUST BE obtained by calling BitSet.MarshalBinary() method. 522 // There's no guarantees about algorithm that will be used to encode/decode. 523 // 524 // Does nothing (and returns nil) if provided `data` is empty. 525 // Returns ErrBitSetInvalidDataToDecode if provided data is invalid. 526 // 527 // WARNING! 528 // User MUST NOT use provided `data` after passing to this method. UB otherwise. 529 // 530 // Despite of warnings and restrictions, this method has O(1) complexity. 531 func (bs *BitSet) UnmarshalBinary(data []byte) error { 532 533 switch l := len(data); { 534 case l == 0: 535 return nil 536 537 case bs == nil: 538 return ErrBitSetInvalid 539 540 case l&_BITSET_BYTES_PER_CHUNK != 0: 541 return ErrBitSetInvalidDataToDecode 542 } 543 544 bs.bs = bsUnsafeFromBytesSlice(data) 545 return nil 546 } 547 548 // MarshalText implements TextMarshaler interface encoding current BitSet 549 // in text form. 550 // 551 // It guarantees that if BitSet is valid, the MarshalText() cannot fail. 552 // Returns nil if BitSet doesn't have any presented underlying chunks. 553 // 554 // MarshalText guarantees that output data will be base64 encoded, 555 // but NOT GUARANTEES that decoded data from base64 is user-friendly 556 // and user can manually read/construct BitSet from that data. 557 // 558 // Provided base64 data is NO URL FRIENDLY! 559 // It means, that was used something but base64.URLEncoding. 560 func (bs *BitSet) MarshalText() ([]byte, error) { 561 562 binaryEncodedData, err := bs.MarshalBinary() 563 if err != nil { 564 return nil, err 565 } 566 567 buf := make([]byte, base64.StdEncoding.EncodedLen(len(binaryEncodedData))) 568 base64.StdEncoding.Encode(buf, binaryEncodedData) 569 570 return buf, nil 571 } 572 573 // UnmarshalText implements TextUnmarshaler interface decoding provided `data` 574 // from text form. 575 // 576 // The current BitSet's data will be overwritten by the decoded one 577 // if decoding operation has been completed successfully. 578 // 579 // Provided `data` MUST BE obtained by calling BitSet.MarshalText() method. 580 // 581 // Does nothing (and returns nil) if provided `data` is empty. 582 // Returns ErrBitSetInvalidDataToDecode if provided data is empty or invalid. 583 // 584 // WARNING! 585 // User MUST NOT use provided `data` after passing to this method. UB otherwise. 586 func (bs *BitSet) UnmarshalText(data []byte) error { 587 588 switch { 589 case len(data) == 0: 590 return nil 591 592 case bs == nil: 593 return ErrBitSetInvalid 594 } 595 596 buf := make([]byte, base64.StdEncoding.DecodedLen(len(data))) 597 n, err := base64.StdEncoding.Decode(buf, data) 598 if err != nil { 599 return err 600 } 601 602 buf = buf[:n] 603 if len(buf)&_BITSET_BYTES_PER_CHUNK != 0 { 604 return ErrBitSetInvalidDataToDecode 605 } 606 607 bs.bs = bsUnsafeFromBytesSlice(buf) 608 return nil 609 } 610 611 // ---------------------------------------------------------------------------- // 612 613 // NewBitSet creates a new BitSet with desired initial capacity. 614 // If capacity is too small, it will be overwritten with default minimum capacity. 615 func NewBitSet(capacity uint) *BitSet { 616 return new(BitSet).GrowUnsafeUpTo(capacity) 617 }