2018-04-25 19:21:58 +00:00
|
|
|
# Stint
|
2018-03-26 09:46:24 +00:00
|
|
|
# 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.
|
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
import
|
|
|
|
# Status lib
|
|
|
|
stew/bitops2
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
when sizeof(int) == 8 and not defined(Stint32):
|
|
|
|
type Word* = uint64
|
2018-03-26 09:46:24 +00:00
|
|
|
else:
|
2020-06-12 16:37:02 +00:00
|
|
|
type Word* = uint32
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 17:23:03 +00:00
|
|
|
const WordBitWidth* = sizeof(Word) * 8
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
func wordsRequired*(bits: int): int {.compileTime.} =
|
|
|
|
## Compute the number of limbs required
|
|
|
|
## from the **announced** bit length
|
|
|
|
(bits + WordBitWidth - 1) div WordBitWidth
|
2018-04-21 10:12:05 +00:00
|
|
|
|
2018-03-26 09:46:24 +00:00
|
|
|
type
|
2020-06-12 17:01:05 +00:00
|
|
|
Limbs*[N: static int] = array[N, Word]
|
2018-03-26 09:46:24 +00:00
|
|
|
|
2018-04-25 10:52:00 +00:00
|
|
|
StUint*[bits: static[int]] = object
|
2020-06-12 16:37:02 +00:00
|
|
|
## Stack-based integer
|
|
|
|
## Unsigned
|
|
|
|
limbs*: Limbs[bits.wordsRequired]
|
2018-04-25 12:27:55 +00:00
|
|
|
|
|
|
|
StInt*[bits: static[int]] = object
|
2020-06-12 16:37:02 +00:00
|
|
|
## Stack-based integer
|
|
|
|
## Signed
|
|
|
|
limbs*: Limbs[bits.wordsRequired]
|
|
|
|
|
|
|
|
Carry* = uint8 # distinct range[0'u8 .. 1]
|
|
|
|
Borrow* = uint8 # distinct range[0'u8 .. 1]
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
const GCC_Compatible* = defined(gcc) or defined(clang) or defined(llvm_gcc)
|
|
|
|
const X86* = defined(amd64) or defined(i386)
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
when sizeof(int) == 8 and GCC_Compatible:
|
|
|
|
type
|
|
|
|
uint128*{.importc: "unsigned __int128".} = object
|
2022-04-07 07:52:36 +00:00
|
|
|
|
2019-10-08 13:11:08 +00:00
|
|
|
template leastSignificantWord*(num: SomeInteger): auto =
|
|
|
|
num
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
func leastSignificantWord*(limbs: Limbs): auto {.inline.} =
|
|
|
|
when cpuEndian == littleEndian:
|
|
|
|
limbs[0]
|
2018-10-25 10:58:40 +00:00
|
|
|
else:
|
2020-06-12 16:37:02 +00:00
|
|
|
limbs[^1]
|
2018-10-25 10:58:40 +00:00
|
|
|
|
2020-06-12 16:37:02 +00:00
|
|
|
func mostSignificantWord*(limbs: Limbs): auto {.inline.} =
|
|
|
|
when cpuEndian == littleEndian:
|
|
|
|
limbs[^1]
|
2018-10-25 10:58:40 +00:00
|
|
|
else:
|
2020-06-12 16:37:02 +00:00
|
|
|
limbs[0]
|
2020-06-12 17:01:05 +00:00
|
|
|
|
|
|
|
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:
|
2020-06-12 17:59:03 +00:00
|
|
|
for i in 0 ..< aLimbs.len:
|
2020-06-12 17:01:05 +00:00
|
|
|
yield (aLimbs[i], bLimbs[i])
|
|
|
|
else:
|
2020-06-12 17:59:03 +00:00
|
|
|
for i in countdown(aLimbs.len-1, 0):
|
2020-06-12 17:01:05 +00:00
|
|
|
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:
|
2020-06-12 17:59:03 +00:00
|
|
|
for i in 0 ..< aLimbs.len:
|
2020-06-12 17:01:05 +00:00
|
|
|
yield (aLimbs[i], bLimbs[i])
|
|
|
|
else:
|
2020-06-12 17:59:03 +00:00
|
|
|
for i in countdown(aLimbs.len-1, 0):
|
2020-06-12 17:01:05 +00:00
|
|
|
yield (aLimbs[i], bLimbs[i])
|
2020-06-12 17:23:03 +00:00
|
|
|
|
|
|
|
iterator leastToMostSig*(cLimbs: var Limbs, aLimbs: Limbs, bLimbs: Limbs): (var Word, Word, Word) =
|
|
|
|
## Iterate from least to most significant word
|
|
|
|
when cpuEndian == littleEndian:
|
2020-06-12 17:59:03 +00:00
|
|
|
for i in 0 ..< aLimbs.len:
|
2020-06-12 17:23:03 +00:00
|
|
|
yield (cLimbs[i], aLimbs[i], bLimbs[i])
|
|
|
|
else:
|
2020-06-12 17:59:03 +00:00
|
|
|
for i in countdown(aLimbs.len-1, 0):
|
2020-06-12 17:23:03 +00:00
|
|
|
yield (cLimbs[i], aLimbs[i], bLimbs[i])
|