package es.uvigo.darwin.jmodeltest.utilities; import java.util.Arrays; /** * A bit-set of fixed size. Size is determined on creation. * * @author Joseph Heled * @version $Id: FixedBitSet.java 591 2006-12-21 02:39:18Z pepster $ */ public class FixedBitSet implements Comparable<FixedBitSet> { int[] bits; int size; //private int intSize = Integer.SIZE; private final static int ADDRESS_BITS_PER_UNIT = 5; private final static int BITS_PER_UNIT = 1 << ADDRESS_BITS_PER_UNIT; private final static int BIT_INDEX_MASK = BITS_PER_UNIT - 1; private static int unitIndex(int bitIndex) { return bitIndex >> ADDRESS_BITS_PER_UNIT; } private int countBits(int b) { int sum = 0; while (b != 0) { // remove most significant bit b = b & (b - 1); ++sum; } return sum; } /** * Given a bit index, return a unit that masks that bit in its unit. * @return the mask */ private static int bit(int bitIndex) { return 1 << (bitIndex & BIT_INDEX_MASK); } public FixedBitSet(int size) { this.size = size; bits = new int[(unitIndex(size - 1) + 1)]; } public FixedBitSet(FixedBitSet bs) { bits = bs.bits.clone(); size = bs.size; } public void set(int position) { int unitIndex = unitIndex(position); bits[unitIndex] |= bit(position); } public void clear(int position) { int unitIndex = unitIndex(position); bits[unitIndex] &= ~bit(position); } /** * @param bitset * @return true if bitset contains this set (this <= bitset) */ public boolean setInclusion(final FixedBitSet bitset) { for (int k = 0; k < bits.length; ++k) { if (bits[k] != (bits[k] & bitset.bits[k])) { return false; } } return true; } public void union(FixedBitSet b) { for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) { bits[k] |= b.bits[k]; } } public void intersect(FixedBitSet b) { for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) { bits[k] &= b.bits[k]; } } public void setMinus(FixedBitSet b) { for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) { bits[k] &= ~b.bits[k]; } } public int intersectCardinality(FixedBitSet b) { int c = 0; for (int k = 0; k < Math.min(bits.length, b.bits.length); ++k) { c += countBits(bits[k] & b.bits[k]); } return c; } public static FixedBitSet complement(FixedBitSet b) { FixedBitSet t = new FixedBitSet(b); t.complement(); return t; } public void complement() { int k; for (k = 0; k < bits.length - 1; ++k) { bits[k] = ~ bits[k]; } bits[k] = ~bits[k]; // reset all higher order bits final int mask = bit(size) - 1; if( mask != 0 ) { bits[k] &= mask; } } private final static byte firstBitLocation[] = { -1, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0}; private int firstOnBit(int i) { for (int k = 0; k < 4; ++k) { char b = (char) (i & 0xff); if (b != 0) { return 8 * k + firstBitLocation[b]; } i = i >> 8; } return -1; } /** * Iteration helper. A typical iteration on set bits might be * FixedBitSet b; * for(int i = b.nextOnBit(0); i >= 0; i = b.nextOnBit(i+1)) ... * * @param fromIndex * @return Next set member whose index is >= fromIndex. -1 if none. */ public int nextOnBit(int fromIndex) { int u = unitIndex(fromIndex); int testIndex = (fromIndex & BIT_INDEX_MASK); int unit = bits[u] >> testIndex; if (unit == 0) { testIndex = 0; while ((unit == 0) && (u < bits.length - 1)) unit = bits[++u]; } if (unit == 0) return -1; testIndex += firstOnBit(unit); return ((u * BITS_PER_UNIT) + testIndex); } public int cardinality() { int sum = 0; for (int b : bits) { sum += countBits(b); } return sum; } public boolean contains(final int i) { final int unitIndex = unitIndex(i); return (bits[unitIndex] & bit(i)) != 0; } @Override public int hashCode() { int code = 0; for (int bit : bits) { code = code ^ bit; } return code; } @Override public boolean equals(Object x) { if (x instanceof FixedBitSet) { final FixedBitSet b = (FixedBitSet) x; return b.size == size && Arrays.equals(bits, b.bits); } return false; } @Override public String toString() { StringBuilder rep = new StringBuilder(); rep.append("{"); for (int b = 0; b < size; ++b) { if (contains(b)) { if (rep.length() > 0) { rep.append("," + b); } else { rep.append("" + b); } } } rep.append("}"); return rep.toString(); } public String splitRepresentation() { StringBuilder rep = new StringBuilder(); for (int b = 0; b < size; ++b) { if (contains(b)) { rep.append("*"); } else { rep.append("-"); } } return rep.toString(); } public int compareTo(FixedBitSet fbs) { int minSize; int defaultValue; if (size < fbs.size) { minSize = size; defaultValue = -1; } else { minSize = fbs.size; if (size == fbs.size) defaultValue = 0; else defaultValue = 1; } for (int i = 0; i < minSize; i++) { if (this.contains(i) && !fbs.contains(i)) { return -1; } if (!this.contains(i) && fbs.contains(i)) { return 1; } } return defaultValue; } }