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
|