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