mirror of
https://github.com/AdaCore/why3.git
synced 2026-02-12 12:34:55 -08:00
63 lines
1.3 KiB
Plaintext
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
|