@Override
 public Container iand(RunContainer x) {
   // could probably be replaced with return iand(x.toBitmapOrArrayContainer());
   final int card = x.getCardinality();
   if (card <= ArrayContainer.DEFAULT_MAX_SIZE) {
     // no point in doing it in-place
     ArrayContainer answer = new ArrayContainer(card);
     answer.cardinality = 0;
     for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
       int runStart = Util.toIntUnsigned(x.getValue(rlepos));
       int runEnd = runStart + Util.toIntUnsigned(x.getLength(rlepos));
       for (int runValue = runStart; runValue <= runEnd; ++runValue) {
         if (this.contains(
             (short)
                 runValue)) { // it looks like contains() should be cheap enough if accessed
                              // sequentially
           answer.content[answer.cardinality++] = (short) runValue;
         }
       }
     }
     return answer;
   }
   int start = 0;
   for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
     int end = Util.toIntUnsigned(x.getValue(rlepos));
     Util.resetBitmapRange(this.bitmap, start, end);
     start = end + Util.toIntUnsigned(x.getLength(rlepos)) + 1;
   }
   Util.resetBitmapRange(this.bitmap, start, Util.maxLowBitAsInteger() + 1);
   computeCardinality();
   if (getCardinality() > ArrayContainer.DEFAULT_MAX_SIZE) return this;
   else return toArrayContainer();
 }
 protected Container lazyor(RunContainer x) {
   BitmapContainer bc = clone();
   bc.cardinality = -1; // invalid
   for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
     int start = Util.toIntUnsigned(x.getValue(rlepos));
     int end = start + Util.toIntUnsigned(x.getLength(rlepos)) + 1;
     Util.setBitmapRange(bc.bitmap, start, end);
   }
   return bc;
 }
 protected Container ilazyor(RunContainer x) {
   // could be implemented as return ilazyor(x.toTemporaryBitmap());
   cardinality = -1; // invalid
   for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
     int start = Util.toIntUnsigned(x.getValue(rlepos));
     int end = start + Util.toIntUnsigned(x.getLength(rlepos)) + 1;
     Util.setBitmapRange(this.bitmap, start, end);
   }
   return this;
 }
 @Override
 public Container ior(RunContainer x) {
   // could probably be replaced with return ior(x.toBitmapOrArrayContainer());
   for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
     int start = Util.toIntUnsigned(x.getValue(rlepos));
     int end = start + Util.toIntUnsigned(x.getLength(rlepos)) + 1;
     Util.setBitmapRange(this.bitmap, start, end);
   }
   computeCardinality();
   return this;
 }
 @Override
 public Container iandNot(RunContainer x) {
   // could probably be replaced with return iandNot(x.toBitmapOrArrayContainer());
   for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
     int start = Util.toIntUnsigned(x.getValue(rlepos));
     int end = start + Util.toIntUnsigned(x.getLength(rlepos)) + 1;
     Util.resetBitmapRange(this.bitmap, start, end);
   }
   computeCardinality();
   if (getCardinality() > ArrayContainer.DEFAULT_MAX_SIZE) return this;
   else return toArrayContainer();
 }
 @Override
 public Container andNot(RunContainer x) {
   // could be rewritten as return andNot(x.toBitmapOrArrayContainer());
   BitmapContainer answer = this.clone();
   for (int rlepos = 0; rlepos < x.nbrruns; ++rlepos) {
     int start = Util.toIntUnsigned(x.getValue(rlepos));
     int end = start + Util.toIntUnsigned(x.getLength(rlepos)) + 1;
     Util.resetBitmapRange(answer.bitmap, start, end);
   }
   answer.computeCardinality();
   if (answer.getCardinality() > ArrayContainer.DEFAULT_MAX_SIZE) return answer;
   else return answer.toArrayContainer();
 }
  @Override
  public Container runOptimize() {
    int numRuns = numberOfRunsLowerBound(MAXRUNS); // decent choice

    int sizeAsRunContainerLowerBound = RunContainer.serializedSizeInBytes(numRuns);

    if (sizeAsRunContainerLowerBound >= getArraySizeInBytes()) return this;
    // else numRuns is a relatively tight bound that needs to be exact
    // in some cases (or if we need to make the runContainer the right
    // size)
    numRuns += numberOfRunsAdjustment();
    int sizeAsRunContainer = RunContainer.serializedSizeInBytes(numRuns);

    if (getArraySizeInBytes() > sizeAsRunContainer) {
      return new RunContainer(this, numRuns);
    } else return this;
  }
 @Override
 public Container and(RunContainer x) {
   return x.and(this);
 }
 @Override
 public boolean intersects(RunContainer x) {
   return x.intersects(this);
 }
 @Override
 public Container xor(RunContainer x) {
   return x.xor(this);
 }