All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.util.BitVector Maven / Gradle / Ivy

/* Soot - a J*va Optimization Framework
 * Copyright (C) 2003 Ondrej Lhotak
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

package soot.util;

/** This is the Soot internal implementation of java.util.BitSet with
 * Felix and Jerome's clever efficient iterator. It was re-implemented
 * from scratch by Ondrej Lhotak to avoid licence issues. It was named
 * BitVector rather than BitSet to avoid a name clash with the one in
 * the standard Java library.
 *
 * @author Ondrej Lhotak
 */
public class BitVector
{ 
    public BitVector() {
        this(64);
    }
    
    /**Copy constructor*/
    //Added by Adam Richard.  More efficient than clone(), and easier to extend
    public BitVector(BitVector other)
    {
        bits = new long[other.bits.length];
        System.arraycopy( other.bits, 0, bits, 0, other.bits.length );
    }
    public BitVector( int numBits ) {
        int lastIndex = indexOf( numBits-1 );
        bits = new long[lastIndex+1];
    }
    private long[] bits;
    private int indexOf( int bit ) {
        return bit >> 6;
    }
    private long mask( int bit ) {
        return 1L << ( bit & 63 );
    }
    public void and(BitVector other) {
        if( this == other ) return;
        long[] otherBits = other.bits;
        int numToAnd = otherBits.length;
        if( bits.length < numToAnd ) numToAnd = bits.length;
        int i;
        for( i = 0; i < numToAnd; i++ ) {
            bits[i] = bits[i] & otherBits[i];
        }
        for( ; i < bits.length; i++ ) {
            bits[i] = 0L;
        }
    }
    public void andNot(BitVector other) {
        long[] otherBits = other.bits;
        int numToAnd = otherBits.length;
        if( bits.length < numToAnd ) numToAnd = bits.length;
        for( int i = 0; i < numToAnd; i++ ) {
            bits[i] = bits[i] & ~otherBits[i];
        }
    }
    public void clear( int bit ) {
        if( indexOf(bit) < bits.length )
            bits[indexOf(bit)] &= ~mask(bit);
    }
    public Object clone() {
        try {
			BitVector ret = (BitVector) super.clone();
	        System.arraycopy( bits, 0, ret.bits, 0, ret.bits.length );
	        return ret;
		} catch (CloneNotSupportedException e) {
			//cannot occur
			throw new RuntimeException(e);
		}
    }
    public boolean equals( Object o ) {
        if( !( o instanceof BitVector ) ) return false;
        BitVector other = (BitVector) o;
        int min = bits.length;
        long[] longer = other.bits;
        if( other.bits.length < min ) {
            min = other.bits.length;
            longer = bits;
        }
        int i;
        for( i = 0; i < min; i++ ) {
            if( bits[i] != other.bits[i] ) return false;
        }
        for( ; i < longer.length; i++ ) {
            if( longer[i] != 0L ) return false;
        }
        return true;
    }
    public boolean get( int bit ) {
        if( indexOf(bit) >= bits.length ) return false;
        return ( bits[indexOf(bit)] & mask(bit) ) != 0L;
    }
    public int hashCode() {
        long ret = 0;
        for (long element : bits) {
            ret ^= element;
        }
        return (int) ( (ret >> 32) ^ ret );
    }
    /** Returns index of highest-numbered one bit. */
    public int length() {
        int i;
        for( i = bits.length-1; i >= 0; i-- ) {
            if( bits[i] != 0L ) break;
        }
        if( i < 0 ) return 0;
        long j = bits[i];
        i++;
        i <<= 6;
        for( long k = 1L << 63; (k&j) == 0L; k >>=1, i-- );
        return i;
    }
    public void copyFrom( BitVector other ) {
        if( this == other ) return;
        long[] otherBits = other.bits;
        int j;
        for( j = otherBits.length-1; j >= 0; j-- ) {
            if( otherBits[j] != 0L ) break;
        }
        expand( j<<6 );
        int i = j+1;
        for( ; j >= 0; j-- ) {
            bits[j] = otherBits[j];
        }
        for( ; i < bits.length; i++ ) {
            bits[i] = 0L;
        }
    }
    public void or( BitVector other ) {
        if( this == other ) return;
        long[] otherBits = other.bits;
        int j;
        for( j = otherBits.length-1; j >= 0; j-- ) {
            if( otherBits[j] != 0L ) break;
        }
        expand( j<<6 );
        for( ; j >= 0; j-- ) {
            bits[j] |= otherBits[j];
        }
    }
    
    /**Count the number of ones in the bitvector.
     * @author Adam Richard
     * This is Brian Kernighan's algorithm from:
     * http://graphics.stanford.edu/~seander/bithacks.html
     * and is efficient for sparse bit sets.
     */
	public int cardinality()
	{
		int c = 0;
		for (long v : bits) {
			while (v != 0)
			{
				v &= v - 1;
				++c;
			}
		}
		return c;
	}

    private void expand( int bit ) {
        int n = indexOf( bit )+1;
        if( n <= bits.length ) return;
        if( bits.length*2 > n ) n = bits.length*2;
        long[] newBits = new long[n];
        System.arraycopy( bits, 0, newBits, 0, bits.length );
        bits = newBits;
    }
    public void xor( BitVector other ) {
        if( this == other ) return;
        long[] otherBits = other.bits;
        int j;
        for( j = otherBits.length-1; j >= 0; j-- ) {
            if( otherBits[j] != 0L ) break;
        }
        expand( j<<6 );
        for( ; j >= 0; j-- ) {
            bits[j] ^= otherBits[j];
        }
    }
    public boolean set( int bit ) {
        expand(bit);
        boolean ret = !get(bit);
        bits[indexOf(bit)] |= mask(bit);
        return ret;
    }
    /** Returns number of bits in the underlying array. */
    public int size() {
        return bits.length << 6;
    }
    public String toString() {
        StringBuffer ret = new StringBuffer();
        ret.append('{');
        boolean start = true;
        BitSetIterator it = new BitSetIterator( bits );
        while( it.hasNext() ) {
            int bit = it.next();
            if( !start ) ret.append( ", " );
            start = false;
            ret.append(bit);
        }
        ret.append('}');
        return ret.toString();
    }
    /*
    public boolean orAndAndNotCheck(BitVector orset, BitVector andset, BitVector andnotset) {
        BitVector orAndAnd = (BitVector) orset.clone();
        if( andset != null ) orAndAnd.and( andset );
        if( andnotset != null ) orAndAnd.andNot( andnotset );
        orAndAnd.or( this );
        boolean ret = !orAndAnd.equals(this);
        orAndAndNotOld( orset, andset, andnotset );
        if( !this.equals( orAndAnd ) ) {
            throw new RuntimeException( "orset is "+orset+"\nandset is "+andset+"\nandnotset is "+andnotset+"\nthis is "+this+"\ncorrect is "+orAndAnd );
        }
        return ret;
    }
    */
    /**
     * Computes this = this OR ((orset AND andset ) AND (NOT andnotset))
     * Returns true iff this is modified.
     * @param set a bit set.
     */
    public boolean orAndAndNot(BitVector orset, BitVector andset, BitVector andnotset) {
        boolean ret = false;
        long[] a = null, b = null, c = null, d = null, e = null;
        int al, bl, cl, dl;
        a = this.bits;
        al = a.length;
        if( orset == null ) {
            bl = 0;
        } else {
            b = orset.bits;
            bl = b.length;
        }
        if( andset == null ) {
            cl = 0;
        } else {
            c = andset.bits;
            cl = c.length;
        }
        if( andnotset == null ) {
            dl = 0;
        } else {
            d = andnotset.bits;
            dl = d.length;
        }

        if( al < bl ) {
            e = new long[bl];
            System.arraycopy( a, 0, e, 0, al );
            this.bits = e;
        } else {
            e = a;
        }
        int i = 0;
        long l;

        if( c == null ) {
            if( dl <= bl ) {
                while( i < dl ) {
                    l = b[i] & ~d[i];
                    if( (l & ~e[i]) != 0 ) ret = true;
                    e[i] |= l;
                    i++;
                }
                while( i < bl ) {
                    l = b[i];
                    if( (l & ~e[i]) != 0 ) ret = true;
                    e[i] |= l;
                    i++;
                }
            } else {
                while( i < bl ) {
                    l = b[i] & ~d[i];
                    if( (l & ~e[i]) != 0 ) ret = true;
                    e[i] |= l;
                    i++;
                }
            }
        } else if( bl <= cl && bl <= dl ) {
            // bl is the shortest
            while( i < bl ) {
                l = b[i] & c[i] & ~d[i];
                if( (l & ~e[i]) != 0 ) ret = true;
                e[i] |= l;
                i++;
            }
        } else if( cl <= bl && cl <= dl ) {
            // cl is the shortest
            while( i < cl ) {
                l = b[i] & c[i] & ~d[i];
                if( (l & ~e[i]) != 0 ) ret = true;
                e[i] |= l;
                i++;
            }
        } else {
            // dl is the shortest
            while( i < dl ) {
                l = b[i] & c[i] & ~d[i];
                if( (l & ~e[i]) != 0 ) ret = true;
                e[i] |= l;
                i++;
            }
            int shorter = cl;
            if( bl < shorter ) shorter = bl;
            while( i < shorter ) {
                l = b[i] & c[i];
                if( (l & ~e[i]) != 0 ) ret = true;
                e[i] |= l;
                i++;
            }
        }

        return ret;
    }
        public static BitVector and( BitVector set1, BitVector set2 ) {
        int min = set1.size();
        {
            int max = set2.size();
            if( min > max ) {
                min = max;
            }
            // max is not necessarily correct at this point, so let it go
            // out of scope
        }

        BitVector ret = new BitVector( min );
        long[] retbits = ret.bits;
        long[] bits1 = set1.bits;
        long[] bits2 = set2.bits;
        min >>= 6;
        for( int i = 0; i < min; i++ ) {
            retbits[i] = bits1[i] & bits2[i];
        }
        return ret;
    }

    public static BitVector or( BitVector set1, BitVector set2 ) {
        int min = set1.size();
        int max = set2.size();
        if( min > max ) {
            min = max;
            max = set1.size();
        }

        BitVector ret = new BitVector( max );
        long[] retbits = ret.bits;
        long[] bits1 = set1.bits;
        long[] bits2 = set2.bits;
        min >>= 6;
        max >>= 6;
        for( int i = 0; i < min; i++ ) {
            retbits[i] = bits1[i] | bits2[i];
        }
        if( bits1.length == min ) {
            System.arraycopy( bits2, min, retbits, min, max-min );
        } else {
            System.arraycopy( bits1, min, retbits, min, max-min );
        }
        return ret;
    }
    public BitSetIterator iterator() {
        return new BitSetIterator(bits);
    }
}






© 2015 - 2024 Weber Informatics LLC | Privacy Policy