/** * */ package net.varkhan.base.containers.array; /** * <b>Static bit manipulation utilities.</b> * <p/> * Utilities for manipulating integer types as bit arrays, * and performing conversions between representations. * <p/> * * @author varkhan * @date Mar 12, 2009 * @time 3:07:18 AM */ public class BitArrays { /** * Private empty constructor that forbids instantiation of this class. */ protected BitArrays() { } /********************************************************************************* ** Bit to boolean conversion **/ /** * Flip the bits of a bit mask according to the values to a boolean array. * * @param mask the original bit mask * @param flags the boolean array * * @return a bit mask whose bits are flipped compared to {@code mask} iff the corresponding boolean is {@literal true} */ public static long flip(long mask, boolean[] flags) { for(int i=0;i<flags.length;i++) { if(flags[i]) mask^=1<<i; } return mask; } /** * Flip the values of a boolean array according to the bits of a bit mask. * * @param flags the original boolean array * @param mask the bit mask * * @return a boolean array whose values are flipped if the corresponding bit is set */ public static boolean[] flip(boolean[] flags, long mask) { for(int i=0;i<flags.length;i++) { flags[i]^=0!=(mask&(1<<i)); } return flags; } /********************************************************************************* ** Bit counting **/ /** * All the counts of set bits */ private static final byte[] byteCSB=new byte[256]; static { for(int i=0;i<256;i++) { int b=i; byte c=0; while(b!=0) { c+=b&0x1; b>>>=1; } byteCSB[i]=c; } } /** * Count the set bits of an integer value. * * @param val the integer * * @return the number of bits set to 1 in the argument */ public static int csb(byte val) { // val = (byte) (val - ((val >>> 1) & 0x5555)); // val = (byte) ((val & 0x3333) + ((val >>> 2) & 0x3333)); // val = (byte) ((val + (val >>> 4)) & 0x0f); // return val & 0x3f; return 0xFF&byteCSB[val&0xFF]; } /** * Count the set bits of an integer value. * * @param val the integer * * @return the number of bits set to 1 in the argument */ public static int csb(short val) { val=(short) (val-((val>>>1)&0x5555)); val=(short) ((val&0x3333)+((val>>>2)&0x3333)); val=(short) ((val+(val>>>4))&0x0f0f); val=(short) (val+(val>>>8)); return val&0x3f; // return (0xFF& byteCSB[val&0xFF]) + // (0xFF& byteCSB[(val>>>8)&0xFF]) ; } /** * Count the set bits of an integer value. * * @param val the integer * * @return the number of bits set to 1 in the argument */ public static int csb(int val) { val=val-((val>>>1)&0x55555555); val=(val&0x33333333)+((val>>>2)&0x33333333); val=(val+(val>>>4))&0x0f0f0f0f; val=val+(val>>>8); val=val+(val>>>16); return val&0x3f; // return (0xFF& byteCSB[val&0xFF]) + // (0xFF& byteCSB[(val>>> 8)&0xFF]) + // (0xFF& byteCSB[(val>>>16)&0xFF]) + // (0xFF& byteCSB[(val>>>24)&0xFF]) ; } /** * Count the set bits of an integer value. * * @param val the integer * * @return the number of bits set to 1 in the argument */ public static int csb(long val) { val=val-((val>>>1)&0x5555555555555555L); val=(val&0x3333333333333333L)+((val>>>2)&0x3333333333333333L); val=(val+(val>>>4))&0x0f0f0f0f0f0f0f0fL; val=val+(val>>>8); val=val+(val>>>16); val=val+(val>>>32); return (int) val&0x7f; // return (0xFF& byteCSB[(int)(val&0xFF)]) + // (0xFF& byteCSB[(int)((val>>> 8)&0xFF)]) + // (0xFF& byteCSB[(int)((val>>>16)&0xFF)]) + // (0xFF& byteCSB[(int)((val>>>24)&0xFF)]) + // (0xFF& byteCSB[(int)((val>>>32)&0xFF)]) + // (0xFF& byteCSB[(int)((val>>>40)&0xFF)]) + // (0xFF& byteCSB[(int)((val>>>48)&0xFF)]) + // (0xFF& byteCSB[(int)((val>>>56)&0xFF)]) ; } /********************************************************************************* ** Left set bit **/ /** * All the left set bits for bytes */ private static final byte[] byteLSB=new byte[256]; static { byteLSB[0]=0; for(int i=1;i<256;i++) { byte c=0; while((i>>>c)!=0) c++; byteLSB[i]=c; } } /** * Return the position of the highest set bit of an integer value. * * @param val the integer * * @return the position of the highest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int lsb(byte val) { return 0xFF&byteLSB[val&0xFF]; } /** * Return the position of the highest set bit of an integer value. * * @param val the integer * * @return the position of the highest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int lsb(short val) { if((val>>>8)==0) return 0xFF&byteLSB[val&0xFF]; return 8+(0xFF&byteLSB[(val>>>8)&0xFF]); } /** * Return the position of the highest set bit of an integer value. * * @param val the integer * * @return the position of the highest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int lsb(int val) { if((val>>>8)==0) return 0xFF&byteLSB[val&0xFF]; if((val>>>16)==0) return 8+(0xFF&byteLSB[(val>>>8)&0xFF]); if((val>>>24)==0) return 16+(0xFF&byteLSB[(val>>>16)&0xFF]); return 24+(0xFF&byteLSB[(val>>>24)&0xFF]); } /** * Return the position of the highest set bit of an integer value. * * @param val the integer * * @return the position of the highest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int lsb(long val) { if((val>>>8)==0) return 0xFF&byteLSB[(int) (val&0xFF)]; if((val>>>16)==0) return 8+(0xFF&byteLSB[(int) ((val>>>8)&0xFF)]); if((val>>>24)==0) return 16+(0xFF&byteLSB[(int) ((val>>>16)&0xFF)]); if((val>>>32)==0) return 24+(0xFF&byteLSB[(int) ((val>>>24)&0xFF)]); if((val>>>40)==0) return 32+(0xFF&byteLSB[(int) ((val>>>32)&0xFF)]); if((val>>>48)==0) return 40+(0xFF&byteLSB[(int) ((val>>>40)&0xFF)]); if((val>>>56)==0) return 48+(0xFF&byteLSB[(int) ((val>>>48)&0xFF)]); return 56+(0xFF&byteLSB[(int) ((val>>>56)&0xFF)]); } /********************************************************************************* ** Right set bit **/ /** * All the right set bits for bytes */ private static final byte[] byteRSB=new byte[256]; static { byteRSB[0]=(byte)-1; for(int i=1;i<256;i++) { byte c=0; while((i&(1<<c))==0) c++; byteRSB[i]=c; } } /** * Return the position of the lowest set bit of an integer value. * * @param val the integer * * @return the position of the lowest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int rsb(byte val) { if(val==0) return -1; return 0xFF&byteRSB[val&0xFF]; } /** * Return the position of the lowest set bit of an integer value. * * @param val the integer * * @return the position of the lowest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int rsb(short val) { if(val==0) return -1; if((val&0xFF)!=0) return 0xFF&byteRSB[val&0xFF]; return 8+(0xFF&byteRSB[(val>>>8)&0xFF]); } /** * Return the position of the lowest set bit of an integer value. * * @param val the integer * * @return the position of the lowest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int rsb(int val) { if(val==0) return -1; if((val&0x000000FF)!=0) return 0xFF&byteRSB[val&0xFF]; if((val&0x0000FF00)!=0) return 8+(0xFF&byteRSB[(val>>>8)&0xFF]); if((val&0x00FF0000)!=0) return 16+(0xFF&byteRSB[(val>>>16)&0xFF]); return 24+(0xFF&byteRSB[(val>>>24)&0xFF]); } /** * Return the position of the lowest set bit of an integer value. * * @param val the integer * * @return the position of the lowest bit set to 1 in the argument, starting at 1 * (or 0 if the argument is zero) */ public static int rsb(long val) { if(val==0) return -1; if((val&0x00000000000000FFL)!=0) return 0xFF&byteRSB[(int) (val&0xFF)]; if((val&0x000000000000FF00L)!=0) return 8+(0xFF&byteRSB[(int) ((val>>>8)&0xFF)]); if((val&0x0000000000FF0000L)!=0) return 16+(0xFF&byteRSB[(int) ((val>>>16)&0xFF)]); if((val&0x00000000FF000000L)!=0) return 24+(0xFF&byteRSB[(int) ((val>>>24)&0xFF)]); if((val&0x000000FF00000000L)!=0) return 32+(0xFF&byteRSB[(int) ((val>>>32)&0xFF)]); if((val&0x0000FF0000000000L)!=0) return 40+(0xFF&byteRSB[(int) ((val>>>40)&0xFF)]); if((val&0x00FF000000000000L)!=0) return 48+(0xFF&byteRSB[(int) ((val>>>48)&0xFF)]); return 56+(0xFF&byteRSB[(int) ((val>>>56)&0xFF)]); } /********************************************************************************* ** Multiplexing **/ /** * All the 2-multiplexings for bytes */ private static final short[] byteMP2=new short[256]; static { for(int i=0;i<256;i++) { short c=0; for(int p=0;p<8;p++) { // Compute the 2*p bit of c as the p-th bit of i c|=(i&(1<<p))<<p; } byteMP2[i]=c; } } /** * Multiplex an integer value 2-fold. * * @param val the integer * * @return the integer whose bit in position {@code 2*k} is the bit in position * {@code k} in the argument, and whose bit in position {@code 2*k+1} is 0 */ public static short mp2(byte val) { return byteMP2[0xFF&val]; } /** * Multiplex an integer value 2-fold. * * @param val the integer * * @return the integer whose bit in position {@code 2*k} is the bit in position * {@code k} in the argument, and whose bit in position {@code 2*k+1} is 0 */ public static int mp2(short val) { return (0xFFFF&byteMP2[0xFF&val])|((0xFFFF&byteMP2[0xFF&(val>>>8)])<<16); } /** * Multiplex an integer value 2-fold. * * @param val the integer * * @return the integer whose bit in position {@code 2*k} is the bit in position * {@code k} in the argument, and whose bit in position {@code 2*k+1} is 0 */ public static long mp2(int val) { return (0xFFFFL&byteMP2[0xFF&val])|((0xFFFFL&byteMP2[0xFF&(val>>>8)])<<16)| ((0xFFFFL&byteMP2[0xFF&(val>>>16)])<<32)|((0xFFFFL&byteMP2[0xFF&(val>>>24)])<<48); } /********************************************************************************* ** Reversing **/ /** * All the reverses for bytes */ private static final byte[] byteREV=new byte[256]; static { for(int i=0;i<256;i++) { byte c=0; for(int p=0;p<8;p++) { // Compute the (8-p-1)th bit of c as the p-th bit of i c|=((i>>p)&1)<<(8-p-1); } byteREV[i]=c; } } /** * Reverses the bits of an integer value. * * @param val the integer * * @return the N-bits integer whose bit in position {@code N-k} is the bit in * position {@code k} in the argument */ public static byte rev(byte val) { return byteREV[val&0xFF]; } /** * Reverses the bits of an integer value. * * @param val the integer * * @return the N-bits integer whose bit in position {@code N-k} is the bit in * position {@code k} in the argument */ public static short rev(short val) { return (short) (((0xFF&byteREV[val&0x00FF])<<8)|((0xFF&byteREV[(val&0xFF00)>>8]))); } /** * Reverses the bits of an integer value. * * @param val the integer * * @return the N-bits integer whose bit in position {@code N-k} is the bit in * position {@code k} in the argument */ public static int rev(int val) { // val = (val & 0x55555555) << 1 | (val >>> 1) & 0x55555555; // val = (val & 0x33333333) << 2 | (val >>> 2) & 0x33333333; // val = (val & 0x0f0f0f0f) << 4 | (val >>> 4) & 0x0f0f0f0f; // val = (val << 24) | ((val & 0xff00) << 8) | ((val >>> 8) & 0xff00) | (val >>> 24); // return val; return ((0xFF&byteREV[(val&0x000000FF)])<<24) |((0xFF&byteREV[(val&0x0000FF00)>>8])<<16) |((0xFF&byteREV[(val&0x00FF0000)>>16])<<8) |((0xFF&byteREV[(val&0xFF000000)>>24])); } /** * Reverses the bits of an integer value. * * @param val the integer * * @return the N-bits integer whose bit in position {@code N-k} is the bit in * position {@code k} in the argument */ public static long rev(long val) { val=(val&0x5555555555555555L)<<1|(val>>>1)&0x5555555555555555L; val=(val&0x3333333333333333L)<<2|(val>>>2)&0x3333333333333333L; val=(val&0x0f0f0f0f0f0f0f0fL)<<4|(val>>>4)&0x0f0f0f0f0f0f0f0fL; val=(val&0x00ff00ff00ff00ffL)<<8|(val>>>8)&0x00ff00ff00ff00ffL; val=(val<<48)|((val&0xffff0000L)<<16)|((val>>>16)&0xffff0000L)|(val>>>48); return val; // return ((0xFFL&byteREV[(int) ((val&0x00000000000000FFL))])<<56) // | ((0xFFL&byteREV[(int) ((val&0x000000000000FF00L)>>8)])<<48) // | ((0xFFL&byteREV[(int) ((val&0x0000000000FF0000L)>>16)])<<40) // | ((0xFFL&byteREV[(int) ((val&0x00000000FF000000L)>>24)])<<32) // | ((0xFFL&byteREV[(int) ((val&0x000000FF00000000L)>>32)])<<24) // | ((0xFFL&byteREV[(int) ((val&0x0000FF0000000000L)>>40)])<<16) // | ((0xFFL&byteREV[(int) ((val&0x00FF000000000000L)>>48)])<<8) // | ((0xFFL&byteREV[(int) ((val&0xFF00000000000000L)>>56)])); } }