com.ibm.wala.util.intset.OffsetBitVector Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com.ibm.wala.util Show documentation
Show all versions of com.ibm.wala.util Show documentation
T. J. Watson Libraries for Analysis
/*
* 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.Arrays;
/** */
public final class OffsetBitVector extends BitVectorBase {
private static final long serialVersionUID = -5846568678514886375L;
int offset;
private static int wordDiff(int offset1, int offset2) {
return (offset1 > offset2)
? (offset1 - offset2) >> LOG_BITS_PER_UNIT
: -((offset2 - offset1) >> LOG_BITS_PER_UNIT);
}
/** Expand this bit vector to size newCapacity. */
private void expand(int newOffset, int newCapacity) {
int wordDiff = wordDiff(newOffset, offset);
int[] oldbits = bits;
bits = new int[subscript(newCapacity) + 1];
System.arraycopy(oldbits, 0, bits, 0 - wordDiff, oldbits.length);
offset = newOffset;
}
private void ensureCapacity(int newOffset, int newCapacity) {
if (newOffset < offset || newCapacity > (bits.length << LOG_BITS_PER_UNIT)) {
expand(newOffset, newCapacity);
}
}
public OffsetBitVector() {
this(0, 1);
}
/**
* Creates an empty string with the specified size.
*
* @param nbits the size of the string
*/
public OffsetBitVector(int offset, int nbits) {
if (nbits < 0) {
throw new IllegalArgumentException("invalid nbits: " + nbits);
}
if (offset < 0) {
throw new IllegalArgumentException("invalid offset: " + offset);
}
offset &= ~LOW_MASK;
this.offset = offset;
this.bits = new int[subscript(nbits) + 1];
}
/**
* Creates a copy of a Bit String
*
* @param s the string to copy
* @throws IllegalArgumentException if s is null
*/
public OffsetBitVector(OffsetBitVector s) {
if (s == null) {
throw new IllegalArgumentException("s is null");
}
offset = s.offset;
bits = s.bits.clone();
}
@Override
public String toString() {
return super.toString() + "(offset:" + offset + ')';
}
void growCapacity(float fraction) {
expand(offset, (int) (fraction * (bits.length << LOG_BITS_PER_UNIT)));
}
public int getOffset() {
return offset;
}
int getSize() {
return bits.length;
}
/**
* Sets a bit.
*
* @param bit the bit to be set
*/
@Override
public void set(int bit) {
if (bit < 0) {
throw new IllegalArgumentException("illegal bit: " + bit);
}
int shiftBits;
int subscript;
if (bit < offset) {
int newOffset = bit & ~LOW_MASK;
expand(newOffset, length() - 1 - newOffset);
shiftBits = bit & LOW_MASK;
subscript = 0;
} else {
bit -= offset;
shiftBits = bit & LOW_MASK;
subscript = subscript(bit);
if (subscript >= bits.length) {
expand(offset, bit);
}
}
try {
bits[subscript] |= (1 << shiftBits);
} catch (RuntimeException e) {
e.printStackTrace();
throw e;
}
}
/**
* Clears a bit.
*
* @param bit the bit to be cleared
*/
@Override
public void clear(int bit) {
if (bit < offset) {
return;
}
bit -= offset;
int ss = subscript(bit);
if (ss >= bits.length) {
return;
}
int shiftBits = bit & LOW_MASK;
bits[ss] &= ~(1 << shiftBits);
}
/**
* Gets a bit.
*
* @param bit the bit to be gotten
*/
@Override
public boolean get(int bit) {
if (DEBUG) {
assert bit >= 0;
}
if (bit < offset) {
return false;
}
bit -= offset;
int ss = subscript(bit);
if (ss >= bits.length) {
return false;
}
int shiftBits = bit & LOW_MASK;
return ((bits[ss] & (1 << shiftBits)) != 0);
}
/**
* @return min j >= start s.t get(j)
*/
@Override
public int nextSetBit(int start) {
int nb = super.nextSetBit(Math.max(0, start - offset));
return nb == -1 ? -1 : offset + nb;
}
/** Logically NOT this bit string */
public void not() {
if (offset != 0) {
expand(0, offset + length() - 1);
}
for (int i = 0; i < bits.length; i++) {
bits[i] ^= MASK;
}
}
@Override
public int max() {
return super.max() + offset;
}
/**
* Calculates and returns the set's size in bits. The maximum element in the set is the size - 1st
* element.
*/
@Override
public int length() {
return (bits.length << LOG_BITS_PER_UNIT) + offset;
}
/** Sets all bits. */
public void setAll() {
expand(0, length() - 1);
Arrays.fill(bits, MASK);
}
/**
* Compares this object against the specified object.
*
* @param obj the object to compare with
* @return true if the objects are the same; false otherwise.
*/
@Override
public boolean equals(Object obj) {
if ((obj != null) && (obj instanceof OffsetBitVector)) {
if (this == obj) { // should help alias analysis
return true;
}
OffsetBitVector set = (OffsetBitVector) obj;
return sameBits(set);
}
return false;
}
/**
* Check if the intersection of the two sets is empty
*
* @param set the set to check intersection with
* @throws IllegalArgumentException if set == null
*/
@Override
public boolean intersectionEmpty(OffsetBitVector set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (this == set) {
return isZero();
}
int wordDiff = wordDiff(offset, set.offset);
int maxWord = Math.min(bits.length, set.bits.length - wordDiff);
int i = Math.max(0, -wordDiff);
for (; i < maxWord; i++) {
if ((bits[i] & set.bits[i + wordDiff]) != 0) {
return false;
}
}
return true;
}
/**
* Compares this object against the specified object.
*
* @param set the object to compare with
* @return true if the objects are the same; false otherwise.
* @throws IllegalArgumentException if set == null
*/
@Override
public boolean sameBits(OffsetBitVector set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (this == set) { // should help alias analysis
return true;
}
int wordDiff = wordDiff(offset, set.offset);
int maxWord = Math.min(bits.length, set.bits.length - wordDiff);
int i = 0;
if (wordDiff < 0) {
for (; i < -wordDiff; i++) {
if (bits[i] != 0) {
return false;
}
}
} else {
for (int j = 0; j < wordDiff; j++) {
if (set.bits[j] != 0) {
return false;
}
}
}
for (; i < maxWord; i++) {
if (bits[i] != set.bits[i + wordDiff]) {
return false;
}
}
for (int j = maxWord + wordDiff; j < set.bits.length; j++) {
if (set.bits[j] != 0) {
return false;
}
}
for (; i < bits.length; i++) {
if (bits[i] != 0) {
return false;
}
}
return true;
}
/*
* @param other @return true iff this is a subset of other
*/
@Override
public boolean isSubset(OffsetBitVector other) throws IllegalArgumentException {
if (other == null) {
throw new IllegalArgumentException("other == null");
}
if (this == other) { // should help alias analysis
return true;
}
int wordDiff = wordDiff(offset, other.offset);
int maxWord = Math.min(bits.length, other.bits.length - wordDiff);
int i = 0;
for (; i < -wordDiff; i++) {
if (bits[i] != 0) {
return false;
}
}
for (; i < maxWord; i++) {
if ((bits[i] & ~other.bits[i + wordDiff]) != 0) {
return false;
}
}
for (; i < bits.length; i++) {
if (bits[i] != 0) {
return false;
}
}
return true;
}
/**
* Copies the values of the bits in the specified set into this set.
*
* @param set the bit set to copy the bits from
* @throws IllegalArgumentException if set is null
*/
public void copyBits(OffsetBitVector set) {
if (set == null) {
throw new IllegalArgumentException("set is null");
}
super.copyBits(set);
offset = set.offset;
}
/**
* Logically ANDs this bit set with the specified set of bits.
*
* @param set the bit set to be ANDed with
* @throws IllegalArgumentException if set == null
*/
@Override
public void and(OffsetBitVector set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (this == set) {
return;
}
int wordDiff = wordDiff(offset, set.offset);
int maxWord = Math.min(bits.length, set.bits.length - wordDiff);
int i = 0;
for (; i < -wordDiff; i++) {
bits[i] = 0;
}
for (; i < maxWord; i++) {
bits[i] &= set.bits[i + wordDiff];
}
for (; i < bits.length; i++) {
bits[i] = 0;
}
}
/**
* Logically ORs this bit set with the specified set of bits.
*
* @param set the bit set to be ORed with
* @throws IllegalArgumentException if set == null
*/
@Override
public void or(OffsetBitVector set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (this == set) { // should help alias analysis
return;
}
int newOffset = Math.min(offset, set.offset);
int newCapacity = Math.max(length(), set.length()) - newOffset;
ensureCapacity(newOffset, newCapacity);
int wordDiff = wordDiff(newOffset, set.offset);
for (int i = 0; i < set.bits.length; i++) {
bits[i - wordDiff] |= set.bits[i];
}
}
/**
* Logically XORs this bit set with the specified set of bits.
*
* @param set the bit set to be XORed with
* @throws IllegalArgumentException if set == null
*/
@Override
public void xor(OffsetBitVector set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (this == set) {
clearAll();
return;
}
int newOffset = Math.min(offset, set.offset);
int newCapacity = Math.max(length(), set.length()) - newOffset;
ensureCapacity(newOffset, newCapacity);
int wordDiff = wordDiff(newOffset, set.offset);
for (int i = 0; i < set.bits.length; i++) {
bits[i - wordDiff] ^= set.bits[i];
}
}
@Override
public void andNot(OffsetBitVector set) throws IllegalArgumentException {
if (set == null) {
throw new IllegalArgumentException("set == null");
}
if (this == set) {
clearAll();
return;
}
int wordDiff = wordDiff(offset, set.offset);
int maxWord = Math.min(bits.length, set.bits.length - wordDiff);
int i = Math.max(0, -wordDiff);
for (; i < maxWord; i++) {
bits[i] &= ~set.bits[i + wordDiff];
}
}
/** Return the NOT of a bit string */
public static OffsetBitVector not(OffsetBitVector s) {
OffsetBitVector b = new OffsetBitVector(s);
b.not();
return b;
}
/**
* Return a new bit string as the AND of two others.
*
* @throws IllegalArgumentException if b2 == null
*/
public static OffsetBitVector and(OffsetBitVector b1, OffsetBitVector b2)
throws IllegalArgumentException {
if (b2 == null) {
throw new IllegalArgumentException("b2 == null");
}
OffsetBitVector b = new OffsetBitVector(b1);
b.and(b2);
return b;
}
/**
* Return a new FixedSizeBitVector as the OR of two others
*
* @throws IllegalArgumentException if b2 == null
*/
public static OffsetBitVector or(OffsetBitVector b1, OffsetBitVector b2)
throws IllegalArgumentException {
if (b2 == null) {
throw new IllegalArgumentException("b2 == null");
}
OffsetBitVector b = new OffsetBitVector(b1);
b.or(b2);
return b;
}
/** Return a new bit string as the AND of two others. */
public static OffsetBitVector andNot(OffsetBitVector b1, OffsetBitVector b2) {
OffsetBitVector b = new OffsetBitVector(b1);
b.andNot(b2);
return b;
}
}