/*license*\
XBN-Java: Copyright (C) 2014, Jeff Epstein (aliteralmind __DASH__ github __AT__ yahoo __DOT__ com)
This software is dual-licensed under the:
- Lesser General Public License (LGPL) version 3.0 or, at your option, any later version;
- Apache Software License (ASL) version 2.0.
Either license may be applied at your discretion. More information may be found at
- http://en.wikipedia.org/wiki/Multi-licensing.
The text of both licenses is available in the root directory of this project, under the names "LICENSE_lgpl-3.0.txt" and "LICENSE_asl-2.0.txt". The latest copies may be downloaded at:
- LGPL 3.0: https://www.gnu.org/licenses/lgpl-3.0.txt
- ASL 2.0: http://www.apache.org/licenses/LICENSE-2.0.txt
\*license*/
package com.github.xbn.examples.util.non_xbn;
/**
<p>Given a 31-bit binary-int, as a string (representing an int with zero or more bit-flags, where the most-significant-bit, the "sign bit", is removed), get the <i>inverted</i> index of the first one-bit (if the left-most bit is a 1, 31 is the result).</p>
<p>{@code java com.github.xbn.examples.util.non_xbn.TwoExponentHighestOneBitUsingInts}</p>
* @since 0.1.0
* @author Copyright (C) 2014, Jeff Epstein ({@code aliteralmind __DASH__ github __AT__ yahoo __DOT__ com}), dual-licensed under the LGPL (version 3.0 or later) or the ASL (version 2.0). See source code for details. <a href="http://xbnjava.aliteralmind.com">{@code http://xbnjava.aliteralmind.com}</a>, <a href="https://github.com/aliteralmind/xbnjava">{@code https://github.com/aliteralmind/xbnjava}</a>
**/
public class TwoExponentHighestOneBitUsingInts {
public static final int VALUE_OF_31ST_ONE_BIT = Integer.parseInt("1000000000000000000000000000000", 2);
public static final void main(String[] ignored) {
//One bit
test(VALUE_OF_31ST_ONE_BIT);
test(Integer.parseInt("0000100000000000000000000000000", 2));
test(Integer.parseInt("0000000000000000000000000000010", 2));
test(Integer.parseInt("0000000000000000000000000000000", 2));
//Two
test(Integer.parseInt("0110000000000000000000000000000", 2));
test(Integer.parseInt("0000000000000000000000000000011", 2));
}
private static final void test(int num) {
System.out.println("Testing: 31-bit binary=" + getIntAsZeroPadded31BitStringNoSign(num) + ", int=" + num);
int exponent = twoExponentOfHighestOneBit(num);
System.out.println(" Highest one-bit is two-to-the-exponent-of: " + exponent);
if(exponent > 0) {
System.out.println(" Next-highest one-bit is two-to-the-exponent-of: " + twoExponentOfHighestOneBitAtMost(num, (exponent - 1)));
}
exponent = twoExponentOfLowestOneBit(num);
System.out.println(" Lowest one-bit is two-to-the-exponent-of: " + exponent);
if(exponent != -1 && exponent < 30) {
System.out.println(" Next-highest one-bit is two-to-the-exponent-of: " + twoExponentOfLowestOneBitAtLeast(num, (exponent + 1)));
}
System.out.println();
}
public static final int twoExponentOfHighestOneBit(int all_flags) {
return twoExponentOfHighestOneBitAtMost(all_flags, 30);
}
public static final int twoExponentOfHighestOneBitAtMost(int all_flags, int twoExponentOfTwo_max0Thr30Incl) {
if(twoExponentOfTwo_max0Thr30Incl < 0 || twoExponentOfTwo_max0Thr30Incl > 30) {
throw new IllegalArgumentException("twoExponentOfTwo_max0Thr30Incl (" + twoExponentOfTwo_max0Thr30Incl + ") must be between 1 and 31, inclusive");
}
//Index of first one bit:
int currentBitMask = VALUE_OF_31ST_ONE_BIT >> (30 - twoExponentOfTwo_max0Thr30Incl);
int exponent = twoExponentOfTwo_max0Thr30Incl;
while(exponent >= 0) {
//System.out.println(" high.currentBitMask=" + getIntAsZeroPadded31BitStringNoSign(currentBitMask) + ", exponent=" + exponent + "");
//System.out.println(" high.all_flags= " + getIntAsZeroPadded31BitStringNoSign(all_flags));
if((all_flags & currentBitMask) == currentBitMask) {
return exponent;
}
//System.out.println();
exponent--;
currentBitMask >>= 1;
}
return -1;
}
public static final int twoExponentOfLowestOneBit(int all_flags) {
return twoExponentOfLowestOneBitAtLeast(all_flags, 0);
}
public static final int twoExponentOfLowestOneBitAtLeast(int all_flags, int twoExponentOfTwo_min0Thr30Incl) {
if(twoExponentOfTwo_min0Thr30Incl < 0 || twoExponentOfTwo_min0Thr30Incl > 30) {
throw new IllegalArgumentException("twoExponentOfTwo_min0Thr30Incl (" + twoExponentOfTwo_min0Thr30Incl + ") must be between 1 and 30, inclusive.");
}
//Index of first one bit:
int currentBitMask = 1 << twoExponentOfTwo_min0Thr30Incl;
int exponent = twoExponentOfTwo_min0Thr30Incl;
while(exponent <= 30) {
//System.out.println(" low.currentBitMask=" + getIntAsZeroPadded31BitStringNoSign(currentBitMask) + ", exponent=" + exponent + "");
//System.out.println(" low.all_flags= " + getIntAsZeroPadded31BitStringNoSign(all_flags));
if((all_flags & currentBitMask) == currentBitMask) {
return exponent;
}
//System.out.println();
exponent++;
currentBitMask <<= 1;
}
return -1;
}
public static final String getIntAsZeroPadded31BitStringNoSign(int num) {
return String.format("%32s", Integer.toBinaryString(num)).replace(' ', '0').substring(1, 32);
}
}