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:
|
else:
|
||||||
error "Unreachable path reached"
|
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 =
|
proc replaceNodes(ast: NimNode, replacing: NimNode, to_replace: NimNode): NimNode =
|
||||||
# Args:
|
# Args:
|
||||||
# - The full syntax tree
|
# - The full syntax tree
|
||||||
|
@ -53,13 +75,6 @@ proc replaceNodes(ast: NimNode, replacing: NimNode, to_replace: NimNode): NimNod
|
||||||
return rTree
|
return rTree
|
||||||
result = inspect(ast)
|
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 =
|
macro asWords*[T](n: UintImpl[T], ignoreEndianness: static[bool], loopBody: untyped): untyped =
|
||||||
## Iterates over n, as an array of words.
|
## Iterates over n, as an array of words.
|
||||||
## Input:
|
## Input:
|
||||||
|
|
|
@ -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, stdlib_bitops
|
import ./datatypes, stdlib_bitops, as_words
|
||||||
export stdlib_bitops
|
export stdlib_bitops
|
||||||
|
|
||||||
# We reuse bitops from Nim standard lib, and expand it for multi-precision int.
|
# 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:
|
result = if hi_clz == maxHalfRepr:
|
||||||
n.lo.countLeadingZeroBits + maxHalfRepr
|
n.lo.countLeadingZeroBits + maxHalfRepr
|
||||||
else: hi_clz
|
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.
|
# 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
|
n == 0
|
||||||
|
|
||||||
func isZero*(n: UintImpl): bool {.inline.} =
|
func isZero*(n: IntImpl): bool {.inline.} =
|
||||||
asWords(n, ignoreEndianness = true):
|
asWords(n, ignoreEndianness = true):
|
||||||
if n != 0:
|
if n != 0:
|
||||||
return false
|
return false
|
||||||
return true
|
return true
|
||||||
|
|
||||||
func `<`*(x, y: UintImpl): bool {.inline.}=
|
func isNegative*(n: IntImpl): bool {.inline.} =
|
||||||
# Lower comparison for multi-precision integers
|
## Returns true if a number is negative:
|
||||||
asWordsZip(x, y, ignoreEndianness = false):
|
n.msb.bool
|
||||||
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
|
|
||||||
|
|
Loading…
Reference in New Issue