51 lines
1.2 KiB
Plaintext
51 lines
1.2 KiB
Plaintext
|
(*
|
||
|
* gcd.whyml
|
||
|
* WhyML implementation of byteback test `algorithm/GCD`
|
||
|
*)
|
||
|
|
||
|
module GCD
|
||
|
use int.Int
|
||
|
use ref.Ref
|
||
|
|
||
|
exception IllegalArgumentException
|
||
|
|
||
|
let rec function gcd_recursive (a b : int) : int
|
||
|
variant { a + b }
|
||
|
=
|
||
|
if a = b then
|
||
|
a
|
||
|
else if a > b then
|
||
|
gcd_recursive (a - b) b
|
||
|
else
|
||
|
gcd_recursive a (b - a)
|
||
|
|
||
|
predicate arguments_are_negative (a b : int) =
|
||
|
a <= 0 || b <= 0
|
||
|
|
||
|
predicate result_is_gcd (a b r : int) =
|
||
|
(not (arguments_are_negative a b)) -> (r = gcd_recursive a b)
|
||
|
|
||
|
let apply (a b : int) : int
|
||
|
raises { IllegalArgumentException -> arguments_are_negative a b }
|
||
|
ensures { result_is_gcd a b result }
|
||
|
(* `result` holds return value *)
|
||
|
=
|
||
|
if a <= 0 || b <= 0 then
|
||
|
raise IllegalArgumentException;
|
||
|
let ref r: int = a in
|
||
|
let ref x: int = b in
|
||
|
|
||
|
while r <> x do
|
||
|
invariant { r > 0 && x > 0 }
|
||
|
invariant { gcd_recursive r x = gcd_recursive a b }
|
||
|
variant { r + x } (* not needed for byteback *)
|
||
|
|
||
|
if r > x then
|
||
|
r <- r - x
|
||
|
else
|
||
|
x <- x - r;
|
||
|
done;
|
||
|
|
||
|
r
|
||
|
end
|