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 ",&nbsp;" (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 }