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

soot.toolkits.scalar.ArrayPackedSet Maven / Gradle / Ivy

There is a newer version: 2.5.0-9
Show newest version
/* Soot - a J*va Optimization Framework
 * Copyright (C) 1997-1999 Raja Vallee-Rai
 *       updated 2002 Florian Loitsch
 *
 * 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.
 */

/*
 * Modified by the Sable Research Group and others 1997-1999.  
 * See the 'credits' file distributed with Soot for the complete list of
 * contributors.  (Soot is distributed at http://www.sable.mcgill.ca/soot)
 */


package soot.toolkits.scalar;

import java.util.*;


/**
 *   Reference implementation for a BoundedFlowSet. Items are stored in an Array.  
 */
public class ArrayPackedSet extends AbstractBoundedFlowSet
{
    ObjectIntMapper map;
    int[] bits;

    public ArrayPackedSet(FlowUniverse universe) {
        this(new ObjectIntMapper(universe));
    }

    ArrayPackedSet(ObjectIntMapper map)
    {
        //int size = universe.getSize();

        //int numWords = size / 32 + (((size % 32) != 0) ? 1 : 0);

        this(map, new int[map.size() / 32 + (((map.size() % 32) != 0) ? 1 : 0)]);
    }
    
    ArrayPackedSet(ObjectIntMapper map, int[] bits)
    {
        this.map = map;
        this.bits = bits.clone();
    }

    /** Returns true if flowSet is the same type of flow set as this. */
    private boolean sameType(Object flowSet)
    {
        return (flowSet instanceof ArrayPackedSet &&
                ((ArrayPackedSet)flowSet).map == map);
    }

    public ArrayPackedSet clone()
    {
        return new ArrayPackedSet(map, bits);
    }

    public Object emptySet()
    {
        return new ArrayPackedSet(map);
    }

    public int size()
    {
        int count = 0;

        for (int word : bits) {
            for(int j = 0; j < 32; j++)
                if((word & (1 << j)) != 0)
                    count++;
        }

        return count;
    }

    public boolean isEmpty()
    {
        for (int element : bits)
			if(element != 0)
                return false;

        return true;
    }


    public void clear()
    {
        for(int i = 0; i < bits.length; i++)
            bits[i] = 0;
    }


    public List toList(int low, int high)
    {
        List elements = new ArrayList();

        int startWord = low / 32,
            startBit = low % 32;

        int endWord = high / 32,
            endBit = high % 32;

        if(low > high)
            return elements;

        // Do the first word
        {
            int word = bits[startWord];

            int offset = startWord * 32;
            int lastBit = (startWord != endWord) ? 32 : (endBit + 1);

            for(int j = startBit; j < lastBit; j++)
            {
                if((word & (1 << j)) != 0)
                    elements.add(map.getObject(offset + j));
            }
        }

        // Do the in between ones
            if(startWord != endWord && startWord + 1 != endWord)
            {
                for(int i = startWord + 1; i < endWord; i++)
                {
                    int word = bits[i];
                    int offset = i * 32;

                    for(int j = 0; j < 32; j++)
                    {
                        if((word & (1 << j)) != 0)
                            elements.add(map.getObject(offset + j));
                    }
                }
            }

        // Do the last one
            if(startWord != endWord)
            {
                int word = bits[endWord];
                int offset = endWord * 32;
                int lastBit = endBit + 1;

                for(int j = 0; j < lastBit; j++)
                {
                    if((word & (1 << j)) != 0)
                        elements.add(map.getObject(offset + j));
                }
            }

        return elements;
    }


    public List toList()
    {
        List elements = new ArrayList();

        for(int i = 0; i < bits.length; i++)
        {
            int word = bits[i];
            int offset = i * 32;

            for(int j = 0; j < 32; j++)
                if((word & (1 << j)) != 0)
                    elements.add(map.getObject(offset + j));
        }

        return elements;
    }

    public void add(Object obj)
    {
        int bitNum = map.getInt(obj);

        bits[bitNum / 32] |= 1 << (bitNum % 32);
    }

    public void complement(FlowSet destFlow)
    {
      if (sameType(destFlow)) {
        ArrayPackedSet dest = (ArrayPackedSet) destFlow;

        for(int i = 0; i < bits.length; i++)
            dest.bits[i] = ~(this.bits[i]);
            
        // Clear the bits which are outside of this universe
            if(bits.length >= 1)
            {
                int lastValidBitCount = map.size() % 32;
                
                if(lastValidBitCount != 0)
                    dest.bits[bits.length - 1] &= ~(0xFFFFFFFF << lastValidBitCount);  
            }
      } else
        super.complement(destFlow);
    }

    public void remove(Object obj)
    {
        int bitNum = map.getInt(obj);

        bits[bitNum / 32] &= ~(1 << (bitNum % 32));
    }

    public void union(FlowSet otherFlow, FlowSet destFlow)
    {
      if (sameType(otherFlow) &&
          sameType(destFlow)) {
        ArrayPackedSet other = (ArrayPackedSet) otherFlow;
        ArrayPackedSet dest = (ArrayPackedSet) destFlow;

        if(!(other instanceof ArrayPackedSet) || bits.length != other.bits.length)
            throw new RuntimeException("Incompatible other set for union");

        for(int i = 0; i < bits.length; i++)
            dest.bits[i] = this.bits[i] | other.bits[i];
      } else
        super.union(otherFlow, destFlow);
    }

    public void difference(FlowSet otherFlow, FlowSet destFlow)
    {
      if (sameType(otherFlow) &&
          sameType(destFlow)) {
        ArrayPackedSet other = (ArrayPackedSet) otherFlow;
        ArrayPackedSet dest = (ArrayPackedSet) destFlow;

        if(!(other instanceof ArrayPackedSet) || bits.length != other.bits.length)
            throw new RuntimeException("Incompatible other set for union");
            
        for(int i = 0; i < bits.length; i++)
            dest.bits[i] = this.bits[i] & ~other.bits[i];
      } else
        super.difference(otherFlow, destFlow);
    }
    
    public void intersection(FlowSet otherFlow, FlowSet destFlow)
    {
      if (sameType(otherFlow) &&
          sameType(destFlow)) {
        ArrayPackedSet other = (ArrayPackedSet) otherFlow;
        ArrayPackedSet dest = (ArrayPackedSet) destFlow;

        if(!(other instanceof ArrayPackedSet) || bits.length != other.bits.length)
            throw new RuntimeException("Incompatible other set for union");

        for(int i = 0; i < bits.length; i++)
            dest.bits[i] = this.bits[i] & other.bits[i];
      } else
        super.intersection(otherFlow, destFlow);
    }

  /** Returns true, if the object is in the set.
   */
    public boolean contains(Object obj)
    {
      /* check if the object is in the map, direct call of map.getInt will
       * add the object into the map.
       */
        if (!map.contains(obj)) return false;

        int bitNum = map.getInt(obj);

        return (bits[bitNum / 32] & (1 << (bitNum % 32))) != 0;
    }

    public boolean equals(Object otherFlow)
    {
      if (sameType(otherFlow)) {
        return Arrays.equals(bits, ((ArrayPackedSet)otherFlow).bits);
      } else
        return super.equals(otherFlow);
    }

    public void copy(FlowSet destFlow)
    {
      if (sameType(destFlow)) {
        ArrayPackedSet dest = (ArrayPackedSet) destFlow;

        for(int i = 0; i < bits.length; i++)
            dest.bits[i] = this.bits[i];
      } else
        super.copy(destFlow);
    }

}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy