@Test
  public void testHighBits() throws IOException {
    // version without any runcontainers (earlier serialization version)
    for (int offset = 1 << 14; offset < 1 << 18; offset *= 2) {
      MutableRoaringBitmap rb = new MutableRoaringBitmap();
      for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE; k += offset) {
        rb.add((int) k);
      }
      for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE; k += offset) {
        Assert.assertTrue(rb.contains((int) k));
      }
      int[] array = rb.toArray();
      ByteBuffer b = ByteBuffer.allocate(rb.serializedSizeInBytes());
      rb.serialize(
          new DataOutputStream(
              new OutputStream() {
                ByteBuffer mBB;

                @Override
                public void close() {}

                @Override
                public void flush() {}

                OutputStream init(final ByteBuffer mbb) {
                  mBB = mbb;
                  return this;
                }

                @Override
                public void write(final byte[] b) {
                  mBB.put(b);
                }

                @Override
                public void write(final byte[] b, final int off, final int l) {
                  mBB.put(b, off, l);
                }

                @Override
                public void write(final int b) {
                  mBB.put((byte) b);
                }
              }.init(b)));
      b.flip();
      ImmutableRoaringBitmap irb = new ImmutableRoaringBitmap(b);
      Assert.assertTrue(irb.equals(rb));
      for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE; k += offset) {
        Assert.assertTrue(irb.contains((int) k));
      }
      Assert.assertTrue(Arrays.equals(array, irb.toArray()));
    }
  }
  @SuppressWarnings("resource")
  @Test
  public void testProperSerialization() throws IOException {
    final int SIZE = 500;
    final Random rand = new Random(0);
    for (int i = 0; i < SIZE; ++i) {
      MutableRoaringBitmap r = new MutableRoaringBitmap();
      for (int k = 0; k < 500000; ++k) {
        if (rand.nextDouble() < .5) {
          r.add(k);
        }
      }
      ByteBuffer b = ByteBuffer.allocate(r.serializedSizeInBytes());
      r.serialize(
          new DataOutputStream(
              new OutputStream() {
                ByteBuffer mBB;

                @Override
                public void close() {}

                @Override
                public void flush() {}

                OutputStream init(final ByteBuffer mbb) {
                  mBB = mbb;
                  return this;
                }

                @Override
                public void write(final byte[] b) {
                  mBB.put(b);
                }

                @Override
                public void write(final byte[] b, final int off, final int l) {
                  mBB.put(b, off, l);
                }

                @Override
                public void write(final int b) {
                  mBB.put((byte) b);
                }
              }.init(b)));
      b.flip();
      ImmutableRoaringBitmap irb = new ImmutableRoaringBitmap(b);
      Assert.assertTrue(irb.equals(r));
      Assert.assertTrue(irb.hashCode() == r.hashCode());
      Assert.assertTrue(irb.getCardinality() == r.getCardinality());
    }
  }
  @SuppressWarnings("resource")
  @Test
  public void testHighBitsA() throws IOException {
    // includes some run containers
    for (int offset = 1 << 14; offset < 1 << 18; offset *= 2) {
      MutableRoaringBitmap rb = new MutableRoaringBitmap();
      for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE - 100000; k += offset) {
        rb.add((int) k);
      }
      for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE - 100000; k += offset) {
        Assert.assertTrue(rb.contains((int) k));
      }

      int runlength = 99000;
      for (int k = Integer.MAX_VALUE - 100000; k < Integer.MAX_VALUE - 100000 + runlength; ++k) {
        rb.add(k);
      }

      rb.runOptimize();

      int[] array = rb.toArray();
      // int pos = 0;
      // check that it is in sorted order according to unsigned order
      for (int k = 0; k < array.length - 1; ++k) {
        Assert.assertTrue((0xFFFFFFFFL & array[k]) <= (0xFFFFFFFFL & array[k + 1]));
      }
      ///////////////////////
      // It was decided that Roaring would consider ints as unsigned
      ///////////////////////
      // for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE-100000; k += offset) {
      // Assert.assertTrue(array[pos++] == (int)k);
      // }
      // Assert.assertTrue(pos+runlength == array.length);
      ByteBuffer b = ByteBuffer.allocate(rb.serializedSizeInBytes());
      rb.serialize(
          new DataOutputStream(
              new OutputStream() {
                ByteBuffer mBB;

                @Override
                public void close() {}

                @Override
                public void flush() {}

                OutputStream init(final ByteBuffer mbb) {
                  mBB = mbb;
                  return this;
                }

                @Override
                public void write(final byte[] b) {
                  mBB.put(b);
                }

                @Override
                public void write(final byte[] b, final int off, final int l) {
                  mBB.put(b, off, l);
                }

                @Override
                public void write(final int b) {
                  mBB.put((byte) b);
                }
              }.init(b)));
      b.flip();
      ImmutableRoaringBitmap irb = new ImmutableRoaringBitmap(b);
      Assert.assertTrue(irb.equals(rb));
      for (long k = Integer.MIN_VALUE; k < Integer.MAX_VALUE - 100000; k += offset) {
        Assert.assertTrue(irb.contains((int) k));
      }

      for (int k = Integer.MAX_VALUE - 100000; k < Integer.MAX_VALUE - 100000 + runlength; ++k) {
        Assert.assertTrue(irb.contains(k));
      }

      array = irb.toArray();
      for (int k = 0; k < array.length - 1; ++k) {
        Assert.assertTrue((0xFFFFFFFFL & array[k]) <= (0xFFFFFFFFL & array[k + 1]));
      }
      // Assert.assertEquals(Integer.MAX_VALUE - 100000 +runlength-1, array[array.length-1]);
    }
  }