mirror of https://github.com/vacp2p/nim-stint.git
use bitops2 from shims (#77)
This commit is contained in:
parent
6853ebe97c
commit
9c51f9e7d5
|
@ -7,7 +7,9 @@ skipDirs = @["tests", "benchmarks"]
|
||||||
### Dependencies
|
### Dependencies
|
||||||
|
|
||||||
# TODO test only requirements don't work: https://github.com/nim-lang/nimble/issues/482
|
# TODO test only requirements don't work: https://github.com/nim-lang/nimble/issues/482
|
||||||
requires "nim >= 0.18" #, "https://github.com/alehander42/nim-quicktest >= 0.18.0", "https://github.com/status-im/nim-ttmath"
|
requires "nim >= 0.19",
|
||||||
|
"std_shims"
|
||||||
|
#, "https://github.com/alehander42/nim-quicktest >= 0.18.0", "https://github.com/status-im/nim-ttmath"
|
||||||
|
|
||||||
proc test(name: string, lang: string = "c") =
|
proc test(name: string, lang: string = "c") =
|
||||||
if not dirExists "build":
|
if not dirExists "build":
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#
|
#
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import ./private/datatypes, macros
|
import ./private/datatypes
|
||||||
export StInt
|
export StInt
|
||||||
export IntImpl, intImpl, bitsof # TODO remove the need to export these
|
export IntImpl, intImpl, bitsof # TODO remove the need to export these
|
||||||
|
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
# Stint
|
|
||||||
# Copyright 2018 Status Research & Development GmbH
|
|
||||||
# Licensed under either of
|
|
||||||
#
|
|
||||||
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
|
||||||
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
|
||||||
#
|
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
|
||||||
|
|
||||||
import ./datatypes, ./conversion, stdlib_bitops
|
|
||||||
export stdlib_bitops
|
|
||||||
|
|
||||||
# We reuse bitops from Nim standard lib, and expand it for multi-precision int.
|
|
||||||
# MpInt rely on no undefined behaviour as often we scan 0. (if 1 is stored in a uint128 for example)
|
|
||||||
# Also countLeadingZeroBits must return the size of the type and not 0 like in the stdlib
|
|
||||||
|
|
||||||
func countLeadingZeroBits*(n: UintImpl): int {.inline.} =
|
|
||||||
## Returns the number of leading zero bits in integer.
|
|
||||||
|
|
||||||
const maxHalfRepr = bitsof(n) div 2
|
|
||||||
|
|
||||||
let hi_clz = n.hi.countLeadingZeroBits
|
|
||||||
|
|
||||||
result = if hi_clz == maxHalfRepr:
|
|
||||||
n.lo.countLeadingZeroBits + maxHalfRepr
|
|
||||||
else: hi_clz
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
# Stint
|
||||||
|
# Copyright 2018 Status Research & Development GmbH
|
||||||
|
# Licensed under either of
|
||||||
|
#
|
||||||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||||
|
#
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import ./datatypes, ./conversion, std_shims/support/bitops2
|
||||||
|
export bitops2
|
||||||
|
|
||||||
|
# Bitops from support library
|
||||||
|
|
||||||
|
func countOnes*(x: UintImpl): int {.inline.} =
|
||||||
|
countOnes(x.lo) + countOnes(x.hi)
|
||||||
|
|
||||||
|
func parity*(x: UintImpl): int {.inline.} =
|
||||||
|
parity(x.lo) xor parity(x.hi)
|
||||||
|
|
||||||
|
func leadingZeros*(x: UintImpl): int {.inline.} =
|
||||||
|
let tmp = x.hi.leadingZeros()
|
||||||
|
if tmp == bitsof(x.hi):
|
||||||
|
x.lo.leadingZeros() + bitsof(x.hi)
|
||||||
|
else:
|
||||||
|
tmp
|
||||||
|
|
||||||
|
func trailingZeros*(x: UintImpl): int {.inline.} =
|
||||||
|
let tmp = x.lo.trailingZeros()
|
||||||
|
if tmp == bitsof(x.lo):
|
||||||
|
tmp + x.hi.trailingZeros()
|
||||||
|
else:
|
||||||
|
tmp
|
||||||
|
|
||||||
|
func firstOne*(x: UintImpl): int {.inline.} =
|
||||||
|
let tmp = trailingZeros(x)
|
||||||
|
if tmp == bitsof(x):
|
||||||
|
0
|
||||||
|
else:
|
||||||
|
1 + tmp
|
|
@ -20,7 +20,7 @@ func toUint*(n: UintImpl or IntImpl or SomeSignedInt): auto {.inline.}=
|
||||||
## Casts an unsigned integer to an uint of the same size
|
## Casts an unsigned integer to an uint of the same size
|
||||||
# TODO: uint128 support
|
# TODO: uint128 support
|
||||||
when n.sizeof > 8:
|
when n.sizeof > 8:
|
||||||
raise newException("Unreachable. You are trying to cast a StUint with more than 64-bit of precision")
|
{.fatal: "Unreachable. You are trying to cast a StUint with more than 64-bit of precision" .}
|
||||||
elif n.sizeof == 8:
|
elif n.sizeof == 8:
|
||||||
cast[uint64](n)
|
cast[uint64](n)
|
||||||
elif n.sizeof == 4:
|
elif n.sizeof == 4:
|
||||||
|
@ -48,7 +48,7 @@ func toInt*(n: UintImpl or IntImpl or SomeInteger): auto {.inline.}=
|
||||||
## Casts an unsigned integer to an uint of the same size
|
## Casts an unsigned integer to an uint of the same size
|
||||||
# TODO: uint128 support
|
# TODO: uint128 support
|
||||||
when n.sizeof > 8:
|
when n.sizeof > 8:
|
||||||
raise newException("Unreachable. You are trying to cast a StUint with more than 64-bit of precision")
|
{.fatal: "Unreachable. You are trying to cast a StUint with more than 64-bit of precision" .}
|
||||||
elif n.sizeof == 8:
|
elif n.sizeof == 8:
|
||||||
cast[int64](n)
|
cast[int64](n)
|
||||||
elif n.sizeof == 4:
|
elif n.sizeof == 4:
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#
|
#
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import ./datatypes, ./bithacks, ./uint_comparison
|
import ./datatypes, ./uint_comparison
|
||||||
|
|
||||||
func isZero*(n: SomeSignedInt): bool {.inline.} =
|
func isZero*(n: SomeSignedInt): bool {.inline.} =
|
||||||
n == 0
|
n == 0
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
#
|
|
||||||
#
|
|
||||||
# Nim's Runtime Library
|
|
||||||
# (c) Copyright 2017 Nim Authors
|
|
||||||
#
|
|
||||||
# See the file "copying.txt", included in this
|
|
||||||
# distribution, for details about the copyright.
|
|
||||||
#
|
|
||||||
|
|
||||||
## This module implements a series of low level methods for bit manipulation.
|
|
||||||
## By default, this module use compiler intrinsics to improve performance
|
|
||||||
## on supported compilers: ``GCC``, ``LLVM_GCC``, ``CLANG``, ``VCC``, ``ICC``.
|
|
||||||
##
|
|
||||||
## The module will fallback to pure nim procs incase the backend is not supported.
|
|
||||||
## You can also use the flag `noIntrinsicsBitOpts` to disable compiler intrinsics.
|
|
||||||
##
|
|
||||||
## This module is also compatible with other backends: ``Javascript``, ``Nimscript``
|
|
||||||
## as well as the ``compiletime VM``.
|
|
||||||
##
|
|
||||||
## As a result of using optimized function/intrinsics some functions can return
|
|
||||||
## undefined results if the input is invalid. You can use the flag `noUndefinedBitOpts`
|
|
||||||
## to force predictable behaviour for all input, causing a small performance hit.
|
|
||||||
##
|
|
||||||
## At this time only `fastLog2`, `firstSetBit, `countLeadingZeroBits`, `countTrailingZeroBits`
|
|
||||||
## may return undefined and/or platform dependant value if given invalid input.
|
|
||||||
|
|
||||||
|
|
||||||
# Bitops from the standard lib modified for MpInt use.
|
|
||||||
# - No undefined behaviour or flag needed
|
|
||||||
# - Note that for CountLeadingZero, it returns sizeof(input) * 8
|
|
||||||
# instead of 0
|
|
||||||
|
|
||||||
|
|
||||||
const useBuiltins* = not defined(noIntrinsicsBitOpts)
|
|
||||||
# const noUndefined* = defined(noUndefinedBitOpts)
|
|
||||||
const useGCC_builtins* = (defined(gcc) or defined(llvm_gcc) or defined(clang)) and useBuiltins
|
|
||||||
const useICC_builtins* = defined(icc) and useBuiltins
|
|
||||||
const useVCC_builtins* = defined(vcc) and useBuiltins
|
|
||||||
const arch64* = sizeof(int) == 8
|
|
||||||
|
|
||||||
|
|
||||||
func fastlog2_nim(x: uint32): int {.inline.} =
|
|
||||||
## Quickly find the log base 2 of a 32-bit or less integer.
|
|
||||||
# https://graphics.stanford.edu/%7Eseander/bithacks.html#IntegerLogDeBruijn
|
|
||||||
# https://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers
|
|
||||||
const lookup: array[32, uint8] = [0'u8, 9, 1, 10, 13, 21, 2, 29, 11, 14, 16, 18,
|
|
||||||
22, 25, 3, 30, 8, 12, 20, 28, 15, 17, 24, 7, 19, 27, 23, 6, 26, 5, 4, 31]
|
|
||||||
var v = x.uint32
|
|
||||||
v = v or v shr 1 # first round down to one less than a power of 2
|
|
||||||
v = v or v shr 2
|
|
||||||
v = v or v shr 4
|
|
||||||
v = v or v shr 8
|
|
||||||
v = v or v shr 16
|
|
||||||
result = lookup[uint32(v * 0x07C4ACDD'u32) shr 27].int
|
|
||||||
|
|
||||||
func fastlog2_nim(x: uint64): int {.inline.} =
|
|
||||||
## Quickly find the log base 2 of a 64-bit integer.
|
|
||||||
# https://graphics.stanford.edu/%7Eseander/bithacks.html#IntegerLogDeBruijn
|
|
||||||
# https://stackoverflow.com/questions/11376288/fast-computing-of-log2-for-64-bit-integers
|
|
||||||
const lookup: array[64, uint8] = [0'u8, 58, 1, 59, 47, 53, 2, 60, 39, 48, 27, 54,
|
|
||||||
33, 42, 3, 61, 51, 37, 40, 49, 18, 28, 20, 55, 30, 34, 11, 43, 14, 22, 4, 62,
|
|
||||||
57, 46, 52, 38, 26, 32, 41, 50, 36, 17, 19, 29, 10, 13, 21, 56, 45, 25, 31,
|
|
||||||
35, 16, 9, 12, 44, 24, 15, 8, 23, 7, 6, 5, 63]
|
|
||||||
var v = x.uint64
|
|
||||||
v = v or v shr 1 # first round down to one less than a power of 2
|
|
||||||
v = v or v shr 2
|
|
||||||
v = v or v shr 4
|
|
||||||
v = v or v shr 8
|
|
||||||
v = v or v shr 16
|
|
||||||
v = v or v shr 32
|
|
||||||
result = lookup[(v * 0x03F6EAF2CD271461'u64) shr 58].int
|
|
||||||
|
|
||||||
|
|
||||||
when useGCC_builtins:
|
|
||||||
# Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
|
|
||||||
proc builtin_clz*(x: cuint): cint {.importc: "__builtin_clz", cdecl.}
|
|
||||||
proc builtin_clzll*(x: culonglong): cint {.importc: "__builtin_clzll", cdecl.}
|
|
||||||
|
|
||||||
elif useVCC_builtins:
|
|
||||||
# Search the mask data from most significant bit (MSB) to least significant bit (LSB) for a set bit (1).
|
|
||||||
proc bitScanReverse*(index: ptr culong, mask: culong): cuchar {.importc: "_BitScanReverse", header: "<intrin.h>", nosideeffect.}
|
|
||||||
proc bitScanReverse64*(index: ptr culong, mask: uint64): cuchar {.importc: "_BitScanReverse64", header: "<intrin.h>", nosideeffect.}
|
|
||||||
|
|
||||||
template vcc_scan_impl*(fnc: untyped; v: untyped): int =
|
|
||||||
var index: culong
|
|
||||||
discard fnc(index.addr, v)
|
|
||||||
index.int
|
|
||||||
|
|
||||||
elif useICC_builtins:
|
|
||||||
# Returns the number of leading 0-bits in x, starting at the most significant bit position. If x is 0, the result is undefined.
|
|
||||||
proc bitScanReverse*(p: ptr uint32, b: uint32): cuchar {.importc: "_BitScanReverse", header: "<immintrin.h>", nosideeffect.}
|
|
||||||
proc bitScanReverse64*(p: ptr uint32, b: uint64): cuchar {.importc: "_BitScanReverse64", header: "<immintrin.h>", nosideeffect.}
|
|
||||||
|
|
||||||
template icc_scan_impl*(fnc: untyped; v: untyped): int =
|
|
||||||
var index: uint32
|
|
||||||
discard fnc(index.addr, v)
|
|
||||||
index.int
|
|
||||||
|
|
||||||
func countLeadingZeroBits*(x: SomeInteger): int {.inline.} =
|
|
||||||
## 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 noUndefined:
|
|
||||||
if x == 0:
|
|
||||||
return sizeof(x) * 8 # Note this differes from the stdlib which returns 0
|
|
||||||
|
|
||||||
when nimvm:
|
|
||||||
when sizeof(x) <= 4: result = sizeof(x)*8 - 1 - fastlog2_nim(x.uint32)
|
|
||||||
else: result = sizeof(x)*8 - 1 - fastlog2_nim(x.uint64)
|
|
||||||
else:
|
|
||||||
when useGCC_builtins:
|
|
||||||
when sizeof(x) <= 4: result = builtin_clz(x.uint32).int - (32 - sizeof(x)*8)
|
|
||||||
else: result = builtin_clzll(x.uint64).int
|
|
||||||
else:
|
|
||||||
when sizeof(x) <= 4: result = sizeof(x)*8 - 1 - fastlog2_nim(x.uint32)
|
|
||||||
else: result = sizeof(x)*8 - 1 - fastlog2_nim(x.uint64)
|
|
|
@ -7,7 +7,7 @@
|
||||||
#
|
#
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import ./bithacks, ./conversion, ./initialization,
|
import ./conversion, ./initialization,
|
||||||
./datatypes,
|
./datatypes,
|
||||||
./uint_comparison,
|
./uint_comparison,
|
||||||
./uint_bitwise_ops
|
./uint_bitwise_ops
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
#
|
#
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import ./bithacks, ./conversion, ./initialization,
|
import ./bitops2, ./conversion, ./initialization,
|
||||||
./datatypes,
|
./datatypes,
|
||||||
./uint_comparison,
|
./uint_comparison,
|
||||||
./uint_bitwise_ops,
|
./uint_bitwise_ops,
|
||||||
|
@ -122,7 +122,7 @@ proc div3n2n[T: SomeUnsignedInt](
|
||||||
|
|
||||||
func div2n1n(q, r: var UintImpl, ah, al, b: UintImpl) =
|
func div2n1n(q, r: var UintImpl, ah, al, b: UintImpl) =
|
||||||
|
|
||||||
# doAssert countLeadingZeroBits(b) == 0, "Divisor was not normalized"
|
# doAssert leadingZeros(b) == 0, "Divisor was not normalized"
|
||||||
|
|
||||||
var s: UintImpl
|
var s: UintImpl
|
||||||
div3n2n(q.hi, s, ah.hi, ah.lo, al.hi, b)
|
div3n2n(q.hi, s, ah.hi, ah.lo, al.hi, b)
|
||||||
|
@ -130,7 +130,7 @@ func div2n1n(q, r: var UintImpl, ah, al, b: UintImpl) =
|
||||||
|
|
||||||
func div2n1n[T: SomeunsignedInt](q, r: var T, n_hi, n_lo, d: T) =
|
func div2n1n[T: SomeunsignedInt](q, r: var T, n_hi, n_lo, d: T) =
|
||||||
|
|
||||||
# doAssert countLeadingZeroBits(d) == 0, "Divisor was not normalized"
|
# doAssert leadingZeros(d) == 0, "Divisor was not normalized"
|
||||||
|
|
||||||
const
|
const
|
||||||
size = bitsof(q)
|
size = bitsof(q)
|
||||||
|
@ -177,7 +177,7 @@ func divmodBZ[T](x, y: UintImpl[T], q, r: var UintImpl[T])=
|
||||||
if x.hi < y.lo:
|
if x.hi < y.lo:
|
||||||
# Normalize
|
# Normalize
|
||||||
let
|
let
|
||||||
clz = countLeadingZeroBits(y.lo)
|
clz = leadingZeros(y.lo)
|
||||||
xx = x shl clz
|
xx = x shl clz
|
||||||
yy = y.lo shl clz
|
yy = y.lo shl clz
|
||||||
|
|
||||||
|
@ -191,7 +191,7 @@ func divmodBZ[T](x, y: UintImpl[T], q, r: var UintImpl[T])=
|
||||||
# General case
|
# General case
|
||||||
|
|
||||||
# Normalization
|
# Normalization
|
||||||
let clz = countLeadingZeroBits(y)
|
let clz = leadingZeros(y)
|
||||||
|
|
||||||
let
|
let
|
||||||
xx = UintImpl[type x](lo: x) shl clz
|
xx = UintImpl[type x](lo: x) shl clz
|
||||||
|
@ -212,7 +212,7 @@ func divmodBS(x, y: UintImpl, q, r: var UintImpl) =
|
||||||
type SubTy = type x.lo
|
type SubTy = type x.lo
|
||||||
|
|
||||||
var
|
var
|
||||||
shift = y.countLeadingZeroBits - x.countLeadingZeroBits
|
shift = y.leadingZeros - x.leadingZeros
|
||||||
d = y shl shift
|
d = y shl shift
|
||||||
|
|
||||||
r = x
|
r = x
|
||||||
|
@ -231,8 +231,8 @@ const BinaryShiftThreshold = 8 # If the difference in bit-length is below 8
|
||||||
|
|
||||||
func divmod*[T](x, y: UintImpl[T]): tuple[quot, rem: UintImpl[T]]=
|
func divmod*[T](x, y: UintImpl[T]): tuple[quot, rem: UintImpl[T]]=
|
||||||
|
|
||||||
let x_clz = x.countLeadingZeroBits
|
let x_clz = x.leadingZeros
|
||||||
let y_clz = y.countLeadingZeroBits
|
let y_clz = y.leadingZeros
|
||||||
|
|
||||||
# We short-circuit division depending on special-cases.
|
# We short-circuit division depending on special-cases.
|
||||||
# TODO: Constant-time division
|
# TODO: Constant-time division
|
||||||
|
|
|
@ -111,14 +111,13 @@ func low*[bits: static[int]](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.}
|
||||||
## Returns the lowest unsigned int of this size. This is always 0.
|
## Returns the lowest unsigned int of this size. This is always 0.
|
||||||
result.data = low(type result.data)
|
result.data = low(type result.data)
|
||||||
|
|
||||||
import ./private/bithacks
|
import ./private/bitops2
|
||||||
|
|
||||||
func countLeadingZeroBits*(x: Stuint): int {.inline.} =
|
func countOnes*(x: StUint): int {.inline.} = countOnes(x.data)
|
||||||
## Logical count of leading zeros
|
func parity*(x: StUint): int {.inline.} = parity(x.data)
|
||||||
## This corresponds to the number of zero bits of the input in
|
func firstOne*(x: StUint): int {.inline.} = firstOne(x.data)
|
||||||
## its big endian representation.
|
func leadingZeros*(x: StUint): int {.inline.} = leadingZeros(x.data)
|
||||||
## If input is zero, the number of bits of the number is returned.
|
func trailingZeros*(x: StUint): int {.inline.} = trailingZeros(x.data)
|
||||||
x.data.countLeadingZeroBits
|
|
||||||
|
|
||||||
import ./private/initialization
|
import ./private/initialization
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
#
|
#
|
||||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
import test_uint_endianness,
|
import test_uint_bitops2,
|
||||||
|
test_uint_endianness,
|
||||||
test_uint_comparison,
|
test_uint_comparison,
|
||||||
test_uint_bitwise,
|
test_uint_bitwise,
|
||||||
test_uint_addsub,
|
test_uint_addsub,
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
# Stint
|
||||||
|
# Copyright 2018 Status Research & Development GmbH
|
||||||
|
# Licensed under either of
|
||||||
|
#
|
||||||
|
# * Apache License, version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
|
||||||
|
# * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
|
||||||
|
#
|
||||||
|
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||||
|
|
||||||
|
import ../stint, unittest
|
||||||
|
|
||||||
|
suite "Testing bitops2":
|
||||||
|
test "Bitops give sane results":
|
||||||
|
|
||||||
|
check:
|
||||||
|
countOnes(0b01000100'u8.stuint(128)) == 2
|
||||||
|
countOnes(0b01000100'u8.stuint(128) shl 100) == 2
|
||||||
|
|
||||||
|
parity(0b00000001'u8.stuint(128)) == 1
|
||||||
|
parity(0b00000001'u8.stuint(128) shl 100) == 1
|
||||||
|
|
||||||
|
firstOne(0b00000010'u8.stuint(128)) == 2
|
||||||
|
firstOne(0b00000010'u8.stuint(128) shl 100) == 102
|
||||||
|
firstOne(0'u8.stuint(128)) == 0
|
||||||
|
|
||||||
|
leadingZeros(0'u8.stuint(128)) == 128
|
||||||
|
leadingZeros(0b00100000'u8.stuint(128)) == 128 - 6
|
||||||
|
leadingZeros(0b00100000'u8.stuint(128) shl 100) == 128 - 106
|
||||||
|
|
||||||
|
trailingZeros(0b00100000'u8.stuint(128)) == 5
|
||||||
|
trailingZeros(0b00100000'u8.stuint(128) shl 100) == 105
|
||||||
|
trailingZeros(0'u8.stuint(128)) == 128
|
|
@ -52,9 +52,3 @@ suite "Testing unsigned int bitwise operations":
|
||||||
test "Shift right - by half the size of the integer":
|
test "Shift right - by half the size of the integer":
|
||||||
check: cast[uint16](b) == z # Sanity check
|
check: cast[uint16](b) == z # Sanity check
|
||||||
check: cast[uint16](b shr 8) == z shr 8
|
check: cast[uint16](b shr 8) == z shr 8
|
||||||
|
|
||||||
test "leading zero bits":
|
|
||||||
var x: StUint[2048]
|
|
||||||
check: x.countLeadingZeroBits() == 2048
|
|
||||||
x = StUint[2048].one()
|
|
||||||
check: x.countLeadingZeroBits() == 2047
|
|
||||||
|
|
Loading…
Reference in New Issue