WALA/com.ibm.wala.util/src/com/ibm/wala/util/intset/MutableSharedBitVectorIntSe...

1118 lines
32 KiB
Java

/*******************************************************************************
* 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 com.ibm.wala.util.collections.CompoundIntIterator;
import com.ibm.wala.util.collections.EmptyIntIterator;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
/**
* The shared bit vector implementation described by [Heintze 1999] TODO: much optimization possible.
*/
public class MutableSharedBitVectorIntSet implements MutableIntSet {
private static final long serialVersionUID = -6630888692508092370L;
private final static boolean DEBUG = false;
private final static boolean PARANOID = false;
private final static int OVERFLOW = 20;
private MutableSparseIntSet privatePart;
private BitVectorIntSet sharedPart;
/**
*
*/
public MutableSharedBitVectorIntSet() {
}
/**
* @param set
* @throws IllegalArgumentException if set is null
*/
public MutableSharedBitVectorIntSet(MutableSharedBitVectorIntSet set) {
if (set == null) {
throw new IllegalArgumentException("set is null");
}
if (set.privatePart != null) {
this.privatePart = MutableSparseIntSet.make(set.privatePart);
}
this.sharedPart = set.sharedPart;
}
/**
* @param s
* @throws IllegalArgumentException if s is null
*/
public MutableSharedBitVectorIntSet(SparseIntSet s) {
if (s == null) {
throw new IllegalArgumentException("s is null");
}
if (s.size() == 0) {
return;
}
this.privatePart = MutableSparseIntSet.make(s);
checkOverflow();
if (PARANOID) {
checkIntegrity();
}
}
/**
* @param s
* @throws IllegalArgumentException if s is null
*/
public MutableSharedBitVectorIntSet(BitVectorIntSet s) {
if (s == null) {
throw new IllegalArgumentException("s is null");
}
copyValue(s);
if (PARANOID) {
checkIntegrity();
}
}
/**
* @param s
*/
private void copyValue(BitVectorIntSet s) {
if (s.size() == 0) {
sharedPart = null;
privatePart = null;
} else if (s.size() < OVERFLOW) {
sharedPart = null;
privatePart = MutableSparseIntSet.make(s);
} else {
sharedPart = BitVectorRepository.findOrCreateSharedSubset(s);
if (sharedPart.size() == s.size()) {
privatePart = null;
} else {
BitVectorIntSet temp = new BitVectorIntSet(s);
temp.removeAll(sharedPart);
if (!temp.isEmpty()) {
privatePart = MutableSparseIntSet.make(temp);
} else {
privatePart = null;
}
}
}
if (PARANOID) {
checkIntegrity();
}
}
/**
*
*/
private void checkIntegrity() {
assert privatePart == null || !privatePart.isEmpty();
assert sharedPart == null || !sharedPart.isEmpty();
if (privatePart != null && sharedPart != null) {
assert privatePart.intersection(sharedPart).isEmpty();
}
}
/**
*
*/
private void checkOverflow() {
if (PARANOID) {
checkIntegrity();
}
if (privatePart != null && privatePart.size() > OVERFLOW) {
if (sharedPart == null) {
BitVectorIntSet temp = new BitVectorIntSet(privatePart);
sharedPart = BitVectorRepository.findOrCreateSharedSubset(temp);
temp.removeAll(sharedPart);
if (!temp.isEmpty())
privatePart = MutableSparseIntSet.make(temp);
else
privatePart = null;
} else {
BitVectorIntSet temp = new BitVectorIntSet(sharedPart);
// when we call findOrCreateSharedSubset, we will ask size() on temp.
// so use addAll instead of addAllOblivious: which incrementally
// updates the population count.
temp.addAll(privatePart);
sharedPart = BitVectorRepository.findOrCreateSharedSubset(temp);
temp.removeAll(sharedPart);
if (!temp.isEmpty())
privatePart = MutableSparseIntSet.make(temp);
else
privatePart = null;
}
}
if (PARANOID) {
checkIntegrity();
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#contains(int)
*/
@Override
public boolean contains(int i) {
if (privatePart != null && privatePart.contains(i)) {
return true;
}
if (sharedPart != null && sharedPart.contains(i)) {
return true;
}
return false;
}
/*
* @see com.ibm.wala.util.intset.IntSet#intersection(com.ibm.wala.util.intset.IntSet)
*/
@Override
public IntSet intersection(IntSet that) {
if (that == null) {
throw new IllegalArgumentException("null that");
}
if (that instanceof MutableSharedBitVectorIntSet) {
return intersection((MutableSharedBitVectorIntSet) that);
} else if (that instanceof BitVectorIntSet) {
MutableSharedBitVectorIntSet m = new MutableSharedBitVectorIntSet((BitVectorIntSet) that);
return intersection(m);
} else if (that instanceof SparseIntSet) {
BitVectorIntSet bv = new BitVectorIntSet(that);
return intersection(bv);
} else {
// really slow. optimize as needed.
BitVectorIntSet result = new BitVectorIntSet();
for (IntIterator it = intIterator(); it.hasNext();) {
int x = it.next();
if (that.contains(x)) {
result.add(x);
}
}
return result;
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#union(com.ibm.wala.util.intset.IntSet)
*/
@Override
public IntSet union(IntSet that) {
MutableSharedBitVectorIntSet temp = new MutableSharedBitVectorIntSet();
temp.addAll(this);
temp.addAll(that);
return temp;
}
/*
* @see com.ibm.wala.util.intset.IntSet#intersection(com.ibm.wala.util.intset.IntSet)
*/
public IntSet intersection(MutableSharedBitVectorIntSet that) {
MutableSparseIntSet t = makeSparseCopy();
t.intersectWith(that);
MutableSharedBitVectorIntSet result = new MutableSharedBitVectorIntSet(t);
if (PARANOID) {
checkIntegrity();
}
return result;
}
/*
* @see com.ibm.wala.util.intset.IntSet#isEmpty()
*/
@Override
public boolean isEmpty() {
return privatePart == null && sharedPart == null;
}
/*
* @see com.ibm.wala.util.intset.IntSet#size()
*/
@Override
public int size() {
int result = 0;
result += (privatePart == null) ? 0 : privatePart.size();
result += (sharedPart == null) ? 0 : sharedPart.size();
return result;
}
/*
* @see com.ibm.wala.util.intset.IntSet#iterator()
*/
@Override
public IntIterator intIterator() {
if (privatePart == null) {
return (sharedPart == null) ? EmptyIntIterator.instance() : sharedPart.intIterator();
} else {
return (sharedPart == null) ? privatePart.intIterator() : new CompoundIntIterator(privatePart.intIterator(), sharedPart
.intIterator());
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#foreach(com.ibm.wala.util.intset.IntSetAction)
*/
@Override
public void foreach(IntSetAction action) {
if (privatePart != null) {
privatePart.foreach(action);
}
if (sharedPart != null) {
sharedPart.foreach(action);
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#foreachExcluding(com.ibm.wala.util.intset.IntSet, com.ibm.wala.util.intset.IntSetAction)
*/
@Override
public void foreachExcluding(IntSet X, IntSetAction action) {
if (X instanceof MutableSharedBitVectorIntSet) {
foreachExcludingInternal((MutableSharedBitVectorIntSet) X, action);
} else {
foreachExcludingGeneral(X, action);
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#foreachExcluding(com.ibm.wala.util.intset.IntSet, com.ibm.wala.util.intset.IntSetAction)
*/
private void foreachExcludingInternal(MutableSharedBitVectorIntSet X, IntSetAction action) {
if (sameSharedPart(this, X)) {
if (privatePart != null) {
if (X.privatePart != null) {
privatePart.foreachExcluding(X.privatePart, action);
} else {
privatePart.foreach(action);
}
}
} else {
if (privatePart != null) {
privatePart.foreachExcluding(X, action);
}
if (sharedPart != null) {
sharedPart.foreachExcluding(X.makeDenseCopy(), action);
}
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#foreachExcluding(com.ibm.wala.util.intset.IntSet, com.ibm.wala.util.intset.IntSetAction)
*/
private void foreachExcludingGeneral(IntSet X, IntSetAction action) {
if (privatePart != null) {
privatePart.foreachExcluding(X, action);
}
if (sharedPart != null) {
sharedPart.foreachExcluding(X, action);
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#max()
*/
@Override
public int max() {
int result = -1;
if (privatePart != null && privatePart.size() > 0) {
result = Math.max(result, privatePart.max());
}
if (sharedPart != null) {
result = Math.max(result, sharedPart.max());
}
return result;
}
/*
* @see com.ibm.wala.util.intset.IntSet#sameValue(com.ibm.wala.util.intset.IntSet)
*/
@Override
public boolean sameValue(IntSet that) throws IllegalArgumentException, UnimplementedError {
if (that == null) {
throw new IllegalArgumentException("that == null");
}
if (that instanceof MutableSharedBitVectorIntSet) {
return sameValue((MutableSharedBitVectorIntSet) that);
} else if (that instanceof SparseIntSet) {
return sameValue((SparseIntSet) that);
} else if (that instanceof BimodalMutableIntSet) {
return that.sameValue(makeSparseCopy());
} else if (that instanceof BitVectorIntSet) {
return sameValue((BitVectorIntSet) that);
} else if (that instanceof SemiSparseMutableIntSet) {
return that.sameValue(this);
} else {
Assertions.UNREACHABLE("unexpected class " + that.getClass());
return false;
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#sameValue(com.ibm.wala.util.intset.IntSet)
*/
private boolean sameValue(SparseIntSet that) {
if (size() != that.size()) {
return false;
}
if (sharedPart == null) {
if (privatePart == null)
/* both parts empty, and that has same (i.e. 0) size */
return true;
else
return privatePart.sameValue(that);
} else {
/* sharedPart != null */
return makeSparseCopy().sameValue(that);
}
}
private boolean sameValue(BitVectorIntSet that) {
if (size() != that.size()) {
return false;
}
if (sharedPart == null) {
if (privatePart == null)
/* both parts empty, and that has same (i.e. 0) size */
return true;
else
// shared part is null and size is same, so number of bits is low
return that.makeSparseCopy().sameValue(privatePart);
} else {
if (privatePart == null)
return sharedPart.sameValue(that);
else
/* sharedPart != null */
return makeDenseCopy().sameValue(that);
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#sameValue(com.ibm.wala.util.intset.IntSet)
*/
private boolean sameValue(MutableSharedBitVectorIntSet that) {
if (size() != that.size()) {
return false;
}
if (sharedPart == null) {
if (privatePart == null) {
/* we must have size() == that.size() == 0 */
return true;
} else {
/* sharedPart == null, privatePart != null */
if (that.sharedPart == null) {
if (that.privatePart == null) {
return privatePart.isEmpty();
} else {
return privatePart.sameValue(that.privatePart);
}
} else {
/* sharedPart = null, privatePart != null, that.sharedPart != null */
if (that.privatePart == null) {
return privatePart.sameValue(that.sharedPart);
} else {
BitVectorIntSet temp = new BitVectorIntSet(that.sharedPart);
temp.addAllOblivious(that.privatePart);
return privatePart.sameValue(temp);
}
}
}
} else {
/* sharedPart != null */
if (privatePart == null) {
if (that.privatePart == null) {
return sharedPart.sameValue(that.sharedPart);
} else {
/* privatePart == null, sharedPart != null, that.privatePart != null */
if (that.sharedPart == null) {
return sharedPart.sameValue(that.privatePart);
} else {
MutableSparseIntSet t = that.makeSparseCopy();
return sharedPart.sameValue(t);
}
}
} else {
/* sharedPart != null , privatePart != null */
if (that.sharedPart == null) {
Assertions.UNREACHABLE();
return false;
} else {
/* that.sharedPart != null */
if (that.privatePart == null) {
SparseIntSet s = makeSparseCopy();
return s.sameValue(that.sharedPart);
} else {
/* that.sharedPart != null, that.privatePart != null */
/* assume reference equality for canonical shared part */
if (sharedPart == that.sharedPart) {
return privatePart.sameValue(that.privatePart);
} else {
SparseIntSet s1 = makeSparseCopy();
SparseIntSet s2 = that.makeSparseCopy();
return s1.sameValue(s2);
}
}
}
}
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#isSubset(com.ibm.wala.util.intset.IntSet)
*/
@Override
public boolean isSubset(IntSet that) {
if (that == null) {
throw new IllegalArgumentException("null that");
}
if (that instanceof MutableSharedBitVectorIntSet) {
return isSubset((MutableSharedBitVectorIntSet) that);
} else {
// really slow. optimize as needed.
for (IntIterator it = intIterator(); it.hasNext();) {
if (!that.contains(it.next())) {
return false;
}
}
return true;
}
}
/*
* @see com.ibm.wala.util.intset.IntSet#sameValue(com.ibm.wala.util.intset.IntSet)
*/
private boolean isSubset(MutableSharedBitVectorIntSet that) {
if (size() > that.size()) {
return false;
}
if (sharedPart == null) {
if (privatePart == null) {
return true;
} else {
if (that.sharedPart == null) {
return privatePart.isSubset(that.privatePart);
} else {
/* sharedPart == null, that.sharedPart != null */
if (that.privatePart == null) {
return privatePart.isSubset(that.sharedPart);
} else {
SparseIntSet s1 = that.makeSparseCopy();
return privatePart.isSubset(s1);
}
}
}
} else {
/* sharedPart != null */
if (privatePart == null) {
/* sharedPart != null, privatePart == null */
if (that.privatePart == null) {
if (that.sharedPart == null) {
return false;
} else {
return sharedPart.isSubset(that.sharedPart);
}
} else {
if (that.sharedPart == null) {
return sharedPart.isSubset(that.privatePart);
} else {
SparseIntSet s1 = that.makeSparseCopy();
return sharedPart.isSubset(s1);
}
}
} else {
/* sharedPart != null, privatePart != null */
if (that.privatePart == null) {
return privatePart.isSubset(that.sharedPart) && sharedPart.isSubset(that.sharedPart);
} else {
/* sharedPart != null, privatePart!= null, that.privatePart != null */
if (that.sharedPart == null) {
return privatePart.isSubset(that.privatePart) && sharedPart.isSubset(that.privatePart);
} else {
/*
* sharedPart != null, privatePart!= null, that.privatePart != null, that.sharedPart != null
*/
if (sharedPart.isSubset(that.sharedPart)) {
if (privatePart.isSubset(that.privatePart)) {
return true;
} else {
SparseIntSet s1 = that.makeSparseCopy();
return privatePart.isSubset(s1);
}
} else {
/* !sharedPart.isSubset(that.sharedPart) */
BitVectorIntSet temp = new BitVectorIntSet(sharedPart);
temp.removeAll(that.sharedPart);
if (temp.isSubset(that.privatePart)) {
/* sharedPart.isSubset(that) */
if (privatePart.isSubset(that.privatePart)) {
return true;
} else {
MutableSparseIntSet t = MutableSparseIntSet.make(privatePart);
t.removeAll(that.privatePart);
if (t.isSubset(that.sharedPart)) {
return true;
} else {
return false;
}
}
} else {
/*
* !((sharedPart-that.sharedPart).isSubset(that.privatePart)) i.e some bit in my shared part is in neither that's
* sharedPart nor that's privatePart, hence I am not a subset of that
*/
return false;
}
}
}
}
}
}
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#copySet(com.ibm.wala.util.intset.IntSet)
*/
@Override
public void copySet(IntSet set) {
if (set instanceof MutableSharedBitVectorIntSet) {
MutableSharedBitVectorIntSet other = (MutableSharedBitVectorIntSet) set;
if (other.privatePart != null) {
this.privatePart = MutableSparseIntSet.make(other.privatePart);
} else {
this.privatePart = null;
}
this.sharedPart = other.sharedPart;
} else {
// really slow. optimize as needed.
clear();
addAll(set);
}
if (PARANOID) {
checkIntegrity();
}
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#addAll(com.ibm.wala.util.intset.IntSet)
*/
@Override
public boolean addAll(IntSet set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (set instanceof MutableSharedBitVectorIntSet) {
boolean result = addAll((MutableSharedBitVectorIntSet) set);
if (PARANOID) {
checkIntegrity();
}
return result;
} else if (set instanceof SparseIntSet) {
boolean result = addAllInternal((SparseIntSet) set);
if (PARANOID) {
checkIntegrity();
}
return result;
} else if (set instanceof BitVectorIntSet) {
boolean result = addAllInternal((BitVectorIntSet) set);
if (PARANOID) {
checkIntegrity();
}
return result;
} else if (set instanceof DebuggingMutableIntSet) {
SparseIntSet temp = new SparseIntSet(set);
boolean result = addAllInternal(temp);
if (PARANOID) {
checkIntegrity();
}
return result;
} else {
// really slow. optimize as needed.
boolean result = false;
for (IntIterator it = set.intIterator(); it.hasNext();) {
int x = it.next();
if (!contains(x)) {
result = true;
add(x);
}
}
return result;
}
}
/**
* @param set
*/
private boolean addAllInternal(BitVectorIntSet set) {
// should have hijacked this case before getting here!
assert sharedPart != set;
if (privatePart == null) {
if (sharedPart == null) {
copyValue(set);
return !set.isEmpty();
}
}
BitVectorIntSet temp = makeDenseCopy();
boolean result = temp.addAll(set);
copyValue(temp);
return result;
}
/**
* @param set
*/
private boolean addAllInternal(SparseIntSet set) {
if (privatePart == null) {
if (sharedPart == null) {
if (!set.isEmpty()) {
privatePart = MutableSparseIntSet.make(set);
sharedPart = null;
checkOverflow();
return true;
} else {
return false;
}
} else {
privatePart = MutableSparseIntSet.make(set);
privatePart.removeAll(sharedPart);
if (privatePart.isEmpty()) {
privatePart = null;
return false;
} else {
checkOverflow();
return true;
}
}
} else { /* privatePart != null */
if (sharedPart == null) {
boolean result = privatePart.addAll(set);
checkOverflow();
return result;
} else {
int oldSize = privatePart.size();
privatePart.addAll(set);
privatePart.removeAll(sharedPart);
boolean result = privatePart.size() > oldSize;
checkOverflow();
return result;
}
}
}
/**
* @param set
*/
private boolean addAll(MutableSharedBitVectorIntSet set) {
if (set.isEmpty()) {
return false;
}
if (isEmpty()) {
if (set.privatePart != null) {
privatePart = MutableSparseIntSet.make(set.privatePart);
}
sharedPart = set.sharedPart;
return true;
}
if (set.sharedPart == null) {
return addAllInternal(set.privatePart);
} else {
// set.sharedPart != null
if (sameSharedPart(this, set)) {
if (set.privatePart == null) {
return false;
} else {
return addAllInternal(set.privatePart);
}
} else {
// !sameSharedPart
if (set.privatePart == null) {
if (sharedPart == null || sharedPart.isSubset(set.sharedPart)) {
// a heuristic that should be profitable if this condition usually
// holds.
int oldSize = size();
if (privatePart != null) {
privatePart.removeAll(set.sharedPart);
privatePart = privatePart.isEmpty() ? null : privatePart;
}
sharedPart = set.sharedPart;
return size() > oldSize;
} else {
BitVectorIntSet temp = makeDenseCopy();
boolean b = temp.addAll(set.sharedPart);
if (b) {
// a heuristic: many times these are the same value,
// so avoid looking up the shared subset in the bv repository
if (temp.sameValue(set.sharedPart)) {
this.privatePart = null;
this.sharedPart = set.sharedPart;
} else {
copyValue(temp);
}
}
return b;
}
} else {
// set.privatePart != null;
BitVectorIntSet temp = makeDenseCopy();
BitVectorIntSet other = set.makeDenseCopy();
boolean b = temp.addAll(other);
if (b) {
// a heuristic: many times these are the same value,
// so avoid looking up the shared subset in the bv repository
if (temp.sameValue(other)) {
this.privatePart = MutableSparseIntSet.make(set.privatePart);
this.sharedPart = set.sharedPart;
} else {
// System.err.println("COPY " + this + " " + set);
copyValue(temp);
}
}
return b;
}
}
}
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#add(int)
*/
@Override
public boolean add(int i) {
if (privatePart == null) {
if (sharedPart == null) {
privatePart = MutableSparseIntSet.makeEmpty();
privatePart.add(i);
return true;
} else {
if (sharedPart.contains(i)) {
return false;
} else {
privatePart = MutableSparseIntSet.makeEmpty();
privatePart.add(i);
return true;
}
}
} else {
if (sharedPart == null) {
boolean result = privatePart.add(i);
checkOverflow();
return result;
} else {
if (sharedPart.contains(i)) {
return false;
} else {
boolean result = privatePart.add(i);
checkOverflow();
return result;
}
}
}
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#remove(int)
*/
@Override
public boolean remove(int i) {
if (privatePart != null) {
if (privatePart.contains(i)) {
privatePart.remove(i);
if (privatePart.size() == 0) {
privatePart = null;
}
return true;
}
}
if (sharedPart != null) {
if (sharedPart.contains(i)) {
privatePart = makeSparseCopy();
privatePart.remove(i);
if (privatePart.size() == 0) {
privatePart = null;
}
sharedPart = null;
checkOverflow();
return true;
}
}
return false;
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#intersectWith(com.ibm.wala.util.intset.IntSet)
*/
@Override
public void intersectWith(IntSet set) {
if (set instanceof MutableSharedBitVectorIntSet) {
intersectWithInternal((MutableSharedBitVectorIntSet) set);
} else if (set instanceof BitVectorIntSet) {
intersectWithInternal(new MutableSharedBitVectorIntSet((BitVectorIntSet) set));
} else {
// this is really slow. optimize as needed.
for (IntIterator it = intIterator(); it.hasNext();) {
int x = it.next();
if (!set.contains(x)) {
remove(x);
}
}
}
if (DEBUG) {
if (privatePart != null && sharedPart != null)
assert privatePart.intersection(sharedPart).isEmpty();
}
}
/**
* @param set
*/
private void intersectWithInternal(MutableSharedBitVectorIntSet set) {
if (sharedPart != null) {
if (sameSharedPart(this, set)) {
// no need to intersect shared part
if (privatePart != null) {
if (set.privatePart == null) {
privatePart = null;
} else {
privatePart.intersectWith(set.privatePart);
if (privatePart.isEmpty()) {
privatePart = null;
}
}
}
} else {
// not the same shared part
if (set.sharedPart == null) {
if (set.privatePart == null) {
privatePart = null;
sharedPart = null;
} else {
MutableSparseIntSet temp = MutableSparseIntSet.make(set.privatePart);
temp.intersectWith(this);
sharedPart = null;
if (temp.isEmpty()) {
privatePart = null;
} else {
privatePart = temp;
checkOverflow();
}
}
} else {
// set.sharedPart != null
BitVectorIntSet b = makeDenseCopy();
b.intersectWith(set.makeDenseCopy());
copyValue(b);
}
}
} else {
if (privatePart != null) {
privatePart.intersectWith(set);
if (privatePart.isEmpty()) {
privatePart = null;
}
}
}
if (PARANOID) {
checkIntegrity();
}
}
public static boolean sameSharedPart(MutableSharedBitVectorIntSet a, MutableSharedBitVectorIntSet b) {
if (b == null) {
throw new IllegalArgumentException("b is null");
}
if (a == null) {
throw new IllegalArgumentException("a is null");
}
return a.sharedPart == b.sharedPart;
}
@Override
public String toString() {
return makeSparseCopy().toString();
}
/**
* Warning: inefficient; this should not be called often.
*/
MutableSparseIntSet makeSparseCopy() {
if (privatePart == null) {
if (sharedPart == null) {
return MutableSparseIntSet.makeEmpty();
} else {
return new MutableSparseIntSetFactory().makeCopy(sharedPart);
}
} else {
if (sharedPart == null) {
return MutableSparseIntSet.make(privatePart);
} else {
/* privatePart != null, sharedPart != null */
MutableSparseIntSet result = MutableSparseIntSet.make(privatePart);
result.addAll(sharedPart);
return result;
}
}
}
/**
*/
BitVectorIntSet makeDenseCopy() {
if (privatePart == null) {
if (sharedPart == null) {
return new BitVectorIntSet();
} else {
return new BitVectorIntSet(sharedPart);
}
} else {
if (sharedPart == null) {
return new BitVectorIntSet(privatePart);
} else {
BitVectorIntSet temp = new BitVectorIntSet(sharedPart);
temp.addAllOblivious(privatePart);
return temp;
}
}
}
public boolean hasSharedPart() {
return sharedPart != null;
}
/*
* @see com.ibm.wala.util.intset.IntSet#containsAny(com.ibm.wala.util.intset.IntSet)
*/
@Override
public boolean containsAny(IntSet set) {
if (set instanceof MutableSharedBitVectorIntSet) {
MutableSharedBitVectorIntSet other = (MutableSharedBitVectorIntSet) set;
if (sharedPart != null) {
// an optimization to make life easier on the underlying
// bitvectorintsets
if (other.sharedPart != null && sharedPart.containsAny(other.sharedPart)) {
return true;
}
if (other.privatePart != null && sharedPart.containsAny(other.privatePart)) {
return true;
}
}
if (privatePart != null && privatePart.containsAny(set)) {
return true;
}
return false;
} else {
if (sharedPart != null && sharedPart.containsAny(set)) {
return true;
}
if (privatePart != null && privatePart.containsAny(set)) {
return true;
}
return false;
}
}
/*
* @see com.ibm.wala.util.intset.MutableIntSet#addAllExcluding(com.ibm.wala.util.intset.IntSet, com.ibm.wala.util.intset.IntSet)
*/
@Override
public boolean addAllInIntersection(IntSet other, IntSet filter) {
if (other instanceof MutableSharedBitVectorIntSet) {
return addAllInIntersectionInternal((MutableSharedBitVectorIntSet) other, filter);
}
return addAllInIntersectionGeneral(other, filter);
}
/**
*/
private boolean addAllInIntersectionGeneral(IntSet other, IntSet filter) {
BitVectorIntSet o = new BitVectorIntSet(other);
o.intersectWith(filter);
return addAll(o);
}
/**
*/
private boolean addAllInIntersectionInternal(MutableSharedBitVectorIntSet other, IntSet filter) {
if (other.sharedPart == null) {
if (other.privatePart == null) {
return false;
} else {
// other.sharedPart == null, other.privatePart != null
return addAllInIntersectionInternal(other.privatePart, filter);
}
} else {
// other.sharedPart != null
if (sharedPart == other.sharedPart) {
// no need to add in other.sharedPart
if (other.privatePart == null) {
return false;
} else {
return addAllInIntersectionInternal(other.privatePart, filter);
}
} else {
MutableSharedBitVectorIntSet o = new MutableSharedBitVectorIntSet(other);
o.intersectWith(filter);
return addAll(o);
}
}
}
/**
* @param other
* @param filter
*/
private boolean addAllInIntersectionInternal(SparseIntSet other, IntSet filter) {
if (sharedPart == null) {
if (privatePart == null) {
privatePart = MutableSparseIntSet.make(other);
privatePart.intersectWith(filter);
if (privatePart.size() == 0) {
privatePart = null;
}
checkOverflow();
return size() > 0;
} else {
/** sharedPart == null, privatePart != null */
boolean result = privatePart.addAllInIntersection(other, filter);
checkOverflow();
return result;
}
} else {
/** sharedPart != null */
if (privatePart == null) {
privatePart = MutableSparseIntSet.make(sharedPart);
sharedPart = null;
boolean result = privatePart.addAllInIntersection(other, filter);
checkOverflow();
return result;
} else {
/** sharedPart != null, privatePart != null */
// note that "other" is likely small
MutableSparseIntSet temp = MutableSparseIntSet.make(other);
temp.intersectWith(filter);
return addAll(temp);
}
}
}
@Override
public void clear() {
privatePart = null;
sharedPart = null;
}
}