2018-03-26 09:46:24 +00:00
|
|
|
# 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.
|
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
import ./uint_type,
|
2018-03-26 09:46:24 +00:00
|
|
|
macros
|
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func initMpUintImpl*[InType, OutType](x: InType, _: typedesc[OutType]): OutType {.inline.} =
|
2018-03-26 10:45:10 +00:00
|
|
|
|
2018-03-28 18:45:39 +00:00
|
|
|
const
|
2018-04-21 10:12:05 +00:00
|
|
|
size_in = getSize(x)
|
|
|
|
size_out = getSize(result)
|
2018-03-28 18:45:39 +00:00
|
|
|
|
|
|
|
static:
|
|
|
|
assert size_out >= size_in, "The result type size should be equal or bigger than the input type size"
|
|
|
|
|
|
|
|
when OutType is SomeUnsignedInt:
|
|
|
|
result = x.OutType
|
|
|
|
elif size_in == size_out:
|
|
|
|
result = cast[type result](x)
|
|
|
|
else:
|
|
|
|
result.lo = initMpUintImpl(x, type result.lo)
|
2018-03-28 15:15:36 +00:00
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func toSubtype*[T: SomeInteger](b: bool, _: typedesc[T]): T {.inline.}=
|
2018-03-26 10:45:10 +00:00
|
|
|
b.T
|
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func toSubtype*[T: MpUintImpl](b: bool, _: typedesc[T]): T {.inline.}=
|
2018-03-26 10:45:10 +00:00
|
|
|
type SubTy = type result.lo
|
|
|
|
result.lo = toSubtype(b, SubTy)
|
2018-03-26 09:46:24 +00:00
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func zero*[T: BaseUint](_: typedesc[T]): T {.inline.}=
|
2018-03-28 18:45:39 +00:00
|
|
|
discard
|
2018-03-26 09:46:24 +00:00
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func one*[T: BaseUint](_: typedesc[T]): T {.inline.}=
|
2018-03-26 09:46:24 +00:00
|
|
|
when T is SomeUnsignedInt:
|
2018-03-28 15:15:36 +00:00
|
|
|
result = T(1)
|
2018-03-26 09:46:24 +00:00
|
|
|
else:
|
2018-04-21 10:12:05 +00:00
|
|
|
let r_ptr = cast[ptr array[getSize(result) div 8, byte]](result.addr)
|
|
|
|
when system.cpuEndian == bigEndian:
|
|
|
|
r_ptr[0] = 1
|
|
|
|
else:
|
|
|
|
r_ptr[r_ptr[].len - 1] = 1
|
2018-03-26 09:46:24 +00:00
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func toUint*(n: MpUIntImpl): auto {.inline.}=
|
2018-03-26 09:46:24 +00:00
|
|
|
## Casts a multiprecision integer to an uint of the same size
|
|
|
|
|
|
|
|
# TODO: uint128 support
|
|
|
|
when n.sizeof > 8:
|
|
|
|
raise newException("Unreachable. You are trying to cast a MpUint with more than 64-bit of precision")
|
|
|
|
elif n.sizeof == 8:
|
|
|
|
cast[uint64](n)
|
|
|
|
elif n.sizeof == 4:
|
|
|
|
cast[uint32](n)
|
|
|
|
elif n.sizeof == 2:
|
|
|
|
cast[uint16](n)
|
|
|
|
else:
|
|
|
|
raise newException("Unreachable. MpUInt must be 16-bit minimum and a power of 2")
|
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func toUint*(n: SomeUnsignedInt): SomeUnsignedInt {.inline.}=
|
2018-03-26 09:46:24 +00:00
|
|
|
## No-op overload of multi-precision int casting
|
|
|
|
n
|
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func asDoubleUint*(n: BaseUint): auto {.inline.} =
|
2018-03-26 09:46:24 +00:00
|
|
|
## Convert an integer or MpUint to an uint with double the size
|
|
|
|
|
|
|
|
type Double = (
|
|
|
|
when n.sizeof == 4: uint64
|
|
|
|
elif n.sizeof == 2: uint32
|
|
|
|
else: uint16
|
|
|
|
)
|
|
|
|
|
|
|
|
n.toUint.Double
|
|
|
|
|
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func toMpUintImpl*(n: uint16|uint32|uint64): auto {.inline.} =
|
2018-03-26 09:46:24 +00:00
|
|
|
## Cast an integer to the corresponding size MpUintImpl
|
|
|
|
# Sometimes direct casting doesn't work and we must cast through a pointer
|
|
|
|
|
|
|
|
when n is uint64:
|
|
|
|
return (cast[ptr [MpUintImpl[uint32]]](unsafeAddr n))[]
|
|
|
|
elif n is uint32:
|
|
|
|
return (cast[ptr [MpUintImpl[uint16]]](unsafeAddr n))[]
|
|
|
|
elif n is uint16:
|
|
|
|
return (cast[ptr [MpUintImpl[uint8]]](unsafeAddr n))[]
|
2018-03-28 18:45:39 +00:00
|
|
|
|
2018-04-21 10:12:05 +00:00
|
|
|
func toMpUintImpl*(n: MpUintImpl): MpUintImpl {.inline.} =
|
2018-03-28 18:45:39 +00:00
|
|
|
## No op
|
|
|
|
n
|