diff --git a/benchmarks/core/mod_pow.bril b/benchmarks/core/mod_pow.bril new file mode 100644 index 000000000..fad926a7d --- /dev/null +++ b/benchmarks/core/mod_pow.bril @@ -0,0 +1,75 @@ +# ARGS: 4 13 497 +@main (base: int, exp: int, mod: int){ + out: int = call @mod_pow base exp mod; + print out; +} +@mod_pow(b: int, e: int, m: int): int { + v1: int = id m; + v2: int = const 1; + v3: bool = eq v1 v2; + br v3 .then.0 .else.0; +.then.0: + v4: int = const 0; + ret v4; +.else.0: + v5: int = const 1; + result: int = id v5; + v6: int = id b; + v7: int = id m; + base: int = call @mod v6 v7; + base: int = id base; + v9: int = id e; + exp: int = id v9; +.for.cond.8: + v10: int = id exp; + v11: int = const 0; + v12: bool = gt v10 v11; + br v12 .for.body.8 .for.end.8; +.for.body.8: + v13: int = id exp; + v14: int = const 2; + bit: int = call @mod v13 v14; + bit: int = id bit; + v16: int = id bit; + v17: int = const 1; + v18: bool = eq v16 v17; + br v18 .then.15 .else.15; +.then.15: + v19: int = id result; + v20: int = id base; + v21: int = mul v19 v20; + result: int = id v21; + v22: int = id result; + v23: int = id m; + v24: int = call @mod v22 v23; + result: int = id v24; + jmp .endif.15; +.else.15: +.endif.15: + v25: int = id base; + v26: int = id base; + v27: int = mul v25 v26; + base: int = id v27; + v28: int = id base; + v29: int = id m; + v30: int = call @mod v28 v29; + base: int = id v30; + v31: int = id exp; + v32: int = const 2; + v33: int = div v31 v32; + exp: int = id v33; + jmp .for.cond.8; +.for.end.8: + v34: int = id result; + ret v34; +} +@mod(n: int, m: int): int { + v0: int = id n; + v1: int = id n; + v2: int = id m; + v3: int = div v1 v2; + v4: int = id m; + v5: int = mul v3 v4; + v6: int = sub v0 v5; + ret v6; +} diff --git a/benchmarks/core/mod_pow.out b/benchmarks/core/mod_pow.out new file mode 100644 index 000000000..e5a135a53 --- /dev/null +++ b/benchmarks/core/mod_pow.out @@ -0,0 +1 @@ +445 diff --git a/benchmarks/core/mod_pow.prof b/benchmarks/core/mod_pow.prof new file mode 100644 index 000000000..f56fd1300 --- /dev/null +++ b/benchmarks/core/mod_pow.prof @@ -0,0 +1 @@ +total_dyn_inst: 243 diff --git a/docs/tools/bench.md b/docs/tools/bench.md index 1634619d3..2d25e3959 100644 --- a/docs/tools/bench.md +++ b/docs/tools/bench.md @@ -46,6 +46,7 @@ The current benchmarks are: * `mat-mul`: Multiplies two `nxn` matrices using the [naive][matmul] matrix multiplication algorithm. The matrices are randomly generated using a [linear congruential generator][rng]. * `max-subarray`: solution to the classic Maximum Subarray problem. * `mod_inv`: Calculates the [modular inverse][modinv] of `n` under to a prime modulus p. +* `mod_pow`: Performs [modular exponentiation][modpow] using the right-to-left binary method as described in the Wikipedia article. * `newton`: Calculate the square root of 99,999 using the [newton method][newton] * `norm`: Calculate the [euclidean norm][euclidean] of a vector * `n_root`: Calculate nth root of a float using newton's method. @@ -113,3 +114,4 @@ Credit for several of these benchmarks goes to Alexa VanHattum and Gregory Yaune [qsort-hoare]: https://en.wikipedia.org/wiki/Quicksort#Hoare_partition_scheme [modinv]: https://en.wikipedia.org/wiki/Modular_multiplicative_inverse [totient]: https://en.wikipedia.org/wiki/Euler's_totient_function +[modpow]: https://en.wikipedia.org/wiki/Modular_exponentiation