/******************************************************************************* * Copyright (c) 2002 - 2006 IBM Corporation. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package com.ibm.wala.util.intset; import java.util.Iterator; import com.ibm.wala.util.debug.Assertions; /** * A bit set is a set of elements, each of which corresponds to a unique integer from [0,MAX]. */ public final class BitSet<T> { /** * The backing bit vector that determines set membership. */ final private BitVector vector; /** * The bijection between integer to object. */ private OrdinalSetMapping<T> map; /** * Constructor: create an empty set corresponding to a given mapping * * @throws IllegalArgumentException if map is null */ public BitSet(OrdinalSetMapping<T> map) { if (map == null) { throw new IllegalArgumentException("map is null"); } int length = map.getMaximumIndex(); vector = new BitVector(length); this.map = map; } public static <T> BitSet<T> createBitSet(BitSet<T> B) { if (B == null) { throw new IllegalArgumentException("null B"); } return new BitSet<T>(B); } private BitSet(BitSet<T> B) { this(B.map); addAll(B); } /** * Add all elements in bitset B to this bit set * * @throws IllegalArgumentException if B is null */ public void addAll(BitSet<?> B) { if (B == null) { throw new IllegalArgumentException("B is null"); } vector.or(B.vector); } /** * Add all bits in BitVector B to this bit set */ public void addAll(BitVector B) { vector.or(B); } /** * Add an object to this bit set. */ public void add(T o) { int n = map.getMappedIndex(o); vector.set(n); } /** * Remove an object from this bit set. * * @param o the object to remove */ public void clear(T o) { int n = map.getMappedIndex(o); if (n == -1) { return; } vector.clear(n); } /** * Does this set contain a certain object? */ public boolean contains(T o) { int n = map.getMappedIndex(o); if (n == -1) { return false; } return vector.get(n); } /** * @return a String representation */ @Override public String toString() { return vector.toString(); } /** * Method copy. Copies the bits in the bit vector, but only assigns the object map. No need to create a new object/bit bijection * object. * * @throws IllegalArgumentException if other is null */ public void copyBits(BitSet<T> other) { if (other == null) { throw new IllegalArgumentException("other is null"); } vector.copyBits(other.vector); map = other.map; } /** * Does this object hold the same bits as other? * * @throws IllegalArgumentException if other is null */ public boolean sameBits(BitSet<?> other) { if (other == null) { throw new IllegalArgumentException("other is null"); } return vector.equals(other.vector); } /** * Not very efficient. */ public Iterator<T> iterator() { return new Iterator<T>() { private int next = -1; { for (int i = 0; i < vector.length(); i++) { if (vector.get(i)) { next = i; break; } } } @Override public boolean hasNext() { return (next != -1); } @Override public T next() { T result = map.getMappedObject(next); int start = next + 1; next = -1; for (int i = start; i < vector.length(); i++) { if (vector.get(i)) { next = i; break; } } return result; } @Override public void remove() { Assertions.UNREACHABLE(); } }; } public int size() { return vector.populationCount(); } public int length() { return vector.length(); } /** * Set all the bits to 0. */ public void clearAll() { vector.clearAll(); } /** * Set all the bits to 1. */ public void setAll() { vector.setAll(); } /** * Perform intersection of two bitsets * * @param other the other bitset in the operation * @throws IllegalArgumentException if other is null */ public void intersect(BitSet<?> other) { if (other == null) { throw new IllegalArgumentException("other is null"); } vector.and(other.vector); } /** * Perform the difference of two bit sets * * @param other the other bitset in the operation * @throws IllegalArgumentException if other is null */ public void difference(BitSet<T> other) { if (other == null) { throw new IllegalArgumentException("other is null"); } vector.and(BitVector.not(other.vector)); } /** */ public boolean isEmpty() { return size() == 0; } }