mirror of
https://github.com/nim-lang/Nim.git
synced 2026-04-18 21:40:32 +00:00
* 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:
@@ -771,7 +771,9 @@ func rotr[T: SomeUnsignedInt](value: T, rot: int32): T {.inline.} =
|
||||
let rot = 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):
|
||||
cint(shift)
|
||||
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:
|
||||
culonglong(shift)
|
||||
|
||||
template shiftTypeTo[T](value: T, shift: int): auto =
|
||||
## Returns the `shift` for the rotation according to the compiler and the size
|
||||
## 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.
|
||||
func rotateLeftBits*[T: SomeUnsignedInt](value: T, shift: range[0..(sizeof(T) * 8)]): T {.inline.} =
|
||||
## Left-rotate bits in a `value`.
|
||||
runnableExamples:
|
||||
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) ==
|
||||
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) ==
|
||||
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) ==
|
||||
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
||||
|
||||
when nimvm:
|
||||
rotl(value, shift.int32)
|
||||
else:
|
||||
when useBuiltinsRotate and defined(amd64):
|
||||
builtin_rotl64(value.culonglong, shiftTypeTo(value, shift)).uint64
|
||||
when useBuiltinsRotate:
|
||||
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:
|
||||
rotl(value, shift.int32)
|
||||
|
||||
func rotateRightBits*(value: uint8, shift: range[0..8]): uint8 {.inline.} =
|
||||
## Right-rotate bits in a 8-bits value.
|
||||
func rotateRightBits*[T: SomeUnsignedInt](value: T, shift: range[0..(sizeof(T) * 8)]): T {.inline.} =
|
||||
## Right-rotate bits in a `value`.
|
||||
runnableExamples:
|
||||
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) ==
|
||||
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) ==
|
||||
0b1111000000001111_0000111111110000'u32
|
||||
|
||||
doAssert rotateRightBits(0b00000000111111111111111100000000_11111111000000000000000011111111'u64, 32) ==
|
||||
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
||||
when nimvm:
|
||||
rotr(value, shift.int32)
|
||||
else:
|
||||
when useBuiltinsRotate:
|
||||
builtin_rotr32(value.cuint, shiftTypeTo(value, shift)).uint32
|
||||
else:
|
||||
rotr(value, shift.int32)
|
||||
|
||||
func rotateRightBits*(value: uint64, shift: range[0..64]): uint64 {.inline.} =
|
||||
## Right-rotate bits in a 64-bits value.
|
||||
runnableExamples:
|
||||
doAssert rotateRightBits(0b00000000111111111111111100000000_11111111000000000000000011111111'u64, 32) ==
|
||||
0b11111111000000000000000011111111_00000000111111111111111100000000'u64
|
||||
|
||||
when nimvm:
|
||||
rotr(value, shift.int32)
|
||||
else:
|
||||
when useBuiltinsRotate and defined(amd64):
|
||||
builtin_rotr64(value.culonglong, shiftTypeTo(value, shift)).uint64
|
||||
const size = sizeof(T)
|
||||
when size == 1:
|
||||
builtin_rotr8(value.cuchar, shiftTypeTo(size, shift)).T
|
||||
elif size == 2:
|
||||
builtin_rotr16(value.cushort, shiftTypeTo(size, shift)).T
|
||||
elif size == 4:
|
||||
builtin_rotr32(value.cuint, shiftTypeTo(size, shift)).T
|
||||
elif size == 8 and arch64:
|
||||
builtin_rotr64(value.culonglong, shiftTypeTo(size, shift)).T
|
||||
else:
|
||||
rotr(value, shift.int32)
|
||||
else:
|
||||
rotr(value, shift.int32)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user