add a new IntVector implementation
git-svn-id: https://wala.svn.sourceforge.net/svnroot/wala/trunk@3386 f5eafffb-2e1d-0410-98e4-8ec43c5233c4
This commit is contained in:
parent
60a0a0ec43
commit
6ea5bef1e6
|
@ -0,0 +1,310 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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.Arrays;
|
||||
|
||||
import com.ibm.wala.util.debug.Assertions;
|
||||
import com.ibm.wala.util.debug.Trace;
|
||||
|
||||
/**
|
||||
* an implementation of {@link IntVector} that uses a mix of backing arrays of type int, char, and byte array, in an attempt to save
|
||||
* space for common data structures.
|
||||
*/
|
||||
public class MultiModalIntVector implements IntVector {
|
||||
|
||||
private final static float INITIAL_GROWTH_FACTOR = 1.5f;
|
||||
|
||||
private final static float MINIMUM_GROWTH_FACTOR = 1.1f;
|
||||
|
||||
private final static float DIFF_GROWTH_FACTOR = INITIAL_GROWTH_FACTOR - MINIMUM_GROWTH_FACTOR;
|
||||
|
||||
private float CURRENT_GROWTH_RATE = INITIAL_GROWTH_FACTOR;
|
||||
|
||||
private final static int MAX_SIZE = 10000;
|
||||
|
||||
private final static int INITIAL_SIZE = 1;
|
||||
|
||||
int maxIndex = -1;
|
||||
|
||||
// private Object store = null;
|
||||
private int[] intStore = new int[0];
|
||||
|
||||
private short[] shortStore = new short[0];
|
||||
|
||||
private byte[] byteStore = new byte[0];
|
||||
|
||||
final int defaultValue;
|
||||
|
||||
public MultiModalIntVector(int defaultValue) {
|
||||
this.defaultValue = defaultValue;
|
||||
init(getInitialSize(), defaultValue);
|
||||
}
|
||||
|
||||
private void init(int initialSize, int defaultValue) {
|
||||
if (NumberUtility.isByte(defaultValue)) {
|
||||
byteStore = new byte[initialSize];
|
||||
byteStore[0] = (byte) defaultValue;
|
||||
} else if (NumberUtility.isShort(defaultValue)) {
|
||||
shortStore = new short[initialSize];
|
||||
shortStore[0] = (short) defaultValue;
|
||||
} else {
|
||||
intStore = new int[initialSize];
|
||||
intStore[0] = defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public MultiModalIntVector(int defaultValue, int initialSize) {
|
||||
this.defaultValue = defaultValue;
|
||||
init(initialSize, defaultValue);
|
||||
}
|
||||
|
||||
int getInitialSize() {
|
||||
return INITIAL_SIZE;
|
||||
}
|
||||
|
||||
float getGrowthFactor() {
|
||||
return INITIAL_GROWTH_FACTOR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will determine a dynamic growth factor that depends on the current size of the array
|
||||
*
|
||||
* @param size
|
||||
* @return the new growth factor
|
||||
*/
|
||||
|
||||
float getGrowthFactor(int size) {
|
||||
if (CURRENT_GROWTH_RATE >= MINIMUM_GROWTH_FACTOR) {
|
||||
|
||||
float val = (float) (1 / (1 + Math.pow(Math.E, (-1) * ((size / MAX_SIZE) * 12.0 - 6.0))));
|
||||
CURRENT_GROWTH_RATE = INITIAL_GROWTH_FACTOR - DIFF_GROWTH_FACTOR * val;
|
||||
}
|
||||
return CURRENT_GROWTH_RATE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.util.intset.IntVector#get(int)
|
||||
*/
|
||||
public int get(int x) {
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(x >= 0);
|
||||
}
|
||||
// print();
|
||||
// System.out.println("getting @" + x);
|
||||
int index = x;
|
||||
if (index < byteStore.length) {
|
||||
// System.out.println(byteStore[index]);
|
||||
return byteStore[index];
|
||||
}
|
||||
index -= byteStore.length;
|
||||
if (index < shortStore.length) {
|
||||
// System.out.println(shortStore[index]);
|
||||
return shortStore[index];
|
||||
}
|
||||
index -= shortStore.length;
|
||||
if (index < intStore.length) {
|
||||
// System.out.println(intStore[index]);
|
||||
return intStore[index];
|
||||
}
|
||||
// System.out.println(defaultValue);
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private int getStoreLength() {
|
||||
return shortStore.length + byteStore.length + intStore.length;
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.util.intset.IntVector#set(int, int)
|
||||
*/
|
||||
public void set(int x, int value) {
|
||||
// System.out.println("Adding " + value + " @ " + x);
|
||||
if (Assertions.verifyAssertions) {
|
||||
Assertions._assert(x >= 0);
|
||||
}
|
||||
maxIndex = Math.max(maxIndex, x); // Find out if the new position is bigger than size of the array
|
||||
handleMorph(x, value);
|
||||
if (value == defaultValue) {
|
||||
int length = getStoreLength();
|
||||
if (x >= length) {
|
||||
return;
|
||||
} else {
|
||||
add(value, x);
|
||||
}
|
||||
} else {
|
||||
ensureCapacity(x, value);
|
||||
add(value, x);
|
||||
}
|
||||
// print();
|
||||
}
|
||||
|
||||
private void add(int value, int index) {
|
||||
if (byteStore.length > index) {
|
||||
byteStore[index] = (byte) value;
|
||||
} else {
|
||||
index -= byteStore.length;
|
||||
if (shortStore.length > index) {
|
||||
shortStore[index] = (short) value;
|
||||
} else {
|
||||
index -= shortStore.length;
|
||||
intStore[index] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleMorph(int index, int value) {
|
||||
if (NumberUtility.isShort(value)) {
|
||||
if (index < byteStore.length) {
|
||||
int newShortSize = byteStore.length - index + shortStore.length;
|
||||
short[] newShortStore = new short[newShortSize];
|
||||
byte[] newByteStore = new byte[index];
|
||||
for (int i = index; i < byteStore.length; i++) {
|
||||
newShortStore[i - index] = byteStore[i];
|
||||
}
|
||||
System.arraycopy(byteStore, 0, newByteStore, 0, index);
|
||||
System.arraycopy(shortStore, 0, newShortStore, byteStore.length - index, shortStore.length);
|
||||
byteStore = newByteStore;
|
||||
shortStore = newShortStore;
|
||||
}
|
||||
} else if (!NumberUtility.isByte(value)) {
|
||||
if (index < byteStore.length) {
|
||||
int newShortSize = byteStore.length - index + intStore.length;
|
||||
int[] newIntStore = new int[newShortSize];
|
||||
for (int i = index; i < byteStore.length; i++) {
|
||||
newIntStore[i - index] = byteStore[i];
|
||||
}
|
||||
byte[] newByteStore = new byte[index];
|
||||
System.arraycopy(byteStore, 0, newByteStore, 0, index);
|
||||
for (int i = 0; i < shortStore.length; i++) {
|
||||
newIntStore[byteStore.length - 1 + i] = shortStore[i];
|
||||
}
|
||||
System.arraycopy(intStore, 0, newIntStore, byteStore.length + shortStore.length - index, intStore.length);
|
||||
intStore = newIntStore;
|
||||
byteStore = newByteStore;
|
||||
shortStore = new short[0];
|
||||
} else {
|
||||
int newindex = index - byteStore.length;
|
||||
if (newindex < shortStore.length) {
|
||||
int newIntSize = shortStore.length - newindex + intStore.length;
|
||||
int[] newIntStore = new int[newIntSize];
|
||||
for (int i = newindex; i < shortStore.length; i++) {
|
||||
newIntStore[i - newindex] = shortStore[i];
|
||||
}
|
||||
short[] newShortStore = new short[newindex];
|
||||
System.arraycopy(shortStore, 0, newShortStore, 0, newindex);
|
||||
System.arraycopy(intStore, 0, newIntStore, shortStore.length - newindex, intStore.length);
|
||||
intStore = newIntStore;
|
||||
shortStore = newShortStore;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* make sure we can store to a particular index
|
||||
*
|
||||
* @param capacity
|
||||
*/
|
||||
private void ensureCapacity(int capacity, int value) {
|
||||
int length = getStoreLength();
|
||||
// Value is an int
|
||||
if (intStore.length > 0 || (!NumberUtility.isShort(value) && !NumberUtility.isByte(value))) {
|
||||
// Need to increase the capacity of the array
|
||||
if (capacity >= length) {
|
||||
// Current array size
|
||||
int[] old = intStore;
|
||||
// New array size
|
||||
// int newSize = 1 + (int) (getGrowthFactor() * capacity) - byteStore.length - shortStore.length;
|
||||
int newSize = 1 + (int) (getGrowthFactor(length) * capacity) - byteStore.length - shortStore.length;
|
||||
int[] newData = new int[newSize];
|
||||
Arrays.fill(newData, defaultValue);
|
||||
System.arraycopy(old, 0, newData, 0, old.length);
|
||||
intStore = newData;
|
||||
}
|
||||
} else if (shortStore.length > 0 || NumberUtility.isShort(value)) {
|
||||
if (capacity >= length) {
|
||||
short[] old = shortStore;
|
||||
// int newSize = 1 + (int) (getGrowthFactor() * capacity) - byteStore.length ;
|
||||
int newSize = 1 + (int) (getGrowthFactor(length) * capacity) - byteStore.length;
|
||||
short[] newData = new short[newSize];
|
||||
Arrays.fill(newData, (short) defaultValue);
|
||||
System.arraycopy(old, 0, newData, 0, old.length);
|
||||
shortStore = newData;
|
||||
}
|
||||
} else {
|
||||
if (capacity >= length) {
|
||||
byte[] old = byteStore;
|
||||
// int newSize = 1 + (int) (getGrowthFactor() * capacity) ;
|
||||
int newSize = 1 + (int) (getGrowthFactor(length) * capacity);
|
||||
byte[] newData = new byte[newSize];
|
||||
Arrays.fill(newData, (byte) defaultValue);
|
||||
System.arraycopy(old, 0, newData, 0, old.length);
|
||||
byteStore = newData;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @see com.ibm.wala.util.intset.IntVector#reportStats()
|
||||
*/
|
||||
public void performVerboseAction() {
|
||||
int length = getStoreLength();
|
||||
Trace.println("size: " + length);
|
||||
Trace.println("occupancy: " + computeOccupancy(length));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the percentage of entries in delegateStore that are non-null
|
||||
*/
|
||||
private double computeOccupancy(int length) {
|
||||
int count1 = 0;
|
||||
int internalLength = length;
|
||||
for (int i = 0; i < internalLength && i < byteStore.length; i++) {
|
||||
if (byteStore[i] != -1) {
|
||||
count1++;
|
||||
}
|
||||
}
|
||||
length -= byteStore.length;
|
||||
for (int i = 0; i < internalLength && i < byteStore.length; i++) {
|
||||
if (shortStore[i] != -1) {
|
||||
count1++;
|
||||
}
|
||||
}
|
||||
length -= shortStore.length;
|
||||
for (int i = 0; i < internalLength && i < intStore.length; i++) {
|
||||
if (intStore[i] != -1) {
|
||||
count1++;
|
||||
}
|
||||
}
|
||||
int count = count1;
|
||||
return (double) count / (double) length;
|
||||
}
|
||||
|
||||
public int getMaxIndex() {
|
||||
return maxIndex;
|
||||
}
|
||||
|
||||
public void print() {
|
||||
String str = "";
|
||||
for (int i = 0; i < byteStore.length; i++) {
|
||||
str += byteStore[i] + ",";
|
||||
}
|
||||
for (int i = 0; i < shortStore.length; i++) {
|
||||
str += shortStore[i] + ",";
|
||||
}
|
||||
for (int i = 0; i < intStore.length; i++) {
|
||||
str += intStore[i] + ",";
|
||||
}
|
||||
System.out.println(str);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2009 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;
|
||||
|
||||
public class NumberUtility {
|
||||
|
||||
static boolean isByte(int number){
|
||||
if (number>=Byte.MIN_VALUE && number<=Byte.MAX_VALUE){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean isShort(int number){
|
||||
if (!isByte(number) && number>=Short.MIN_VALUE && number<=Short.MAX_VALUE){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue