* Rotation right and left refactored to generics Continuation of [16622](https://github.com/nim-lang/Nim/pull/16622) * add runnableExamples
This commit is contained in:
parent
f5b1e384a4
commit
af2a7e8cbc
1 changed files with 32 additions and 89 deletions
|
|
@ -771,7 +771,9 @@ func rotr[T: SomeUnsignedInt](value: T, rot: int32): T {.inline.} =
|
||||||
let rot = rot and mask
|
let rot = rot and mask
|
||||||
(value shr rot) or (value shl ((-rot) and mask))
|
(value shr rot) or (value shl ((-rot) and mask))
|
||||||
|
|
||||||
func shiftTypeToImpl(size: static int, shift: int): auto {.inline.} =
|
func shiftTypeTo(size: static int, shift: int): auto {.inline.} =
|
||||||
|
## Returns the `shift` for the rotation according to the compiler and the
|
||||||
|
## `size`.
|
||||||
when (defined(vcc) and (size in [4, 8])) or defined(gcc) or defined(icl):
|
when (defined(vcc) and (size in [4, 8])) or defined(gcc) or defined(icl):
|
||||||
cint(shift)
|
cint(shift)
|
||||||
elif (defined(vcc) and (size in [1, 2])) or (defined(clang) and size == 1):
|
elif (defined(vcc) and (size in [1, 2])) or (defined(clang) and size == 1):
|
||||||
|
|
@ -784,118 +786,59 @@ func shiftTypeToImpl(size: static int, shift: int): auto {.inline.} =
|
||||||
elif size == 8:
|
elif size == 8:
|
||||||
culonglong(shift)
|
culonglong(shift)
|
||||||
|
|
||||||
template shiftTypeTo[T](value: T, shift: int): auto =
|
func rotateLeftBits*[T: SomeUnsignedInt](value: T, shift: range[0..(sizeof(T) * 8)]): T {.inline.} =
|
||||||
## Returns the `shift` for the rotation according to the compiler and the size
|
## Left-rotate bits in a `value`.
|
||||||
## of the` value`.
|
|
||||||
shiftTypeToImpl(sizeof(value), shift)
|
|
||||||
|
|
||||||
func rotateLeftBits*(value: uint8, shift: range[0..8]): uint8 {.inline.} =
|
|
||||||
## Left-rotate bits in a 8-bits value.
|
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert rotateLeftBits(0b0110_1001'u8, 4) == 0b1001_0110'u8
|
doAssert rotateLeftBits(0b0110_1001'u8, 4) == 0b1001_0110'u8
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
rotl(value, shift.int32)
|
|
||||||
else:
|
|
||||||
when useBuiltinsRotate:
|
|
||||||
builtin_rotl8(value.cuchar, shiftTypeTo(value, shift)).uint8
|
|
||||||
else:
|
|
||||||
rotl(value, shift.int32)
|
|
||||||
|
|
||||||
func rotateLeftBits*(value: uint16, shift: range[0..16]): uint16 {.inline.} =
|
|
||||||
## Left-rotate bits in a 16-bits value.
|
|
||||||
runnableExamples:
|
|
||||||
doAssert rotateLeftBits(0b00111100_11000011'u16, 8) ==
|
doAssert rotateLeftBits(0b00111100_11000011'u16, 8) ==
|
||||||
0b11000011_00111100'u16
|
0b11000011_00111100'u16
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
rotl(value, shift.int32)
|
|
||||||
else:
|
|
||||||
when useBuiltinsRotate:
|
|
||||||
builtin_rotl16(value.cushort, shiftTypeTo(value, shift)).uint16
|
|
||||||
else:
|
|
||||||
rotl(value, shift.int32)
|
|
||||||
|
|
||||||
func rotateLeftBits*(value: uint32, shift: range[0..32]): uint32 {.inline.} =
|
|
||||||
## Left-rotate bits in a 32-bits value.
|
|
||||||
runnableExamples:
|
|
||||||
doAssert rotateLeftBits(0b0000111111110000_1111000000001111'u32, 16) ==
|
doAssert rotateLeftBits(0b0000111111110000_1111000000001111'u32, 16) ==
|
||||||
0b1111000000001111_0000111111110000'u32
|
0b1111000000001111_0000111111110000'u32
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
rotl(value, shift.int32)
|
|
||||||
else:
|
|
||||||
when useBuiltinsRotate:
|
|
||||||
builtin_rotl32(value.cuint, shiftTypeTo(value, shift)).uint32
|
|
||||||
else:
|
|
||||||
rotl(value, shift.int32)
|
|
||||||
|
|
||||||
func rotateLeftBits*(value: uint64, shift: range[0..64]): uint64 {.inline.} =
|
|
||||||
## Left-rotate bits in a 64-bits value.
|
|
||||||
runnableExamples:
|
|
||||||
doAssert rotateLeftBits(0b00000000111111111111111100000000_11111111000000000000000011111111'u64, 32) ==
|
doAssert rotateLeftBits(0b00000000111111111111111100000000_11111111000000000000000011111111'u64, 32) ==
|
||||||
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
||||||
|
|
||||||
when nimvm:
|
when nimvm:
|
||||||
rotl(value, shift.int32)
|
rotl(value, shift.int32)
|
||||||
else:
|
else:
|
||||||
when useBuiltinsRotate and defined(amd64):
|
when useBuiltinsRotate:
|
||||||
builtin_rotl64(value.culonglong, shiftTypeTo(value, shift)).uint64
|
const size = sizeof(T)
|
||||||
|
when size == 1:
|
||||||
|
builtin_rotl8(value.cuchar, shiftTypeTo(size, shift)).T
|
||||||
|
elif size == 2:
|
||||||
|
builtin_rotl16(value.cushort, shiftTypeTo(size, shift)).T
|
||||||
|
elif size == 4:
|
||||||
|
builtin_rotl32(value.cuint, shiftTypeTo(size, shift)).T
|
||||||
|
elif size == 8 and arch64:
|
||||||
|
builtin_rotl64(value.culonglong, shiftTypeTo(size, shift)).T
|
||||||
|
else:
|
||||||
|
rotl(value, shift.int32)
|
||||||
else:
|
else:
|
||||||
rotl(value, shift.int32)
|
rotl(value, shift.int32)
|
||||||
|
|
||||||
func rotateRightBits*(value: uint8, shift: range[0..8]): uint8 {.inline.} =
|
func rotateRightBits*[T: SomeUnsignedInt](value: T, shift: range[0..(sizeof(T) * 8)]): T {.inline.} =
|
||||||
## Right-rotate bits in a 8-bits value.
|
## Right-rotate bits in a `value`.
|
||||||
runnableExamples:
|
runnableExamples:
|
||||||
doAssert rotateRightBits(0b0110_1001'u8, 4) == 0b1001_0110'u8
|
doAssert rotateRightBits(0b0110_1001'u8, 4) == 0b1001_0110'u8
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
rotr(value, shift.int32)
|
|
||||||
else:
|
|
||||||
when useBuiltinsRotate:
|
|
||||||
builtin_rotr8(value.cuchar, shiftTypeTo(value, shift)).uint8
|
|
||||||
else:
|
|
||||||
rotr(value, shift.int32)
|
|
||||||
|
|
||||||
func rotateRightBits*(value: uint16, shift: range[0..16]): uint16 {.inline.} =
|
|
||||||
## Right-rotate bits in a 16-bits value.
|
|
||||||
runnableExamples:
|
|
||||||
doAssert rotateRightBits(0b00111100_11000011'u16, 8) ==
|
doAssert rotateRightBits(0b00111100_11000011'u16, 8) ==
|
||||||
0b11000011_00111100'u16
|
0b11000011_00111100'u16
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
rotr(value, shift.int32)
|
|
||||||
else:
|
|
||||||
when useBuiltinsRotate:
|
|
||||||
builtin_rotr16(value.cushort, shiftTypeTo(value, shift)).uint16
|
|
||||||
else:
|
|
||||||
rotr(value, shift.int32)
|
|
||||||
|
|
||||||
func rotateRightBits*(value: uint32, shift: range[0..32]): uint32 {.inline.} =
|
|
||||||
## Right-rotate bits in a 32-bits value.
|
|
||||||
runnableExamples:
|
|
||||||
doAssert rotateRightBits(0b0000111111110000_1111000000001111'u32, 16) ==
|
doAssert rotateRightBits(0b0000111111110000_1111000000001111'u32, 16) ==
|
||||||
0b1111000000001111_0000111111110000'u32
|
0b1111000000001111_0000111111110000'u32
|
||||||
|
doAssert rotateRightBits(0b00000000111111111111111100000000_11111111000000000000000011111111'u64, 32) ==
|
||||||
|
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
||||||
when nimvm:
|
when nimvm:
|
||||||
rotr(value, shift.int32)
|
rotr(value, shift.int32)
|
||||||
else:
|
else:
|
||||||
when useBuiltinsRotate:
|
when useBuiltinsRotate:
|
||||||
builtin_rotr32(value.cuint, shiftTypeTo(value, shift)).uint32
|
const size = sizeof(T)
|
||||||
else:
|
when size == 1:
|
||||||
rotr(value, shift.int32)
|
builtin_rotr8(value.cuchar, shiftTypeTo(size, shift)).T
|
||||||
|
elif size == 2:
|
||||||
func rotateRightBits*(value: uint64, shift: range[0..64]): uint64 {.inline.} =
|
builtin_rotr16(value.cushort, shiftTypeTo(size, shift)).T
|
||||||
## Right-rotate bits in a 64-bits value.
|
elif size == 4:
|
||||||
runnableExamples:
|
builtin_rotr32(value.cuint, shiftTypeTo(size, shift)).T
|
||||||
doAssert rotateRightBits(0b00000000111111111111111100000000_11111111000000000000000011111111'u64, 32) ==
|
elif size == 8 and arch64:
|
||||||
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
builtin_rotr64(value.culonglong, shiftTypeTo(size, shift)).T
|
||||||
|
else:
|
||||||
when nimvm:
|
rotr(value, shift.int32)
|
||||||
rotr(value, shift.int32)
|
|
||||||
else:
|
|
||||||
when useBuiltinsRotate and defined(amd64):
|
|
||||||
builtin_rotr64(value.culonglong, shiftTypeTo(value, shift)).uint64
|
|
||||||
else:
|
else:
|
||||||
rotr(value, shift.int32)
|
rotr(value, shift.int32)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue