ArrayPackedSet(ObjectIntMapper<T> 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)]);
  }
  /** Returns true, if the object is in the set. */
  public boolean contains(T 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 List<T> toList(int low, int high) {
    List<T> elements = new ArrayList<T>();

    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<T> toList() {
    List<T> elements = new ArrayList<T>();

    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 complement(FlowSet<T> destFlow) {
    if (sameType(destFlow)) {
      ArrayPackedSet<T> dest = (ArrayPackedSet<T>) 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(T obj) {
    int bitNum = map.getInt(obj);

    bits[bitNum / 32] &= ~(1 << (bitNum % 32));
  }
  public void add(T obj) {
    int bitNum = map.getInt(obj);

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