/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.lucene.util; // from org.apache.solr.util rev 555343
A variety of high efficiency bit twiddling routines.
@lucene.internal
/** A variety of high efficiency bit twiddling routines.
* @lucene.internal
*/
public final class BitUtil {
// magic numbers for bit interleaving
private static final long MAGIC[] = {
0x5555555555555555L, 0x3333333333333333L,
0x0F0F0F0F0F0F0F0FL, 0x00FF00FF00FF00FFL,
0x0000FFFF0000FFFFL, 0x00000000FFFFFFFFL,
0xAAAAAAAAAAAAAAAAL
};
// shift values for bit interleaving
private static final short SHIFT[] = {1, 2, 4, 8, 16};
private BitUtil() {} // no instance
// 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. /** 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. /** 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. /** 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 A & ~B
. Neither array is modified. /** 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. /** 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/** returns the next highest power of two, or the current value if it's already a power of two or zero*/
public static int nextHighestPowerOfTwo(int v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v++;
return v;
}
returns the next highest power of two, or the current value if it's already a power of two or zero/** returns the next highest power of two, or the current value if it's already a power of two or zero*/
public static long nextHighestPowerOfTwo(long v) {
v--;
v |= v >> 1;
v |= v >> 2;
v |= v >> 4;
v |= v >> 8;
v |= v >> 16;
v |= v >> 32;
v++;
return v;
}
Interleaves the first 32 bits of each long value
Adapted from: http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
/**
* Interleaves the first 32 bits of each long value
*
* Adapted from: http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN
*/
public static long interleave(int even, int odd) {
long v1 = 0x00000000FFFFFFFFL & even;
long v2 = 0x00000000FFFFFFFFL & odd;
v1 = (v1 | (v1 << SHIFT[4])) & MAGIC[4];
v1 = (v1 | (v1 << SHIFT[3])) & MAGIC[3];
v1 = (v1 | (v1 << SHIFT[2])) & MAGIC[2];
v1 = (v1 | (v1 << SHIFT[1])) & MAGIC[1];
v1 = (v1 | (v1 << SHIFT[0])) & MAGIC[0];
v2 = (v2 | (v2 << SHIFT[4])) & MAGIC[4];
v2 = (v2 | (v2 << SHIFT[3])) & MAGIC[3];
v2 = (v2 | (v2 << SHIFT[2])) & MAGIC[2];
v2 = (v2 | (v2 << SHIFT[1])) & MAGIC[1];
v2 = (v2 | (v2 << SHIFT[0])) & MAGIC[0];
return (v2<<1) | v1;
}
Extract just the even-bits value as a long from the bit-interleaved value
/**
* Extract just the even-bits value as a long from the bit-interleaved value
*/
public static long deinterleave(long b) {
b &= MAGIC[0];
b = (b ^ (b >>> SHIFT[0])) & MAGIC[1];
b = (b ^ (b >>> SHIFT[1])) & MAGIC[2];
b = (b ^ (b >>> SHIFT[2])) & MAGIC[3];
b = (b ^ (b >>> SHIFT[3])) & MAGIC[4];
b = (b ^ (b >>> SHIFT[4])) & MAGIC[5];
return b;
}
flip flops odd with even bits
/**
* flip flops odd with even bits
*/
public static final long flipFlop(final long b) {
return ((b & MAGIC[6]) >>> 1) | ((b & MAGIC[0]) << 1 );
}
Same as zigZagEncode(long)
but on integers. /** Same as {@link #zigZagEncode(long)} but on integers. */
public static int zigZagEncode(int i) {
return (i >> 31) ^ (i << 1);
}
Zig-zag
encode the provided long. Assuming the input is a signed long whose
absolute value can be stored on n bits, the returned value will
be an unsigned long that can be stored on n+1 bits.
/**
* <a href="https://developers.google.com/protocol-buffers/docs/encoding#types">Zig-zag</a>
* encode the provided long. Assuming the input is a signed long whose
* absolute value can be stored on <tt>n</tt> bits, the returned value will
* be an unsigned long that can be stored on <tt>n+1</tt> bits.
*/
public static long zigZagEncode(long l) {
return (l >> 63) ^ (l << 1);
}
Decode an int previously encoded with zigZagEncode(int)
. /** Decode an int previously encoded with {@link #zigZagEncode(int)}. */
public static int zigZagDecode(int i) {
return ((i >>> 1) ^ -(i & 1));
}
Decode a long previously encoded with zigZagEncode(long)
. /** Decode a long previously encoded with {@link #zigZagEncode(long)}. */
public static long zigZagDecode(long l) {
return ((l >>> 1) ^ -(l & 1));
}
}