implement a pow for x, y: UintImpl as well
This commit is contained in:
parent
11f62d42c9
commit
1283d582a1
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue