Implement addition (including proper overflow behaviour)

This commit is contained in:
mratsim 2018-02-15 20:26:10 +01:00
parent 839123b2a4
commit fc6483d42e
4 changed files with 71 additions and 3 deletions

View File

@ -2,7 +2,9 @@
# Distributed under the MIT License (license terms are at http://opensource.org/licenses/MIT).
import ./uint_type,
./uint_init
./uint_init,
./uint_binary_ops
export uint_type,
uint_init
uint_init,
uint_binary_ops

19
src/uint_binary_ops.nim Normal file
View File

@ -0,0 +1,19 @@
# 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 `+=`*[T: MpUint](a: var T, b: T) {.noSideEffect.}=
type Base = type a.lo
let tmp = a.lo
a.lo += b.lo
a.hi += (a.lo < tmp).Base + b.hi
# Optimized assembly should contain adc instruction (add with carry)
# Clang on MacOS does with the -d:release switch.
proc `+`*[T: MpUint](a: T, b: T): T {.noSideEffect, noInit.}=
result = a
result += b

View File

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

46
tests/test_addition.nim Normal file
View File

@ -0,0 +1,46 @@
# 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 addition implementation":
test "In-place addition gives expected result":
var a = initMpUint(20182018, uint32)
let b = initMpUint(20172017, uint32)
a += b
check: cast[uint64](a) == 20182018'u64 + 20172017'u64
test "Addition gives expected result":
let a = initMpUint(20182018, uint32)
let b = initMpUint(20172017, uint32)
check: cast[uint64](a+b) == 20182018'u64 + 20172017'u64
test "When the low half overflows, it is properly carried":
# uint8 (low half) overflow at 255
let a = initMpUint(100, uint8)
let b = initMpUint(100, uint8)
check: cast[uint16](a+b) == 200
test "Full overflow is handled like native unsigned types":
# uint16 overflows after 65535
let a = initMpUint(100, uint8)
var z = initMpUint(0, uint8)
let o = initMpUint(36, uint8)
for _ in 0 ..< 655:
z += a
check: cast[uint16](z) == 65500
check: cast[uint16](z + o) == 0
z += a
check: cast[uint16](z) == 64
z += a
check: cast[uint16](z) == 164