mirror of
https://github.com/status-im/nim-stint.git
synced 2025-02-16 08:57:18 +00:00
Implement multiprecision addition / substraction
This commit is contained in:
parent
cbbffe4e9c
commit
206ffa92cf
@ -82,26 +82,26 @@ iterator leastToMostSig*(limbs: var Limbs): var Word =
|
||||
iterator leastToMostSig*(aLimbs, bLimbs: Limbs): (Word, Word) =
|
||||
## Iterate from least to most significant word
|
||||
when cpuEndian == littleEndian:
|
||||
for i in 0 ..< limbs.len:
|
||||
for i in 0 ..< aLimbs.len:
|
||||
yield (aLimbs[i], bLimbs[i])
|
||||
else:
|
||||
for i in countdown(limbs.len-1, 0):
|
||||
for i in countdown(aLimbs.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:
|
||||
for i in 0 ..< aLimbs.len:
|
||||
yield (aLimbs[i], bLimbs[i])
|
||||
else:
|
||||
for i in countdown(limbs.len-1, 0):
|
||||
for i in countdown(aLimbs.len-1, 0):
|
||||
yield (aLimbs[i], bLimbs[i])
|
||||
|
||||
iterator leastToMostSig*(cLimbs: var Limbs, aLimbs: Limbs, bLimbs: Limbs): (var Word, Word, Word) =
|
||||
## Iterate from least to most significant word
|
||||
when cpuEndian == littleEndian:
|
||||
for i in 0 ..< limbs.len:
|
||||
for i in 0 ..< aLimbs.len:
|
||||
yield (cLimbs[i], aLimbs[i], bLimbs[i])
|
||||
else:
|
||||
for i in countdown(limbs.len-1, 0):
|
||||
for i in countdown(aLimbs.len-1, 0):
|
||||
yield (cLimbs[i], aLimbs[i], bLimbs[i])
|
||||
|
@ -7,36 +7,40 @@
|
||||
#
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
import ./conversion, ./initialization,
|
||||
./datatypes,
|
||||
./uint_comparison,
|
||||
./uint_bitwise_ops
|
||||
import
|
||||
./datatypes, ./uint_comparison, ./uint_bitwise_ops,
|
||||
./primitives/addcarry_subborrow
|
||||
|
||||
# ############ Addition & Substraction ############ #
|
||||
{.push raises: [], inline, noInit, gcsafe.}
|
||||
|
||||
func `+`*(x, y: UintImpl): UintImpl {.inline.}
|
||||
# Forward declaration
|
||||
|
||||
func `+=`*(x: var UintImpl, y: UintImpl) {.inline.}=
|
||||
## In-place addition for multi-precision unsigned int
|
||||
type SubTy = type x.lo
|
||||
x.lo += y.lo
|
||||
x.hi += (x.lo < y.lo).toSubtype(SubTy) + y.hi # This helps the compiler produce ADC (add with carry)
|
||||
|
||||
func `+`*(x, y: UintImpl): UintImpl {.inline.}=
|
||||
func `+`*(x, y: Limbs): Limbs =
|
||||
# Addition for multi-precision unsigned int
|
||||
result = x
|
||||
result += y
|
||||
var carry = Carry(0)
|
||||
for wr, wx, wy in leastToMostSig(result, x, y):
|
||||
addC(carry, wr, wx, wy, carry)
|
||||
|
||||
func `-`*(x, y: UintImpl): UintImpl {.inline.}=
|
||||
func `+=`*(x: var Limbs, y: Limbs) =
|
||||
## In-place addition for multi-precision unsigned int
|
||||
var carry = Carry(0)
|
||||
for wx, wy in leastToMostSig(x, y):
|
||||
addC(carry, wx, wx, wy, carry)
|
||||
|
||||
func `-`*(x, y: Limbs): Limbs =
|
||||
# Substraction for multi-precision unsigned int
|
||||
type SubTy = type x.lo
|
||||
result.lo = x.lo - y.lo
|
||||
result.hi = x.hi - y.hi - (x.lo < y.lo).toSubtype(SubTy) # This might (?) help the compiler produce SBB (sub with borrow)
|
||||
var borrow = Borrow(0)
|
||||
for wr, wx, wy in leastToMostSig(result, x, y):
|
||||
subB(borrow, wr, wx, wy, borrow)
|
||||
|
||||
func `-=`*(x: var UintImpl, y: UintImpl) {.inline.}=
|
||||
func `-=`*(x: var Limbs, y: Limbs) =
|
||||
## In-place substraction for multi-precision unsigned int
|
||||
x = x - y
|
||||
var borrow = Borrow(0)
|
||||
for wx, wy in leastToMostSig(x, y):
|
||||
subB(borrow, wx, wx, wy, borrow)
|
||||
|
||||
func inc*(x: var UintImpl){.inline.}=
|
||||
x += one(type x)
|
||||
func inc*(x: var Limbs, w: SomeUnsignedInt = 1) =
|
||||
var carry = Carry(0)
|
||||
when cpuEndian == littleEndian:
|
||||
addC(carry, x[0], x[0], w, carry)
|
||||
for i in 1 ..< x.len:
|
||||
addC(carry, x[i], x[i], 0, carry)
|
||||
|
@ -9,27 +9,29 @@
|
||||
|
||||
import ./datatypes
|
||||
|
||||
func `not`*(x: Limbs): Limbs {.inline.}=
|
||||
{.push raises: [], inline, noInit, gcsafe.}
|
||||
|
||||
func `not`*(x: Limbs): Limbs =
|
||||
## Bitwise complement of unsigned integer x
|
||||
for wr, wx in leastToMostSig(result, x):
|
||||
wr = not wx
|
||||
|
||||
func `or`*(x, y: Limbs): Limbs {.inline.}=
|
||||
func `or`*(x, y: Limbs): Limbs =
|
||||
## `Bitwise or` of numbers x and y
|
||||
for wr, wx, wy in leastToMostSig(result, x, y):
|
||||
wr = wx or wy
|
||||
|
||||
func `and`*(x, y: Limbs): Limbs {.inline.}=
|
||||
func `and`*(x, y: Limbs): Limbs =
|
||||
## `Bitwise and` of numbers x and y
|
||||
for wr, wx, wy in leastToMostSig(result, x, y):
|
||||
wr = wx and wy
|
||||
|
||||
func `xor`*(x, y: Limbs): Limbs {.inline.}=
|
||||
func `xor`*(x, y: Limbs): Limbs =
|
||||
## `Bitwise xor` of numbers x and y
|
||||
for wr, wx, wy in leastToMostSig(result, x, y):
|
||||
wr = wx xor wy
|
||||
|
||||
func `shr`*(x: Limbs, k: SomeInteger): Limbs {.inline.} =
|
||||
func `shr`*(x: Limbs, k: SomeInteger): Limbs =
|
||||
## Shift right by k.
|
||||
##
|
||||
## k MUST be less than the base word size (2^32 or 2^64)
|
||||
@ -46,7 +48,7 @@ func `shr`*(x: Limbs, k: SomeInteger): Limbs {.inline.} =
|
||||
result[i] = (x[i] shr k) or (x[i-1] shl (WordBitWidth - k))
|
||||
result[0] = x[0] shr k
|
||||
|
||||
func `shl`*(x: Limbs, k: SomeInteger): Limbs {.inline.}=
|
||||
func `shl`*(x: Limbs, k: SomeInteger): Limbs =
|
||||
## Compute the `shift left` operation of x and k
|
||||
when cpuEndian == littleEndian:
|
||||
result[0] = x[0] shl k
|
||||
|
@ -11,16 +11,18 @@ import
|
||||
./datatypes,
|
||||
./primitives/addcarry_subborrow
|
||||
|
||||
func isZero*(n: SomeUnsignedInt): bool {.inline.} =
|
||||
{.push raises: [], inline, noInit, gcsafe.}
|
||||
|
||||
func isZero*(n: SomeUnsignedInt): bool =
|
||||
n == 0
|
||||
|
||||
func isZero*(limbs: Limbs): bool {.inline.} =
|
||||
func isZero*(limbs: Limbs): bool =
|
||||
for word in limbs:
|
||||
if not word.isZero():
|
||||
return false
|
||||
return true
|
||||
|
||||
func `<`*(x, y: Limbs): bool {.inline.}=
|
||||
func `<`*(x, y: Limbs): bool =
|
||||
# Lower comparison for multi-precision integers
|
||||
var diff: Word
|
||||
var borrow: Borrow
|
||||
@ -28,25 +30,25 @@ func `<`*(x, y: Limbs): bool {.inline.}=
|
||||
subB(borrow, diff, wx, wy, borrow)
|
||||
return bool(borrow)
|
||||
|
||||
func `==`*(x, y: Limbs): bool {.inline.}=
|
||||
func `==`*(x, y: Limbs): bool =
|
||||
# Equal comparison for multi-precision integers
|
||||
for wx, wy in leastToMostSig(x, y):
|
||||
if wx != wy:
|
||||
return false
|
||||
return true
|
||||
|
||||
func `<=`*(x, y: Limbs): bool {.inline.}=
|
||||
func `<=`*(x, y: Limbs): bool =
|
||||
# Lower or equal comparison for multi-precision integers
|
||||
not(y < x)
|
||||
|
||||
func isEven*(x: SomeUnsignedInt): bool {.inline.} =
|
||||
func isEven*(x: SomeUnsignedInt): bool =
|
||||
(x and 1) == 0
|
||||
|
||||
func isEven*(x: Limbs): bool {.inline.}=
|
||||
func isEven*(x: Limbs): bool =
|
||||
x.leastSignificantWord.isEven
|
||||
|
||||
func isOdd*(x: SomeUnsignedInt): bool {.inline.} =
|
||||
func isOdd*(x: SomeUnsignedInt): bool =
|
||||
not x.isEven
|
||||
|
||||
func isOdd*(x: Limbs): bool {.inline.}=
|
||||
func isOdd*(x: Limbs): bool =
|
||||
not x.isEven
|
||||
|
Loading…
x
Reference in New Issue
Block a user