2018-04-25 21:21:25 +02:00
|
|
|
# Stint
|
2018-03-26 11:46:24 +02: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.
|
|
|
|
|
2018-04-25 14:27:55 +02:00
|
|
|
import ./private/datatypes, macros
|
|
|
|
export StUint, UintImpl, uintImpl # TODO remove the need to export UintImpl and this macro
|
2018-05-06 22:29:08 +02:00
|
|
|
|
2018-03-26 11:46:24 +02:00
|
|
|
template make_unary(op, ResultTy): untyped =
|
2018-05-06 22:29:08 +02:00
|
|
|
func `op`*(x: StUint): ResultTy {.inline.} =
|
2018-04-25 12:52:00 +02:00
|
|
|
when ResultTy is StUint:
|
2018-03-26 11:46:24 +02:00
|
|
|
result.data = op(x.data)
|
|
|
|
else:
|
|
|
|
op(x.data)
|
|
|
|
export op
|
|
|
|
|
|
|
|
template make_binary(op, ResultTy): untyped =
|
2018-05-06 22:29:08 +02:00
|
|
|
func `op`*(x, y: StUint): ResultTy {.inline.} =
|
2018-04-25 12:52:00 +02:00
|
|
|
when ResultTy is StUint:
|
2018-03-26 11:46:24 +02:00
|
|
|
result.data = op(x.data, y.data)
|
|
|
|
else:
|
|
|
|
op(x.data, y.data)
|
|
|
|
export `op`
|
|
|
|
|
|
|
|
template make_binary_inplace(op): untyped =
|
2018-04-25 12:52:00 +02:00
|
|
|
func `op`*(x: var StUint, y: StUint) {.inline.} =
|
2018-03-26 11:46:24 +02:00
|
|
|
op(x.data, y.data)
|
|
|
|
export op
|
|
|
|
|
2018-04-21 12:12:05 +02:00
|
|
|
import ./private/uint_addsub
|
2018-03-26 11:46:24 +02:00
|
|
|
|
2018-04-25 12:52:00 +02:00
|
|
|
make_binary(`+`, StUint)
|
2018-03-26 11:46:24 +02:00
|
|
|
make_binary_inplace(`+=`)
|
2018-04-25 12:52:00 +02:00
|
|
|
make_binary(`-`, StUint)
|
2018-03-26 11:46:24 +02:00
|
|
|
make_binary_inplace(`-=`)
|
2018-04-21 12:12:05 +02:00
|
|
|
|
|
|
|
import ./private/uint_mul
|
2018-04-25 12:52:00 +02:00
|
|
|
make_binary(`*`, StUint)
|
2018-04-20 11:13:47 +02:00
|
|
|
|
2018-04-21 12:12:05 +02:00
|
|
|
import ./private/uint_div
|
2018-04-20 11:13:47 +02:00
|
|
|
|
2018-04-25 12:52:00 +02:00
|
|
|
make_binary(`div`, StUint)
|
|
|
|
make_binary(`mod`, StUint)
|
2018-05-06 22:29:08 +02:00
|
|
|
func divmod*(x, y: StUint): tuple[quot, rem: StUint] {.inline.} =
|
2018-03-26 11:46:24 +02:00
|
|
|
(result.quot.data, result.rem.data) = divmod(x.data, y.data)
|
|
|
|
|
|
|
|
import ./private/uint_comparison
|
|
|
|
|
|
|
|
make_binary(`<`, bool)
|
|
|
|
make_binary(`<=`, bool)
|
2018-04-21 12:12:05 +02:00
|
|
|
make_binary(`==`, bool)
|
2018-05-16 10:41:46 +02:00
|
|
|
make_unary(isZero, bool)
|
|
|
|
|
|
|
|
func isOdd(x: SomeUnsignedInt): bool {.inline.}=
|
|
|
|
# internal
|
|
|
|
bool(x and 1)
|
|
|
|
|
|
|
|
func isEven(x: SomeUnsignedInt): bool {.inline.}=
|
|
|
|
# internal
|
|
|
|
not x.isOdd
|
|
|
|
|
|
|
|
make_unary(isOdd, bool)
|
|
|
|
make_unary(isEven, bool)
|
2018-03-26 11:46:24 +02:00
|
|
|
|
|
|
|
import ./private/uint_bitwise_ops
|
|
|
|
|
2018-04-25 12:52:00 +02:00
|
|
|
make_unary(`not`, StUint)
|
|
|
|
make_binary(`or`, StUint)
|
|
|
|
make_binary(`and`, StUint)
|
|
|
|
make_binary(`xor`, StUint)
|
2018-05-14 19:02:39 +02:00
|
|
|
func `shr`*(x: StUint, y: SomeInteger): StUint {.inline.} =
|
2018-03-26 11:46:24 +02:00
|
|
|
result.data = x.data shr y
|
2018-05-14 19:02:39 +02:00
|
|
|
func `shl`*(x: StUint, y: SomeInteger): StUint {.inline.} =
|
2018-03-26 11:46:24 +02:00
|
|
|
result.data = x.data shl y
|
2018-05-06 22:19:00 +02:00
|
|
|
|
2018-05-06 22:24:51 +02:00
|
|
|
import ./private/uint_highlow
|
|
|
|
|
2018-05-06 22:19:00 +02:00
|
|
|
func high*[bits: static[int]](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.} =
|
|
|
|
result.data = high(type result.data)
|
|
|
|
|
|
|
|
func low*[bits: static[int]](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.} =
|
|
|
|
result.data = low(type result.data)
|
2018-05-06 23:02:50 +02:00
|
|
|
|
|
|
|
import ./private/bithacks
|
|
|
|
|
|
|
|
func countLeadingZeroBits*(x: StUint): int {.inline.} =
|
|
|
|
x.data.countLeadingZeroBits
|
2018-05-08 13:49:58 +02:00
|
|
|
|
|
|
|
import ./private/initialization
|
|
|
|
|
|
|
|
func zero*[bits: static[int]](T: typedesc[Stuint[bits] or Stint[bits]]): T {.inline.} =
|
|
|
|
discard
|
2018-05-14 19:02:39 +02:00
|
|
|
|
2018-06-16 18:54:40 +02:00
|
|
|
func one*[bits: static[int]](T: typedesc[Stuint[bits]]): T {.inline.} =
|
|
|
|
result.data = one(type result.data)
|
|
|
|
|
2018-05-14 19:02:39 +02:00
|
|
|
import ./private/uint_exp, math
|
|
|
|
|
|
|
|
func pow*(x: StUint, y: Natural): StUint {.inline.} =
|
|
|
|
when x.data is UintImpl:
|
|
|
|
result.data = x.data.pow(y)
|
|
|
|
else:
|
|
|
|
result.data = x.data ^ y
|
2018-05-14 19:44:39 +02:00
|
|
|
|
|
|
|
func pow*(x: StUint, y: StUint): StUint {.inline.} =
|
|
|
|
when x.data is UintImpl:
|
|
|
|
result.data = x.data.pow(y.data)
|
|
|
|
else:
|
|
|
|
result.data = x.data ^ y.data
|