implement a pow for x, y: UintImpl as well

This commit is contained in:
mratsim 2018-05-14 19:44:39 +02:00
parent 11f62d42c9
commit 1283d582a1
4 changed files with 37 additions and 2 deletions

View File

@ -9,7 +9,7 @@
import
./datatypes,
./uint_bitwise_ops, ./uint_mul, ./initialization
./uint_bitwise_ops, ./uint_mul, ./initialization, ./uint_comparison
func pow*(x: UintImpl, y: Natural): UintImpl =
## Compute ``x`` to the power of ``y``,
@ -29,3 +29,22 @@ func pow*(x: UintImpl, y: Natural): UintImpl =
if y == 0:
break
x = x * x
func pow*(x: UintImpl, y: UintImpl): UintImpl =
## Compute ``x`` to the power of ``y``,
## ``x`` must be non-negative
# Implementation uses exponentiation by squaring
# See Nim math module: https://github.com/nim-lang/Nim/blob/4ed24aa3eb78ba4ff55aac3008ec3c2427776e50/lib/pure/math.nim#L429
# And Eli Bendersky's blog: https://eli.thegreenplace.net/2009/03/21/efficient-integer-exponentiation-algorithms
var (x, y) = (x, y)
result = one(type x)
while true:
if not (y and one(type y)).isZero:
result = result * x
y = y shr 1
if y.isZero:
break
x = x * x

View File

@ -94,3 +94,9 @@ func pow*(x: StUint, y: Natural): StUint {.inline.} =
result.data = x.data.pow(y)
else:
result.data = x.data ^ y
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

View File

@ -223,9 +223,16 @@ suite "Property-based testing (testing with random inputs) - uint64 on 64-bit /
let
tx = cast[StUint[64]](x)
tz = tx.pow(y)
ty = cast[StUint[64]](y)
tz2 = tx.pow(ty)
else:
let
tx = cast[StUint[32]](x)
tz = tx.pow(y)
ty = cast[StUint[32]](y)
tz2 = tx.pow(ty)
check(cast[uint](tz) == x ^ y)
check(cast[uint](tz2) == x ^ y)

View File

@ -17,7 +17,9 @@ suite "Testing unsigned exponentiation":
b = 3
u = a.stuint(64)
check: cast[uint64](u.pow(b)) == a ^ b
check:
cast[uint64](u.pow(b)) == a ^ b
cast[uint64](u.pow(b.stuint(64))) == a ^ b
test "12 ^ 34 == 4922235242952026704037113243122008064":
# https://www.wolframalpha.com/input/?i=12+%5E+34
@ -26,3 +28,4 @@ suite "Testing unsigned exponentiation":
b = 34
check: a.pow(b) == "4922235242952026704037113243122008064".u256
check: a.pow(b.stuint(256)) == "4922235242952026704037113243122008064".u256