Files
why3/examples/power.mlw
2023-07-25 10:48:55 +02:00

63 lines
1.3 KiB
Plaintext

(** {1 Fast exponentiation} *)
module FastExponentiation
use int.Int
use int.Power
use int.ComputerDivision
lemma Power_even:
forall x, n. n >= 0 -> mod n 2 = 0 ->
power x n = power (x*x) (div n 2)
by n = div n 2 + div n 2
(* recursive implementation *)
let rec fast_exp (x n: int) : int
variant { n }
requires { 0 <= n }
ensures { result = power x n }
= if n = 0 then
1
else
let r = fast_exp x (div n 2) in
if mod n 2 = 0 then r * r else r * r * x
(* recursive implementation with an accumulator *)
let rec fast_exp_2 (x n acc: int) : int
variant { n }
requires { 0 <= n }
ensures { result = power x n * acc }
= if n = 0 then
acc
else if mod n 2 = 0 then
fast_exp_2 (x * x) (div n 2) acc
else
fast_exp_2 x (n - 1) (x * acc)
(* non-recursive implementation using a while loop *)
use ref.Ref
let fast_exp_imperative (x n: int) : int
requires { 0 <= n }
ensures { result = power x n }
= let ref r = 1 in
let ref p = x in
let ref e = n in
while e > 0 do
invariant { 0 <= e }
invariant { r * power p e = power x n }
variant { e }
label L in
if mod e 2 = 1 then r := r * p;
p := p * p;
e := div e 2;
assert { power p e = let x = power (p at L) e in x * x }
done;
r
end