whyml-tests/whyml/gcd.why
2023-07-17 15:52:16 +02:00

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