why3doc index index
module Add_1 use int.Int use mach.int.Int32 use import mach.int.UInt64GMP as Limb use int.Power use ref.Ref use mach.c.C use array.Array use map.Map use types.Types use types.Int32Eq use types.UInt64Eq use lemmas.Lemmas use int.EuclideanDivision (* r and x must be separated. This is enforced by Why3 regions in typing *) let wmpn_add_1 (r x:t) (sz:int32) (y:limb) : limb requires { valid x sz } requires { valid r sz } requires { sz > 0 } (* ? GMP does the same for 0 and 1*) requires { writable r } ensures { value r sz + (power radix sz) * result = value x sz + y } ensures { 0 <= result <= 1 } ensures { forall j. (j < offset r \/ offset r + sz <= j) -> (pelts r)[j] = old (pelts r)[j] } writes { r.data.elts } = let ref lx = C.get x in let res = add_mod lx y in let ref i = 1 in let ref c = 0 in C.set r res; if (res < lx) then begin c <- 1; assert { radix + res = lx + y }; while (i < sz) do invariant { 1 <= i <= sz } invariant { 0 <= c <= 1 } invariant { i = sz \/ c = 1 } invariant { value r i + (power radix i) * c = value x i + y } invariant { forall j. (j < offset r \/ offset r + sz <= j) -> (pelts r)[j] = old (pelts r)[j] } variant { sz - i } assert { c = 1 }; lx <- get_ofs x i; let res = add_mod lx 1 in set_ofs r i res; assert { value r i + (power radix i) * c = value x i + y }; value_tail r i; value_tail x i; i <- i + 1; if res <> 0 then begin c <- 0; assert { res = lx + 1 }; assert { value r i = value x i + y }; break end else begin assert { radix + res = lx + 1 }; assert { value r i + power radix i = value x i + y }; end done; end; while i < sz do invariant { i = sz \/ c = 0 } invariant { 0 <= i <= sz } invariant { value r i + (power radix i) * c = value x i + y } invariant { forall j. (j < offset r \/ offset r + sz <= j) -> (pelts r)[j] = old (pelts r)[j] } variant { sz - i } lx <- get_ofs x i; set_ofs r i lx; assert { value r i + (power radix i) * c = value x i + y }; value_tail r i; value_tail x i; i <- i + 1; done; c
wmpn_add_1 r x sz y
adds to x
the value of the limb y
,
writes the result in r
and returns the carry. r
and x
have size sz
. This corresponds to the function mpn_add_1
let wmpn_incr (x:t) (ghost sz:int32) (y:limb) : unit requires { valid x sz } requires { sz > 0 } requires { value x sz + y < power radix sz } requires { writable x } ensures { value x sz = value (old x) sz + y } ensures { forall j. j < x.offset \/ x.offset + sz <= j -> (pelts x)[j] = (pelts (old x))[j] } writes { x.data.elts } = let ghost ox = { x } in let ref c = 0:limb in let ref lx : limb = C.get x in let ref xp = C.incr x 1 in let ghost ref i : int32 = 1 in let res = add_mod lx y in C.set x res; if (res < lx) then begin c <- 1; assert { radix + res = lx + y }; while (c <> 0) do invariant { 1 <= i <= sz } invariant { offset xp = offset x + i } invariant { pelts xp = pelts x } invariant { plength xp = plength x } invariant { min xp = min x /\ max xp = max x } invariant { i = sz -> c = 0 } invariant { 0 <= c <= 1 } invariant { writable xp } invariant { value x i + (power radix i) * c = value ox i + y } invariant { forall j. i <= j < sz -> (pelts x)[x.offset + j] = (pelts ox)[x.offset + j] } invariant { forall j. j < x.offset \/ x.offset + sz <= j -> (pelts x)[j] = (pelts ox)[j] } variant { sz - i } assert { c = 1 }; lx <- C.get xp; assert { lx = (pelts ox)[ox.offset + i] }; let res = add_mod lx 1 in value_sub_update_no_change (pelts x) (x.offset + p2i i) (x.offset + p2i i + 1) (x.offset + p2i sz) res; C.set xp res; assert { forall j. i < j < sz -> (pelts x)[x.offset + j] = (pelts ox)[x.offset + j] }; assert { value x i + (power radix i) * c = value ox i + y }; value_tail x i; value_tail ox i; i <- i + 1; xp <- C.incr xp 1; if res <> 0 then begin c <- 0; assert { res = lx + 1 }; assert { value x i = value ox i + y }; assert { forall j. j < x.offset \/ x.offset + sz <= j -> (pelts x)[j] = (pelts ox)[j] }; break end else begin assert { radix + res = lx + 1 }; assert { value x i + power radix i = value ox i + y by power radix (i-1) * res + power radix i = power radix (i-1) * lx + power radix (i-1) * c }; end; assert { i = sz -> c = 0 by value x sz + power radix sz * c = value ox sz + y so value ox sz + y < power radix sz so 0 <= c <= 1 }; done end; value_concat x i sz; value_concat ox i sz; assert { forall j. x.offset + i <= j < x.offset + sz -> (pelts x)[j] = (pelts ox)[j] by let k = j - x.offset in i <= k < sz so (pelts x)[x.offset + k] = (pelts ox)[x.offset + k]}; value_sub_frame (pelts x) (pelts ox) (x.offset + p2i i) (x.offset + p2i sz)
wmpn_incr x sz y
adds to x
the value of the limb y
in place.
x
has size sz
. The addition must not overflow. This corresponds
to mpn_incr
let wmpn_incr_1 (x:t) (ghost sz:int32) : unit requires { valid x sz } requires { sz > 0 } requires { value x sz + 1 < power radix sz } requires { writable x } ensures { value x sz = value (old x) sz + 1 } ensures { forall j. j < x.offset \/ x.offset + sz <= j -> (pelts x)[j] = (pelts (old x))[j] } writes { x.data.elts } = let ghost ox = { x } in let ref r :limb = 0 in let ghost ref c : limb = 1 in let ref lx : limb = 0 in let ghost ref i : int32 = 0 in let ref xp = C.incr x 0 in while (r = 0) do invariant { 0 <= i <= sz } invariant { i = sz -> r <> 0 } invariant { offset xp = offset x + i } invariant { pelts xp = pelts x } invariant { plength xp = plength x } invariant { min xp = min x /\ max xp = max x } invariant { r <> 0 <-> c = 0 } invariant { 0 <= c <= 1 } invariant { writable xp } invariant { value x i + (power radix i) * c = value ox i + 1 } invariant { forall j. i <= j < sz -> (pelts x)[x.offset + j] = (pelts ox)[x.offset + j] } invariant { forall j. j < x.offset \/ x.offset + sz <= j -> (pelts x)[j] = (pelts ox)[j] } variant { sz - i } label StartLoop in lx <- C.get xp; assert { lx = (pelts ox)[ox.offset + i] }; let res = add_mod lx 1 in r <- res; ghost (if res = 0 then c <- 1 else c <- 0); assert { res + radix * c = lx + 1 }; value_sub_update_no_change (pelts x) (x.offset + p2i i) (x.offset + p2i i + 1) (x.offset + p2i sz) res; C.set xp res; assert { forall j. i < j < sz -> (pelts x)[x.offset + j] = (pelts ox)[x.offset + j] }; assert { value x i + (power radix i) * (c at StartLoop) = value ox i + 1 }; value_tail x i; value_tail ox i; assert { value x (i+1) + power radix (i+1) * c = value ox (i+1) + 1 by power radix i * res + power radix (i+1) * c = power radix i * lx + power radix i * (c at StartLoop) so value x (i+1) + power radix (i+1) * c = value x i + power radix i * res + power radix (i+1) * c }; i <- i + 1; xp <- C.incr xp 1; assert { i = sz -> c = 0 by value x sz + power radix sz * c = value ox sz + 1 so value ox sz + 1 < power radix sz so 0 <= c <= 1}; done; value_concat x i sz; value_concat ox i sz; assert { forall j. x.offset + i <= j < x.offset + sz -> (pelts x)[j] = (pelts ox)[j] by let k = j - x.offset in i <= k < sz so (pelts x)[x.offset + k] = (pelts ox)[x.offset + k]}; value_sub_frame (pelts x) (pelts ox) (x.offset + p2i i) (x.offset + p2i sz)
wmpn_incr_1 x sz
adds 1 to x
in place.
x
has size sz
. The addition must not overflow.
This corresponds to mpn_incr_1
let wmpn_add_1_in_place (x:t) (sz:int32) (y:limb) : limb requires { valid x sz } requires { sz > 0 } requires { writable x } ensures { value x sz + (power radix sz) * result = value (old x) sz + y } ensures { 0 <= result <= 1 } ensures { forall j. (j < offset x \/ offset x + sz <= j) -> (pelts x)[j] = old (pelts x)[j] } writes { x.data.elts } = let ghost ox = { x } in let ref c = 0 in let ref lx = C.get x in let ref i = 1 in let res = add_mod lx y in C.set x res; if (res < lx) then begin c <- 1; assert { radix + res = lx + y }; while i < sz do invariant { 1 <= i <= sz } invariant { 0 <= c <= 1 } invariant { c = 1 \/ i = sz } invariant { value x i + (power radix i) * c = value ox i + y } invariant { forall j. (j < offset x \/ offset x + i <= j) -> (pelts x)[j] = old (pelts x)[j] } variant { sz - i } assert { c = 1 }; lx <- get_ofs x i; assert { lx = (pelts ox)[offset ox + i] }; let res = add_mod lx 1 in value_sub_update_no_change (pelts x) (x.offset + p2i i) (x.offset + p2i i + 1) (x.offset + p2i sz) res; set_ofs x i res; assert { forall j. i < j < sz -> (pelts x)[x.offset + j] = (pelts ox)[x.offset + j] }; assert { value x i + (power radix i) * c = value ox i + y }; value_tail x i; value_tail ox i; i <- i + 1; if (res <> 0) then begin c <- 0; assert { res = lx + 1 }; assert { value x i = value ox i + y }; break end else begin assert { radix + res = lx + 1 }; assert { value x i + power radix i = value ox i + y }; end; done; end; value_concat x i sz; value_concat ox i sz; assert { forall j. x.offset + i <= j < x.offset + sz -> (pelts x)[j] = (pelts ox)[j] by let k = j - x.offset in i <= k < sz so (pelts x)[x.offset + k] = (pelts ox)[x.offset + k]}; value_sub_frame (pelts x) (pelts ox) (x.offset + p2i i) (x.offset + p2i sz); c end
Generated by why3doc 1.7.0