Files
why3/examples/swap.mlw
Jean-Christophe Filliatre 3ae7cf7583 example: swapping two integers
2020-04-29 13:12:53 +02:00

89 lines
1.8 KiB
Plaintext

(** Swapping two integers in-place *)
module Swap
use int.Int
use ref.Ref
let swap (ref a b: int) : unit
writes { a, b }
ensures { a = old b /\ b = old a }
=
a <- a + b;
b <- a - b;
a <- a - b
end
(** It also works fine with machine integers, even with overflows *)
module SwapInt32
use int.Int
use ref.Ref
(** a simple model of 32-bit integers with addition, subtraction,
and possible overflows *)
type int32 = < range -0x8000_0000 0x7fff_ffff >
meta coercion function int32'int
constant width : int = int32'maxInt - int32'minInt + 1
val (+) (a: int32) (b: int32) : int32
ensures { result =
if a + b < int32'minInt then a + b + width
else if a + b > int32'maxInt then a + b - width
else a + b }
val (-) (a: int32) (b: int32) : int32
ensures { result =
if a - b < int32'minInt then a - b + width
else if a - b > int32'maxInt then a - b - width
else a - b }
predicate in_bounds (n: int32) = int32'minInt <= n <= int32'maxInt
(** purely applicative version first *)
let swap (a b: int32) : (x: int32, y: int32)
requires { in_bounds a /\ in_bounds b }
ensures { int32'int x = b /\ int32'int y = a }
=
let a = a + b in
let b = a - b in
let a = a - b in
a, b
(** then rephrased with mutable variables *)
let swap_ref (ref a b: int32) : unit
requires { in_bounds a /\ in_bounds b }
writes { a, b }
ensures { int32'int a = old b /\ int32'int b = old a }
=
a <- a + b;
b <- a - b;
a <- a - b
end
(** with bitwise XOR this time *)
module SwapInt32xor
use bv.BV32
use ref.Ref
let swap (ref a b: t) : unit
writes { a, b }
ensures { a = old b /\ b = old a }
= a <- bw_xor a b;
b <- bw_xor a b;
a <- bw_xor a b
end