/*******************************************************************************
* 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;
}
}