/lib/antlr-2.7.5/antlr/collections/impl/BitSet.java
Java | 483 lines | 341 code | 48 blank | 94 comment | 84 complexity | c9f9debc45c1a5c31ddd3bfa318a6b60 MD5 | raw file
Possible License(s): GPL-2.0
- package antlr.collections.impl;
- /* ANTLR Translator Generator
- * Project led by Terence Parr at http://www.jGuru.com
- * Software rights: http://www.antlr.org/license.html
- *
- * $Id: //depot/code/org.antlr/release/antlr-2.7.5/antlr/collections/impl/BitSet.java#1 $
- */
- import antlr.CharFormatter;
- /**A BitSet to replace java.util.BitSet.
- * Primary differences are that most set operators return new sets
- * as opposed to oring and anding "in place". Further, a number of
- * operations were added. I cannot contain a BitSet because there
- * is no way to access the internal bits (which I need for speed)
- * and, because it is final, I cannot subclass to add functionality.
- * Consider defining set degree. Without access to the bits, I must
- * call a method n times to test the ith bit...ack!
- *
- * Also seems like or() from util is wrong when size of incoming set is bigger
- * than this.bits.length.
- *
- * @author Terence Parr
- * @author <br><a href="mailto:pete@yamuna.demon.co.uk">Pete Wells</a>
- */
- public class BitSet implements Cloneable {
- protected final static int BITS = 64; // number of bits / long
- protected final static int NIBBLE = 4;
- protected final static int LOG_BITS = 6; // 2^6 == 64
- /* We will often need to do a mod operator (i mod nbits). Its
- * turns out that, for powers of two, this mod operation is
- * same as (i & (nbits-1)). Since mod is slow, we use a
- * precomputed mod mask to do the mod instead.
- */
- protected final static int MOD_MASK = BITS - 1;
- /** The actual data bits */
- protected long bits[];
- /** Construct a bitset of size one word (64 bits) */
- public BitSet() {
- this(BITS);
- }
- /** Construction from a static array of longs */
- public BitSet(long[] bits_) {
- bits = bits_;
- }
- /** Construct a bitset given the size
- * @param nbits The size of the bitset in bits
- */
- public BitSet(int nbits) {
- bits = new long[((nbits - 1) >> LOG_BITS) + 1];
- }
- /** or this element into this set (grow as necessary to accommodate) */
- public void add(int el) {
- //System.out.println("add("+el+")");
- int n = wordNumber(el);
- //System.out.println("word number is "+n);
- //System.out.println("bits.length "+bits.length);
- if (n >= bits.length) {
- growToInclude(el);
- }
- bits[n] |= bitMask(el);
- }
- public BitSet and(BitSet a) {
- BitSet s = (BitSet)this.clone();
- s.andInPlace(a);
- return s;
- }
- public void andInPlace(BitSet a) {
- int min = Math.min(bits.length, a.bits.length);
- for (int i = min - 1; i >= 0; i--) {
- bits[i] &= a.bits[i];
- }
- // clear all bits in this not present in a (if this bigger than a).
- for (int i = min; i < bits.length; i++) {
- bits[i] = 0;
- }
- }
- private final static long bitMask(int bitNumber) {
- int bitPosition = bitNumber & MOD_MASK; // bitNumber mod BITS
- return 1L << bitPosition;
- }
- public void clear() {
- for (int i = bits.length - 1; i >= 0; i--) {
- bits[i] = 0;
- }
- }
- public void clear(int el) {
- int n = wordNumber(el);
- if (n >= bits.length) { // grow as necessary to accommodate
- growToInclude(el);
- }
- bits[n] &= ~bitMask(el);
- }
- public Object clone() {
- BitSet s;
- try {
- s = (BitSet)super.clone();
- s.bits = new long[bits.length];
- System.arraycopy(bits, 0, s.bits, 0, bits.length);
- }
- catch (CloneNotSupportedException e) {
- throw new InternalError();
- }
- return s;
- }
- public int degree() {
- int deg = 0;
- for (int i = bits.length - 1; i >= 0; i--) {
- long word = bits[i];
- if (word != 0L) {
- for (int bit = BITS - 1; bit >= 0; bit--) {
- if ((word & (1L << bit)) != 0) {
- deg++;
- }
- }
- }
- }
- return deg;
- }
- /** code "inherited" from java.util.BitSet */
- public boolean equals(Object obj) {
- if ((obj != null) && (obj instanceof BitSet)) {
- BitSet set = (BitSet)obj;
- int n = Math.min(bits.length, set.bits.length);
- for (int i = n; i-- > 0;) {
- if (bits[i] != set.bits[i]) {
- return false;
- }
- }
- if (bits.length > n) {
- for (int i = bits.length; i-- > n;) {
- if (bits[i] != 0) {
- return false;
- }
- }
- }
- else if (set.bits.length > n) {
- for (int i = set.bits.length; i-- > n;) {
- if (set.bits[i] != 0) {
- return false;
- }
- }
- }
- return true;
- }
- return false;
- }
- /** Find ranges in a set element array. @param elems The array of
- * elements representing the set, usually from Bit Set.toArray().
- * @return Vector of ranges.
- */
- public static Vector getRanges(int[] elems) {
- if (elems.length == 0) {
- return null;
- }
- int begin = elems[0];
- int end = elems[elems.length - 1];
- if (elems.length <= 2) {
- // Not enough elements for a range expression
- return null;
- }
- Vector ranges = new Vector(5);
- // look for ranges
- for (int i = 0; i < elems.length - 2; i++) {
- int lastInRange;
- lastInRange = elems.length - 1;
- for (int j = i + 1; j < elems.length; j++) {
- if (elems[j] != elems[j - 1] + 1) {
- lastInRange = j - 1;
- break;
- }
- }
- // found a range
- if (lastInRange - i > 2) {
- ranges.appendElement(new IntRange(elems[i], elems[lastInRange]));
- }
- }
- return ranges;
- }
- /**
- * Grows the set to a larger number of bits.
- * @param bit element that must fit in set
- */
- public void growToInclude(int bit) {
- int newSize = Math.max(bits.length << 1, numWordsToHold(bit));
- long newbits[] = new long[newSize];
- System.arraycopy(bits, 0, newbits, 0, bits.length);
- bits = newbits;
- }
- public boolean member(int el) {
- int n = wordNumber(el);
- if (n >= bits.length) return false;
- return (bits[n] & bitMask(el)) != 0;
- }
- public boolean nil() {
- for (int i = bits.length - 1; i >= 0; i--) {
- if (bits[i] != 0) return false;
- }
- return true;
- }
- public BitSet not() {
- BitSet s = (BitSet)this.clone();
- s.notInPlace();
- return s;
- }
- public void notInPlace() {
- for (int i = bits.length - 1; i >= 0; i--) {
- bits[i] = ~bits[i];
- }
- }
- /** complement bits in the range 0..maxBit. */
- public void notInPlace(int maxBit) {
- notInPlace(0, maxBit);
- }
- /** complement bits in the range minBit..maxBit.*/
- public void notInPlace(int minBit, int maxBit) {
- // make sure that we have room for maxBit
- growToInclude(maxBit);
- for (int i = minBit; i <= maxBit; i++) {
- int n = wordNumber(i);
- bits[n] ^= bitMask(i);
- }
- }
- private final int numWordsToHold(int el) {
- return (el >> LOG_BITS) + 1;
- }
- public static BitSet of(int el) {
- BitSet s = new BitSet(el + 1);
- s.add(el);
- return s;
- }
- /** return this | a in a new set */
- public BitSet or(BitSet a) {
- BitSet s = (BitSet)this.clone();
- s.orInPlace(a);
- return s;
- }
- public void orInPlace(BitSet a) {
- // If this is smaller than a, grow this first
- if (a.bits.length > bits.length) {
- setSize(a.bits.length);
- }
- int min = Math.min(bits.length, a.bits.length);
- for (int i = min - 1; i >= 0; i--) {
- bits[i] |= a.bits[i];
- }
- }
- // remove this element from this set
- public void remove(int el) {
- int n = wordNumber(el);
- if (n >= bits.length) {
- growToInclude(el);
- }
- bits[n] &= ~bitMask(el);
- }
- /**
- * Sets the size of a set.
- * @param nwords how many words the new set should be
- */
- private void setSize(int nwords) {
- long newbits[] = new long[nwords];
- int n = Math.min(nwords, bits.length);
- System.arraycopy(bits, 0, newbits, 0, n);
- bits = newbits;
- }
- public int size() {
- return bits.length << LOG_BITS; // num words * bits per word
- }
- /** return how much space is being used by the bits array not
- * how many actually have member bits on.
- */
- public int lengthInLongWords() {
- return bits.length;
- }
- /**Is this contained within a? */
- public boolean subset(BitSet a) {
- if (a == null || !(a instanceof BitSet)) return false;
- return this.and(a).equals(this);
- }
- /**Subtract the elements of 'a' from 'this' in-place.
- * Basically, just turn off all bits of 'this' that are in 'a'.
- */
- public void subtractInPlace(BitSet a) {
- if (a == null) return;
- // for all words of 'a', turn off corresponding bits of 'this'
- for (int i = 0; i < bits.length && i < a.bits.length; i++) {
- bits[i] &= ~a.bits[i];
- }
- }
- public int[] toArray() {
- int[] elems = new int[degree()];
- int en = 0;
- for (int i = 0; i < (bits.length << LOG_BITS); i++) {
- if (member(i)) {
- elems[en++] = i;
- }
- }
- return elems;
- }
- public long[] toPackedArray() {
- return bits;
- }
- public String toString() {
- return toString(",");
- }
- /** Transform a bit set into a string by formatting each element as an integer
- * @separator The string to put in between elements
- * @return A commma-separated list of values
- */
- public String toString(String separator) {
- String str = "";
- for (int i = 0; i < (bits.length << LOG_BITS); i++) {
- if (member(i)) {
- if (str.length() > 0) {
- str += separator;
- }
- str = str + i;
- }
- }
- return str;
- }
- /** Transform a bit set into a string of characters.
- * @separator The string to put in between elements
- * @param formatter An object implementing the CharFormatter interface.
- * @return A commma-separated list of character constants.
- */
- public String toString(String separator, CharFormatter formatter) {
- String str = "";
- for (int i = 0; i < (bits.length << LOG_BITS); i++) {
- if (member(i)) {
- if (str.length() > 0) {
- str += separator;
- }
- str = str + formatter.literalChar(i);
- }
- }
- return str;
- }
- /**Create a string representation where instead of integer elements, the
- * ith element of vocabulary is displayed instead. Vocabulary is a Vector
- * of Strings.
- * @separator The string to put in between elements
- * @return A commma-separated list of character constants.
- */
- public String toString(String separator, Vector vocabulary) {
- if (vocabulary == null) {
- return toString(separator);
- }
- String str = "";
- for (int i = 0; i < (bits.length << LOG_BITS); i++) {
- if (member(i)) {
- if (str.length() > 0) {
- str += separator;
- }
- if (i >= vocabulary.size()) {
- str += "<bad element " + i + ">";
- }
- else if (vocabulary.elementAt(i) == null) {
- str += "<" + i + ">";
- }
- else {
- str += (String)vocabulary.elementAt(i);
- }
- }
- }
- return str;
- }
- /**
- * Dump a comma-separated list of the words making up the bit set.
- * Split each 64 bit number into two more manageable 32 bit numbers.
- * This generates a comma-separated list of C++-like unsigned long constants.
- */
- public String toStringOfHalfWords() {
- String s = new String();
- for (int i = 0; i < bits.length; i++) {
- if (i != 0) s += ", ";
- long tmp = bits[i];
- tmp &= 0xFFFFFFFFL;
- s += (tmp + "UL");
- s += ", ";
- tmp = bits[i] >>> 32;
- tmp &= 0xFFFFFFFFL;
- s += (tmp + "UL");
- }
- return s;
- }
- /**
- * Dump a comma-separated list of the words making up the bit set.
- * This generates a comma-separated list of Java-like long int constants.
- */
- public String toStringOfWords() {
- String s = new String();
- for (int i = 0; i < bits.length; i++) {
- if (i != 0) s += ", ";
- s += (bits[i] + "L");
- }
- return s;
- }
- /** Print out the bit set but collapse char ranges. */
- public String toStringWithRanges(String separator, CharFormatter formatter) {
- String str = "";
- int[] elems = this.toArray();
- if (elems.length == 0) {
- return "";
- }
- // look for ranges
- int i = 0;
- while (i < elems.length) {
- int lastInRange;
- lastInRange = 0;
- for (int j = i + 1; j < elems.length; j++) {
- if (elems[j] != elems[j - 1] + 1) {
- break;
- }
- lastInRange = j;
- }
- // found a range
- if (str.length() > 0) {
- str += separator;
- }
- if (lastInRange - i >= 2) {
- str += formatter.literalChar(elems[i]);
- str += "..";
- str += formatter.literalChar(elems[lastInRange]);
- i = lastInRange; // skip past end of range for next range
- }
- else { // no range, just print current char and move on
- str += formatter.literalChar(elems[i]);
- }
- i++;
- }
- return str;
- }
- private final static int wordNumber(int bit) {
- return bit >> LOG_BITS; // bit / BITS
- }
- }