Add sub, proper negate bound checking, high and low, most significant word mutation

This commit is contained in:
mratsim 2018-04-25 19:51:14 +02:00
parent 8b412b879d
commit 0296b5eca9
4 changed files with 82 additions and 13 deletions

View File

@ -43,7 +43,7 @@ macro most_significant_word*(x: IntImpl): untyped =
let optim_type = optimInt(x)
if optim_type.isInt:
result = quote do:
cast[`optim_type`](`x`)
(cast[ptr `optim_type`](`x`.unsafeAddr))[]
else:
when system.cpuEndian == littleEndian:
let size = getSize(x)
@ -51,7 +51,7 @@ macro most_significant_word*(x: IntImpl): untyped =
else:
let msw_pos = 0
result = quote do:
cast[`optim_type`](`x`)[`msw_pos`]
(cast[ptr `optim_type`](`x`)[`msw_pos`.unsafeAddr])[]
macro asSignedWordsZip*[T](
x, y: IntImpl[T],

View File

@ -7,20 +7,43 @@
#
# at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./datatypes, ./int_bitwise_ops, ./initialization
import ./datatypes, ./int_bitwise_ops,
./initialization, ./as_signed_words, ./int_highlow
func `+=`*(x: var IntImpl, y: IntImpl) {.inline.}=
## In-place addition for multi-precision signed int
type SubTy = type x.lo
x.lo += y.lo
x.hi += (x.lo < y.lo).toSubtype(SubTy) + y.hi
func `+`*(x, y: UintImpl): UintImpl {.noInit, inline.}=
func `+`*(x, y: IntImpl): IntImpl {.noInit, inline.}=
# Addition for multi-precision signed int
result = x
result += y
type SubTy = type x.lo
result.lo = x.lo + y.lo
result.hi = (x.lo < y.lo).toSubtype(SubTy) + x.hi + y.hi
when compileOption("boundChecks"):
if unlikely(
(result.most_significant_word xor a.most_significant_word >= 0) or
(result.most_significant_word xor b.most_significant_word >= 0)
):
raise newException(OverflowError, "Addition overflow")
func `-`*[T: IntImpl](x: T): T {.noInit, inline.}=
result = not x
result += one(T)
when compileOption("boundChecks"):
if unlikely(x == low(T)):
raise newException(OverflowError, "The lowest negative number cannot be negated")
func `-`*(x, y: IntImpl): IntImpl {.noInit, inline.}=
# Substraction for multi-precision signed int
type SubTy = type x.lo
result.lo = x.lo - y.lo
result.hi = x.hi - y.hi - (x.lo < y.lo).toSubtype(SubTy)
when compileOption("boundChecks"):
if unlikely(
(result.most_significant_word xor a.most_significant_word >= 0) or
(result.most_significant_word xor (not b).most_significant_word >= 0)
):
raise newException(OverflowError, "Substraction underflow")
func `-=`*(x: var IntImpl, y: IntImpl) {.inline.}=
## In-place substraction for multi-precision signed int
x = x - y

View File

@ -0,0 +1,30 @@
# Mpint
# 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.
import ./datatypes, ./as_signed_words
func low*(T: typedesc[UintImpl]): T {.inline.}=
# The lowest signed int has representation
# 0b1000_0000_0000_0000 ....
# so we only have to set the most significant bit.
type Msw = type result.most_significant_word
when Msw is uint64:
type U = int64
else:
type U = Msw
result.most_significant_word = low(U)
func high*(T: typedesc[UintImpl]): T {.inline, noInit.}=
# The lowest signed int has representation
# 0b0111_1111_1111_1111 ....
# so we only have to unset the most significant bit.
not low(T)

View File

@ -0,0 +1,16 @@
# Mpint
# 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.
import ./datatypes, ./initialization
func low*(T: typedesc[UintImpl]): T {.inline, noInit.}=
zero(T)
func high*(T: typedesc[UintImpl]): T {.inline, noInit.}=
not zero(T)