Implement comparison

This commit is contained in:
Mamy André-Ratsimbazafy 2020-06-12 19:01:05 +02:00 committed by jangko
parent de87739635
commit 36cc2b2e02
No known key found for this signature in database
GPG Key ID: 31702AE10541E6B9
2 changed files with 62 additions and 16 deletions

View File

@ -16,7 +16,7 @@ when sizeof(int) == 8 and not defined(Stint32):
else:
type Word* = uint32
type Word* = uint32
const WordBitWidth = sizeof(Word) * 8
func wordsRequired*(bits: int): int {.compileTime.} =
## Compute the number of limbs required
@ -24,7 +24,7 @@ func wordsRequired*(bits: int): int {.compileTime.} =
(bits + WordBitWidth - 1) div WordBitWidth
type
Limbs*[N: static int] = array[N, BaseUint]
Limbs*[N: static int] = array[N, Word]
StUint*[bits: static[int]] = object
## Stack-based integer
@ -60,3 +60,39 @@ func mostSignificantWord*(limbs: Limbs): auto {.inline.} =
limbs[^1]
else:
limbs[0]
iterator leastToMostSig*(limbs: Limbs): Word =
## Iterate from least to most significant word
when cpuEndian == littleEndian:
for i in 0 ..< limbs.len:
yield limbs[i]
else:
for i in countdown(limbs.len-1, 0):
yield limbs[i]
iterator leastToMostSig*(limbs: var Limbs): var Word =
## Iterate from least to most significant word
when cpuEndian == littleEndian:
for i in 0 ..< limbs.len:
yield limbs[i]
else:
for i in countdown(limbs.len-1, 0):
yield limbs[i]
iterator leastToMostSig*(aLimbs, bLimbs: Limbs): (Word, Word) =
## Iterate from least to most significant word
when cpuEndian == littleEndian:
for i in 0 ..< limbs.len:
yield (aLimbs[i], bLimbs[i])
else:
for i in countdown(limbs.len-1, 0):
yield (aLimbs[i], bLimbs[i])
iterator leastToMostSig*(aLimbs: var Limbs, bLimbs: Limbs): (var Word, Word) =
## Iterate from least to most significant word
when cpuEndian == littleEndian:
for i in 0 ..< limbs.len:
yield (aLimbs[i], bLimbs[i])
else:
for i in countdown(limbs.len-1, 0):
yield (aLimbs[i], bLimbs[i])

View File

@ -7,36 +7,46 @@
#
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./datatypes
import
./datatypes,
./primitives/addcarry_subborrow
func isZero*(n: SomeUnsignedInt): bool {.inline.} =
n == 0
func isZero*(n: UintImpl): bool {.inline.} =
n.hi.isZero and n.lo.isZero
func isZero*(limbs: Limbs): bool {.inline.} =
for word in limbs:
if not word.isZero():
return false
return true
func `<`*(x, y: UintImpl): bool {.inline.}=
func `<`*(x, y: Limbs): bool {.inline.}=
# Lower comparison for multi-precision integers
x.hi < y.hi or
(x.hi == y.hi and x.lo < y.lo)
var diff: Word
var borrow: Borrow
for wx, wy in leastToMostSig(x, y):
subB(borrow, diff, wx, wy, borrow)
return bool(borrow)
func `==`*(x, y: UintImpl): bool {.inline.}=
func `==`*(x, y: Limbs): bool {.inline.}=
# Equal comparison for multi-precision integers
x.hi == y.hi and x.lo == y.lo
for wx, wy in leastToMostSig(x, y):
if wx != wy:
return false
return true
func `<=`*(x, y: UintImpl): bool {.inline.}=
func `<=`*(x, y: Limbs): bool {.inline.}=
# Lower or equal comparison for multi-precision integers
x.hi < y.hi or
(x.hi == y.hi and x.lo <= y.lo)
not(y < x)
func isEven*(x: SomeUnsignedInt): bool {.inline.} =
(x and 1) == 0
func isEven*(x: UintImpl): bool {.inline.}=
x.lo.isEven
func isEven*(x: Limbs): bool {.inline.}=
x.leastSignificantWord.isEven
func isOdd*(x: SomeUnsignedInt): bool {.inline.} =
not x.isEven
func isOdd*(x: UintImpl): bool {.inline.}=
func isOdd*(x: Limbs): bool {.inline.}=
not x.isEven