Skip to content

Instantly share code, notes, and snippets.

@EdmundKorley
Created September 30, 2017 16:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save EdmundKorley/a489508def59416e77ec036ea576489b to your computer and use it in GitHub Desktop.
Save EdmundKorley/a489508def59416e77ec036ea576489b to your computer and use it in GitHub Desktop.
Closest isoweight bit string
package closestisoweight;
public class ClosestIsoweight {
private ClosestIsoweight() {
}
/**
* Find the nearest isoweight word in linear time and constant space.
*
* @param word a 64-bit word
* @return the nearest isoweight word
*/
public static long isoweight(long word) {
int i = 0;
while (i < 63) {
if (((word >> i) & 0x1) != ((word >> (i + 1)) & 0x1)) {
return word ^ ((1L << i) | (1L << i + 1));
}
i++;
}
throw new IllegalArgumentException("All bits are set (-1) or not set (0)");
}
/**
* Find the nearest isoweight word in constant time and space.
*
* @param word a 64-bit word
* @return the nearest isoweight word
*/
public static long isoweightOptimized(long word) throws IllegalArgumentException {
long swapMask = getAdjacentPolarBits(word);
return word ^ swapMask;
}
private static long getAdjacentPolarBits(long word) {
long leastSignificantSetBit = ~word | (word - 1);
if (leastSignificantSetBit == word) throw new IllegalArgumentException("Bit string is all zeroes (0)");
else leastSignificantSetBit = ~leastSignificantSetBit; // properly isolate bit, e.g. 0b..11110111 -> 0b..00001000
long leastSignificantUnsetBit = ~word & (word + 1);
if (leastSignificantUnsetBit == 0) throw new IllegalArgumentException("Bit string is all ones (-1)");
if (leastSignificantSetBit > leastSignificantUnsetBit) {
return leastSignificantSetBit | leastSignificantSetBit >>> 1;
}
return leastSignificantUnsetBit | leastSignificantUnsetBit >>> 1;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment