Add basic data structure, initialization and endianess test

This commit is contained in:
mratsim 2018-02-15 15:01:08 +01:00
parent 364e11cf28
commit 6f77899709
7 changed files with 109 additions and 1 deletions

View File

@ -8,3 +8,16 @@ srcDir = "src"
### Dependencies ### Dependencies
requires "nim >= 0.17.2" requires "nim >= 0.17.2"
proc test(name: string, lang: string = "cpp") =
if not dirExists "build":
mkDir "build"
if not dirExists "nimcache":
mkDir "nimcache"
--run
--nimcache: "nimcache"
switch("out", ("./build/" & name))
setCommand lang, "tests/" & name & ".nim"
task test, "Run all tests":
test "all_tests"

8
src/mpint.nim Normal file
View File

@ -0,0 +1,8 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
import ./uint_type,
./uint_init
export uint_type,
uint_init

24
src/private/utils.nim Normal file
View File

@ -0,0 +1,24 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
import ../uint_type
proc bit_length*[T: BaseUint](n: T): int {.noSideEffect.}=
## Calculates how many bits are necessary to represent the number
result = 1
var y: T = n shr 1
while y > 0.T:
y = y shr 1
inc(result)
proc bit_length*[T: Natural](n: T): int {.noSideEffect.}=
## Calculates how many bits are necessary to represent the number
#
# For some reason using "BaseUint or Natural" directly makes Nim compiler
# throw a type mismatch
result = 1
var y: T = n shr 1
while y > 0.T:
y = y shr 1
inc(result)

29
src/uint_init.nim Normal file
View File

@ -0,0 +1,29 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
import typetraits
import private/utils,
uint_type
proc initMpUint*[T: BaseUint; U: BaseUInt](n: T, base_type: typedesc[U]): MpUint[U] {.noSideEffect.} =
let len = n.bit_length
const sizeU_bits = sizeof(U) * 8
when not (T is type result):
if len >= 2 * sizeU_bits:
# Todo print n
raise newException(ValueError, "Input cannot be stored in a multi-precision integer of base " & $T.name &
"\nIt requires at least " & $len & " bits of precision")
elif len < sizeU_bits:
result.lo = n.U # TODO: converter for MpInts
else:
raise newException(ValueError, "Unsupported at the moment: are you trying to build MpUint[uint32] from an uint64?")
else:
n
proc u128*[T: BaseUInt](n: T): UInt128 {.noSideEffect, inline.}=
initMpUint(n, uint64)
proc u256*[T: BaseUInt](n: T): UInt256 {.noSideEffect, inline.}=
initMpUint(n, UInt256)

16
src/uint_type.nim Normal file
View File

@ -0,0 +1,16 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
type
MpUint*{.packed.}[BaseUint] = object
when system.cpuEndian == littleEndian:
lo*, hi*: BaseUint
else:
hi*, lo*: BaseUint
BaseUint* = SomeUnsignedInt or MpUint
UInt128* = MpUint[uint64]
UInt256* = MpUint[UInt128]

4
tests/all_tests.nim Normal file
View File

@ -0,0 +1,4 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).$
import test_endianness

14
tests/test_endianness.nim Normal file
View File

@ -0,0 +1,14 @@
# Copyright (c) 2018 Status Research & Development GmbH
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
import ../src/mpint, unittest
suite "Testing byte representation":
test "Byte representation conforms to the platform endianness":
let a = initMpUint(20182018, uint32)
let b = 20182018'u64
type AsBytes = array[8, byte]
check cast[AsBytes](a) == cast[AsBytes](b)