implement a pow for x, y: UintImpl as well
This commit is contained in:
parent
11f62d42c9
commit
1283d582a1
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
import
|
import
|
||||||
./datatypes,
|
./datatypes,
|
||||||
./uint_bitwise_ops, ./uint_mul, ./initialization
|
./uint_bitwise_ops, ./uint_mul, ./initialization, ./uint_comparison
|
||||||
|
|
||||||
func pow*(x: UintImpl, y: Natural): UintImpl =
|
func pow*(x: UintImpl, y: Natural): UintImpl =
|
||||||
## Compute ``x`` to the power of ``y``,
|
## Compute ``x`` to the power of ``y``,
|
||||||
|
@ -29,3 +29,22 @@ func pow*(x: UintImpl, y: Natural): UintImpl =
|
||||||
if y == 0:
|
if y == 0:
|
||||||
break
|
break
|
||||||
x = x * x
|
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
|
||||||
|
|
|
@ -94,3 +94,9 @@ func pow*(x: StUint, y: Natural): StUint {.inline.} =
|
||||||
result.data = x.data.pow(y)
|
result.data = x.data.pow(y)
|
||||||
else:
|
else:
|
||||||
result.data = x.data ^ y
|
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
|
||||||
|
|
|
@ -223,9 +223,16 @@ suite "Property-based testing (testing with random inputs) - uint64 on 64-bit /
|
||||||
let
|
let
|
||||||
tx = cast[StUint[64]](x)
|
tx = cast[StUint[64]](x)
|
||||||
tz = tx.pow(y)
|
tz = tx.pow(y)
|
||||||
|
|
||||||
|
ty = cast[StUint[64]](y)
|
||||||
|
tz2 = tx.pow(ty)
|
||||||
else:
|
else:
|
||||||
let
|
let
|
||||||
tx = cast[StUint[32]](x)
|
tx = cast[StUint[32]](x)
|
||||||
tz = tx.pow(y)
|
tz = tx.pow(y)
|
||||||
|
|
||||||
|
ty = cast[StUint[32]](y)
|
||||||
|
tz2 = tx.pow(ty)
|
||||||
|
|
||||||
check(cast[uint](tz) == x ^ y)
|
check(cast[uint](tz) == x ^ y)
|
||||||
|
check(cast[uint](tz2) == x ^ y)
|
||||||
|
|
|
@ -17,7 +17,9 @@ suite "Testing unsigned exponentiation":
|
||||||
b = 3
|
b = 3
|
||||||
u = a.stuint(64)
|
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":
|
test "12 ^ 34 == 4922235242952026704037113243122008064":
|
||||||
# https://www.wolframalpha.com/input/?i=12+%5E+34
|
# https://www.wolframalpha.com/input/?i=12+%5E+34
|
||||||
|
@ -26,3 +28,4 @@ suite "Testing unsigned exponentiation":
|
||||||
b = 34
|
b = 34
|
||||||
|
|
||||||
check: a.pow(b) == "4922235242952026704037113243122008064".u256
|
check: a.pow(b) == "4922235242952026704037113243122008064".u256
|
||||||
|
check: a.pow(b.stuint(256)) == "4922235242952026704037113243122008064".u256
|
||||||
|
|
Loading…
Reference in New Issue