/******************************************************************************* * Copyright 2014 Analog Devices, Inc. * * Licensed 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 com.analog.lyric.collect; import java.util.BitSet; public class BitSetUtil { /** * Constructs a new {@link BitSet} of given {@code size} whose set bits are specified * by {@code indices}. * * @throws IndexOutOfBoundsException if any index is negative or not less than {@code size}. * @throws IllegalArgumentException if any index is specified more than once. * @see #bitsetToIndices */ public static BitSet bitsetFromIndices(int size, int ... indices) { final BitSet bitset = new BitSet(size); for (int index : indices) { if (index < 0 || index >= size) { throw new IndexOutOfBoundsException(String.format("Index %d out of range [0, %d]", index, size - 1)); } if (bitset.get(index)) { throw new IllegalArgumentException(String.format("Duplicate index %d", index)); } bitset.set(index); } return bitset; } /** * Returns a newly constructed array containing the indices of the non-zero bits. * @since 0.07 * @see #bitsetFromIndices */ public static int[] bitsetToIndices(BitSet bits) { final int[] indices = new int[bits.cardinality()]; for (int i = 0, index = -1, end = indices.length; i < end; ++i) { index = bits.nextSetBit(++index); indices[i] = index; } return indices; } /** * True if all bits set in first bitset are also set in second. * @since 0.08 */ public static boolean isSubset(BitSet bits1, BitSet bits2) { int index = -1; while (true) { if (0 > (index = bits1.nextSetBit(++index))) break; if (!bits2.get(index)) return false; } return true; } /** * Sets bit at {@code index} in {@code bits} to zero. * * @param bits * @param index must be in the range [0,31] identifies which bit to clear. * @since 0.05 */ public static int clearBit(int bits, int index) { return bits & ~(1 << index); } /** * Sets bit at {@code index} in {@code bits} to zero. * * @param bits * @param index must be in the range [0,63] identifies which bit to clear. * @since 0.05 */ public static long clearBit(long bits, int index) { return bits & ~(1L << index); } /** * @since 0.05 */ public static int clearMask(int bits, int mask) { return bits & ~mask; } /** * @since 0.05 */ public static long clearMask(long bits, long mask) { return bits & ~mask; } /** * Returns masked bits of value (i.e. "bitwise and" of two values) * * @param word is the original word. * @param mask specifies the bits of {@code word} to be returned. * * @since 0.06 */ public static int getMaskedValue(int word, int mask) { return word & mask; } /** * Returns masked bits of value (i.e. "bitwise and" of two values) * * @param word is the original word. * @param mask specifies the bits of {@code word} to be returned. * * @since 0.06 */ public static long getMaskedValue(long word, long mask) { return word & mask; } /** * True if bit at {@code index} in {@code bits} is one. * * @param bits * @param index must be in the range [0,31] identifies which bit to clear. */ public static boolean isBitSet(int bits, int index) { return (bits & (1 << index)) != 0; } /** * True if bit at {@code index} in {@code bits} is one. * * @param bits * @param index must be in the range [0,63] identifies which bit to clear. */ public static boolean isBitSet(long bits, int index) { return (bits & (1L << index)) != 0; } /** * True if all bits in {@code mask} are set in {@code bits}. */ public static boolean isMaskSet(int bits, int mask) { return (bits & mask) == mask; } /** * True if all bits in {@code mask} are set in {@code bits}. */ public static boolean isMaskSet(long bits, long mask) { return (bits & mask) == mask; } /** * Sets bit at {@code index} in {@code bits} to one. * * @param bits * @param index must be in the range [0,31] identifies which bit to clear. */ public static int setBit(int bits, int index) { return bits | (1 << index); } /** * Sets bit at {@code index} in {@code bits} to one. * * @param bits * @param index must be in the range [0,63] identifies which bit to clear. */ public static long setBit(long bits, int index) { return bits | (1L << index); } /** * Sets all bits in {@code mask} in {@code bits} (i.e. "bitwise or" of two values). */ public static int setMask(int bits, int mask) { return bits | mask; } /** * Sets all bits in {@code mask} in {@code bits} (i.e. "bitwise or" of two values). */ public static long setMask(long bits, long mask) { return bits | mask; } /** * Sets a range of bits to specified value. * * @param word is the original word. * @param mask specifies which bits in {@code word} will be set. * @param value must only use bits that are set in {@code mask} or else an incorrect value will be returned. * * @since 0.06 */ public static int setMaskedValue(int word, int mask, int value) { return (word & ~mask) | value; } /** * Sets a range of bits to specified value. * * @param word is the original word. * @param mask specifies which bits in {@code word} will be set. * @param value must only use bits that are set in {@code mask} or else an incorrect value will be returned. * * @since 0.06 */ public static long setMaskedValue(long word, long mask, long value) { return (word & ~mask) | value; } }