bitops: add reverseBits and test (#10835)
This commit is contained in:
parent
091da5c979
commit
cd3a58d7b0
2 changed files with 87 additions and 0 deletions
|
|
@ -446,3 +446,48 @@ proc rotateRightBits*(value: uint64;
|
||||||
## Right-rotate bits in a 64-bits value.
|
## Right-rotate bits in a 64-bits value.
|
||||||
let amount = amount and 63
|
let amount = amount and 63
|
||||||
result = (value shr amount) or (value shl ( (-amount) and 63))
|
result = (value shr amount) or (value shl ( (-amount) and 63))
|
||||||
|
|
||||||
|
proc repeatBits[T: SomeUnsignedInt](x: SomeUnsignedInt; retType: type[T]): T {.
|
||||||
|
noSideEffect.} =
|
||||||
|
result = x
|
||||||
|
var i = 1
|
||||||
|
while i != (sizeof(T) div sizeof(x)):
|
||||||
|
result = (result shl (sizeof(x)*8*i)) or result
|
||||||
|
i *= 2
|
||||||
|
|
||||||
|
proc reverseBits*[T: SomeUnsignedInt](x: T): T {.noSideEffect.} =
|
||||||
|
## Return the bit reversal of x.
|
||||||
|
runnableExamples:
|
||||||
|
doAssert reverseBits(0b10100100'u8) == 0b00100101'u8
|
||||||
|
doAssert reverseBits(0xdd'u8) == 0xbb'u8
|
||||||
|
doAssert reverseBits(0xddbb'u16) == 0xddbb'u16
|
||||||
|
doAssert reverseBits(0xdeadbeef'u32) == 0xf77db57b'u32
|
||||||
|
|
||||||
|
template repeat(x: SomeUnsignedInt): T = repeatBits(x, T)
|
||||||
|
|
||||||
|
result = x
|
||||||
|
result =
|
||||||
|
((repeat(0x55u8) and result) shl 1) or
|
||||||
|
((repeat(0xaau8) and result) shr 1)
|
||||||
|
result =
|
||||||
|
((repeat(0x33u8) and result) shl 2) or
|
||||||
|
((repeat(0xccu8) and result) shr 2)
|
||||||
|
when sizeof(T) == 1:
|
||||||
|
result = (result shl 4) or (result shr 4)
|
||||||
|
when sizeof(T) >= 2:
|
||||||
|
result =
|
||||||
|
((repeat(0x0fu8) and result) shl 4) or
|
||||||
|
((repeat(0xf0u8) and result) shr 4)
|
||||||
|
when sizeof(T) == 2:
|
||||||
|
result = (result shl 8) or (result shr 8)
|
||||||
|
when sizeof(T) >= 4:
|
||||||
|
result =
|
||||||
|
((repeat(0x00ffu16) and result) shl 8) or
|
||||||
|
((repeat(0xff00u16) and result) shr 8)
|
||||||
|
when sizeof(T) == 4:
|
||||||
|
result = (result shl 16) or (result shr 16)
|
||||||
|
when sizeof(T) == 8:
|
||||||
|
result =
|
||||||
|
((repeat(0x0000ffffu32) and result) shl 16) or
|
||||||
|
((repeat(0xffff0000u32) and result) shr 16)
|
||||||
|
result = (result shl 32) or (result shr 32)
|
||||||
|
|
|
||||||
|
|
@ -169,6 +169,48 @@ proc main() =
|
||||||
v.setBit(63)
|
v.setBit(63)
|
||||||
doAssert v == 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000'u64
|
doAssert v == 0b1000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000_0000'u64
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc testReverseBitsInvo(x: SomeUnsignedInt) =
|
||||||
|
doAssert(reverseBits(reverseBits(x)) == x)
|
||||||
|
|
||||||
|
proc testReverseBitsPerType(x, reversed: uint64) =
|
||||||
|
doAssert reverseBits(x) == reversed
|
||||||
|
doAssert reverseBits(uint32(x)) == uint32(reversed shr 32)
|
||||||
|
doAssert reverseBits(uint32(x shr 16)) == uint32(reversed shr 16)
|
||||||
|
doAssert reverseBits(uint16(x)) == uint16(reversed shr 48)
|
||||||
|
doAssert reverseBits(uint8(x)) == uint8(reversed shr 56)
|
||||||
|
|
||||||
|
testReverseBitsInvo(x)
|
||||||
|
testReverseBitsInvo(uint32(x))
|
||||||
|
testReverseBitsInvo(uint16(x))
|
||||||
|
testReverseBitsInvo(uint8(x))
|
||||||
|
|
||||||
|
proc testReverseBitsRefl(x, reversed: uint64) =
|
||||||
|
testReverseBitsPerType(x, reversed)
|
||||||
|
testReverseBitsPerType(reversed, x)
|
||||||
|
|
||||||
|
proc testReverseBitsShift(d, b: uint64) =
|
||||||
|
var
|
||||||
|
x = d
|
||||||
|
y = b
|
||||||
|
|
||||||
|
for i in 1..64:
|
||||||
|
testReverseBitsRefl(x, y)
|
||||||
|
x = x shl 1
|
||||||
|
y = y shr 1
|
||||||
|
|
||||||
|
proc testReverseBits(d, b: uint64) =
|
||||||
|
testReverseBitsShift(d, b)
|
||||||
|
|
||||||
|
testReverseBits(0x0u64, 0x0u64)
|
||||||
|
testReverseBits(0xffffffffffffffffu64, 0xffffffffffffffffu64)
|
||||||
|
testReverseBits(0x0123456789abcdefu64, 0xf7b3d591e6a2c480u64)
|
||||||
|
testReverseBits(0x5555555555555555u64, 0xaaaaaaaaaaaaaaaau64)
|
||||||
|
testReverseBits(0x5555555500000001u64, 0x80000000aaaaaaaau64)
|
||||||
|
testReverseBits(0x55555555aaaaaaaau64, 0x55555555aaaaaaaau64)
|
||||||
|
testReverseBits(0xf0f0f0f00f0f0f0fu64, 0xf0f0f0f00f0f0f0fu64)
|
||||||
|
testReverseBits(0x181881810ff00916u64, 0x68900ff081811818u64)
|
||||||
|
|
||||||
echo "OK"
|
echo "OK"
|
||||||
|
|
||||||
block: # not ready for vm because exception is compile error
|
block: # not ready for vm because exception is compile error
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue