@Override public MappeableArrayContainer and(final MappeableArrayContainer value2) { MappeableArrayContainer value1 = this; final int desiredCapacity = Math.min(value1.getCardinality(), value2.getCardinality()); MappeableArrayContainer answer = new MappeableArrayContainer(desiredCapacity); if (BufferUtil.isBackedBySimpleArray(this.content) && BufferUtil.isBackedBySimpleArray(value2.content)) answer.cardinality = org.roaringbitmap.Util.unsignedIntersect2by2( value1.content.array(), value1.getCardinality(), value2.content.array(), value2.getCardinality(), answer.content.array()); else answer.cardinality = BufferUtil.unsignedIntersect2by2( value1.content, value1.getCardinality(), value2.content, value2.getCardinality(), answer.content.array()); 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; }
/** * 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 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; }
// shares lots of code with inot; candidate for refactoring @Override public MappeableContainer not(final int firstOfRange, final int lastOfRange) { // TODO: this can be optimized for performance if (firstOfRange >= lastOfRange) { return clone(); // empty range } // determine the span of array indices to be affected int startIndex = BufferUtil.unsignedBinarySearch(content, 0, cardinality, (short) firstOfRange); if (startIndex < 0) startIndex = -startIndex - 1; int lastIndex = BufferUtil.unsignedBinarySearch(content, 0, cardinality, (short) (lastOfRange - 1)); if (lastIndex < 0) lastIndex = -lastIndex - 2; final int currentValuesInRange = lastIndex - startIndex + 1; final int spanToBeFlipped = lastOfRange - firstOfRange; final int newValuesInRange = spanToBeFlipped - currentValuesInRange; final int cardinalityChange = newValuesInRange - currentValuesInRange; final int newCardinality = cardinality + cardinalityChange; if (newCardinality > DEFAULT_MAX_SIZE) return toBitmapContainer().not(firstOfRange, lastOfRange); final MappeableArrayContainer answer = new MappeableArrayContainer(newCardinality); if (!BufferUtil.isBackedBySimpleArray(answer.content)) throw new RuntimeException("Should not happen. Internal bug."); short[] sarray = answer.content.array(); for (int i = 0; i < startIndex; ++i) // copy stuff before the active area sarray[i] = content.get(i); int outPos = startIndex; int inPos = startIndex; // item at inPos always >= valInRange int valInRange = firstOfRange; for (; valInRange < lastOfRange && inPos <= lastIndex; ++valInRange) { if ((short) valInRange != content.get(inPos)) sarray[outPos++] = (short) valInRange; else { ++inPos; } } for (; valInRange < lastOfRange; ++valInRange) { answer.content.put(outPos++, (short) valInRange); } // content after the active range for (int i = lastIndex + 1; i < cardinality; ++i) answer.content.put(outPos++, content.get(i)); answer.cardinality = newCardinality; return answer; }
@Override public MappeableArrayContainer iand(final MappeableArrayContainer value2) { final MappeableArrayContainer value1 = this; if (!BufferUtil.isBackedBySimpleArray(value1.content)) throw new RuntimeException("Should not happen. Internal bug."); value1.cardinality = BufferUtil.unsignedIntersect2by2( value1.content, value1.getCardinality(), value2.content, value2.getCardinality(), value1.content.array()); return this; }
@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 MappeableContainer remove(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 = indexend - indexstart; MappeableArrayContainer answer = clone(); BufferUtil.arraycopy( content, indexstart + rangelength, answer.content, indexstart, cardinality - indexstart - rangelength); answer.cardinality = cardinality - rangelength; return answer; }