001package regexodus.ds;
002
003import java.util.Arrays;
004
005/**
006 * An implementation of BitSet (that does not technically extend BitSet due to BitSet not existing under GWT) using 32-bit
007 * sections instead of the normal 64-bit (again, for GWT reasons; 64-bit integer math is slower on GWT).
008 * Created by Tommy Ettinger on 3/30/2016.
009 */
010public class IntBitSet {
011    private int[] data;
012    public IntBitSet() {
013        data = new int[8];
014    }
015
016    public IntBitSet(int disregard)
017    {
018        this();
019    }
020
021    /**
022     * Constructs a CharBitSet that includes all bits between start and end, inclusive.
023     * @param start inclusive
024     * @param end inclusive
025     */
026    public IntBitSet(int start, int end) {
027        data = new int[8];
028        set(start, end+1);
029    }
030    public IntBitSet(int[] ints) {
031        data = new int[8];
032        System.arraycopy(ints, 0, data, 0, Math.min(8, ints.length));
033    }
034
035    public void flip(int bitIndex) {
036        data[bitIndex >> 5] ^= 1 << (bitIndex & 31);
037    }
038
039    public void flip(int fromIndex, int toIndex) {
040        for (int i = fromIndex; i <= toIndex; i++) {
041            data[i >> 5] ^= 1 << (i & 31);
042        }
043    }
044
045    public void set(int bitIndex) {
046        data[bitIndex >> 5] |= 1 << (bitIndex & 31);
047    }
048
049    public void set(int bitIndex, boolean value) {
050        data[bitIndex >> 5] ^= ((value ? -1 : 0) ^ data[bitIndex >> 5]) & (1 << (bitIndex & 31));
051    }
052
053    public void set(int fromIndex, int toIndex) {
054        for (int i = fromIndex; i <= toIndex; i++) {
055            data[i >> 5] |= 1 << (i & 31);
056        }
057    }
058
059    public void set(int fromIndex, int toIndex, boolean value) {
060        int val = (value ? -1 : 0);
061        for (int bitIndex = fromIndex; bitIndex <= toIndex; bitIndex++) {
062            data[bitIndex >> 5] ^= (val ^ data[bitIndex >> 5]) & (1 << (bitIndex & 31));
063        }
064
065    }
066
067    public void clear(int bitIndex) {
068        data[bitIndex >> 5] &= ~(1 << (bitIndex & 31));
069    }
070
071    public void clear(int fromIndex, int toIndex) {
072        for (int bitIndex = fromIndex; bitIndex <= toIndex; bitIndex++) {
073            data[bitIndex >> 5] &= ~(1 << (bitIndex & 31));
074        }
075    }
076
077    public void clear() {
078        Arrays.fill(data, 0);
079    }
080
081    public boolean get(int bitIndex) {
082        return ((data[bitIndex >> 5] >> (bitIndex & 31)) & 1) != 0;
083    }
084
085    public IntBitSet get(int fromIndex, int toIndex) {
086        IntBitSet ibs = new IntBitSet();
087        for (int bitIndex = fromIndex; bitIndex <= toIndex; bitIndex++) {
088            ibs.set(bitIndex, get(bitIndex));
089        }
090        return ibs;
091    }
092
093    public int length() {
094        return 32 * data.length;
095    }
096
097    public boolean isEmpty() {
098        for (int i = 0; i < 8; i++) {
099            if(data[i] != 0)
100                return false;
101        }
102        return true;
103    }
104
105    public boolean intersects(IntBitSet set) {
106        for (int i = 0; i < 8; i++) {
107            if((data[i] & set.data[i]) != 0)
108                return true;
109        }
110        return false;
111    }
112
113    public int cardinality() {
114        int card = 0;
115        for (int i = 0; i < 8; i++) {
116            card += Integer.bitCount(data[i]);
117        }
118        return card;
119    }
120
121    public IntBitSet and(IntBitSet set) {
122        for (int i = 0; i < 8; i++) {
123            data[i] &= set.data[i];
124        }
125        return this;
126    }
127
128    public IntBitSet or(IntBitSet set) {
129        for (int i = 0; i < 8; i++) {
130            data[i] |= set.data[i];
131        }
132        return this;
133    }
134
135    public IntBitSet xor(IntBitSet set) {
136        for (int i = 0; i < 8; i++) {
137            data[i] ^= set.data[i];
138        }
139        return this;
140    }
141
142    public IntBitSet andNot(IntBitSet set) {
143        for (int i = 0; i < 8; i++) {
144            data[i] &= ~set.data[i];
145        }
146        return this;
147    }
148    public IntBitSet negate()
149    {
150        for (int i = 0; i < 8; i++) {
151            data[i] = ~data[i];
152        }
153        return this;
154    }
155    public int nextSetBit(int current)
156    {
157        int low = 0;
158        for (int i = current >>> 5; i < 8; i++) {
159            if (current % 32 != 31)
160                low += Integer.numberOfTrailingZeros(Integer.lowestOneBit(data[(current) >>> 5] >>> (current & 31)));
161            if (low != 32)
162                return current + low;
163            current = ((current >>> 5) + 1) * 32;
164        }
165        return -1;
166    }
167    public int nextClearBit(int current)
168    {
169        int low = 0;
170        for (int i = current >>> 5; i < 8; i++) {
171            if (current % 32 != 31)
172                low += Integer.numberOfTrailingZeros(Integer.lowestOneBit(~(data[(current) >>> 5] >>> (current & 31))));
173            if (low != 32)
174                return current + low;
175            current = ((current >>> 5) + 1) * 32;
176        }
177        return -1;
178    }
179
180    public int size() {
181        return 256;
182    }
183
184    @Override
185    public boolean equals(Object o) {
186        if (this == o) return true;
187        if (o == null || getClass() != o.getClass()) return false;
188
189        IntBitSet intBitSet = (IntBitSet) o;
190
191        return Arrays.equals(data, intBitSet.data);
192
193    }
194
195    @Override
196    public int hashCode() {
197        return Arrays.hashCode(data);
198    }
199
200    public IntBitSet clone() {
201        return new IntBitSet(data);
202    }
203
204}