/*******************************************************************************
* 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.debug.Assertions;
import com.ibm.wala.util.debug.UnimplementedError;
/**
* Utilities for dealing with LongSets
*/
public class LongSetUtil {
public static final String INT_SET_FACTORY_CONFIG_PROPERTY_NAME = "com.ibm.wala.mutableLongSetFactory";
private static MutableLongSetFactory defaultLongSetFactory;
static {
MutableLongSetFactory defaultFactory = new MutableSparseLongSetFactory();
if (System.getProperty(INT_SET_FACTORY_CONFIG_PROPERTY_NAME) != null) {
try {
Class<?> intSetFactoryClass = Class.forName(System.getProperty(INT_SET_FACTORY_CONFIG_PROPERTY_NAME));
MutableLongSetFactory intSetFactory = (MutableLongSetFactory) intSetFactoryClass.newInstance();
setDefaultLongSetFactory(intSetFactory);
} catch (Exception e) {
System.err.println(("Cannot use int set factory " + System.getProperty(INT_SET_FACTORY_CONFIG_PROPERTY_NAME)));
setDefaultLongSetFactory(defaultFactory);
}
} else {
setDefaultLongSetFactory(defaultFactory);
}
assert defaultLongSetFactory != null;
}
public static MutableLongSet make() {
return defaultLongSetFactory.make();
}
private final static boolean DEBUG = false;
/**
* This method constructs an appropriate mutable copy of set.
*
* @param set
* @return a new MutableLongSet object with the same value as set
* @throws UnimplementedError if (not ( set instanceof com.ibm.wala.util.intset.SparseLongSet ) ) and (not ( set instanceof
* com.ibm.wala.util.intset.BitVectorLongSet ) ) and (not ( set instanceof
* com.ibm.wala.util.intset.BimodalMutableLongSet ) ) and (not ( set instanceof
* com.ibm.wala.util.intset.DebuggingMutableLongSet ) ) and (not ( set instanceof
* com.ibm.wala.util.intset.SemiSparseMutableLongSet ) ) and (not ( set instanceof
* com.ibm.wala.util.intset.MutableSharedBitVectorLongSet ) )
* @throws IllegalArgumentException if set == null
*/
public static MutableLongSet makeMutableCopy(LongSet set) throws IllegalArgumentException, UnimplementedError {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (set instanceof SparseLongSet) {
return MutableSparseLongSet.make(set);
} else {
Assertions.UNREACHABLE(set.getClass().toString());
return null;
}
}
/**
* Compute the asymmetric difference of two sets, a \ b.
*/
public static LongSet diff(LongSet A, LongSet B) {
if (A == null) {
throw new IllegalArgumentException("null A");
}
if (B == null) {
throw new IllegalArgumentException("null B");
}
return diff(A, B, LongSetUtil.getDefaultLongSetFactory());
}
private static LongSet defaultSlowDiff(LongSet A, LongSet B, MutableLongSetFactory factory) {
// TODO: this is slow ... optimize please.
MutableLongSet result = factory.makeCopy(A);
if (DEBUG) {
System.err.println(("initial result " + result + " " + result.getClass()));
}
for (LongIterator it = B.longIterator(); it.hasNext();) {
long I = it.next();
result.remove(I);
if (DEBUG) {
System.err.println(("removed " + I + " now is " + result));
}
}
if (DEBUG) {
System.err.println(("return " + result));
}
return result;
}
/**
* Compute the asymmetric difference of two sets, a \ b.
*/
public static LongSet diff(LongSet A, LongSet B, MutableLongSetFactory factory) {
if (A == null) {
throw new IllegalArgumentException("null A");
}
if (B == null) {
throw new IllegalArgumentException("null B");
}
if (A instanceof SparseLongSet && B instanceof SparseLongSet) {
return SparseLongSet.diff((SparseLongSet) A, (SparseLongSet) B);
} else {
return defaultSlowDiff(A, B, factory);
}
}
/**
* Subtract two sets, i.e. a = a \ b.
*
* @throws IllegalArgumentException if A == null || B == null
*/
public static MutableLongSet removeAll(MutableLongSet A, LongSet B) throws IllegalArgumentException {
if (A == null) {
throw new IllegalArgumentException("A == null");
}
if (B == null) {
throw new IllegalArgumentException("B == null");
}
for (LongIterator it = B.longIterator(); it.hasNext();) {
long I = it.next();
A.remove(I);
if (DEBUG) {
System.err.println(("removed " + I + " now is " + A));
}
}
if (DEBUG) {
System.err.println(("return " + A));
}
return A;
}
/**
* @return index \in [low,high] s.t. data[index] = key, or -1 if not found
*/
public static int binarySearch(long[] data, long key, int low, int high) throws IllegalArgumentException {
if (data == null) {
throw new IllegalArgumentException("null array");
}
if (data.length == 0) {
return -1;
}
if (low <= high && (low < 0 || high < 0)) {
throw new IllegalArgumentException("can't search negative indices");
}
if (high > data.length - 1) {
high = data.length - 1;
}
if (low <= high) {
int mid = (low + high) / 2;
long midValue = data[mid];
if (midValue == key) {
return mid;
} else if (midValue > key) {
return binarySearch(data, key, low, mid - 1);
} else {
return binarySearch(data, key, mid + 1, high);
}
} else {
return -1;
}
}
public static MutableLongSetFactory getDefaultLongSetFactory() {
return defaultLongSetFactory;
}
public static void setDefaultLongSetFactory(MutableLongSetFactory defaultLongSetFactory) {
if (defaultLongSetFactory == null) {
throw new IllegalArgumentException("null defaultLongSetFactory");
}
LongSetUtil.defaultLongSetFactory = defaultLongSetFactory;
}
/**
* @return a new sparse int set which adds j to s
* @throws IllegalArgumentException if s == null
*/
public static LongSet add(LongSet s, int j) throws IllegalArgumentException {
if (s == null) {
throw new IllegalArgumentException("s == null");
}
if (s instanceof SparseLongSet) {
SparseLongSet sis = (SparseLongSet) s;
return SparseLongSet.add(sis, j);
} else {
// really slow. optimize as needed.
MutableSparseLongSet result = MutableSparseLongSet.make(s);
result.add(j);
return result;
}
}
}