1 package antlr.collections.impl;
2
3 import antlr.CharFormatter;
4
5 * Primary differences are that most set operators return new sets
7 * as opposed to oring and anding "in place". Further, a number of
8 * operations were added. I cannot contain a BitSet because there
9 * is no way to access the internal bits (which I need for speed)
10 * and, because it is final, I cannot subclass to add functionality.
11 * Consider defining set degree. Without access to the bits, I must
12 * call a method n times to test the ith bit...ack!
13 *
14 * Also seems like or() from util is wrong when size of incoming set is bigger
15 * than this.bits.length.
16 *
17 * @author Terence Parr, MageLang Institute
18 * @author <br><a href="mailto:pete@yamuna.demon.co.uk">Pete Wells</a>
19 */
20 public class BitSet implements Cloneable {
21 protected final static int BITS = 64; protected final static int NIBBLE = 4;
23 protected final static int LOG_BITS = 6; * that, for powers of two, this mod operation is same as (i & (nbits-1)).
26 * Since mod is slow, we use a precomputed mod mask to do the mod instead.
27 */
28 protected final static int MOD_MASK = BITS-1;
29 protected long bits[];
30
31
32
33 public BitSet() {
34 this(BITS);
35 }
36
37 public BitSet(long[] bits_)
38 {
39 bits = bits_;
40 }
41 * @param nbits The size of the bitset in bits
43 */
44 public BitSet(int nbits) {
45 bits = new long[((nbits-1) >> LOG_BITS) + 1];
46 }
47 public void add(int el) {
49 int n = wordNumber(el);
51 if (n >= bits.length) {
54 growToInclude(el);
55 }
56 bits[n] |= bitMask(el);
57 }
58 public BitSet and(BitSet a) {
59 BitSet s = (BitSet)this.clone();
60 s.andInPlace(a);
61 return s;
62 }
63 public void andInPlace(BitSet a) {
64 int min = Math.min(bits.length, a.bits.length);
65 for (int i = min-1; i >= 0; i--) {
66 bits[i] &= a.bits[i];
67 }
68 for (int i = min; i < bits.length ; i++) {
70 bits[i] = 0;
71 }
72 }
73 private final long bitMask(int bitNumber) {
74 int bitPosition = bitNumber&MOD_MASK; return 1L << bitPosition;
76 }
77 public void clear() {
78 for (int i = bits.length-1; i >= 0; i--) {
79 bits[i] = 0;
80 }
81 }
82 public void clear(int el) {
83 int n = wordNumber(el);
84 if (n >= bits.length) { growToInclude(el);
86 }
87 bits[n] &= ~bitMask(el);
88 }
89 public Object clone() {
90 BitSet s;
91 try {
92 s = (BitSet)super.clone();
93 s.bits = new long[bits.length];
94 System.arraycopy(bits, 0, s.bits, 0, bits.length);
95 }
96 catch (CloneNotSupportedException e) {
97 throw new InternalError();
98 }
99 return s;
100 }
101 public int degree() {
102 int deg = 0;
103 for (int i=bits.length-1; i>=0; i--) {
104 long word = bits[i];
105 if (word != 0L) {
106 for (int bit=BITS-1; bit>=0; bit--) {
107 if ( (word & (1L << bit)) != 0 ) {
108 deg++;
109 }
110 }
111 }
112 }
113 return deg;
114 }
115 public boolean equals(Object obj) {
117 if ((obj != null) && (obj instanceof BitSet)) {
118 BitSet set = (BitSet)obj;
119
120 int n = Math.min(bits.length, set.bits.length);
121 for (int i = n ; i-- > 0 ;) {
122 if (bits[i] != set.bits[i]) {
123 return false;
124 }
125 }
126 if (bits.length > n) {
127 for (int i = bits.length ; i-- > n ;) {
128 if (bits[i] != 0) {
129 return false;
130 }
131 }
132 } else if (set.bits.length > n) {
133 for (int i = set.bits.length ; i-- > n ;) {
134 if (set.bits[i] != 0) {
135 return false;
136 }
137 }
138 }
139 return true;
140 }
141 return false;
142 }
143 * @param elems The array of elements representing the set, usually from Bit
145 Set.toArray().
146 * @return Vector of ranges.
147 */
148 public static Vector getRanges(int[] elems) {
149 if (elems.length==0) {
150 return null;
151 }
152 int begin = elems[0];
153 int end = elems[elems.length-1];
154 if ( elems.length<=2 ) {
155 return null;
157 }
158
159 Vector ranges = new Vector(5);
160 for (int i=0; i<elems.length-2; i++) {
162 int lastInRange;
163 lastInRange = elems.length-1;
164 for (int j=i+1; j<elems.length; j++) {
165 if ( elems[j] != elems[j-1]+1 ) {
166 lastInRange = j-1;
167 break;
168 }
169 }
170 if ( lastInRange-i > 2 ) {
172 ranges.appendElement(new IntRange(elems[i],elems[lastInRange]));
173 }
174 }
175 return ranges;
176 }
177 * Grows the set to a larger number of bits.
179 * @param bit element that must fit in set
180 */
181 public void growToInclude(int bit) {
182 int newSize = Math.max(bits.length<<1, numWordsToHold(bit));
183 long newbits[] = new long[newSize];
184 System.arraycopy(bits, 0, newbits, 0, bits.length);
185 bits = newbits;
186 }
187 public boolean member(int el) {
188 int n = wordNumber(el);
189 if (n > bits.length) return false;
190 return (bits[n] & bitMask(el)) != 0;
191 }
192 public boolean nil() {
193 for (int i=bits.length-1; i>=0; i--) {
194 if ( bits[i]!=0 ) return false;
195 }
196 return true;
197 }
198 public BitSet not() {
199 BitSet s = (BitSet)this.clone();
200 s.notInPlace();
201 return s;
202 }
203 public void notInPlace() {
204 for (int i = bits.length-1; i >= 0; i--) {
205 bits[i] = ~bits[i];
206 }
207 }
208
209 public void notInPlace(int maxBit) {
210 notInPlace(0, maxBit);
211 }
212
213 public void notInPlace(int minBit, int maxBit) {
214 growToInclude(maxBit);
216 for (int i = minBit; i <= maxBit; i++) {
217 int n = wordNumber(i);
218 bits[n] ^= bitMask(i);
219 }
220 }
221 private final int numWordsToHold(int el) {
222 return (el>>LOG_BITS) + 1;
223 }
224 public static BitSet of(int el) {
225 BitSet s = new BitSet(el+1);
226 s.add(el);
227 return s;
228 }
229
230 public BitSet or(BitSet a) {
231 BitSet s = (BitSet)this.clone();
232 s.orInPlace(a);
233 return s;
234 }
235 public void orInPlace(BitSet a) {
236 if ( a.bits.length > bits.length ) {
238 setSize(a.bits.length);
239 }
240 int min = Math.min(bits.length, a.bits.length);
241 for (int i = min-1; i >= 0; i--) {
242 bits[i] |= a.bits[i];
243 }
244 }
245 public void remove(int el) {
247 int n = wordNumber(el);
248 if (n >= bits.length) {
249 growToInclude(el);
250 }
251 bits[n] &= ~bitMask(el);
252 }
253 * Sets the size of a set.
255 * @param nwords how many words the new set should be
256 */
257 private void setSize(int nwords) {
258 long newbits[] = new long[nwords];
259 int n = Math.min(nwords, bits.length);
260 System.arraycopy(bits, 0, newbits, 0, n);
261 bits = newbits;
262 }
263 public int size() {
264 return bits.length << LOG_BITS; }
266
267 public boolean subset(BitSet a) {
268 if ( a==null || !(a instanceof BitSet) ) return false;
269 return this.and(a).equals(this);
270 }
271 * Basically, just turn off all bits of 'this' that are in 'a'.
273 */
274 public void subtractInPlace(BitSet a) {
275 if ( a==null ) return;
276 for (int i = 0; i<bits.length&&i<a.bits.length; i++) {
278 bits[i] &= ~a.bits[i];
279 }
280 }
281 public int[] toArray() {
282 int[] elems = new int[degree()];
283 int en = 0;
284 for (int i = 0; i < (bits.length << LOG_BITS); i++) {
285 if (member(i)) {
286 elems[en++] = i;
287 }
288 }
289 return elems;
290 }
291 public String toString() {
292 return toString(",");
293 }
294 * @separator The string to put in between elements
296 * @return A commma-separated list of values
297 */
298 public String toString(String separator) {
299 String str = "";
300 for (int i = 0; i < (bits.length << LOG_BITS); i++) {
301 if (member(i)) {
302 if (str.length() > 0) {
303 str += separator;
304 }
305 str = str + i;
306 }
307 }
308 return str;
309 }
310 * @separator The string to put in between elements
312 * @param formatter An object implementing the CharFormatter interface.
313 * @return A commma-separated list of character constants.
314 */
315 public String toString(String separator, CharFormatter formatter) {
316 String str = "";
317
318 for (int i = 0; i < (bits.length << LOG_BITS); i++) {
319 if (member(i)) {
320 if (str.length() > 0) {
321 str += separator;
322 }
323 str = str + formatter.literalChar(i);
324 }
325 }
326 return str;
327 }
328 * ith element of vocabulary is displayed instead. Vocabulary is a Vector
330 * of Strings.
331 * @separator The string to put in between elements
332 * @return A commma-separated list of character constants.
333 */
334 public String toString(String separator, Vector vocabulary) {
335 if ( vocabulary == null ) {
336 return toString(separator);
337 }
338 String str = "";
339 for (int i = 0; i < (bits.length << LOG_BITS); i++) {
340 if (member(i)) {
341 if (str.length() > 0) {
342 str += separator;
343 }
344 if ( i>=vocabulary.size() ) {
345 str += "<bad element "+i+">";
346 }
347 else if ( vocabulary.elementAt(i)==null ) {
348 str += "<"+i+">";
349 }
350 else {
351 str += (String)vocabulary.elementAt(i);
352 }
353 }
354 }
355 return str;
356 }
357 * Dump a comma-separated list of the words making up the bit set.
359 * Split each 64 bit number into two more manageable 32 bit numbers.
360 * This generates a comma-separated list of C++-like unsigned long constants.
361 */
362 public String toStringOfHalfWords()
363 {
364 String s = new String();
365 for (int i = 0; i < bits.length; i++)
366 {
367 if (i!=0) s += ", ";
368 long tmp = bits[i];
369 tmp &= 0xFFFFFFFFL;
370 s += (tmp + "UL");
371 s += ", ";
372 tmp = bits[i]>>>32;
373 tmp &= 0xFFFFFFFFL;
374 s += (tmp + "UL");
375 }
376 return s;
377 }
378 * Dump a comma-separated list of the words making up the bit set.
380 * This generates a comma-separated list of Java-like long int constants.
381 */
382 public String toStringOfWords()
383 {
384 String s = new String();
385 for (int i = 0; i < bits.length; i++)
386 {
387 if (i!=0) s += ", ";
388 s += (bits[i] + "L");
389 }
390 return s;
391 }
392 */
394 public String toStringWithRanges(String separator, CharFormatter formatter) {
395 String str = "";
396 int[] elems = this.toArray();
397 if (elems.length==0) {
398 return "";
399 }
400 int i=0;
402 while (i<elems.length) {
403 int lastInRange;
404 lastInRange = 0;
405 for (int j=i+1; j<elems.length; j++) {
406 if ( elems[j] != elems[j-1]+1 ) {
407 break;
408 }
409 lastInRange = j;
410 }
411 if (str.length() > 0) {
413 str += separator;
414 }
415 if ( lastInRange-i >= 2 ) {
416 str += formatter.literalChar(elems[i]);
417 str += "..";
418 str += formatter.literalChar(elems[lastInRange]);
419 i = lastInRange; }
421 else { str += formatter.literalChar(elems[i]);
423 }
424 i++;
425 }
426 return str;
427 }
428 private final int wordNumber(int bit) {
429 return bit>>LOG_BITS; }
431 }
432