Hint Extern 3 (is_int I32 _ (Znth _ (map Vint _))) =>
(apply  is_int_I32_Znth_map_Vint; rewrite ?Zlength_map; omega).
Definition minimum_spec :=
DECLARE _minimum
WITH a: val, n: Z, al: list Z
PRE [ _a OF tptr tint , _n OF tint ]
PROP  (1 <= n <= Int.max_signed; Forall repable_signed al)
LOCAL (temp _a a; temp _n (Vint (Int.repr n)))
SEP   (data_at Ews (tarray tint n) (map Vint (map Int.repr al)) a)
POST [ tint ]
PROP ()
LOCAL(temp ret_temp  (Vint (Int.repr (fold_right Z.min (hd 0 al) al))))
SEP   (data_at Ews (tarray tint n) (map Vint (map Int.repr al)) a).
Definition Gprog : funspecs :=
ltac:(with_library prog [minimum_spec]).

(* Specifications: *)
(* First approach from "Modular Verification for Computer Security", proved using forward_for_simple_bound *)
Lemma body_min: semax_body Vprog Gprog f_minimum minimum_spec.
(* Demonstration of the same theorem, but using forward_for  instead of forward_for_simple_bound *)
Lemma body_min': semax_body Vprog Gprog f_minimum minimum_spec.
Definition minimum_spec2 :=
DECLARE _minimum
WITH a: val, n: Z, al: list Z
PRE [ _a OF tptr tint , _n OF tint ]
PROP  (1 <= n <= Int.max_signed; Forall repable_signed al)
LOCAL (temp _a a; temp _n (Vint (Int.repr n)))
SEP   (data_at Ews (tarray tint n) (map Vint (map Int.repr al)) a)
POST [ tint ]
EX j: Z,
PROP (In j al; Forall (fun x => j<=x) al)
LOCAL(temp ret_temp  (Vint (Int.repr j)))
SEP   (data_at Ews (tarray tint n) (map Vint (map Int.repr al)) a).
(* Second approach from "Modular Verification for Computer Security", proved using forward_for_simple_bound *)
Lemma body_min2: semax_body Vprog Gprog f_minimum minimum_spec2.