I have gathered from around the web a few functions and such to land on this:
const LEADING_ZERO_BIT_TABLE = makeLeadingZeroTable()
function makeLeadingZeroTable() {
let i = 0
const table = new Uint8Array(256)
while (i < 256) {
let count = 8
let index = i
while (index > 0) {
index = (index / 2) | 0
count--
}
table[i] = count
i++
}
return table
}
// https://cs-fundamentals.com/tech-interview/c/c-program-to-count-number-of-ones-in-unsigned-integer
function clz1(n)
{
let accum = 0;
accum += LEADING_ZERO_BIT_TABLE[n >> 24];
accum += (accum == 8 ) ? LEADING_ZERO_BIT_TABLE[(n >> 16) & 0xFF] : 0;
accum += (accum == 16) ? LEADING_ZERO_BIT_TABLE[(n >> 8) & 0xFF] : 0;
accum += (accum == 24) ? LEADING_ZERO_BIT_TABLE[ n & 0xFF] : 0;
return accum;
}
function clz2(n)
{
let accum = LEADING_ZERO_BIT_TABLE[n >> 24];
if (accum === 8) {
accum += LEADING_ZERO_BIT_TABLE[(n >> 16) & 0xFF]
}
if (accum === 16) {
accum += LEADING_ZERO_BIT_TABLE[(n >> 8) & 0xFF]
}
if (accum === 24) {
accum += LEADING_ZERO_BIT_TABLE[ n & 0xFF]
}
return accum;
}
console.log('clz1', clz1(0b00100010001000100010001000100010))
console.log('clz1', clz1(0b00000010001000100010001000100010))
console.log('clz2', clz2(0b00100010001000100010001000100010))
console.log('clz2', clz2(0b00000010001000100010001000100010))
How do I transform clz2
so it has the same output as clz1
, but it does it in a more optimal way? I feel like the +=
can be optimized away somehow? Is there a way to remove the conditional branching? Or is this as good as it's going to get?
P.S. I know about the clz32
and other related builtins, just doing this out of curiosity and for a custom programming language.
I basically have this as of now, but would like to get rid of the conditional branching if possible.
function countLeadingZeroes32JS(n)
{
let accum = LEADING_ZERO_BIT_TABLE[n >>> 24];
if (accum === 8) {
accum += LEADING_ZERO_BIT_TABLE[(n >>> 16)]
}
if (accum === 16) {
accum += LEADING_ZERO_BIT_TABLE[(n >>> 8)]
}
if (accum === 24) {
accum += LEADING_ZERO_BIT_TABLE[ n ]
}
return accum;
}