@Override
 public Container add(int begin, int end) {
   BitmapContainer answer = clone();
   Util.setBitmapRange(answer.bitmap, begin, end);
   answer.computeCardinality();
   return answer;
 }
 @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();
 }
 @Override
 public Container iremove(int begin, int end) {
   Util.resetBitmapRange(bitmap, begin, end);
   computeCardinality();
   if (getCardinality() <= ArrayContainer.DEFAULT_MAX_SIZE) return toArrayContainer();
   return this;
 }
 @Override
 public Container remove(int begin, int end) {
   BitmapContainer answer = clone();
   Util.resetBitmapRange(answer.bitmap, begin, end);
   answer.computeCardinality();
   if (answer.getCardinality() <= ArrayContainer.DEFAULT_MAX_SIZE)
     return answer.toArrayContainer();
   return answer;
 }
 @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 iadd(int begin, int end) {
   Util.setBitmapRange(bitmap, begin, end);
   computeCardinality();
   return this;
 }
 @Override
 public Container repairAfterLazy() {
   if (getCardinality() < 0) computeCardinality();
   return this;
 }