possible bug in uint128.lastWithBitZero
josharian opened this issue · comments
// lastWithBitZero returns a copy of u with the given bit
// cleared and the following all set.
func (u uint128) lastWithBitZero(bit uint8) uint128 {
u.clear(bit)
for ; bit < 128; bit++ {
u.set(bit)
}
return u
}
The docs say it clears the given bit and sets the following.
The code clears the given bit, and then sets it again, along with the following.
Seems like it needs a bit++
before the for loop.
Something similar is true for uint128.firstWithBitOne
.
Also, it's unclear from the docs which direction bit counting commences from--is the 0th bit the highest or the lowest order bit?
I also suspect that this can be implemented without a loop, using a branch on whether bit
is above/below 64 and a helper like:
func u64LastWithBitZero(x uint64, bit uint8) uint64 {
x &^= 1 << bit
x |= (1 << bit) - 1
return x
}
but before doing that I want to correct, document, and stabilize the existing code.
Debugging. It looks like it works because the caller adds +1,
dst = appendRangePrefixes(dst, makePrefix, a, a.lastWithBitZero(common+1))
dst = appendRangePrefixes(dst, makePrefix, b.firstWithBitOne(common+1), b)
And that previous bit was already correct, always a zero first in a
, and set in b, because
ais less than
b`, due to it being a valid range.
I wonder if I changed my mind on how to implement midway through and forgot to rename the funcs or I was just saved by what is kinda two off by one errors.
I'll rename & clarify. You can optimize later.
Picture of debug output, FWIW: