/******************************************************************************* * 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 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; } }