summary refs log tree commit diff stats
path: root/lib/pure
diff options
context:
space:
mode:
authorOscar NihlgÄrd <oscarnihlgard@gmail.com>2019-05-25 20:48:13 +0200
committerAndreas Rumpf <rumpf_a@web.de>2019-05-25 20:48:13 +0200
commit3a06022071d3ecf62c8e2f4812062e2e2fe71954 (patch)
treeb565dbc9ab69e92ab9d0d7bff26b1a9acf8b75b3 /lib/pure
parent70fb3a93e9b051b2ba91769a43d63251d0d7a5b3 (diff)
downloadNim-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.nim18
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