diff options
Diffstat (limited to 'lib/pure')
-rw-r--r-- | lib/pure/bitops.nim | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/lib/pure/bitops.nim b/lib/pure/bitops.nim index b32b5dc67..51e4a6c6a 100644 --- a/lib/pure/bitops.nim +++ b/lib/pure/bitops.nim @@ -33,6 +33,12 @@ const useICC_builtins = defined(icc) and useBuiltins const useVCC_builtins = defined(vcc) and useBuiltins const arch64 = sizeof(int) == 8 +template toUnsigned(x: int8): uint8 = cast[uint8](x) +template toUnsigned(x: int16): uint16 = cast[uint16](x) +template toUnsigned(x: int32): uint32 = cast[uint32](x) +template toUnsigned(x: int64): uint64 = cast[uint64](x) +template toUnsigned(x: int): uint = cast[uint](x) + template forwardImpl(impl, arg) {.dirty.} = when sizeof(x) <= 4: when x is SomeSignedInt: @@ -242,6 +248,8 @@ proc countSetBits*(x: SomeInteger): int {.inline, nosideeffect.} = ## Counts the set bits in integer. (also called `Hamming weight`:idx:.) # TODO: figure out if ICC support _popcnt32/_popcnt64 on platform without POPCNT. # like GCC and MSVC + when x is SomeSignedInt: + let x = x.toUnsigned when nimvm: result = forwardImpl(countSetBits_nim, x) else: @@ -272,6 +280,8 @@ proc parityBits*(x: SomeInteger): int {.inline, nosideeffect.} = ## is odd parity is 1, otherwise 0. # Can be used a base if creating ASM version. # https://stackoverflow.com/questions/21617970/how-to-check-if-value-has-even-parity-of-bits-or-odd + when x is SomeSignedInt: + let x = x.toUnsigned when nimvm: result = forwardImpl(parity_impl, x) else: @@ -287,6 +297,8 @@ proc firstSetBit*(x: SomeInteger): int {.inline, nosideeffect.} = ## If `x` is zero, when ``noUndefinedBitOpts`` is set, result is 0, ## otherwise result is undefined. # GCC builtin 'builtin_ffs' already handle zero input. + when x is SomeSignedInt: + let x = x.toUnsigned when nimvm: when noUndefined: if x == 0: @@ -321,6 +333,8 @@ proc fastLog2*(x: SomeInteger): int {.inline, nosideeffect.} = ## Quickly find the log base 2 of an integer. ## If `x` is zero, when ``noUndefinedBitOpts`` is set, result is -1, ## otherwise result is undefined. + when x is SomeSignedInt: + let x = x.toUnsigned when noUndefined: if x == 0: return -1 @@ -352,6 +366,8 @@ proc countLeadingZeroBits*(x: SomeInteger): int {.inline, nosideeffect.} = ## Returns the number of leading zero bits in integer. ## If `x` is zero, when ``noUndefinedBitOpts`` is set, result is 0, ## otherwise result is undefined. + when x is SomeSignedInt: + let x = x.toUnsigned when noUndefined: if x == 0: return 0 @@ -369,6 +385,8 @@ proc countTrailingZeroBits*(x: SomeInteger): int {.inline, nosideeffect.} = ## Returns the number of trailing zeros in integer. ## If `x` is zero, when ``noUndefinedBitOpts`` is set, result is 0, ## otherwise result is undefined. + when x is SomeSignedInt: + let x = x.toUnsigned when noUndefined: if x == 0: return 0 |