4 use export real.RealInfix
9 type or_integer_float = Integer int | Real real
11 (* nth element of the list *)
12 function get_nth (i: int) (e: list or_integer_float) : or_integer_float =
14 | None -> Integer (-1)
18 (* no integer zero till x (excluding) *)
19 predicate no_zero_int (e: list or_integer_float) (x: int) =
20 forall j: int. 0 <= j < x /\ x < length(e) ->
23 | Some y -> match y with
24 | (Integer n) -> n <> 0
29 (* no real less than 0.5 till x (excluding) *)
30 predicate no_zero_real (e: list or_integer_float) (x: int) =
31 forall j: int. 0 <= j < x /\ x < length(e) ->
34 | Some y -> match y with
36 | (Real r) -> r >=. 0.5
40 (* no integer zero and no real less than 0.5 till x (excluding) *)
41 predicate no_zero (e: list or_integer_float) (x: int) =
42 forall j: int. 0 <= j < x /\ x < length(e) ->
45 | Some y -> match y with
46 | (Integer n) -> n <> 0
47 | (Real r) -> r >=. 0.5
51 (* integer zero at x *)
52 predicate zero_at_int (e: list or_integer_float) (x: int) =
55 | Some y -> match y with
56 | (Integer n) -> n = 0
61 (* real less than 0.5 at x *)
62 predicate zero_at_real (e: list or_integer_float) (x: int) =
65 | Some y -> match y with
66 | (Integer n) -> false
67 | (Real r) -> r <. 0.5
72 (* sum integers in a list *)
73 function add_int (e: list or_integer_float) (i: int) (j: int) : int =
77 | Cons (Integer n) t -> if n = 0 then 0 else n + add_int t (i+1) j
78 | Cons _ t -> add_int t (i+1) j
83 (* sum reals in a list *)
84 function add_real (e: list or_integer_float) (i: int) (j: int) : real =
88 | Cons (Real x) t -> if x <. 0.5 then 0.0 else x +. add_real t (i+1) j
89 | Cons _ t -> add_real t (i+1) j
105 let sum (l: list or_integer_float) : (int, real) =
110 let x = ref (any or_integer_float) in
112 for i = 0 to length(l) - 1 do
113 invariant { !si = add_int (l) (0) (!status) /\ !sf = add_real (l) (0) (!status)
114 /\ 0 <= !status < length(l)
119 | (Integer n) -> if n = 0 then raise Break else si := !si + n
120 | (Real r) -> if r <. 0.5 then raise Break else sf := !sf +. r
125 with Break -> (!si, !sf)
127 { let (si, sf) = result in
128 ( !status = -1 /\ si = add_int (l) (0) (length(l)) /\ sf = add_real (l) (0) (length(l))
129 /\ no_zero (l) (length(l)) ) \/
130 ( 0 <= !status < length(l) /\ si = add_int (l) (0) (!status) /\ sf = add_real (l) (0) (!status)
131 /\ no_zero_int (l) (!status) /\ no_zero_real (l) (!status)
132 /\ ( zero_at_int (l) (!status) \/ zero_at_real (l) (!status) ) )
138 Cons (Integer 5) (Cons (Real 3.3) (Cons (Integer 8)
139 (Cons (Real 1.4) (Cons (Integer 9) Nil))))