1 /* 2 * Hunt - A refined core library for D programming language. 3 * 4 * Copyright (C) 2018-2019 HuntLabs 5 * 6 * Website: https://www.huntlabs.net/ 7 * 8 * Licensed under the Apache-2.0 License. 9 * 10 */ 11 12 module hunt.collection.BitSet; 13 14 // import java.nio.ByteBuffer; 15 // import java.nio.ByteOrder; 16 // import java.nio.LongBuffer; 17 // import java.util.function.IntConsumer; 18 // import java.util.stream.IntStream; 19 // import java.util.stream.StreamSupport; 20 21 import hunt.Exceptions; 22 import hunt.Long; 23 24 import std.algorithm; 25 import std.conv; 26 27 /** 28 * This class implements a vector of bits that grows as needed. Each 29 * component of the bit set has a {@code bool} value. The 30 * bits of a {@code BitSet} are indexed by nonnegative integers. 31 * Individual indexed bits can be examined, set, or cleared. One 32 * {@code BitSet} may be used to modify the contents of another 33 * {@code BitSet} through logical AND, logical inclusive OR, and 34 * logical exclusive OR operations. 35 * 36 * <p>By default, all bits in the set initially have the value 37 * {@code false}. 38 * 39 * <p>Every bit set has a current size, which is the number of bits 40 * of space currently in use by the bit set. Note that the size is 41 * related to the implementation of a bit set, so it may change with 42 * implementation. The length of a bit set relates to logical length 43 * of a bit set and is defined independently of implementation. 44 * 45 * <p>Unless otherwise noted, passing a null parameter to any of the 46 * methods in a {@code BitSet} will result in a 47 * {@code NullPointerException}. 48 * 49 * <p>A {@code BitSet} is not safe for multithreaded use without 50 * external synchronization. 51 * 52 * @author Arthur van Hoff 53 * @author Michael McCloskey 54 * @author Martin Buchholz 55 */ 56 class BitSet { // : Cloneable, java.io.Serializable 57 /* 58 * BitSets are packed into arrays of "words." Currently a word is 59 * a long, which consists of 64 bits, requiring 6 address bits. 60 * The choice of word size is determined purely by performance concerns. 61 */ 62 private enum int ADDRESS_BITS_PER_WORD = 6; 63 private enum int BITS_PER_WORD = 1 << ADDRESS_BITS_PER_WORD; 64 private enum int BIT_INDEX_MASK = BITS_PER_WORD - 1; 65 66 /* Used to shift left or right for a partial word mask */ 67 private enum long WORD_MASK = 0xffffffffffffffffL; 68 69 /** 70 * @serialField bits long[] 71 * 72 * The bits in this BitSet. The ith bit is stored in bits[i/64] at 73 * bit position i % 64 (where bit position 0 refers to the least 74 * significant bit and 63 refers to the most significant bit). 75 */ 76 // private static final ObjectStreamField[] serialPersistentFields = { 77 // new ObjectStreamField("bits", long[].class), 78 // }; 79 80 /** 81 * The internal field corresponding to the serialField "bits". 82 */ 83 private long[] words; 84 85 /** 86 * The number of words in the logical size of this BitSet. 87 */ 88 private size_t wordsInUse = 0; 89 90 /** 91 * Whether the size of "words" is user-specified. If so, we assume 92 * the user knows what he's doing and try harder to preserve it. 93 */ 94 private bool sizeIsSticky = false; 95 96 /** 97 * Given a bit index, return word index containing it. 98 */ 99 private static size_t wordIndex(size_t bitIndex) { 100 return bitIndex >> ADDRESS_BITS_PER_WORD; 101 } 102 103 /** 104 * Every method must preserve these invariants. 105 */ 106 private void checkInvariants() { 107 assert(wordsInUse == 0 || words[wordsInUse - 1] != 0); 108 assert(wordsInUse >= 0 && wordsInUse <= words.length); 109 assert(wordsInUse == words.length || words[wordsInUse] == 0); 110 } 111 112 /** 113 * Sets the field wordsInUse to the logical size in words of the bit set. 114 * WARNING:This method assumes that the number of words actually in use is 115 * less than or equal to the current value of wordsInUse! 116 */ 117 private void recalculateWordsInUse() { 118 // Traverse the bitset until a used word is found 119 size_t i; 120 for (i = wordsInUse-1; i >= 0; i--) 121 if (words[i] != 0) 122 break; 123 124 wordsInUse = i+1; // The new logical size 125 } 126 127 /** 128 * Creates a new bit set. All bits are initially {@code false}. 129 */ 130 this() { 131 initWords(BITS_PER_WORD); 132 sizeIsSticky = false; 133 } 134 135 /** 136 * Creates a bit set whose initial size is large enough to explicitly 137 * represent bits with indices in the range {@code 0} through 138 * {@code nbits-1}. All bits are initially {@code false}. 139 * 140 * @param nbits the initial size of the bit set 141 * @throws NegativeArraySizeException if the specified initial size 142 * is negative 143 */ 144 this(size_t nbits) { 145 // nbits can't be negative; size 0 is OK 146 if (nbits < 0) 147 throw new NegativeArraySizeException("nbits < 0: " ~ nbits.to!string()); 148 149 initWords(nbits); 150 sizeIsSticky = true; 151 } 152 153 private void initWords(size_t nbits) { 154 words = new long[wordIndex(nbits-1) + 1]; 155 } 156 157 /** 158 * Creates a bit set using words as the internal representation. 159 * The last word (if there is one) must be non-zero. 160 */ 161 private this(long[] words) { 162 this.words = words; 163 this.wordsInUse = words.length; 164 checkInvariants(); 165 } 166 167 /** 168 * Returns a new bit set containing all the bits in the given long array. 169 * 170 * <p>More precisely, 171 * <br>{@code BitSet.valueOf(longs).get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)} 172 * <br>for all {@code n < 64 * longs.length}. 173 * 174 * <p>This method is equivalent to 175 * {@code BitSet.valueOf(LongBuffer.wrap(longs))}. 176 * 177 * @param longs a long array containing a little-endian representation 178 * of a sequence of bits to be used as the initial bits of the 179 * new bit set 180 * @return a {@code BitSet} containing all the bits in the long array 181 */ 182 // static BitSet valueOf(long[] longs) { 183 // int n; 184 // for (n = longs.length; n > 0 && longs[n - 1] == 0; n--){ 185 // } 186 // return new BitSet(Arrays.copyOf(longs, n)); 187 // } 188 189 /** 190 * Returns a new bit set containing all the bits in the given long 191 * buffer between its position and limit. 192 * 193 * <p>More precisely, 194 * <br>{@code BitSet.valueOf(lb).get(n) == ((lb.get(lb.position()+n/64) & (1L<<(n%64))) != 0)} 195 * <br>for all {@code n < 64 * lb.remaining()}. 196 * 197 * <p>The long buffer is not modified by this method, and no 198 * reference to the buffer is retained by the bit set. 199 * 200 * @param lb a long buffer containing a little-endian representation 201 * of a sequence of bits between its position and limit, to be 202 * used as the initial bits of the new bit set 203 * @return a {@code BitSet} containing all the bits in the buffer in the 204 * specified range 205 */ 206 // static BitSet valueOf(LongBuffer lb) { 207 // lb = lb.slice(); 208 // int n; 209 // for (n = lb.remaining(); n > 0 && lb.get(n - 1) == 0; n--){ 210 // } 211 // long[] words = new long[n]; 212 // lb.get(words); 213 // return new BitSet(words); 214 // } 215 216 /** 217 * Returns a new bit set containing all the bits in the given byte array. 218 * 219 * <p>More precisely, 220 * <br>{@code BitSet.valueOf(bytes).get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)} 221 * <br>for all {@code n < 8 * bytes.length}. 222 * 223 * <p>This method is equivalent to 224 * {@code BitSet.valueOf(ByteBuffer.wrap(bytes))}. 225 * 226 * @param bytes a byte array containing a little-endian 227 * representation of a sequence of bits to be used as the 228 * initial bits of the new bit set 229 * @return a {@code BitSet} containing all the bits in the byte array 230 */ 231 // static BitSet valueOf(byte[] bytes) { 232 // return BitSet.valueOf(ByteBuffer.wrap(bytes)); 233 // } 234 235 /** 236 * Returns a new bit set containing all the bits in the given byte 237 * buffer between its position and limit. 238 * 239 * <p>More precisely, 240 * <br>{@code BitSet.valueOf(bb).get(n) == ((bb.get(bb.position()+n/8) & (1<<(n%8))) != 0)} 241 * <br>for all {@code n < 8 * bb.remaining()}. 242 * 243 * <p>The byte buffer is not modified by this method, and no 244 * reference to the buffer is retained by the bit set. 245 * 246 * @param bb a byte buffer containing a little-endian representation 247 * of a sequence of bits between its position and limit, to be 248 * used as the initial bits of the new bit set 249 * @return a {@code BitSet} containing all the bits in the buffer in the 250 * specified range 251 */ 252 // static BitSet valueOf(ByteBuffer bb) { 253 // bb = bb.slice().order(ByteOrder.LITTLE_ENDIAN); 254 // int n; 255 // for (n = bb.remaining(); n > 0 && bb.get(n - 1) == 0; n--) 256 // ; 257 // long[] words = new long[(n + 7) / 8]; 258 // bb.limit(n); 259 // int i = 0; 260 // while (bb.remaining() >= 8) 261 // words[i++] = bb.getLong(); 262 // for (int remaining = bb.remaining(), j = 0; j < remaining; j++) 263 // words[i] |= (bb.get() & 0xffL) << (8 * j); 264 // return new BitSet(words); 265 // } 266 267 /** 268 * Returns a new byte array containing all the bits in this bit set. 269 * 270 * <p>More precisely, if 271 * <br>{@code byte[] bytes = s.toByteArray();} 272 * <br>then {@code bytes.length == (s.length()+7)/8} and 273 * <br>{@code s.get(n) == ((bytes[n/8] & (1<<(n%8))) != 0)} 274 * <br>for all {@code n < 8 * bytes.length}. 275 * 276 * @return a byte array containing a little-endian representation 277 * of all the bits in this bit set 278 */ 279 // byte[] toByteArray() { 280 // int n = wordsInUse; 281 // if (n == 0) 282 // return new byte[0]; 283 // int len = 8 * (n-1); 284 // for (long x = words[n - 1]; x != 0; x >>>= 8) 285 // len++; 286 // byte[] bytes = new byte[len]; 287 // ByteBuffer bb = ByteBuffer.wrap(bytes).order(ByteOrder.LITTLE_ENDIAN); 288 // for (int i = 0; i < n - 1; i++) 289 // bb.putLong(words[i]); 290 // for (long x = words[n - 1]; x != 0; x >>>= 8) 291 // bb.put((byte) (x & 0xff)); 292 // return bytes; 293 // } 294 295 /** 296 * Returns a new long array containing all the bits in this bit set. 297 * 298 * <p>More precisely, if 299 * <br>{@code long[] longs = s.toLongArray();} 300 * <br>then {@code longs.length == (s.length()+63)/64} and 301 * <br>{@code s.get(n) == ((longs[n/64] & (1L<<(n%64))) != 0)} 302 * <br>for all {@code n < 64 * longs.length}. 303 * 304 * @return a long array containing a little-endian representation 305 * of all the bits in this bit set 306 */ 307 long[] toLongArray() { 308 return words[0..wordsInUse].dup; // Arrays.copyOf(words, wordsInUse); 309 } 310 311 /** 312 * Ensures that the BitSet can hold enough words. 313 * @param wordsRequired the minimum acceptable number of words. 314 */ 315 private void ensureCapacity(size_t wordsRequired) { 316 size_t len = words.length; 317 if (len < wordsRequired) { 318 // Allocate larger of doubled size or required size 319 size_t request = max(2 * len, wordsRequired); 320 long[] newWords = new long[request]; 321 newWords[0..len] = words[0..$]; 322 words = newWords; 323 sizeIsSticky = false; 324 } 325 } 326 327 /** 328 * Ensures that the BitSet can accommodate a given wordIndex, 329 * temporarily violating the invariants. The caller must 330 * restore the invariants before returning to the user, 331 * possibly using recalculateWordsInUse(). 332 * @param wordIndex the index to be accommodated. 333 */ 334 private void expandTo(size_t wordIndex) { 335 size_t wordsRequired = wordIndex+1; 336 if (wordsInUse < wordsRequired) { 337 ensureCapacity(wordsRequired); 338 wordsInUse = wordsRequired; 339 } 340 } 341 342 /** 343 * Checks that fromIndex ... toIndex is a valid range of bit indices. 344 */ 345 private static void checkRange(size_t fromIndex, size_t toIndex) { 346 if (fromIndex < 0) 347 throw new IndexOutOfBoundsException("fromIndex < 0: " ~ fromIndex.to!string()); 348 if (toIndex < 0) 349 throw new IndexOutOfBoundsException("toIndex < 0: " ~ toIndex.to!string()); 350 if (fromIndex > toIndex) 351 throw new IndexOutOfBoundsException("fromIndex: " ~ fromIndex.to!string() ~ 352 " > toIndex: " ~ toIndex.to!string()); 353 } 354 355 /** 356 * Sets the bit at the specified index to the complement of its 357 * current value. 358 * 359 * @param bitIndex the index of the bit to flip 360 * @throws IndexOutOfBoundsException if the specified index is negative 361 */ 362 void flip(size_t bitIndex) { 363 if (bitIndex < 0) 364 throw new IndexOutOfBoundsException("bitIndex < 0: " ~ bitIndex.to!string()); 365 366 size_t wordIndex = wordIndex(bitIndex); 367 expandTo(wordIndex); 368 369 words[wordIndex] ^= (1L << bitIndex); 370 371 recalculateWordsInUse(); 372 checkInvariants(); 373 } 374 375 // /** 376 // * Sets each bit from the specified {@code fromIndex} (inclusive) to the 377 // * specified {@code toIndex} (exclusive) to the complement of its current 378 // * value. 379 // * 380 // * @param fromIndex index of the first bit to flip 381 // * @param toIndex index after the last bit to flip 382 // * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, 383 // * or {@code toIndex} is negative, or {@code fromIndex} is 384 // * larger than {@code toIndex} 385 // */ 386 // void flip(int fromIndex, int toIndex) { 387 // checkRange(fromIndex, toIndex); 388 389 // if (fromIndex == toIndex) 390 // return; 391 392 // int startWordIndex = wordIndex(fromIndex); 393 // int endWordIndex = wordIndex(toIndex - 1); 394 // expandTo(endWordIndex); 395 396 // long firstWordMask = WORD_MASK << fromIndex; 397 // long lastWordMask = WORD_MASK >>> -toIndex; 398 // if (startWordIndex == endWordIndex) { 399 // // Case 1: One word 400 // words[startWordIndex] ^= (firstWordMask & lastWordMask); 401 // } else { 402 // // Case 2: Multiple words 403 // // Handle first word 404 // words[startWordIndex] ^= firstWordMask; 405 406 // // Handle intermediate words, if any 407 // for (int i = startWordIndex+1; i < endWordIndex; i++) 408 // words[i] ^= WORD_MASK; 409 410 // // Handle last word 411 // words[endWordIndex] ^= lastWordMask; 412 // } 413 414 // recalculateWordsInUse(); 415 // checkInvariants(); 416 // } 417 418 /** 419 * Sets the bit at the specified index to {@code true}. 420 * 421 * @param bitIndex a bit index 422 * @throws IndexOutOfBoundsException if the specified index is negative 423 */ 424 void set(size_t bitIndex) { 425 if (bitIndex < 0) 426 throw new IndexOutOfBoundsException("bitIndex < 0: " ~ bitIndex.to!string()); 427 428 size_t wordIndex = wordIndex(bitIndex); 429 expandTo(wordIndex); 430 431 words[wordIndex] |= (1L << bitIndex); // Restores invariants 432 433 checkInvariants(); 434 } 435 436 /** 437 * Sets the bit at the specified index to the specified value. 438 * 439 * @param bitIndex a bit index 440 * @param value a bool value to set 441 * @throws IndexOutOfBoundsException if the specified index is negative 442 */ 443 void set(int bitIndex, bool value) { 444 if (value) 445 set(bitIndex); 446 else 447 clear(bitIndex); 448 } 449 450 /** 451 * Sets the bits from the specified {@code fromIndex} (inclusive) to the 452 * specified {@code toIndex} (exclusive) to {@code true}. 453 * 454 * @param fromIndex index of the first bit to be set 455 * @param toIndex index after the last bit to be set 456 * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, 457 * or {@code toIndex} is negative, or {@code fromIndex} is 458 * larger than {@code toIndex} 459 */ 460 void set(int fromIndex, int toIndex) { 461 checkRange(fromIndex, toIndex); 462 463 if (fromIndex == toIndex) 464 return; 465 466 // Increase capacity if necessary 467 size_t startWordIndex = wordIndex(fromIndex); 468 size_t endWordIndex = wordIndex(toIndex - 1); 469 expandTo(endWordIndex); 470 471 long firstWordMask = WORD_MASK << fromIndex; 472 long lastWordMask = WORD_MASK >>> -toIndex; 473 if (startWordIndex == endWordIndex) { 474 // Case 1: One word 475 words[startWordIndex] |= (firstWordMask & lastWordMask); 476 } else { 477 // Case 2: Multiple words 478 // Handle first word 479 words[startWordIndex] |= firstWordMask; 480 481 // Handle intermediate words, if any 482 for (size_t i = startWordIndex+1; i < endWordIndex; i++) 483 words[i] = WORD_MASK; 484 485 // Handle last word (restores invariants) 486 words[endWordIndex] |= lastWordMask; 487 } 488 489 checkInvariants(); 490 } 491 492 /** 493 * Sets the bits from the specified {@code fromIndex} (inclusive) to the 494 * specified {@code toIndex} (exclusive) to the specified value. 495 * 496 * @param fromIndex index of the first bit to be set 497 * @param toIndex index after the last bit to be set 498 * @param value value to set the selected bits to 499 * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, 500 * or {@code toIndex} is negative, or {@code fromIndex} is 501 * larger than {@code toIndex} 502 */ 503 void set(int fromIndex, int toIndex, bool value) { 504 if (value) 505 set(fromIndex, toIndex); 506 else 507 clear(fromIndex, toIndex); 508 } 509 510 /** 511 * Sets the bit specified by the index to {@code false}. 512 * 513 * @param bitIndex the index of the bit to be cleared 514 * @throws IndexOutOfBoundsException if the specified index is negative 515 */ 516 void clear(size_t bitIndex) { 517 if (bitIndex < 0) 518 throw new IndexOutOfBoundsException("bitIndex < 0: " ~ bitIndex.to!string()); 519 520 size_t wordIndex = wordIndex(bitIndex); 521 if (wordIndex >= wordsInUse) 522 return; 523 524 words[wordIndex] &= ~(1L << bitIndex); 525 526 recalculateWordsInUse(); 527 checkInvariants(); 528 } 529 530 /** 531 * Sets the bits from the specified {@code fromIndex} (inclusive) to the 532 * specified {@code toIndex} (exclusive) to {@code false}. 533 * 534 * @param fromIndex index of the first bit to be cleared 535 * @param toIndex index after the last bit to be cleared 536 * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, 537 * or {@code toIndex} is negative, or {@code fromIndex} is 538 * larger than {@code toIndex} 539 */ 540 void clear(size_t fromIndex, size_t toIndex) { 541 checkRange(fromIndex, toIndex); 542 543 if (fromIndex == toIndex) 544 return; 545 546 size_t startWordIndex = wordIndex(fromIndex); 547 if (startWordIndex >= wordsInUse) 548 return; 549 550 size_t endWordIndex = wordIndex(toIndex - 1); 551 if (endWordIndex >= wordsInUse) { 552 toIndex = length(); 553 endWordIndex = wordsInUse - 1; 554 } 555 556 long firstWordMask = WORD_MASK << fromIndex; 557 long lastWordMask = WORD_MASK >>> -toIndex; 558 if (startWordIndex == endWordIndex) { 559 // Case 1: One word 560 words[startWordIndex] &= ~(firstWordMask & lastWordMask); 561 } else { 562 // Case 2: Multiple words 563 // Handle first word 564 words[startWordIndex] &= ~firstWordMask; 565 566 // Handle intermediate words, if any 567 for (size_t i = startWordIndex+1; i < endWordIndex; i++) 568 words[i] = 0; 569 570 // Handle last word 571 words[endWordIndex] &= ~lastWordMask; 572 } 573 574 recalculateWordsInUse(); 575 checkInvariants(); 576 } 577 578 /** 579 * Sets all of the bits in this BitSet to {@code false}. 580 * 581 */ 582 void clear() { 583 while (wordsInUse > 0) 584 words[--wordsInUse] = 0; 585 } 586 587 /** 588 * Returns the value of the bit with the specified index. The value 589 * is {@code true} if the bit with the index {@code bitIndex} 590 * is currently set in this {@code BitSet}; otherwise, the result 591 * is {@code false}. 592 * 593 * @param bitIndex the bit index 594 * @return the value of the bit with the specified index 595 * @throws IndexOutOfBoundsException if the specified index is negative 596 */ 597 bool get(size_t bitIndex) { 598 if (bitIndex < 0) 599 throw new IndexOutOfBoundsException("bitIndex < 0: " ~ bitIndex.to!string()); 600 601 checkInvariants(); 602 603 size_t wordIndex = wordIndex(bitIndex); 604 return (wordIndex < wordsInUse) 605 && ((words[wordIndex] & (1L << bitIndex)) != 0); 606 } 607 608 /** 609 * Returns a new {@code BitSet} composed of bits from this {@code BitSet} 610 * from {@code fromIndex} (inclusive) to {@code toIndex} (exclusive). 611 * 612 * @param fromIndex index of the first bit to include 613 * @param toIndex index after the last bit to include 614 * @return a new {@code BitSet} from a range of this {@code BitSet} 615 * @throws IndexOutOfBoundsException if {@code fromIndex} is negative, 616 * or {@code toIndex} is negative, or {@code fromIndex} is 617 * larger than {@code toIndex} 618 */ 619 BitSet get(size_t fromIndex, size_t toIndex) { 620 checkRange(fromIndex, toIndex); 621 622 checkInvariants(); 623 624 size_t len = length(); 625 626 // If no set bits in range return empty bitset 627 if (len <= fromIndex || fromIndex == toIndex) 628 return new BitSet(0); 629 630 // An optimization 631 if (toIndex > len) 632 toIndex = len; 633 634 BitSet result = new BitSet(toIndex - fromIndex); 635 size_t targetWords = wordIndex(toIndex - fromIndex - 1) + 1; 636 size_t sourceIndex = wordIndex(fromIndex); 637 bool wordAligned = ((fromIndex & BIT_INDEX_MASK) == 0); 638 639 // Process all words but the last word 640 for (size_t i = 0; i < targetWords - 1; i++, sourceIndex++) 641 result.words[i] = wordAligned ? words[sourceIndex] : 642 (words[sourceIndex] >>> fromIndex) | 643 (words[sourceIndex+1] << -fromIndex); 644 645 // Process the last word 646 long lastWordMask = WORD_MASK >>> -toIndex; 647 result.words[targetWords - 1] = 648 ((toIndex-1) & BIT_INDEX_MASK) < (fromIndex & BIT_INDEX_MASK) 649 ? /* straddles source words */ 650 ((words[sourceIndex] >>> fromIndex) | 651 (words[sourceIndex+1] & lastWordMask) << -fromIndex) 652 : 653 ((words[sourceIndex] & lastWordMask) >>> fromIndex); 654 655 // Set wordsInUse correctly 656 result.wordsInUse = targetWords; 657 result.recalculateWordsInUse(); 658 result.checkInvariants(); 659 660 return result; 661 } 662 663 /** 664 * Returns the index of the first bit that is set to {@code true} 665 * that occurs on or after the specified starting index. If no such 666 * bit exists then {@code -1} is returned. 667 * 668 * <p>To iterate over the {@code true} bits in a {@code BitSet}, 669 * use the following loop: 670 * 671 * <pre> {@code 672 * for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i+1)) { 673 * // operate on index i here 674 * if (i == Integer.MAX_VALUE) { 675 * break; // or (i+1) would overflow 676 * } 677 * }}</pre> 678 * 679 * @param fromIndex the index to start checking from (inclusive) 680 * @return the index of the next set bit, or {@code -1} if there 681 * is no such bit 682 * @throws IndexOutOfBoundsException if the specified index is negative 683 */ 684 size_t nextSetBit(size_t fromIndex) { 685 if (fromIndex < 0) 686 throw new IndexOutOfBoundsException("fromIndex < 0: " ~ fromIndex.to!string()); 687 688 checkInvariants(); 689 690 size_t u = wordIndex(fromIndex); 691 if (u >= wordsInUse) 692 return -1; 693 694 long word = words[u] & (WORD_MASK << fromIndex); 695 696 while (true) { 697 if (word != 0) 698 return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word); 699 if (++u == wordsInUse) 700 return -1; 701 word = words[u]; 702 } 703 } 704 705 /** 706 * Returns the index of the first bit that is set to {@code false} 707 * that occurs on or after the specified starting index. 708 * 709 * @param fromIndex the index to start checking from (inclusive) 710 * @return the index of the next clear bit 711 * @throws IndexOutOfBoundsException if the specified index is negative 712 */ 713 size_t nextClearBit(int fromIndex) { 714 // Neither spec nor implementation handle bitsets of maximal length. 715 // See 4816253. 716 if (fromIndex < 0) 717 throw new IndexOutOfBoundsException("fromIndex < 0: " ~ fromIndex.to!string()); 718 719 checkInvariants(); 720 721 size_t u = wordIndex(fromIndex); 722 if (u >= wordsInUse) 723 return fromIndex; 724 725 long word = ~words[u] & (WORD_MASK << fromIndex); 726 727 while (true) { 728 if (word != 0) 729 return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word); 730 if (++u == wordsInUse) 731 return cast(int)wordsInUse * BITS_PER_WORD; 732 word = ~words[u]; 733 } 734 } 735 736 /** 737 * Returns the index of the nearest bit that is set to {@code true} 738 * that occurs on or before the specified starting index. 739 * If no such bit exists, or if {@code -1} is given as the 740 * starting index, then {@code -1} is returned. 741 * 742 * <p>To iterate over the {@code true} bits in a {@code BitSet}, 743 * use the following loop: 744 * 745 * <pre> {@code 746 * for (int i = bs.length(); (i = bs.previousSetBit(i-1)) >= 0; ) { 747 * // operate on index i here 748 * }}</pre> 749 * 750 * @param fromIndex the index to start checking from (inclusive) 751 * @return the index of the previous set bit, or {@code -1} if there 752 * is no such bit 753 * @throws IndexOutOfBoundsException if the specified index is less 754 * than {@code -1} 755 */ 756 size_t previousSetBit(size_t fromIndex) { 757 if (fromIndex < 0) { 758 if (fromIndex == -1) 759 return -1; 760 throw new IndexOutOfBoundsException( 761 "fromIndex < -1: " ~ fromIndex.to!string()); 762 } 763 764 checkInvariants(); 765 766 size_t u = wordIndex(fromIndex); 767 if (u >= wordsInUse) 768 return length() - 1; 769 770 long word = words[u] & (WORD_MASK >>> -(fromIndex+1)); 771 772 while (true) { 773 if (word != 0) 774 return (u+1) * BITS_PER_WORD - 1 - Long.numberOfLeadingZeros(word); 775 if (u-- == 0) 776 return -1; 777 word = words[u]; 778 } 779 } 780 781 /** 782 * Returns the index of the nearest bit that is set to {@code false} 783 * that occurs on or before the specified starting index. 784 * If no such bit exists, or if {@code -1} is given as the 785 * starting index, then {@code -1} is returned. 786 * 787 * @param fromIndex the index to start checking from (inclusive) 788 * @return the index of the previous clear bit, or {@code -1} if there 789 * is no such bit 790 * @throws IndexOutOfBoundsException if the specified index is less 791 * than {@code -1} 792 */ 793 size_t previousClearBit(size_t fromIndex) { 794 if (fromIndex < 0) { 795 if (fromIndex == -1) 796 return -1; 797 throw new IndexOutOfBoundsException( 798 "fromIndex < -1: " ~ fromIndex.to!string()); 799 } 800 801 checkInvariants(); 802 803 size_t u = wordIndex(fromIndex); 804 if (u >= wordsInUse) 805 return fromIndex; 806 807 long word = ~words[u] & (WORD_MASK >>> -(fromIndex+1)); 808 809 while (true) { 810 if (word != 0) 811 return (u+1) * BITS_PER_WORD -1 - Long.numberOfLeadingZeros(word); 812 if (u-- == 0) 813 return -1; 814 word = ~words[u]; 815 } 816 } 817 818 /** 819 * Returns the "logical size" of this {@code BitSet}: the index of 820 * the highest set bit in the {@code BitSet} plus one. Returns zero 821 * if the {@code BitSet} contains no set bits. 822 * 823 * @return the logical size of this {@code BitSet} 824 */ 825 size_t length() { 826 if (wordsInUse == 0) 827 return 0; 828 829 return BITS_PER_WORD * (wordsInUse - 1) + 830 (BITS_PER_WORD - Long.numberOfLeadingZeros(words[wordsInUse - 1])); 831 } 832 833 /** 834 * Returns true if this {@code BitSet} contains no bits that are set 835 * to {@code true}. 836 * 837 * @return bool indicating whether this {@code BitSet} is empty 838 */ 839 bool isEmpty() { 840 return wordsInUse == 0; 841 } 842 843 /** 844 * Returns true if the specified {@code BitSet} has any bits set to 845 * {@code true} that are also set to {@code true} in this {@code BitSet}. 846 * 847 * @param set {@code BitSet} to intersect with 848 * @return bool indicating whether this {@code BitSet} intersects 849 * the specified {@code BitSet} 850 */ 851 bool intersects(BitSet set) { 852 for (size_t i = min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--) 853 if ((words[i] & set.words[i]) != 0) 854 return true; 855 return false; 856 } 857 858 /** 859 * Returns the number of bits set to {@code true} in this {@code BitSet}. 860 * 861 * @return the number of bits set to {@code true} in this {@code BitSet} 862 */ 863 size_t cardinality() { 864 size_t sum = 0; 865 for (size_t i = 0; i < wordsInUse; i++) 866 sum += Long.bitCount(words[i]); 867 return sum; 868 } 869 870 /** 871 * Performs a logical <b>AND</b> of this target bit set with the 872 * argument bit set. This bit set is modified so that each bit in it 873 * has the value {@code true} if and only if it both initially 874 * had the value {@code true} and the corresponding bit in the 875 * bit set argument also had the value {@code true}. 876 * 877 * @param set a bit set 878 */ 879 void and(BitSet set) { 880 if (this == set) 881 return; 882 883 while (wordsInUse > set.wordsInUse) 884 words[--wordsInUse] = 0; 885 886 // Perform logical AND on words in common 887 for (size_t i = 0; i < wordsInUse; i++) 888 words[i] &= set.words[i]; 889 890 recalculateWordsInUse(); 891 checkInvariants(); 892 } 893 894 /** 895 * Performs a logical <b>OR</b> of this bit set with the bit set 896 * argument. This bit set is modified so that a bit in it has the 897 * value {@code true} if and only if it either already had the 898 * value {@code true} or the corresponding bit in the bit set 899 * argument has the value {@code true}. 900 * 901 * @param set a bit set 902 */ 903 void or(BitSet set) { 904 if (this == set) 905 return; 906 907 size_t wordsInCommon = min(wordsInUse, set.wordsInUse); 908 909 if (wordsInUse < set.wordsInUse) { 910 ensureCapacity(set.wordsInUse); 911 wordsInUse = set.wordsInUse; 912 } 913 914 // Perform logical OR on words in common 915 for (size_t i = 0; i < wordsInCommon; i++) 916 words[i] |= set.words[i]; 917 918 // Copy any remaining words 919 if (wordsInCommon < set.wordsInUse) { 920 words[wordsInCommon .. wordsInUse] = set.words[wordsInCommon .. wordsInUse]; 921 } 922 // System.arraycopy(set.words, wordsInCommon, 923 // words, wordsInCommon, 924 // wordsInUse - wordsInCommon); 925 926 // recalculateWordsInUse() is unnecessary 927 checkInvariants(); 928 } 929 930 /** 931 * Performs a logical <b>XOR</b> of this bit set with the bit set 932 * argument. This bit set is modified so that a bit in it has the 933 * value {@code true} if and only if one of the following 934 * statements holds: 935 * <ul> 936 * <li>The bit initially has the value {@code true}, and the 937 * corresponding bit in the argument has the value {@code false}. 938 * <li>The bit initially has the value {@code false}, and the 939 * corresponding bit in the argument has the value {@code true}. 940 * </ul> 941 * 942 * @param set a bit set 943 */ 944 void xor(BitSet set) { 945 size_t wordsInCommon = min(wordsInUse, set.wordsInUse); 946 947 if (wordsInUse < set.wordsInUse) { 948 ensureCapacity(set.wordsInUse); 949 wordsInUse = set.wordsInUse; 950 } 951 952 // Perform logical XOR on words in common 953 for (size_t i = 0; i < wordsInCommon; i++) 954 words[i] ^= set.words[i]; 955 956 // Copy any remaining words 957 if (wordsInCommon < set.wordsInUse) { 958 words[wordsInCommon .. wordsInUse] = set.words[wordsInCommon .. wordsInUse]; 959 } 960 // System.arraycopy(set.words, wordsInCommon, 961 // words, wordsInCommon, 962 // set.wordsInUse - wordsInCommon); 963 964 recalculateWordsInUse(); 965 checkInvariants(); 966 } 967 968 /** 969 * Clears all of the bits in this {@code BitSet} whose corresponding 970 * bit is set in the specified {@code BitSet}. 971 * 972 * @param set the {@code BitSet} with which to mask this 973 * {@code BitSet} 974 */ 975 void andNot(BitSet set) { 976 // Perform logical (a & !b) on words in common 977 for (size_t i = min(wordsInUse, set.wordsInUse) - 1; i >= 0; i--) 978 words[i] &= ~set.words[i]; 979 980 recalculateWordsInUse(); 981 checkInvariants(); 982 } 983 984 /** 985 * Returns the hash code value for this bit set. The hash code depends 986 * only on which bits are set within this {@code BitSet}. 987 * 988 * <p>The hash code is defined to be the result of the following 989 * calculation: 990 * <pre> {@code 991 * int hashCode() { 992 * long h = 1234; 993 * long[] words = toLongArray(); 994 * for (int i = words.length; --i >= 0; ) 995 * h ^= words[i] * (i + 1); 996 * return (int)((h >> 32) ^ h); 997 * }}</pre> 998 * Note that the hash code changes if the set of bits is altered. 999 * 1000 * @return the hash code value for this bit set 1001 */ 1002 override size_t toHash() @trusted nothrow { 1003 long h = 1234; 1004 for (size_t i = wordsInUse; --i >= 0; ) 1005 h ^= words[i] * (i + 1); 1006 1007 return cast(size_t)((h >> 32) ^ h); 1008 } 1009 1010 /** 1011 * Returns the number of bits of space actually in use by this 1012 * {@code BitSet} to represent bit values. 1013 * The maximum element in the set is the size - 1st element. 1014 * 1015 * @return the number of bits currently in this bit set 1016 */ 1017 size_t size() { 1018 return words.length * BITS_PER_WORD; 1019 } 1020 1021 /** 1022 * Compares this object against the specified object. 1023 * The result is {@code true} if and only if the argument is 1024 * not {@code null} and is a {@code Bitset} object that has 1025 * exactly the same set of bits set to {@code true} as this bit 1026 * set. That is, for every nonnegative {@code int} index {@code k}, 1027 * <pre>((BitSet)obj).get(k) == this.get(k)</pre> 1028 * must be true. The current sizes of the two bit sets are not compared. 1029 * 1030 * @param obj the object to compare with 1031 * @return {@code true} if the objects are the same; 1032 * {@code false} otherwise 1033 * @see #size() 1034 */ 1035 bool equals(Object obj) { 1036 if (this is obj) 1037 return true; 1038 1039 BitSet set = cast(BitSet) obj; 1040 if (set is null) 1041 return false; 1042 1043 checkInvariants(); 1044 set.checkInvariants(); 1045 1046 if (wordsInUse != set.wordsInUse) 1047 return false; 1048 1049 // Check words in use by both BitSets 1050 for (int i = 0; i < wordsInUse; i++) 1051 if (words[i] != set.words[i]) 1052 return false; 1053 1054 return true; 1055 } 1056 1057 // /** 1058 // * Cloning this {@code BitSet} produces a new {@code BitSet} 1059 // * that is equal to it. 1060 // * The clone of the bit set is another bit set that has exactly the 1061 // * same bits set to {@code true} as this bit set. 1062 // * 1063 // * @return a clone of this bit set 1064 // * @see #size() 1065 // */ 1066 // Object clone() { 1067 // if (! sizeIsSticky) 1068 // trimToSize(); 1069 1070 // try { 1071 // BitSet result = (BitSet) super.clone(); 1072 // result.words = words.clone(); 1073 // result.checkInvariants(); 1074 // return result; 1075 // } catch (CloneNotSupportedException e) { 1076 // throw new InternalError(e); 1077 // } 1078 // } 1079 1080 // /** 1081 // * Attempts to reduce internal storage used for the bits in this bit set. 1082 // * Calling this method may, but is not required to, affect the value 1083 // * returned by a subsequent call to the {@link #size()} method. 1084 // */ 1085 // private void trimToSize() { 1086 // if (wordsInUse != words.length) { 1087 // words = Arrays.copyOf(words, wordsInUse); 1088 // checkInvariants(); 1089 // } 1090 // } 1091 1092 // /** 1093 // * Save the state of the {@code BitSet} instance to a stream (i.e., 1094 // * serialize it). 1095 // */ 1096 // private void writeObject(ObjectOutputStream s) 1097 // throws IOException { 1098 1099 // checkInvariants(); 1100 1101 // if (! sizeIsSticky) 1102 // trimToSize(); 1103 1104 // ObjectOutputStream.PutField fields = s.putFields(); 1105 // fields.put("bits", words); 1106 // s.writeFields(); 1107 // } 1108 1109 // /** 1110 // * Reconstitute the {@code BitSet} instance from a stream (i.e., 1111 // * deserialize it). 1112 // */ 1113 // private void readObject(ObjectInputStream s) 1114 // throws IOException, ClassNotFoundException { 1115 1116 // ObjectInputStream.GetField fields = s.readFields(); 1117 // words = (long[]) fields.get("bits", null); 1118 1119 // // Assume maximum length then find real length 1120 // // because recalculateWordsInUse assumes maintenance 1121 // // or reduction in logical size 1122 // wordsInUse = words.length; 1123 // recalculateWordsInUse(); 1124 // sizeIsSticky = (words.length > 0 && words[words.length-1] == 0L); // heuristic 1125 // checkInvariants(); 1126 // } 1127 1128 // /** 1129 // * Returns a string representation of this bit set. For every index 1130 // * for which this {@code BitSet} contains a bit in the set 1131 // * state, the decimal representation of that index is included in 1132 // * the result. Such indices are listed in order from lowest to 1133 // * highest, separated by ", " (a comma and a space) and 1134 // * surrounded by braces, resulting in the usual mathematical 1135 // * notation for a set of integers. 1136 // * 1137 // * <p>Example: 1138 // * <pre> 1139 // * BitSet drPepper = new BitSet();</pre> 1140 // * Now {@code drPepper.toString()} returns "{@code {}}". 1141 // * <pre> 1142 // * drPepper.set(2);</pre> 1143 // * Now {@code drPepper.toString()} returns "{@code {2}}". 1144 // * <pre> 1145 // * drPepper.set(4); 1146 // * drPepper.set(10);</pre> 1147 // * Now {@code drPepper.toString()} returns "{@code {2, 4, 10}}". 1148 // * 1149 // * @return a string representation of this bit set 1150 // */ 1151 // String toString() { 1152 // checkInvariants(); 1153 1154 // int numBits = (wordsInUse > 128) ? 1155 // cardinality() : wordsInUse * BITS_PER_WORD; 1156 // StringBuilder b = new StringBuilder(6*numBits + 2); 1157 // b.append('{'); 1158 1159 // int i = nextSetBit(0); 1160 // if (i != -1) { 1161 // b.append(i); 1162 // while (true) { 1163 // if (++i < 0) break; 1164 // if ((i = nextSetBit(i)) < 0) break; 1165 // int endOfRun = nextClearBit(i); 1166 // do { b.append(", ").append(i); } 1167 // while (++i != endOfRun); 1168 // } 1169 // } 1170 1171 // b.append('}'); 1172 // return b.toString(); 1173 // } 1174 1175 // /** 1176 // * Returns a stream of indices for which this {@code BitSet} 1177 // * contains a bit in the set state. The indices are returned 1178 // * in order, from lowest to highest. The size of the stream 1179 // * is the number of bits in the set state, equal to the value 1180 // * returned by the {@link #cardinality()} method. 1181 // * 1182 // * <p>The stream binds to this bit set when the terminal stream operation 1183 // * commences (specifically, the spliterator for the stream is 1184 // * <a href="Spliterator.html#binding"><em>late-binding</em></a>). If the 1185 // * bit set is modified during that operation then the result is undefined. 1186 // * 1187 // * @return a stream of integers representing set indices 1188 // */ 1189 // IntStream stream() { 1190 // class BitSetSpliterator implements Spliterator.OfInt { 1191 // private int index; // current bit index for a set bit 1192 // private int fence; // -1 until used; then one past last bit index 1193 // private int est; // size estimate 1194 // private bool root; // true if root and not split 1195 // // root == true then size estimate is accurate 1196 // // index == -1 or index >= fence if fully traversed 1197 // // Special case when the max bit set is Integer.MAX_VALUE 1198 1199 // BitSetSpliterator(int origin, int fence, int est, bool root) { 1200 // this.index = origin; 1201 // this.fence = fence; 1202 // this.est = est; 1203 // this.root = root; 1204 // } 1205 1206 // private int getFence() { 1207 // int hi; 1208 // if ((hi = fence) < 0) { 1209 // // Round up fence to maximum cardinality for allocated words 1210 // // This is sufficient and cheap for sequential access 1211 // // When splitting this value is lowered 1212 // hi = fence = (wordsInUse >= wordIndex(Integer.MAX_VALUE)) 1213 // ? Integer.MAX_VALUE 1214 // : wordsInUse << ADDRESS_BITS_PER_WORD; 1215 // est = cardinality(); 1216 // index = nextSetBit(0); 1217 // } 1218 // return hi; 1219 // } 1220 1221 // @Override 1222 // bool tryAdvance(IntConsumer action) { 1223 // Objects.requireNonNull(action); 1224 1225 // int hi = getFence(); 1226 // int i = index; 1227 // if (i < 0 || i >= hi) { 1228 // // Check if there is a final bit set for Integer.MAX_VALUE 1229 // if (i == Integer.MAX_VALUE && hi == Integer.MAX_VALUE) { 1230 // index = -1; 1231 // action.accept(Integer.MAX_VALUE); 1232 // return true; 1233 // } 1234 // return false; 1235 // } 1236 1237 // index = nextSetBit(i + 1, wordIndex(hi - 1)); 1238 // action.accept(i); 1239 // return true; 1240 // } 1241 1242 // @Override 1243 // void forEachRemaining(IntConsumer action) { 1244 // Objects.requireNonNull(action); 1245 1246 // int hi = getFence(); 1247 // int i = index; 1248 // index = -1; 1249 1250 // if (i >= 0 && i < hi) { 1251 // action.accept(i++); 1252 1253 // int u = wordIndex(i); // next lower word bound 1254 // int v = wordIndex(hi - 1); // upper word bound 1255 1256 // words_loop: 1257 // for (; u <= v && i <= hi; u++, i = u << ADDRESS_BITS_PER_WORD) { 1258 // long word = words[u] & (WORD_MASK << i); 1259 // while (word != 0) { 1260 // i = (u << ADDRESS_BITS_PER_WORD) + Long.numberOfTrailingZeros(word); 1261 // if (i >= hi) { 1262 // // Break out of outer loop to ensure check of 1263 // // Integer.MAX_VALUE bit set 1264 // break words_loop; 1265 // } 1266 1267 // // Flip the set bit 1268 // word &= ~(1L << i); 1269 1270 // action.accept(i); 1271 // } 1272 // } 1273 // } 1274 1275 // // Check if there is a final bit set for Integer.MAX_VALUE 1276 // if (i == Integer.MAX_VALUE && hi == Integer.MAX_VALUE) { 1277 // action.accept(Integer.MAX_VALUE); 1278 // } 1279 // } 1280 1281 // @Override 1282 // OfInt trySplit() { 1283 // int hi = getFence(); 1284 // int lo = index; 1285 // if (lo < 0) { 1286 // return null; 1287 // } 1288 1289 // // Lower the fence to be the upper bound of last bit set 1290 // // The index is the first bit set, thus this spliterator 1291 // // covers one bit and cannot be split, or two or more 1292 // // bits 1293 // hi = fence = (hi < Integer.MAX_VALUE || !get(Integer.MAX_VALUE)) 1294 // ? previousSetBit(hi - 1) + 1 1295 // : Integer.MAX_VALUE; 1296 1297 // // Find the mid point 1298 // int mid = (lo + hi) >>> 1; 1299 // if (lo >= mid) { 1300 // return null; 1301 // } 1302 1303 // // Raise the index of this spliterator to be the next set bit 1304 // // from the mid point 1305 // index = nextSetBit(mid, wordIndex(hi - 1)); 1306 // root = false; 1307 1308 // // Don't lower the fence (mid point) of the returned spliterator, 1309 // // traversal or further splitting will do that work 1310 // return new BitSetSpliterator(lo, mid, est >>>= 1, false); 1311 // } 1312 1313 // @Override 1314 // long estimateSize() { 1315 // getFence(); // force init 1316 // return est; 1317 // } 1318 1319 // @Override 1320 // int characteristics() { 1321 // // Only sized when root and not split 1322 // return (root ? Spliterator.SIZED : 0) | 1323 // Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.SORTED; 1324 // } 1325 1326 // @Override 1327 // Comparator<? super Integer> getComparator() { 1328 // return null; 1329 // } 1330 // } 1331 // return StreamSupport.intStream(new BitSetSpliterator(0, -1, 0, true), false); 1332 // } 1333 1334 // /** 1335 // * Returns the index of the first bit that is set to {@code true} 1336 // * that occurs on or after the specified starting index and up to and 1337 // * including the specified word index 1338 // * If no such bit exists then {@code -1} is returned. 1339 // * 1340 // * @param fromIndex the index to start checking from (inclusive) 1341 // * @param toWordIndex the last word index to check (inclusive) 1342 // * @return the index of the next set bit, or {@code -1} if there 1343 // * is no such bit 1344 // */ 1345 // private int nextSetBit(int fromIndex, int toWordIndex) { 1346 // int u = wordIndex(fromIndex); 1347 // // Check if out of bounds 1348 // if (u > toWordIndex) 1349 // return -1; 1350 1351 // long word = words[u] & (WORD_MASK << fromIndex); 1352 1353 // while (true) { 1354 // if (word != 0) 1355 // return (u * BITS_PER_WORD) + Long.numberOfTrailingZeros(word); 1356 // // Check if out of bounds 1357 // if (++u > toWordIndex) 1358 // return -1; 1359 // word = words[u]; 1360 // } 1361 // } 1362 1363 }