All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.lucene.util.BitUtil Maven / Gradle / Ivy

There is a newer version: 6.4.2_1
Show newest version
/*
 * 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

import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;

/**
 * A variety of high efficiency bit twiddling routines and encoders for primitives.
 *
 * @lucene.internal
 */
public final class BitUtil {

  private BitUtil() {} // no instance

  /**
   * Native byte order.
   *
   * 

Warning: This constant is {@link ByteOrder#nativeOrder()} only in production environments, * during testing we randomize it. If you need to communicate with native APIs (e.g., Java's * Panama API), use {@link ByteOrder#nativeOrder()}. */ public static final ByteOrder NATIVE_BYTE_ORDER = getNativeByteOrder(); private static ByteOrder getNativeByteOrder() { try { var prop = System.getProperty("tests.seed"); if (prop != null) { return (prop.hashCode() % 2 == 0) ? ByteOrder.LITTLE_ENDIAN : ByteOrder.BIG_ENDIAN; } } catch ( @SuppressWarnings("unused") SecurityException se) { // fall-through } return ByteOrder.nativeOrder(); } /** * A {@link VarHandle} to read/write little endian {@code short} from/to a byte array. Shape: * {@code short vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, short * val)} */ public static final VarHandle VH_LE_SHORT = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.LITTLE_ENDIAN); /** * A {@link VarHandle} to read/write little endian {@code int} from a byte array. Shape: {@code * int vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, int val)} */ public static final VarHandle VH_LE_INT = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.LITTLE_ENDIAN); /** * A {@link VarHandle} to read/write little endian {@code long} from a byte array. Shape: {@code * long vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, long val)} */ public static final VarHandle VH_LE_LONG = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.LITTLE_ENDIAN); /** * A {@link VarHandle} to read/write little endian {@code float} from a byte array. Shape: {@code * float vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, float val)} */ public static final VarHandle VH_LE_FLOAT = MethodHandles.byteArrayViewVarHandle(float[].class, ByteOrder.LITTLE_ENDIAN); /** * A {@link VarHandle} to read/write little endian {@code double} from a byte array. Shape: {@code * double vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, double val)} */ public static final VarHandle VH_LE_DOUBLE = MethodHandles.byteArrayViewVarHandle(double[].class, ByteOrder.LITTLE_ENDIAN); /** * A {@link VarHandle} to read/write native endian {@code short} from/to a byte array. Shape: * {@code short vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, short * val)} * *

Warning: This handle uses default order only in production environments, during testing we * randomize it. If you need to communicate with native APIs (e.g., Java's Panama API), use {@link * ByteOrder#nativeOrder()}. */ public static final VarHandle VH_NATIVE_SHORT = MethodHandles.byteArrayViewVarHandle(short[].class, NATIVE_BYTE_ORDER); /** * A {@link VarHandle} to read/write native endian {@code int} from a byte array. Shape: {@code * int vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, int val)} * *

Warning: This handle uses default order only in production environments, during testing we * randomize it. If you need to communicate with native APIs (e.g., Java's Panama API), use {@link * ByteOrder#nativeOrder()}. */ public static final VarHandle VH_NATIVE_INT = MethodHandles.byteArrayViewVarHandle(int[].class, NATIVE_BYTE_ORDER); /** * A {@link VarHandle} to read/write native endian {@code long} from a byte array. Shape: {@code * long vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, long val)} * *

Warning: This handle uses default order only in production environments, during testing we * randomize it. If you need to communicate with native APIs (e.g., Java's Panama API), use {@link * ByteOrder#nativeOrder()}. */ public static final VarHandle VH_NATIVE_LONG = MethodHandles.byteArrayViewVarHandle(long[].class, NATIVE_BYTE_ORDER); /** * A {@link VarHandle} to read/write native endian {@code float} from a byte array. Shape: {@code * float vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, float val)} * *

Warning: This handle uses default order only in production environments, during testing we * randomize it. If you need to communicate with native APIs (e.g., Java's Panama API), use {@link * ByteOrder#nativeOrder()}. */ public static final VarHandle VH_NATIVE_FLOAT = MethodHandles.byteArrayViewVarHandle(float[].class, NATIVE_BYTE_ORDER); /** * A {@link VarHandle} to read/write native endian {@code double} from a byte array. Shape: {@code * double vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, double val)} * *

Warning: This handle uses default order only in production environments, during testing we * randomize it. If you need to communicate with native APIs (e.g., Java's Panama API), use {@link * ByteOrder#nativeOrder()}. */ public static final VarHandle VH_NATIVE_DOUBLE = MethodHandles.byteArrayViewVarHandle(double[].class, NATIVE_BYTE_ORDER); /** * A {@link VarHandle} to read/write big endian {@code short} from a byte array. Shape: {@code * short vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, short val)} * * @deprecated Better use little endian unless it is needed for backwards compatibility. */ @Deprecated public static final VarHandle VH_BE_SHORT = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.BIG_ENDIAN); /** * A {@link VarHandle} to read/write big endian {@code int} from a byte array. Shape: {@code int * vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, int val)} * * @deprecated Better use little endian unless it is needed for backwards compatibility. */ @Deprecated public static final VarHandle VH_BE_INT = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN); /** * A {@link VarHandle} to read/write big endian {@code long} from a byte array. Shape: {@code long * vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, long val)} * * @deprecated Better use little endian unless it is needed for backwards compatibility. */ @Deprecated public static final VarHandle VH_BE_LONG = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN); /** * A {@link VarHandle} to read/write big endian {@code float} from a byte array. Shape: {@code * float vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, float val)} * * @deprecated Better use little endian unless it is needed for backwards compatibility. */ @Deprecated public static final VarHandle VH_BE_FLOAT = MethodHandles.byteArrayViewVarHandle(float[].class, ByteOrder.BIG_ENDIAN); /** * A {@link VarHandle} to read/write big endian {@code double} from a byte array. Shape: {@code * double vh.get(byte[] arr, int ofs)} and {@code void vh.set(byte[] arr, int ofs, double val)} * * @deprecated Better use little endian unless it is needed for backwards compatibility. */ @Deprecated public static final VarHandle VH_BE_DOUBLE = MethodHandles.byteArrayViewVarHandle(double[].class, ByteOrder.BIG_ENDIAN); /** * 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 */ 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; } // magic numbers for bit interleaving private static final long MAGIC0 = 0x5555555555555555L; private static final long MAGIC1 = 0x3333333333333333L; private static final long MAGIC2 = 0x0F0F0F0F0F0F0F0FL; private static final long MAGIC3 = 0x00FF00FF00FF00FFL; private static final long MAGIC4 = 0x0000FFFF0000FFFFL; private static final long MAGIC5 = 0x00000000FFFFFFFFL; private static final long MAGIC6 = 0xAAAAAAAAAAAAAAAAL; // shift values for bit interleaving private static final long SHIFT0 = 1; private static final long SHIFT1 = 2; private static final long SHIFT2 = 4; private static final long SHIFT3 = 8; private static final long SHIFT4 = 16; /** * 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 << SHIFT4)) & MAGIC4; v1 = (v1 | (v1 << SHIFT3)) & MAGIC3; v1 = (v1 | (v1 << SHIFT2)) & MAGIC2; v1 = (v1 | (v1 << SHIFT1)) & MAGIC1; v1 = (v1 | (v1 << SHIFT0)) & MAGIC0; v2 = (v2 | (v2 << SHIFT4)) & MAGIC4; v2 = (v2 | (v2 << SHIFT3)) & MAGIC3; v2 = (v2 | (v2 << SHIFT2)) & MAGIC2; v2 = (v2 | (v2 << SHIFT1)) & MAGIC1; v2 = (v2 | (v2 << SHIFT0)) & MAGIC0; return (v2 << 1) | v1; } /** Extract just the even-bits value as a long from the bit-interleaved value */ public static long deinterleave(long b) { b &= MAGIC0; b = (b ^ (b >>> SHIFT0)) & MAGIC1; b = (b ^ (b >>> SHIFT1)) & MAGIC2; b = (b ^ (b >>> SHIFT2)) & MAGIC3; b = (b ^ (b >>> SHIFT3)) & MAGIC4; b = (b ^ (b >>> SHIFT4)) & MAGIC5; return b; } /** flip flops odd with even bits */ public static long flipFlop(final long b) { return ((b & MAGIC6) >>> 1) | ((b & MAGIC0) << 1); } /** 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. */ public static long zigZagEncode(long l) { return (l >> 63) ^ (l << 1); } /** 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 {@link #zigZagEncode(long)}. */ public static long zigZagDecode(long l) { return ((l >>> 1) ^ -(l & 1)); } /** * Return true if, and only if, the provided integer - treated as an unsigned integer - is either * 0 or a power of two. */ public static boolean isZeroOrPowerOfTwo(int x) { return (x & (x - 1)) == 0; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy