(* * 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