@Override public MappeableContainer add(int begin, int end) { int indexstart = BufferUtil.unsignedBinarySearch(content, 0, cardinality, (short) begin); if (indexstart < 0) indexstart = -indexstart - 1; int indexend = BufferUtil.unsignedBinarySearch(content, 0, cardinality, (short) (end - 1)); if (indexend < 0) indexend = -indexend - 1; else indexend++; int rangelength = end - begin; int newcardinality = indexstart + (cardinality - indexend) + rangelength; if (newcardinality > DEFAULT_MAX_SIZE) { MappeableBitmapContainer a = this.toBitmapContainer(); return a.iadd(begin, end); } MappeableArrayContainer answer = new MappeableArrayContainer(newcardinality, content); if (!BufferUtil.isBackedBySimpleArray(answer.content)) throw new RuntimeException("Should not happen. Internal bug."); BufferUtil.arraycopy( content, indexend, answer.content, indexstart + rangelength, cardinality - indexend); short[] answerarray = answer.content.array(); for (int k = 0; k < rangelength; ++k) { answerarray[k + indexstart] = (short) (begin + k); } answer.cardinality = newcardinality; return answer; }
@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; }
@Override public MappeableContainer iadd(int begin, int end) { int indexstart = BufferUtil.unsignedBinarySearch(content, 0, cardinality, (short) begin); if (indexstart < 0) indexstart = -indexstart - 1; int indexend = BufferUtil.unsignedBinarySearch(content, 0, cardinality, (short) (end - 1)); if (indexend < 0) indexend = -indexend - 1; else indexend++; int rangelength = end - begin; int newcardinality = indexstart + (cardinality - indexend) + rangelength; if (newcardinality > DEFAULT_MAX_SIZE) { MappeableBitmapContainer a = this.toBitmapContainer(); return a.iadd(begin, end); } if (newcardinality >= this.content.limit()) increaseCapacity(newcardinality); BufferUtil.arraycopy( content, indexend, content, indexstart + rangelength, cardinality - indexend); if (BufferUtil.isBackedBySimpleArray(content)) { short[] contentarray = content.array(); for (int k = 0; k < rangelength; ++k) { contentarray[k + indexstart] = (short) (begin + k); } } else { for (int k = 0; k < rangelength; ++k) { content.put(k + indexstart, (short) (begin + k)); } } cardinality = newcardinality; return this; }
boolean validate(MappeableBitmapContainer bc, MappeableArrayContainer ac) { // Checking the cardinalities of each container if (bc.getCardinality() != ac.getCardinality()) { System.out.println("cardinality differs"); return false; } // Checking that the two containers contain the same values int counter = 0; int i = bc.nextSetBit(0); while (i >= 0) { ++counter; if (!ac.contains((short) i)) { System.out.println("content differs"); System.out.println(bc); System.out.println(ac); return false; } i = bc.nextSetBit(i + 1); } // checking the cardinality of the BitmapContainer return counter == bc.getCardinality(); }
@Override public MappeableContainer flip(short x) { if (BufferUtil.isBackedBySimpleArray(this.content)) { short[] sarray = content.array(); int loc = Util.unsignedBinarySearch(sarray, 0, cardinality, x); if (loc < 0) { // Transform the ArrayContainer to a BitmapContainer // when cardinality = DEFAULT_MAX_SIZE if (cardinality >= DEFAULT_MAX_SIZE) { MappeableBitmapContainer a = this.toBitmapContainer(); a.add(x); return a; } if (cardinality >= sarray.length) { increaseCapacity(); sarray = content.array(); } // insertion : shift the elements > x by one position to // the right // and put x in it's appropriate place System.arraycopy(sarray, -loc - 1, sarray, -loc, cardinality + loc + 1); sarray[-loc - 1] = x; ++cardinality; } else { System.arraycopy(sarray, loc + 1, sarray, loc, cardinality - loc - 1); --cardinality; } return this; } else { int loc = BufferUtil.unsignedBinarySearch(content, 0, cardinality, x); if (loc < 0) { // Transform the ArrayContainer to a BitmapContainer // when cardinality = DEFAULT_MAX_SIZE if (cardinality >= DEFAULT_MAX_SIZE) { MappeableBitmapContainer a = this.toBitmapContainer(); a.add(x); return a; } if (cardinality >= content.limit()) { increaseCapacity(); } // insertion : shift the elements > x by one position to // the right // and put x in it's appropriate place for (int k = cardinality; k > -loc - 1; --k) content.put(k, content.get(k - 1)); content.put(-loc - 1, x); ++cardinality; } else { for (int k = loc + 1; k < cardinality; --k) { content.put(k - 1, content.get(k)); } --cardinality; } return this; } }
@Test public void BitmapContainerCardinalityTest() { final MappeableBitmapContainer ac = new MappeableBitmapContainer(); for (short k = 0; k < 100; ++k) { ac.add(k); Assert.assertEquals(ac.getCardinality(), k + 1); } for (short k = 0; k < 100; ++k) { ac.add(k); Assert.assertEquals(ac.getCardinality(), 100); } }
@Test public void bitmaptest() { final MappeableBitmapContainer rr = new MappeableBitmapContainer(); rr.add((short) 110); rr.add((short) 114); rr.add((short) 115); final short[] array = new short[3]; int pos = 0; for (final short i : rr) array[pos++] = i; Assert.assertEquals(array[0], (short) 110); Assert.assertEquals(array[1], (short) 114); Assert.assertEquals(array[2], (short) 115); }
@Override public MappeableArrayContainer andNot(MappeableBitmapContainer value2) { final MappeableArrayContainer answer = new MappeableArrayContainer(content.limit()); int pos = 0; short[] sarray = answer.content.array(); if (BufferUtil.isBackedBySimpleArray(this.content)) { short[] c = content.array(); for (int k = 0; k < cardinality; ++k) if (!value2.contains(c[k])) sarray[pos++] = c[k]; } else for (int k = 0; k < cardinality; ++k) { short v = this.content.get(k); if (!value2.contains(v)) sarray[pos++] = v; } answer.cardinality = pos; return answer; }
@Override public MappeableArrayContainer iandNot(MappeableBitmapContainer value2) { if (!BufferUtil.isBackedBySimpleArray(this.content)) throw new RuntimeException("Should not happen. Internal bug."); short[] c = this.content.array(); int pos = 0; for (int k = 0; k < cardinality; ++k) if (!value2.contains(c[k])) c[pos++] = c[k]; this.cardinality = pos; return this; }
@Override public MappeableContainer iand(MappeableBitmapContainer value2) { int pos = 0; for (int k = 0; k < cardinality; ++k) { short v = this.content.get(k); if (value2.contains(v)) this.content.put(pos++, v); } cardinality = pos; return this; }
@Test public void ContainerFactory() { MappeableBitmapContainer bc1, bc2, bc3; MappeableArrayContainer ac1, ac2, ac3; bc1 = new MappeableBitmapContainer(); bc2 = new MappeableBitmapContainer(); bc3 = new MappeableBitmapContainer(); ac1 = new MappeableArrayContainer(); ac2 = new MappeableArrayContainer(); ac3 = new MappeableArrayContainer(); for (short i = 0; i < 5000; i++) bc1.add((short) (i * 70)); for (short i = 0; i < 5000; i++) bc2.add((short) (i * 70)); for (short i = 0; i < 5000; i++) bc3.add((short) (i * 70)); for (short i = 0; i < 4000; i++) ac1.add((short) (i * 50)); for (short i = 0; i < 4000; i++) ac2.add((short) (i * 50)); for (short i = 0; i < 4000; i++) ac3.add((short) (i * 50)); MappeableBitmapContainer rbc; rbc = ac1.clone().toBitmapContainer(); Assert.assertTrue(validate(rbc, ac1)); rbc = ac2.clone().toBitmapContainer(); Assert.assertTrue(validate(rbc, ac2)); rbc = ac3.clone().toBitmapContainer(); Assert.assertTrue(validate(rbc, ac3)); }
@Override public MappeableContainer xor(MappeableBitmapContainer x) { return x.xor(this); }
/** * Copies the data in a bitmap container. * * @return the bitmap container */ public MappeableBitmapContainer toBitmapContainer() { final MappeableBitmapContainer bc = new MappeableBitmapContainer(); bc.loadData(this); return bc; }
protected void loadData(final MappeableBitmapContainer bitmapContainer) { this.cardinality = bitmapContainer.cardinality; if (!BufferUtil.isBackedBySimpleArray(this.content)) throw new RuntimeException("Should not happen. Internal bug."); bitmapContainer.fillArray(content.array()); }
@Override public MappeableContainer and(MappeableBitmapContainer x) { return x.and(this); }