diff options
author | Oscar NihlgÄrd <oscarnihlgard@gmail.com> | 2019-05-25 20:48:13 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-05-25 20:48:13 +0200 |
commit | 3a06022071d3ecf62c8e2f4812062e2e2fe71954 (patch) | |
tree | b565dbc9ab69e92ab9d0d7bff26b1a9acf8b75b3 /lib/pure | |
parent | 70fb3a93e9b051b2ba91769a43d63251d0d7a5b3 (diff) | |
download | Nim-3a06022071d3ecf62c8e2f4812062e2e2fe71954.tar.gz |
Enable range checking for unsigned integers (#11313)
* Enable range checking for unsigned integers * Make the tests green
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 |