LUCENE-10311: Remove pop_XXX helpers from `BitUtil`. (#724)

As @rmuir noted, it would be as simple and create less cognitive overhead to
use `Long#bitCount` directly.
This commit is contained in:
Adrien Grand 2022-03-05 18:38:57 +01:00 committed by GitHub
parent 8086ef9f45
commit ae16917c1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 64 deletions

View File

@ -115,58 +115,6 @@ public final class BitUtil {
public static final VarHandle VH_BE_DOUBLE =
MethodHandles.byteArrayViewVarHandle(double[].class, ByteOrder.BIG_ENDIAN);
// The pop methods used to rely on bit-manipulation tricks for speed but it
// turns out that it is faster to use the Long.bitCount method (which is an
// intrinsic since Java 6u18) in a naive loop, see LUCENE-2221
/** Returns the number of set bits in an array of longs. */
public static long pop_array(long[] arr, int wordOffset, int numWords) {
long popCount = 0;
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
popCount += Long.bitCount(arr[i]);
}
return popCount;
}
/**
* Returns the popcount or cardinality of the two sets after an intersection. Neither array is
* modified.
*/
public static long pop_intersect(long[] arr1, long[] arr2, int wordOffset, int numWords) {
long popCount = 0;
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
popCount += Long.bitCount(arr1[i] & arr2[i]);
}
return popCount;
}
/** Returns the popcount or cardinality of the union of two sets. Neither array is modified. */
public static long pop_union(long[] arr1, long[] arr2, int wordOffset, int numWords) {
long popCount = 0;
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
popCount += Long.bitCount(arr1[i] | arr2[i]);
}
return popCount;
}
/** Returns the popcount or cardinality of {@code A & ~B}. Neither array is modified. */
public static long pop_andnot(long[] arr1, long[] arr2, int wordOffset, int numWords) {
long popCount = 0;
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
popCount += Long.bitCount(arr1[i] & ~arr2[i]);
}
return popCount;
}
/** Returns the popcount or cardinality of A ^ B Neither array is modified. */
public static long pop_xor(long[] arr1, long[] arr2, int wordOffset, int numWords) {
long popCount = 0;
for (int i = wordOffset, end = wordOffset + numWords; i < end; ++i) {
popCount += Long.bitCount(arr1[i] ^ arr2[i]);
}
return popCount;
}
/**
* returns the next highest power of two, or the current value if it's already a power of two or
* zero

View File

@ -73,17 +73,27 @@ public final class FixedBitSet extends BitSet {
*/
public static long intersectionCount(FixedBitSet a, FixedBitSet b) {
// Depends on the ghost bits being clear!
return BitUtil.pop_intersect(a.bits, b.bits, 0, Math.min(a.numWords, b.numWords));
long tot = 0;
final int numCommonWords = Math.min(a.numWords, b.numWords);
for (int i = 0; i < numCommonWords; ++i) {
tot += Long.bitCount(a.bits[i] & b.bits[i]);
}
return tot;
}
/** Returns the popcount or cardinality of the union of the two sets. Neither set is modified. */
public static long unionCount(FixedBitSet a, FixedBitSet b) {
// Depends on the ghost bits being clear!
long tot = BitUtil.pop_union(a.bits, b.bits, 0, Math.min(a.numWords, b.numWords));
if (a.numWords < b.numWords) {
tot += BitUtil.pop_array(b.bits, a.numWords, b.numWords - a.numWords);
} else if (a.numWords > b.numWords) {
tot += BitUtil.pop_array(a.bits, b.numWords, a.numWords - b.numWords);
long tot = 0;
final int numCommonWords = Math.min(a.numWords, b.numWords);
for (int i = 0; i < numCommonWords; ++i) {
tot += Long.bitCount(a.bits[i] | b.bits[i]);
}
for (int i = numCommonWords; i < a.numWords; ++i) {
tot += Long.bitCount(a.bits[i]);
}
for (int i = numCommonWords; i < b.numWords; ++i) {
tot += Long.bitCount(b.bits[i]);
}
return tot;
}
@ -94,9 +104,13 @@ public final class FixedBitSet extends BitSet {
*/
public static long andNotCount(FixedBitSet a, FixedBitSet b) {
// Depends on the ghost bits being clear!
long tot = BitUtil.pop_andnot(a.bits, b.bits, 0, Math.min(a.numWords, b.numWords));
if (a.numWords > b.numWords) {
tot += BitUtil.pop_array(a.bits, b.numWords, a.numWords - b.numWords);
long tot = 0;
final int numCommonWords = Math.min(a.numWords, b.numWords);
for (int i = 0; i < numCommonWords; ++i) {
tot += Long.bitCount(a.bits[i] & ~b.bits[i]);
}
for (int i = numCommonWords; i < a.numWords; ++i) {
tot += Long.bitCount(a.bits[i]);
}
return tot;
}
@ -173,7 +187,11 @@ public final class FixedBitSet extends BitSet {
@Override
public int cardinality() {
// Depends on the ghost bits being clear!
return (int) BitUtil.pop_array(bits, 0, numWords);
long tot = 0;
for (int i = 0; i < numWords; ++i) {
tot += Long.bitCount(bits[i]);
}
return Math.toIntExact(tot);
}
@Override
@ -193,7 +211,9 @@ public final class FixedBitSet extends BitSet {
long popCount = 0;
int maxWord;
for (maxWord = 0; maxWord + interval < numWords; maxWord += interval) {
popCount += BitUtil.pop_array(bits, maxWord, rangeLength);
for (int i = 0; i < rangeLength; ++i) {
popCount += Long.bitCount(bits[maxWord + i]);
}
}
popCount *= (interval / rangeLength) * numWords / maxWord;

View File

@ -136,7 +136,11 @@ public final class LongBitSet implements Accountable {
*/
public long cardinality() {
// Depends on the ghost bits being clear!
return BitUtil.pop_array(bits, 0, numWords);
long tot = 0;
for (int i = 0; i < numWords; ++i) {
tot += Long.bitCount(bits[i]);
}
return tot;
}
public boolean get(long index) {