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}