Add most significant bit and isNegative proc
This commit is contained in:
parent
b3dedf7824
commit
97fbe56353
|
@ -30,6 +30,28 @@ proc optim(x: NimNode): NimNode =
|
|||
else:
|
||||
error "Unreachable path reached"
|
||||
|
||||
proc isUint(x: NimNode): static[bool] =
|
||||
if eqIdent(x, "uint64"): true
|
||||
elif eqIdent(x, "uint32"): true
|
||||
elif eqIdent(x, "uint16"): true
|
||||
elif eqIdent(x, "uint8"): true
|
||||
else: false
|
||||
|
||||
macro most_significant_word*(x: IntImpl): untyped =
|
||||
|
||||
let optim_type = optim(x)
|
||||
if optim_type.isUint:
|
||||
result = quote do:
|
||||
cast[`optim_type`](`x`)
|
||||
else:
|
||||
when system.cpuEndian == littleEndian:
|
||||
let size = getSize(x)
|
||||
let msw_pos = size - 1
|
||||
else:
|
||||
let msw_pos = 0
|
||||
result = quote do:
|
||||
cast[`optim_type`](`x`)[`msw_pos`]
|
||||
|
||||
proc replaceNodes(ast: NimNode, replacing: NimNode, to_replace: NimNode): NimNode =
|
||||
# Args:
|
||||
# - The full syntax tree
|
||||
|
@ -53,13 +75,6 @@ proc replaceNodes(ast: NimNode, replacing: NimNode, to_replace: NimNode): NimNod
|
|||
return rTree
|
||||
result = inspect(ast)
|
||||
|
||||
proc isUint(x: NimNode): static[bool] =
|
||||
if eqIdent(x, "uint64"): true
|
||||
elif eqIdent(x, "uint32"): true
|
||||
elif eqIdent(x, "uint16"): true
|
||||
elif eqIdent(x, "uint8"): true
|
||||
else: false
|
||||
|
||||
macro asWords*[T](n: UintImpl[T], ignoreEndianness: static[bool], loopBody: untyped): untyped =
|
||||
## Iterates over n, as an array of words.
|
||||
## Input:
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ./datatypes, stdlib_bitops
|
||||
import ./datatypes, stdlib_bitops, as_words
|
||||
export stdlib_bitops
|
||||
|
||||
# We reuse bitops from Nim standard lib, and expand it for multi-precision int.
|
||||
|
@ -24,3 +24,25 @@ func countLeadingZeroBits*(n: UintImpl): int {.inline.} =
|
|||
result = if hi_clz == maxHalfRepr:
|
||||
n.lo.countLeadingZeroBits + maxHalfRepr
|
||||
else: hi_clz
|
||||
|
||||
func msb*[T: SomeInteger](n: T): T =
|
||||
## Returns the most significant bit of an integer.
|
||||
|
||||
when T is int64 or (T is int and sizeof(int) == 8):
|
||||
type UInt = uint64
|
||||
elif T is int32 or (T is int and sizeof(int) == 4):
|
||||
type Uint = uint32
|
||||
elif T is int16:
|
||||
type Uint = uint16
|
||||
elif T is int8:
|
||||
type Uint = uint8
|
||||
else:
|
||||
type Uint = T
|
||||
|
||||
const msb_pos = sizeof(T) * 8 - 1
|
||||
result = T(cast[Uint](n) shr msb_pos)
|
||||
|
||||
func msb*(n: IntImpl): auto =
|
||||
## Returns the most significant bit of an arbitrary precision integer.
|
||||
|
||||
result = msb most_significant_word(n)
|
||||
|
|
|
@ -7,34 +7,18 @@
|
|||
#
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ./datatypes, ./as_words, ./uint_comparison
|
||||
import ./datatypes, ./bithacks, ./as_words,
|
||||
./bithacks
|
||||
|
||||
func isZero*(n: SomeUnsignedInt): bool {.inline.} =
|
||||
func isZero*(n: SomeSignedInt): bool {.inline.} =
|
||||
n == 0
|
||||
|
||||
func isZero*(n: UintImpl): bool {.inline.} =
|
||||
func isZero*(n: IntImpl): bool {.inline.} =
|
||||
asWords(n, ignoreEndianness = true):
|
||||
if n != 0:
|
||||
return false
|
||||
return true
|
||||
|
||||
func `<`*(x, y: UintImpl): bool {.inline.}=
|
||||
# Lower comparison for multi-precision integers
|
||||
asWordsZip(x, y, ignoreEndianness = false):
|
||||
if x != y:
|
||||
return x < y
|
||||
return false # they're equal
|
||||
|
||||
func `==`*(x, y: UintImpl): bool {.inline.}=
|
||||
# Equal comparison for multi-precision integers
|
||||
asWordsZip(x, y, ignoreEndianness = true):
|
||||
if x != y:
|
||||
return false
|
||||
return true # they're equal
|
||||
|
||||
func `<=`*(x, y: UintImpl): bool {.inline.}=
|
||||
# Lower or equal comparison for multi-precision integers
|
||||
asWordsZip(x, y, ignoreEndianness = false):
|
||||
if x != y:
|
||||
return x < y
|
||||
return true # they're equal
|
||||
func isNegative*(n: IntImpl): bool {.inline.} =
|
||||
## Returns true if a number is negative:
|
||||
n.msb.bool
|
||||
|
|
Loading…
Reference in New Issue