Enable range checking for unsigned integers (#11313)

* Enable range checking for unsigned integers

* Make the tests green
This commit is contained in:
Oscar Nihlgård
2019-05-25 20:48:13 +02:00
committed by Andreas Rumpf
parent 70fb3a93e9
commit 3a06022071
5 changed files with 24 additions and 7 deletions

View File

@@ -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