why3doc index index
module Z use int.Int use int.Abs use mach.int.Int32 use mach.c.C use map.Map use types.Types use types.Int32Eq use types.UInt64Eq use lemmas.Lemmas use import mach.int.UInt64GMP as Limb use int.Power type mpz_ptr val predicate mpz_eq (x y: mpz_ptr) ensures { result <-> x = y } type mpz_memo = abstract { mutable abs_value_of : map mpz_ptr int; mutable alloc : map mpz_ptr int; mutable abs_size : map mpz_ptr int; mutable sgn : map mpz_ptr int; mutable readers : map mpz_ptr int; mutable zones : map mpz_ptr C.zone; } invariant { forall p. 0 <= alloc p /\ (sgn p = 1 \/ sgn p = -1) /\ abs_size p <= alloc p /\ 0 <= abs_size p <= max_int32 /\ 0 <= abs_value_of p /\ (abs_size p >= 1 -> power radix (abs_size p - 1) <= abs_value_of p) /\ abs_value_of p < power radix (abs_size p) } by { abs_value_of = (fun _ -> 0); alloc = (fun _ -> 0); abs_size = (fun _ -> 0); sgn = (fun _ -> 1); readers = (fun _ -> 0); zones = (fun _ -> null_zone) } (* readers : = 0 means there is currently no access = -1 means exactly one read-write access = n > 0 means there are n read-only accesses = -2 means the pointer is invalid *) val ghost mpz : mpz_memo function value_of (x:mpz_ptr) (memo: mpz_memo) : int = memo.sgn[x] * memo.abs_value_of[x] function sgn_value (p:ptr limb) (sz:int32) : int = if sz >= 0 then value p sz else - value p (- sz) predicate mpz_unchanged (x: mpz_ptr) (memo1 memo2: mpz_memo) = memo1.readers[x] = memo2.readers[x] /\ (memo1.readers[x] > - 2 -> (memo1.abs_value_of[x] = memo2.abs_value_of[x] /\ memo1.alloc[x] = memo2.alloc[x] /\ memo1.abs_size[x] = memo2.abs_size[x] /\ memo1.sgn[x] = memo2.sgn[x] /\ memo1.zones[x] = memo2.zones[x])) let ghost unchanged (x:mpz_ptr) (memo1 memo2: mpz_memo) : unit requires { mpz_unchanged x memo1 memo2 } ensures { memo1.readers[x] = memo2.readers[x] } ensures { memo1.readers[x] > - 2 -> (memo1.abs_value_of[x] = memo2.abs_value_of[x] /\ memo1.alloc[x] = memo2.alloc[x] /\ memo1.abs_size[x] = memo2.abs_size[x] /\ memo1.sgn[x] = memo2.sgn[x] /\ memo1.readers[x] = memo2.readers[x] /\ memo1.zones[x] = memo2.zones[x]) } = () lemma unchanged_transitive: forall x m1 m2 m3. mpz_unchanged x m1 m2 -> mpz_unchanged x m2 m3 -> mpz_unchanged x m1 m3 (* SIZ mpz macro *) val size_of (x: mpz_ptr) : int32 requires { mpz.readers[x] > -2 } ensures { result = mpz.sgn[x] * mpz.abs_size[x] } val alloc_of (x: mpz_ptr) : int32 requires { mpz.readers[x] > -2 } ensures { result = mpz.alloc[x] } let abs [@extraction:inline] (x:int32) : int32 requires { x > min_int32 } ensures { result = abs x } = if Int32.(>=) x 0 then x else Int32.(-_) x (* ABSIZ mpz macro *) let abs_size_of [@extraction:inline] (x: mpz_ptr) : int32 requires { mpz.readers[x] > -2 } ensures { result = mpz.abs_size[x] } = abs (size_of x) type mpz_struct = { ghost addr: mpz_ptr } end module Zutil use int.Int use int.Abs use mach.int.Int32 use mach.c.C use map.Map use types.Types use types.Int32Eq use types.UInt64Eq use lemmas.Lemmas use import mach.int.UInt64GMP as Limb use int.Power use ref.Ref use Z (* Sets the size of an mpz_ptr, leaving other fields unchanged. *) val set_size (x:mpz_ptr) (sz:int32) (ghost p: ptr limb) : unit requires { mpz.zones[x] = zone p } requires { mpz.readers[x] = -1 } requires { offset p = 0 } requires { min p = 0 } requires { max p = plength p } requires { abs sz <= plength p } requires { plength p = mpz.alloc[x] } requires { sz <> 0 -> value p (abs sz) >= power radix (abs sz - 1) } writes { mpz.sgn } writes { mpz.abs_size } writes { mpz.abs_value_of } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.sgn[x] = 1 <-> 0 <= sz } ensures { mpz.sgn[x] = - 1 <-> sz < 0 } ensures { mpz.abs_size[x] = abs sz } ensures { mpz.abs_value_of[x] = value p (abs sz) } (* ensures size_of x = sz *) (* Sets the size of an mpz_ptr to 0 *) val set_size_0 (x:mpz_ptr) : unit requires { -1 <= mpz.readers[x] <= 0 } writes { mpz.abs_size } writes { mpz.abs_value_of } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.abs_size[x] = 0 } ensures { mpz.abs_value_of[x] = 0 } (* Sets the size of an mpz_ptr to minus its former size. *) val wmpz_minus (x:mpz_ptr) : unit requires { mpz.readers[x] = -1 } writes { mpz.abs_size } writes { mpz.abs_value_of } writes { mpz.sgn } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.sgn[x] = - old mpz.sgn[x] } ensures { mpz.abs_size[x] = old mpz.abs_size[x] } ensures { mpz.abs_value_of[x] = old mpz.abs_value_of[x] } val set_alloc (x:mpz_ptr) (al:int32) : unit requires { mpz.abs_size[x] <= al } requires { -1 <= mpz.readers[x] <= 0 } writes { mpz.alloc } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.alloc[x] = al } val set_ptr (x:mpz_ptr) (p:ptr limb) : unit requires { offset p = 0 } requires { writable p } requires { min p = 0 } requires { max p = plength p } requires { plength p = mpz.alloc[x] } requires { mpz.readers[x] = 0 \/ mpz.readers[x] = -1 } writes { mpz.abs_value_of } writes { mpz.zones } writes { mpz.readers } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.abs_value_of[x] = value p (mpz.abs_size[x]) } ensures { mpz.readers[x] = -1 } ensures { mpz.zones[x] = zone p } val ghost value_of (x: mpz_ptr) : int ensures { result = mpz.sgn[x] * mpz.abs_value_of[x] } val get_read_ptr (x: mpz_ptr) : ptr limb requires { mpz.readers[x] >= 0 } writes { mpz.readers } ensures { mpz.readers[x] = old mpz.readers[x] + 1 } ensures { forall y. x <> y -> mpz.readers[y] = old mpz.readers[y] } ensures { value result (mpz.abs_size[x]) = mpz.abs_value_of[x] } ensures { plength result = mpz.alloc[x] } ensures { offset result = 0 } ensures { min result = 0 } ensures { max result = plength result } ensures { zone result = mpz.zones[x] } val get_write_ptr (x: mpz_ptr) : ptr limb requires { mpz.readers[x] = 0 } writes { mpz.readers } ensures { mpz.readers[x] = -1 } ensures { forall y. x <> y -> mpz.readers[y] = old mpz.readers[y] } ensures { value result (mpz.abs_size[x]) = mpz.abs_value_of[x] } ensures { plength result = mpz.alloc[x] } ensures { offset result = 0 } ensures { min result = 0 } ensures { max result = plength result } ensures { writable result } ensures { zone result = mpz.zones[x] } val release_reader (x: mpz_ptr) (p:ptr limb) : unit requires { mpz.zones[x] = zone p } requires { mpz.readers[x] >= 1 } requires { min p = 0 } requires { max p = plength p } writes { mpz.readers } writes { p } (* invalidates p and its aliases *) ensures { mpz.readers[x] = old mpz.readers[x] - 1 } ensures { forall y. y <> x -> mpz.readers[y] = old mpz.readers[y] } val release_writer (x: mpz_ptr) (p:ptr limb) : unit requires { mpz.zones[x] = zone p } requires { mpz.readers[x] = -1 } requires { min p = 0 } requires { max p = plength p } requires { mpz.abs_value_of[x] = value p mpz.abs_size[x] } writes { mpz.readers } writes { p } (* invalidates p and its aliases *) ensures { mpz.readers[x] = 0 } ensures { forall y. y <> x -> mpz.readers[y] = old mpz.readers[y] } type mpz_mem = abstract { ptr: mpz_ptr; mutable ok: bool } val wmpz_struct_to_ptr (x:mpz_struct) : (res:mpz_ptr, ghost memo:mpz_mem) ensures { res = x.addr } ensures { memo.ptr = res } ensures { memo.ok } val wmpz_tmp_decl [@extraction:c_declaration] () : mpz_struct writes { mpz } ensures { old mpz.readers[result.addr] = -2 } (*result is fresh*) ensures { forall x. x <> result.addr -> mpz_unchanged x mpz (old mpz) } ensures { mpz.readers[result.addr] = 0 } ensures { mpz.alloc[result.addr] = 0 } ensures { mpz.abs_size[result.addr] = 0 } val ghost wmpz_tmp_clear (x:mpz_ptr) (memo: mpz_mem) : unit requires { memo.ok } requires { x = memo.ptr } requires { -1 <= mpz.readers[x] <= 0 } writes { mpz } writes { memo } ensures { mpz.readers[x] = -2 } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } let wmpz_ptr_decl [@extraction:inline] () : (ptr: mpz_ptr, ghost memo:mpz_mem) writes { mpz } ensures { ptr = memo.ptr } ensures { memo.ok } ensures { mpz.readers[ptr] = 0 } ensures { mpz.alloc[ptr] = 0 } ensures { mpz.abs_size[ptr] = 0 } ensures { old mpz.readers[ptr] = -2 } ensures { forall x. x <> ptr -> mpz_unchanged x mpz (old mpz) } = let t = wmpz_tmp_decl () in wmpz_struct_to_ptr t val partial wmpz_init (p: mpz_ptr) : unit requires { mpz.readers[p] = 0 } writes { mpz } ensures { forall x. x <> p -> mpz_unchanged x mpz (old mpz) } ensures { mpz.readers[p] = 0 } ensures { mpz.abs_value_of[p] = 0 } ensures { mpz.abs_size[p] = 0 } ensures { mpz.sgn[p] = 1 } ensures { mpz.alloc[p] = 1 } ensures { mpz.zones[p] <> null_zone } val wmpz_clear (x:mpz_ptr) : unit (* scrambles mpz._[x] *) writes { mpz } requires { mpz.readers[x] = 0 } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } let partial wmpz_do_realloc (x:mpz_ptr) (sz:int32) : ptr limb requires { 1 <= sz } (* GMP does sz = max (sz,1) instead, do that if needed *) requires { mpz.readers[x] = 0 } requires { 1 <= mpz.alloc[x] } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.readers[x] = -1 } ensures { mpz.alloc[x] = sz } ensures { mpz.abs_value_of[x] = value result (mpz.abs_size[x]) } ensures { mpz.zones[x] = zone result } ensures { offset result = 0 } ensures { plength result = sz } ensures { min result = 0 } ensures { max result = sz } ensures { writable result } ensures { if sz >= old mpz.abs_size[x] then mpz.abs_size[x] = old mpz.abs_size[x] /\ value result (old mpz.abs_size[x]) = old mpz.abs_value_of[x] else mpz.abs_size[x] = 0 } = let p = get_write_ptr x in assert { forall y. y <> x -> mpz_unchanged y mpz (old mpz) }; let ghost op = { p } in let ghost os = abs_size_of x in label Realloc in let q = realloc p sz in c_assert (is_not_null q); if Int32.(>) (abs_size_of x) sz then begin set_size_0 x; (* data has shrunk, reset x to 0 *) end else begin value_sub_frame (pelts q) (pelts op) 0 (p2i os); end; set_alloc x sz; set_ptr x q; q let wmpz_realloc (x:mpz_ptr) (sz:int32) : ptr limb requires { mpz.readers[x] = 0 } requires { 1 <= mpz.alloc[x] } ensures { forall y. y <> x -> mpz_unchanged y mpz (old mpz) } ensures { mpz.readers[x] = -1 } ensures { mpz.abs_value_of[x] = value result (mpz.abs_size[x]) } ensures { mpz.zones[x] = zone result } ensures { offset result = 0 } ensures { plength result = mpz.alloc[x] } ensures { min result = 0 } ensures { max result = plength result } ensures { writable result } ensures { mpz.abs_size[x] = old mpz.abs_size[x] } ensures { value result (old mpz.abs_size[x]) = old mpz.abs_value_of[x] } ensures { if sz > old mpz.alloc[x] then mpz.alloc[x] = sz else mpz.alloc[x] = old mpz.alloc[x] } = if sz > alloc_of x then wmpz_do_realloc x sz else get_write_ptr x let mpz_ptr_swap [@extraction:inline] (ref x y: mpz_ptr) requires { mpz.readers[x] = 0 /\ mpz.readers[y] = 0 } ensures { mpz.readers[x] = 0 /\ mpz.readers[y] = 0 } ensures { x = old y } ensures { y = old x } = let z = x in x <- y; y <- z end
Generated by why3doc 1.7.0