@Override
  int numberOfRuns() {
    if (cardinality == 0) return 0; // should never happen

    if (BufferUtil.isBackedBySimpleArray(content)) {
      short[] c = content.array();
      int numRuns = 1;
      for (int i = 0; i < cardinality - 1; i++) {
        // this way of doing the computation maximizes superscalar opportunities, can even
        // vectorize!
        if (BufferUtil.toIntUnsigned(c[i]) + 1 != BufferUtil.toIntUnsigned(c[i + 1])) ++numRuns;
      }
      return numRuns;
    } else {
      int numRuns = 0;
      int previous = -2;
      // we do not proceed like above for fear that calling "get" twice per loop would be too much
      for (int i = 0; i < cardinality; i++) {
        int val = BufferUtil.toIntUnsigned(content.get(i));
        if (val != previous + 1) ++numRuns;
        previous = val;
      }
      return numRuns;
    }
  }
 @Override
 public MappeableContainer or(final MappeableArrayContainer value2) {
   final MappeableArrayContainer value1 = this;
   final int totalCardinality = value1.getCardinality() + value2.getCardinality();
   if (totalCardinality > DEFAULT_MAX_SIZE) { // it could be a bitmap!
     final MappeableBitmapContainer bc = new MappeableBitmapContainer();
     if (!BufferUtil.isBackedBySimpleArray(bc.bitmap))
       throw new RuntimeException("Should not happen. Internal bug.");
     long[] bitArray = bc.bitmap.array();
     if (BufferUtil.isBackedBySimpleArray(value2.content)) {
       short[] sarray = value2.content.array();
       for (int k = 0; k < value2.cardinality; ++k) {
         final int i = BufferUtil.toIntUnsigned(sarray[k]) >>> 6;
         bitArray[i] |= (1l << sarray[k]);
       }
     } else
       for (int k = 0; k < value2.cardinality; ++k) {
         short v2 = value2.content.get(k);
         final int i = BufferUtil.toIntUnsigned(v2) >>> 6;
         bitArray[i] |= (1l << v2);
       }
     if (BufferUtil.isBackedBySimpleArray(this.content)) {
       short[] sarray = this.content.array();
       for (int k = 0; k < this.cardinality; ++k) {
         final int i = BufferUtil.toIntUnsigned(sarray[k]) >>> 6;
         bitArray[i] |= (1l << sarray[k]);
       }
     } else
       for (int k = 0; k < this.cardinality; ++k) {
         final int i = BufferUtil.toIntUnsigned(this.content.get(k)) >>> 6;
         bitArray[i] |= (1l << this.content.get(k));
       }
     bc.cardinality = 0;
     int len = bc.bitmap.limit();
     for (int index = 0; index < len; ++index) {
       bc.cardinality += Long.bitCount(bitArray[index]);
     }
     if (bc.cardinality <= DEFAULT_MAX_SIZE) return bc.toArrayContainer();
     return bc;
   }
   final MappeableArrayContainer answer = new MappeableArrayContainer(totalCardinality);
   if (BufferUtil.isBackedBySimpleArray(value1.content)
       && BufferUtil.isBackedBySimpleArray(value2.content))
     answer.cardinality =
         org.roaringbitmap.Util.unsignedUnion2by2(
             value1.content.array(),
             value1.getCardinality(),
             value2.content.array(),
             value2.getCardinality(),
             answer.content.array());
   else
     answer.cardinality =
         BufferUtil.unsignedUnion2by2(
             value1.content,
             value1.getCardinality(),
             value2.content,
             value2.getCardinality(),
             answer.content.array());
   return answer;
 }
  /**
   * it must return items in (unsigned) sorted order. Possible candidate for Container interface? *
   */
  private MappeableContainer or(ShortIterator it, boolean exclusive) {
    MappeableArrayContainer ac = new MappeableArrayContainer();
    int myItPos = 0;
    ac.cardinality = 0;
    // do a merge.  int -1 denotes end of input.
    int myHead = (myItPos == cardinality) ? -1 : BufferUtil.toIntUnsigned(content.get(myItPos++));
    int hisHead = advance(it);

    while (myHead != -1 && hisHead != -1) {
      if (myHead < hisHead) {
        ac.emit((short) myHead);
        myHead = (myItPos == cardinality) ? -1 : BufferUtil.toIntUnsigned(content.get(myItPos++));
      } else if (myHead > hisHead) {
        ac.emit((short) hisHead);
        hisHead = advance(it);
      } else {
        if (!exclusive) ac.emit((short) hisHead);
        hisHead = advance(it);
        myHead = (myItPos == cardinality) ? -1 : BufferUtil.toIntUnsigned(content.get(myItPos++));
      }
    }

    while (myHead != -1) {
      ac.emit((short) myHead);
      myHead = (myItPos == cardinality) ? -1 : BufferUtil.toIntUnsigned(content.get(myItPos++));
    }

    while (hisHead != -1) {
      ac.emit((short) hisHead);
      hisHead = advance(it);
    }

    if (ac.cardinality > DEFAULT_MAX_SIZE) return ac.toBitmapContainer();
    else return ac;
  }
  @Override
  public MappeableContainer andNot(final MappeableRunContainer x) {
    int writeLocation = 0;
    int runStart, runEnd; // the current or upcoming run.
    int whichRun;
    if (x.nbrruns == 0) return clone();

    ShortBuffer buffer = ShortBuffer.allocate(cardinality);

    runStart = BufferUtil.toIntUnsigned(x.getValue(0));
    runEnd = runStart + BufferUtil.toIntUnsigned(x.getLength(0));
    whichRun = 0;

    short val;
    for (int i = 0; i < cardinality; ++i) {
      val = content.get(i);
      int valInt = BufferUtil.toIntUnsigned(val);
      if (valInt < runStart) {
        buffer.put(writeLocation++, val);
      } else if (valInt <= runEnd) ; // don't want item
      else {
        // greater than this run, need to do an advanceUntil on runs
        // done sequentially for now (no galloping attempts).
        do {
          if (whichRun + 1 < x.nbrruns) {
            whichRun++;
            runStart = BufferUtil.toIntUnsigned(x.getValue(whichRun));
            runEnd = runStart + BufferUtil.toIntUnsigned(x.getLength(whichRun));
          } else runStart = runEnd = (1 << 16) + 1; // infinity....
        } while (valInt > runEnd);
        --i; // need to re-process this val
      }
    }
    return new MappeableArrayContainer(writeLocation, buffer);
  }
  @Override
  public void fillLeastSignificant16bits(int[] x, int i, int mask) {
    if (BufferUtil.isBackedBySimpleArray(this.content)) {
      short[] c = this.content.array();
      for (int k = 0; k < this.cardinality; ++k) x[k + i] = BufferUtil.toIntUnsigned(c[k]) | mask;

    } else
      for (int k = 0; k < this.cardinality; ++k)
        x[k + i] = BufferUtil.toIntUnsigned(this.content.get(k)) | mask;
  }
 private int advance(ShortIterator it) {
   if (it.hasNext()) return BufferUtil.toIntUnsigned(it.next());
   else return -1;
 }
 @Override
 public int nextAsInt() {
   return BufferUtil.toIntUnsigned(content[pos--]);
 }
 @Override
 public int nextAsInt() {
   return BufferUtil.toIntUnsigned(parent.content.get(pos--));
 }