stew updates

* simplify int api (fixes #68)
* implement endians api
* implement some more bitops
This commit is contained in:
Jacek Sieka 2019-07-09 15:59:24 +02:00
parent 33562884a1
commit 8bf328b4f0
No known key found for this signature in database
GPG Key ID: A1B09461ABB656B8
18 changed files with 360 additions and 257 deletions

View File

@ -7,8 +7,8 @@
# #
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
import stint/[uint_public, int_public, io, modular_arithmetic, literals_stint] import stint/[bitops2, endians2, intops, io, modular_arithmetic, literals_stint]
export uint_public, int_public, io, modular_arithmetic, literals_stint export bitops2, endians2, intops, io, modular_arithmetic, literals_stint
type type
Int128* = Stint[128] Int128* = Stint[128]

16
stint/bitops2.nim Normal file
View File

@ -0,0 +1,16 @@
# Stint
# 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 ./private/[bitops2_priv, datatypes]
func countOnes*(x: StUint): int {.inline.} = countOnes(x.data)
func parity*(x: StUint): int {.inline.} = parity(x.data)
func firstOne*(x: StUint): int {.inline.} = firstOne(x.data)
func leadingZeros*(x: StUint): int {.inline.} = leadingZeros(x.data)
func trailingZeros*(x: StUint): int {.inline.} = trailingZeros(x.data)

105
stint/endians2.nim Normal file
View File

@ -0,0 +1,105 @@
# Stint
# 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 private/[bitops2_priv, endians2_priv, datatypes]
import stew/endians2
export endians2
func swapBytes*(x: StUint): StUint {.inline.} = StUint(data: swapBytes(x.data))
func toBytes*[bits: static int](x: StUint[bits], endian: Endianness = system.cpuEndian):
array[bits div 8, byte] {.inline.} =
toBytes(x.data, endian)
func toBytesLE*[bits: static int](x: StUint[bits]):
array[bits div 8, byte] {.inline.} =
toBytes(x, littleEndian)
func toBytesBE*[bits: static int](x: StUint[bits]):
array[bits div 8, byte] {.inline.} =
toBytes(x, bigEndian)
func fromBytes*[bits: static int](
T: typedesc[StUint[bits]],
x: array[bits div 8, byte],
endian: Endianness = system.cpuEndian): T {.inline, noinit.} =
# TODO compile-time version
copyMem(addr result, unsafeAddr x[0], bits div 8)
if endian != system.cpuEndian:
result = swapBytes(result)
func fromBytes*[bits: static int](
T: typedesc[StUint[bits]],
x: openArray[byte],
endian: Endianness = system.cpuEndian): T {.inline.} =
# TODO fromBytesBE in io.nim handles this better, merge the two!
var tmp: array[bits div 8, byte]
if x.len < tmp.len:
let offset = if endian == bigEndian: tmp.len - x.len else: 0
for i in 0..<x.len: # Loop since vm can't copymem
tmp[i + offset] = x[i]
else:
for i in 0..<tmp.len: # Loop since vm can't copymem
tmp[i] = x[i]
fromBytes(T, tmp, endian)
func fromBytesBE*[bits: static int](
T: typedesc[StUint[bits]],
x: array[bits div 8, byte]): T {.inline.} =
## Read big endian bytes and convert to an integer. By default, native
## endianess is used which is not
## portable!
fromBytes(T, x, bigEndian)
func fromBytesBE*[bits: static int](
T: typedesc[StUint[bits]],
x: openArray[byte]): T {.inline.} =
## Read big endian bytes and convert to an integer. At runtime, v must contain
## at least sizeof(T) bytes. By default, native endianess is used which is not
## portable!
fromBytes(T, x, bigEndian)
func toBE*[bits: static int](x: StUint[bits]): StUint[bits] {.inline.} =
## Convert a native endian value to big endian. Consider toBytesBE instead
## which may prevent some confusion.
if cpuEndian == bigEndian: x
else: x.swapBytes
func fromBE*[bits: static int](x: StUint[bits]): StUint[bits] {.inline.} =
## Read a big endian value and return the corresponding native endian
# there's no difference between this and toBE, except when reading the code
toBE(x)
func fromBytesLE*[bits: static int](
T: typedesc[StUint[bits]],
x: array[bits div 8, byte]): StUint[bits] {.inline.} =
## Read little endian bytes and convert to an integer. By default, native
## endianess is used which is not portable!
fromBytes(T, x, littleEndian)
func fromBytesLE*[bits: static int](
T: typedesc[StUint[bits]],
x: openArray[byte]): StUint[bits] {.inline.} =
## Read little endian bytes and convert to an integer. At runtime, v must
## contain at least sizeof(T) bytes. By default, native endianess is used
## which is not portable!
fromBytes(T, x, littleEndian)
func toLE*[bits: static int](x: StUint[bits]): StUint[bits] {.inline.} =
## Convert a native endian value to little endian. Consider toBytesLE instead
## which may prevent some confusion.
if cpuEndian == littleEndian: x
else: x.swapBytes
func fromLE*[bits: static int](x: StUint[bits]): StUint[bits] {.inline.} =
## Read a little endian value and return the corresponding native endian
# there's no difference between this and toLE, except when reading the code
toLE(x)

View File

@ -1,94 +0,0 @@
# Stint
# 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 ./private/datatypes
export StInt
export IntImpl, intImpl, bitsof # TODO remove the need to export these
template make_unary(op, ResultTy): untyped =
func `op`*(x: Stint): ResultTy {.inline.} =
when ResultTy is Stint:
result.data = op(x.data)
else:
op(x.data)
export op
template make_binary(op, ResultTy): untyped =
func `op`*(x, y: Stint): ResultTy {.inline.} =
when ResultTy is Stint:
result.data = op(x.data, y.data)
else:
op(x.data, y.data)
export `op`
template make_binary_inplace(op): untyped =
func `op`*(x: var Stint, y: Stint) {.inline.} =
op(x.data, y.data)
export op
import ./private/int_addsub
make_binary(`+`, Stint)
make_binary_inplace(`+=`)
make_binary(`-`, Stint)
make_binary_inplace(`-=`)
import ./private/int_negabs
make_unary(`-`, Stint)
make_unary(abs, Stint)
import ./private/int_mul
make_binary(`*`, Stint)
import ./private/int_div
make_binary(`div`, Stint)
make_binary(`mod`, Stint)
func divmod*(x, y: Stint): tuple[quot, rem: Stint] {.inline.} =
(result.quot.data, result.rem.data) = divmod(x.data, y.data)
import ./private/int_comparison
make_binary(`<`, bool)
make_binary(`<=`, bool)
make_binary(`==`, bool)
make_unary(isZero, bool)
make_unary(isNegative, bool)
func isOdd(x: SomeSignedInt): bool {.inline.}=
# internal
bool(x and 1)
func isEven(x: SomeSignedInt): bool {.inline.}=
# internal
not x.isOdd
make_unary(isOdd, bool)
make_unary(isEven, bool)
import ./private/int_bitwise_ops
make_unary(`not`, Stint)
make_binary(`or`, Stint)
make_binary(`and`, Stint)
make_binary(`xor`, Stint)
func `shr`*(x: Stint, y: SomeInteger): Stint {.inline.} =
result.data = x.data shr y
func `shl`*(x: Stint, y: SomeInteger): Stint {.inline.} =
result.data = x.data shl y
func ashr*(x: Stint, y: SomeInteger): Stint {.inline.} =
result.data = ashr(x.data, y)
import ./private/int_highlow
func high*[bits: static[int]](_: typedesc[Stint[bits]]): Stint[bits] {.inline.} =
result.data = high(type result.data)
func low*[bits: static[int]](_: typedesc[Stint[bits]]): Stint[bits] {.inline.} =
result.data = low(type result.data)

159
stint/intops.nim Normal file
View File

@ -0,0 +1,159 @@
# Stint
# 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 ./private/[bitops2_priv, datatypes]
export Stint, StUint
export IntImpl, intImpl, UintImpl, uintImpl, bitsof # TODO: remove the need to export those
type SomeBigInteger = Stuint|Stint
import ./private/initialization
func zero*[bits: static[int]](T: typedesc[Stuint[bits] or Stint[bits]]): T {.inline.} =
## Returns the zero of the input type
discard
func one*[bits: static[int]](T: typedesc[Stuint[bits]]): T {.inline.} =
## Returns the one of the input type
result.data = one(type result.data)
import ./private/[int_addsub, uint_addsub]
func `+`*(x, y: SomeBigInteger): SomeBigInteger {.inline.} =
## Integer addition
result.data = x.data + y.data
func `+=`*(x: var SomeBigInteger, y: SomeBigInteger) {.inline.} =
## Integer addition
x.data += y.data
func `-`*(x, y: SomeBigInteger): SomeBigInteger {.inline.} =
## Integer substraction
result.data = x.data - y.data
func `-=`*(x: var SomeBigInteger, y: SomeBigInteger) {.inline.} =
## Integer substraction
x.data -= y.data
import ./private/int_negabs
func `-`*(x: Stint): Stint {.inline.} =
## Returns true if input is zero
## false otherwise
result.data = -x.data
func abs*(x: Stint): Stint {.inline.} =
## Returns true if input is zero
## false otherwise
result.data = abs(x.data)
import ./private/[int_mul, uint_mul]
func `*`*(x, y: SomeBigInteger): SomeBigInteger {.inline.} =
## Integer multiplication
result.data = x.data * y.data
import ./private/[int_div, uint_div]
func `div`*(x, y: SomeBigInteger): SomeBigInteger {.inline.} =
## Integer division
result.data = x.data div y.data
func `mod`*(x, y: SomeBigInteger): SomeBigInteger {.inline.} =
## Integer modulo
## This returns the remainder of x / y.
## i.e. x = y * quotient + remainder
result.data = x.data mod y.data
func divmod*(x, y: SomeBigInteger): tuple[quot, rem: SomeBigInteger] {.inline.} =
## Fused integer division and modulo
## Return both the quotient and remainder
## of x / y
(result.quot.data, result.rem.data) = divmod(x.data, y.data)
import ./private/[int_comparison, uint_comparison]
func `<`*(x, y: SomeBigInteger): bool {.inline.} =
## Unsigned `less than` comparison
x.data < y.data
func `<=`*(x, y: SomeBigInteger): bool {.inline.} =
## Unsigned `less or equal` comparison
x.data <= y.data
func `==`*(x, y: SomeBigInteger): bool {.inline.} =
## Unsigned `equal` comparison
x.data == y.data
export `<`, `<=`, `==` # Address Generic Instantiation too nested: https://github.com/status-im/nim-stint/pull/66#issuecomment-427557655
func isZero*(x: SomeBigInteger): bool {.inline.} =
## Returns true if input is zero
## false otherwise
x.data.isZero
func isNegative*(x: SomeBigInteger): bool {.inline.} =
## Returns true if input is negative (< 0)
## false otherwise
x.data.isNegative
func isOdd*(x: SomeBigInteger): bool {.inline.} =
## Returns true if input is zero
## false otherwise
x.data.isOdd
func isEven*(x: SomeBigInteger): bool {.inline.} =
## Returns true if input is zero
## false otherwise
x.data.isEven
export isEven, isOdd
import ./private/[int_bitwise_ops, uint_bitwise_ops]
func `not`*(x: SomeBigInteger): SomeBigInteger {.inline.}=
## Bitwise `not` i.e. flips all bits of the input
result.data = x.data.not
func `or`*(x, y: SomeBigInteger): SomeBigInteger {.inline.}=
## Bitwise `or`
result.data = x.data or y.data
func `and`*(x, y: SomeBigInteger): SomeBigInteger {.inline.}=
## Bitwise `and`
result.data = x.data and y.data
func `xor`*(x, y: SomeBigInteger): SomeBigInteger {.inline.}=
## Bitwise `xor`
result.data = x.data xor y.data
func `shr`*(x: SomeBigInteger, y: SomeInteger): SomeBigInteger {.inline.} =
result.data = x.data shr y
func `shl`*(x: SomeBigInteger, y: SomeInteger): SomeBigInteger {.inline.} =
result.data = x.data shl y
func ashr*(x: Stint, y: SomeInteger): Stint {.inline.} =
result.data = ashr(x.data, y)
import ./private/[int_highlow, uint_highlow]
func high*[bits](_: typedesc[Stint[bits]]): Stint[bits] {.inline.} =
result.data = high(type result.data)
func high*[bits](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.} =
result.data = high(type result.data)
func low*[bits](_: typedesc[Stint[bits]]): Stint[bits] {.inline.} =
result.data = low(type result.data)
func low*[bits](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.} =
result.data = low(type result.data)
import ./private/uint_exp, math
func pow*(x: StUint, y: Natural): StUint {.inline.} =
## Returns x raised at the power of y
when x.data is UintImpl:
result.data = x.data.pow(y)
else:
result.data = x.data ^ y
func pow*(x: StUint, y: StUint): StUint {.inline.} =
## Returns x raised at the power of y
when x.data is UintImpl:
result.data = x.data.pow(y.data)
else:
result.data = x.data ^ y.data

View File

@ -10,7 +10,7 @@
import import
./private/datatypes, ./private/datatypes,
./private/int_negabs, ./private/int_negabs,
./int_public, ./uint_public, ./intops,
typetraits, algorithm typetraits, algorithm
template static_check_size(T: typedesc[SomeInteger], bits: static[int]) = template static_check_size(T: typedesc[SomeInteger], bits: static[int]) =

View File

@ -9,7 +9,7 @@
## This file provides syntactic sugar to work with literals ## This file provides syntactic sugar to work with literals
import ./int_public, ./uint_public, macros import ./intops, macros
type Signedness = enum type Signedness = enum
BothSigned, IntOnly, UintOnly BothSigned, IntOnly, UintOnly

View File

@ -7,7 +7,7 @@
# #
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./uint_public import ./intops
func addmod_internal(a, b, m: Stuint): Stuint {.inline.}= func addmod_internal(a, b, m: Stuint): Stuint {.inline.}=
## Modular addition ## Modular addition

View File

@ -12,9 +12,27 @@ export bitops2
# Bitops from support library # Bitops from support library
template bitsof*(x: UintImpl): int =
# XXX: https://github.com/nim-lang/Nim/issues/9494
mixin bitsof
bitsof(x.lo) * 2
template bitsof*(x: IntImpl): int =
# XXX: https://github.com/nim-lang/Nim/issues/9494
mixin bitsof
bitsof(x.lo) * 2
template bitsof*(x: typedesc[UintImpl]): int =
# XXX: https://github.com/nim-lang/Nim/issues/9494
mixin bitsof
bitsof(x.lo) * 2
func countOnes*(x: UintImpl): int {.inline.} = func countOnes*(x: UintImpl): int {.inline.} =
countOnes(x.lo) + countOnes(x.hi) countOnes(x.lo) + countOnes(x.hi)
func countZeros*(x: UintImpl): int {.inline.} =
countZeros(x.lo) + countOnes(x.hi)
func parity*(x: UintImpl): int {.inline.} = func parity*(x: UintImpl): int {.inline.} =
parity(x.lo) xor parity(x.hi) parity(x.lo) xor parity(x.hi)

View File

@ -166,14 +166,6 @@ type
StInt*[bits: static[int]] = object StInt*[bits: static[int]] = object
data*: intImpl(bits) data*: intImpl(bits)
template bitsof*(x: SomeInteger): untyped =
sizeof(x) * 8
template bitsof*(x: UintImpl|IntImpl): untyped =
# XXX: https://github.com/nim-lang/Nim/issues/9494
mixin bitsof
bitsof(x.lo) * 2
template applyHiLo*(a: UintImpl | IntImpl, c: untyped): untyped = template applyHiLo*(a: UintImpl | IntImpl, c: untyped): untyped =
## Apply `c` to each of `hi` and `lo` ## Apply `c` to each of `hi` and `lo`
var res: type a var res: type a

View File

@ -0,0 +1,21 @@
import ./bitops2_priv, ./datatypes
import stew/endians2
export endians2
func swapBytes*(x: UintImpl): UintImpl {.inline.} =
let lo = swapBytes(x.hi)
let hi = swapBytes(x.lo)
UintImpl(hi: hi, lo: lo)
func toBytes*(x: UintImpl, endian: Endianness = system.cpuEndian): auto {.inline.} =
# TODO can't use bitsof in return type (compiler bug?), hence return auto
# TODO compile-time version
var ret: array[bitsof(x) div 8, byte]
if endian == system.cpuEndian:
copyMem(addr ret[0], unsafeAddr x, ret.len)
else:
let v = swapBytes(x)
copyMem(addr ret[0], unsafeAddr v, ret.len)
ret

View File

@ -7,7 +7,7 @@
# #
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./datatypes, ./uint_bitwise_ops import ./datatypes, ./bitops2_priv, ./uint_bitwise_ops
func `not`*(x: IntImpl): IntImpl {.inline.}= func `not`*(x: IntImpl): IntImpl {.inline.}=
## Bitwise complement of unsigned integer x ## Bitwise complement of unsigned integer x

View File

@ -36,6 +36,12 @@ func `<=`*(x, y: IntImpl): bool {.inline.}=
x.hi < y.hi or x.hi < y.hi or
(x.hi == y.hi and x.lo <= y.lo) (x.hi == y.hi and x.lo <= y.lo)
func isOdd*(x: SomeSignedInt): bool {.inline.}=
bool(x and 1)
func isEven*(x: SomeSignedInt): bool {.inline.}=
not x.isOdd
func isEven*(x: IntImpl): bool {.inline.}= func isEven*(x: IntImpl): bool {.inline.}=
x.lo.isEven x.lo.isEven

View File

@ -10,7 +10,7 @@
import import
./datatypes, ./datatypes,
./initialization, ./int_highlow, ./initialization, ./int_highlow,
./int_addsub, ./int_comparison ./int_addsub, ./int_comparison, ./int_bitwise_ops
func `-`*(x: IntImpl): IntImpl {.inline.}= func `-`*(x: IntImpl): IntImpl {.inline.}=
# Negate a multi-precision signed int. # Negate a multi-precision signed int.

View File

@ -7,7 +7,7 @@
# #
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./datatypes import ./datatypes, ./bitops2_priv
func `not`*(x: UintImpl): UintImpl {.inline.}= func `not`*(x: UintImpl): UintImpl {.inline.}=
## Bitwise complement of unsigned integer x ## Bitwise complement of unsigned integer x

View File

@ -7,7 +7,7 @@
# #
# at your option. This file may not be copied, modified, or distributed except according to those terms. # at your option. This file may not be copied, modified, or distributed except according to those terms.
import ./bitops2, ./conversion, ./initialization, import ./bitops2_priv, ./conversion, ./initialization,
./datatypes, ./datatypes,
./uint_comparison, ./uint_comparison,
./uint_bitwise_ops, ./uint_bitwise_ops,

View File

@ -1,146 +0,0 @@
# Stint
# 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 ./private/datatypes
export StUint
export UintImpl, uintImpl, bitsof # TODO: remove the need to export those
import ./private/uint_addsub
func `+`*(x, y: Stuint): Stuint {.inline.} =
## Unsigned integer addition
result.data = x.data + y.data
func `+=`*(x: var Stuint, y: Stuint) {.inline.} =
## Unsigned integer addition
x.data += y.data
func `-`*(x, y: Stuint): Stuint {.inline.} =
## Unsigned integer substraction
result.data = x.data - y.data
func `-=`*(x: var Stuint, y: Stuint) {.inline.} =
## Unsigned integer substraction
x.data -= y.data
import ./private/uint_mul
func `*`*(x, y: Stuint): Stuint {.inline.} =
## Unsigned integer multiplication
result.data = x.data * y.data
import ./private/uint_div
func `div`*(x, y: Stuint): Stuint {.inline.} =
## Unsigned integer division
result.data = x.data div y.data
func `mod`*(x, y: Stuint): Stuint {.inline.} =
## Unsigned integer modulo
## This returns the remainder of x / y.
## i.e. x = y * quotient + remainder
result.data = x.data mod y.data
func divmod*(x, y: StUint): tuple[quot, rem: StUint] {.inline.} =
## Fused unsigned integer division and modulo
## Return both the quotient and remainder
## of x / y
(result.quot.data, result.rem.data) = divmod(x.data, y.data)
import ./private/uint_comparison
func `<`*(x, y: Stuint): bool {.inline.} =
## Unsigned `less than` comparison
x.data < y.data
func `<=`*(x, y: Stuint): bool {.inline.} =
## Unsigned `less or equal` comparison
x.data <= y.data
func `==`*(x, y: Stuint): bool {.inline.} =
## Unsigned `equal` comparison
x.data == y.data
export `<`, `<=`, `==` # Address Generic Instantiation too nested: https://github.com/status-im/nim-stint/pull/66#issuecomment-427557655
func isZero*(x: Stuint): bool {.inline.} =
## Returns true if input is zero
## false otherwise
x.data.isZero
export isEven, isOdd
func isEven*(x: Stuint): bool {.inline.}=
## Returns true if input is even
## false otherwise
x.data.isEven
func isOdd*(x: Stuint): bool {.inline.}=
## Returns true if input is odd
## false otherwise
not x.isEven
import ./private/uint_bitwise_ops
func `not`*(x: Stuint): Stuint {.inline.}=
## Bitwise `not` i.e. flips all bits of the input
result.data = x.data.not
func `or`*(x, y: Stuint): Stuint {.inline.}=
## Bitwise `or`
result.data = x.data or y.data
func `and`*(x, y: Stuint): Stuint {.inline.}=
## Bitwise `and`
result.data = x.data and y.data
func `xor`*(x, y: Stuint): Stuint {.inline.}=
## Bitwise `xor`
result.data = x.data xor y.data
func `shr`*(x: StUint, y: SomeInteger): StUint {.inline.} =
## Logical shift right
result.data = x.data shr y
func `shl`*(x: StUint, y: SomeInteger): StUint {.inline.} =
## Logical shift right
## Similar to C standard, result is undefined if y is bigger
## than the number of bits in x.
result.data = x.data shl y
import ./private/uint_highlow
func high*[bits: static[int]](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.} =
## Returns the highest unsigned int of this size. I.e. bits are all ones.
result.data = high(type result.data)
func low*[bits: static[int]](_: typedesc[Stuint[bits]]): Stuint[bits] {.inline.} =
## Returns the lowest unsigned int of this size. This is always 0.
result.data = low(type result.data)
import ./private/bitops2
func countOnes*(x: StUint): int {.inline.} = countOnes(x.data)
func parity*(x: StUint): int {.inline.} = parity(x.data)
func firstOne*(x: StUint): int {.inline.} = firstOne(x.data)
func leadingZeros*(x: StUint): int {.inline.} = leadingZeros(x.data)
func trailingZeros*(x: StUint): int {.inline.} = trailingZeros(x.data)
import ./private/initialization
func zero*[bits: static[int]](T: typedesc[Stuint[bits] or Stint[bits]]): T {.inline.} =
## Returns the zero of the input type
discard
func one*[bits: static[int]](T: typedesc[Stuint[bits]]): T {.inline.} =
## Returns the one of the input type
result.data = one(type result.data)
import ./private/uint_exp, math
func pow*(x: StUint, y: Natural): StUint {.inline.} =
## Returns x raised at the power of y
when x.data is UintImpl:
result.data = x.data.pow(y)
else:
result.data = x.data ^ y
func pow*(x: StUint, y: StUint): StUint {.inline.} =
## Returns x raised at the power of y
when x.data is UintImpl:
result.data = x.data.pow(y.data)
else:
result.data = x.data ^ y.data

View File

@ -0,0 +1,26 @@
# Stint
# 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 ../stint, unittest
suite "Testing endians":
test "Endians give sane results":
check:
1.u128.toBytesBE() ==
[0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]
1.u128.toBytesLE() ==
[1'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
1.u128 == UInt128.fromBytesBE(
[0'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1])
1.u128 == UInt128.fromBytesLE(
[1'u8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])