diff --git a/stint/io.nim b/stint/io.nim index 17b9482..49a96f2 100644 --- a/stint/io.nim +++ b/stint/io.nim @@ -9,17 +9,12 @@ import # Standard library - typetraits, algorithm, hashes, - # Status libraries - # stew/byteutils, + std/[typetraits, algorithm, hashes], # Internal ./private/datatypes, - # ./private/int_negabs, - # ./private/compiletime_helpers, - # ./intops, ./uintops, ./endians2 -from stew/byteutils import toHex # Why are we exporting readHexChar in byteutils? +from stew/byteutils import toHex template leastSignificantWord*(a: SomeBigInteger): Word = a.limbs[0] @@ -33,20 +28,10 @@ template signedWordType*(_: type SomeBigInteger): type = template wordType*(_: type SomeBigInteger): type = Word -template static_check_size(T: typedesc[SomeInteger], bits: static[int]) = - # To avoid a costly runtime check, we refuse storing into StUint types smaller - # than the input type. - - static: doAssert sizeof(T) * 8 <= bits, "Input type (" & $T & - ") cannot be stored in a multi-precision " & - $bits & "-bit integer." & - "\nUse a smaller input type instead. This is a compile-time check" & - " to avoid a costly run-time bit_length check at each StUint initialization." - func stuint*[T: SomeInteger](n: T, bits: static[int]): StUint[bits] {.inline.}= ## Converts an integer to an arbitrary precision integer. when sizeof(n) > sizeof(Word): - result.limbs[0] = Word(n and Word.high) + result.limbs[0] = Word(n and Word.high.T) result.limbs[1] = Word(n shr WordBitWidth) else: result.limbs[0] = Word(n) @@ -57,7 +42,11 @@ func stint*[T: SomeInteger](n: T, bits: static[int]): StInt[bits] {.inline.}= result.imp = stuint(n, bits) else: if n < 0: - result.imp = stuint(-n, bits) + if n == low(T): + # special case, bug #92 workaround + result.imp = stuint(high(T), bits) + stuint(1, bits) + else: + result.imp = stuint(-n, bits) result.negate else: result.imp = stuint(n, bits) diff --git a/tests/test_int_addsub.nim b/tests/test_int_addsub.nim index b1c51e2..4fdb5c4 100644 --- a/tests/test_int_addsub.nim +++ b/tests/test_int_addsub.nim @@ -90,12 +90,15 @@ template testAddSub(chk, tst: untyped) = chkNegation(chk, 127, -127, 128) chkNegation(chk, 32768, -32768, 128) chkNegation(chk, 32767, -32767, 128) - # With Nim 1.6, it seems like https://github.com/status-im/nim-stint/issues/92 - # can now happen on 32-bit platforms. - #when (NimMajor,NimMinor,NimPatch) < (1,6,0): chkNegation(chk, 2147483648, -2147483648, 128) chkNegation(chk, 2147483647, -2147483647, 128) - # chkNegation(chk, 9223372036854775808, -9223372036854775808, 128) # TODO: bug #92 + + let x = int64.high.i128 + chk -x == -9223372036854775807'i64.i128 + + let y = int64.low.i128 + let z = int64.high.i128 + 1.i128 + chk -y == z tst "absolute integer": chkAbs(chk, 0, 0, 128)