2014-01-27 17:39:34 +01:00
|
|
|
(** {1 Arrays with bounded-size integers}
|
|
|
|
|
|
|
|
|
|
Note: We currently duplicate code to get the various modules below
|
|
|
|
|
but we should eventually be able to implement a single module and
|
|
|
|
|
then to clone it. *)
|
2014-01-16 11:24:18 +01:00
|
|
|
|
|
|
|
|
(** {2 Arrays with 32-bit indices} *)
|
|
|
|
|
|
|
|
|
|
module Array32
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int32
|
|
|
|
|
use map.Map as M
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2019-05-14 15:00:35 +02:00
|
|
|
type array [@extraction:array] 'a = private {
|
2016-03-09 16:50:38 +01:00
|
|
|
mutable ghost elts : int -> 'a;
|
2015-08-24 15:36:41 +02:00
|
|
|
length : int32;
|
2017-06-08 13:50:07 +02:00
|
|
|
} invariant { 0 <= length }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2016-03-09 16:50:38 +01:00
|
|
|
function ([]) (a: array 'a) (i: int) : 'a = a.elts i
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val ([]) (a: array 'a) (i: int32) : 'a
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { result = a[i] }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val ([]<-) (a: array 'a) (i: int32) (v: 'a) : unit writes {a}
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
2018-06-15 16:45:31 +02:00
|
|
|
ensures { a.elts = M.set (old a.elts) i v }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
|
|
|
|
(** unsafe get/set operations with no precondition *)
|
2017-12-15 18:10:56 +01:00
|
|
|
|
2014-01-16 11:24:18 +01:00
|
|
|
exception OutOfBounds
|
|
|
|
|
|
|
|
|
|
let defensive_get (a: array 'a) (i: int32)
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { 0 <= i < a.length }
|
|
|
|
|
ensures { result = a[i] }
|
|
|
|
|
raises { OutOfBounds -> i < 0 \/ i >= a.length }
|
2014-01-16 11:24:18 +01:00
|
|
|
= if i < of_int 0 || i >= length a then raise OutOfBounds;
|
|
|
|
|
a[i]
|
|
|
|
|
|
|
|
|
|
let defensive_set (a: array 'a) (i: int32) (v: 'a)
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { 0 <= i < a.length }
|
2018-06-15 16:45:31 +02:00
|
|
|
ensures { a.elts = M.set (old a.elts) i v }
|
2018-02-17 10:46:39 +01:00
|
|
|
raises { OutOfBounds -> (i < 0 \/ i >= a.length) /\ a = old a }
|
2014-01-16 11:24:18 +01:00
|
|
|
= if i < of_int 0 || i >= length a then raise OutOfBounds;
|
|
|
|
|
a[i] <- v
|
|
|
|
|
|
2019-05-14 15:00:35 +02:00
|
|
|
val make [@extraction:array_make] (n: int32) (v: 'a) : array 'a
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:array creation size] n >= 0 }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < n -> result[i] = v }
|
2016-03-07 18:06:43 +01:00
|
|
|
ensures { result.length = n }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val append (a1: array 'a) (a2: array 'a) : array 'a
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { result.length = a1.length + a2.length }
|
|
|
|
|
ensures { forall i:int. 0 <= i < a1.length -> result[i] = a1[i] }
|
|
|
|
|
ensures { forall i:int. 0 <= i < a2.length ->
|
|
|
|
|
result[a1.length + i] = a2[i] }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val sub (a: array 'a) (ofs: int32) (len: int32) : array 'a
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs /\ 0 <= len }
|
|
|
|
|
requires { ofs + len <= a.length }
|
2014-01-16 11:24:18 +01:00
|
|
|
ensures { result.length = len }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < len ->
|
|
|
|
|
result[i] = a[ofs + i] }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val copy (a: array 'a) : array 'a
|
2014-01-16 11:24:18 +01:00
|
|
|
ensures { result.length = a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < result.length -> result[i] = a[i] }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2017-01-31 19:18:09 +01:00
|
|
|
val fill (a: array 'a) (ofs: int32) (len: int32) (v: 'a) : unit writes {a}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs /\ 0 <= len }
|
|
|
|
|
requires { ofs + len <= a.length }
|
2014-01-16 11:24:18 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs \/
|
|
|
|
|
ofs + len <= i < a.length) -> a[i] = (old a)[i] }
|
|
|
|
|
ensures { forall i:int. ofs <= i < ofs + len ->
|
2014-01-16 11:24:18 +01:00
|
|
|
a[i] = v }
|
|
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val blit (a1: array 'a) (ofs1: int32)
|
2014-01-16 11:24:18 +01:00
|
|
|
(a2: array 'a) (ofs2: int32) (len: int32) : unit writes {a2}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs1 /\ 0 <= len }
|
|
|
|
|
requires { ofs1 + len <= a1.length }
|
|
|
|
|
requires { 0 <= ofs2 /\
|
|
|
|
|
ofs2 + len <= a2.length }
|
2014-01-16 11:24:18 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs2 \/
|
|
|
|
|
ofs2 + len <= i < a2.length) ->
|
2014-01-16 11:24:18 +01:00
|
|
|
a2[i] = (old a2)[i] }
|
|
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
ofs2 <= i < ofs2 + len ->
|
|
|
|
|
a2[i] = a1[ofs1 + i - ofs2] }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val self_blit (a: array 'a) (ofs1: int32) (ofs2: int32) (len: int32) : unit
|
2014-01-16 11:24:18 +01:00
|
|
|
writes {a}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs1 /\ 0 <= len /\
|
|
|
|
|
ofs1 + len <= a.length }
|
|
|
|
|
requires { 0 <= ofs2 /\ ofs2 + len <= a.length }
|
2014-01-16 11:24:18 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs2 \/
|
|
|
|
|
ofs2 + len <= i < a.length) -> a[i] = (old a)[i] }
|
2014-01-16 11:24:18 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
ofs2 <= i < ofs2 + len ->
|
|
|
|
|
a[i] = (old a)[ofs1 + i - ofs2] }
|
2014-01-16 11:24:18 +01:00
|
|
|
|
|
|
|
|
end
|
2014-01-27 17:39:34 +01:00
|
|
|
|
|
|
|
|
(** {2 Arrays with 31-bit indices} *)
|
|
|
|
|
|
|
|
|
|
module Array31
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int31
|
|
|
|
|
use map.Map as M
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
type array 'a = private {
|
2016-03-09 16:50:38 +01:00
|
|
|
mutable ghost elts : int -> 'a;
|
2015-08-24 15:36:41 +02:00
|
|
|
length : int31;
|
2017-06-08 13:50:07 +02:00
|
|
|
} invariant { 0 <= length }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2016-03-09 16:50:38 +01:00
|
|
|
function ([]) (a: array 'a) (i: int) : 'a = a.elts i
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val ([]) (a: array 'a) (i: int31) : 'a
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { result = a[i] }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val ([]<-) (a: array 'a) (i: int31) (v: 'a) : unit writes {a}
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
2018-06-15 16:45:31 +02:00
|
|
|
ensures { a.elts = M.set (old a.elts) i v }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
|
|
|
|
(** unsafe get/set operations with no precondition *)
|
2017-12-15 18:10:56 +01:00
|
|
|
|
2014-01-27 17:39:34 +01:00
|
|
|
exception OutOfBounds
|
|
|
|
|
|
|
|
|
|
let defensive_get (a: array 'a) (i: int31)
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { 0 <= i < a.length }
|
|
|
|
|
ensures { result = a[i] }
|
|
|
|
|
raises { OutOfBounds -> i < 0 \/ i >= a.length }
|
2014-01-27 17:39:34 +01:00
|
|
|
= if i < of_int 0 || i >= length a then raise OutOfBounds;
|
|
|
|
|
a[i]
|
|
|
|
|
|
|
|
|
|
let defensive_set (a: array 'a) (i: int31) (v: 'a)
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { 0 <= i < a.length }
|
2018-06-15 16:45:31 +02:00
|
|
|
ensures { a.elts = M.set (old a.elts) i v }
|
2018-02-17 10:46:39 +01:00
|
|
|
raises { OutOfBounds -> (i < 0 \/ i >= a.length) /\ a = old a }
|
2014-01-27 17:39:34 +01:00
|
|
|
= if i < of_int 0 || i >= length a then raise OutOfBounds;
|
|
|
|
|
a[i] <- v
|
|
|
|
|
|
2016-03-07 18:06:43 +01:00
|
|
|
val make (n: int31) (v: 'a) : array 'a
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:array creation size] n >= 0 }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < n -> result[i] = v }
|
2016-03-07 18:06:43 +01:00
|
|
|
ensures { result.length = n }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val append (a1: array 'a) (a2: array 'a) : array 'a
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { result.length = a1.length + a2.length }
|
|
|
|
|
ensures { forall i:int. 0 <= i < a1.length -> result[i] = a1[i] }
|
|
|
|
|
ensures { forall i:int. 0 <= i < a2.length ->
|
|
|
|
|
result[a1.length + i] = a2[i] }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val sub (a: array 'a) (ofs: int31) (len: int31) : array 'a
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs /\ 0 <= len }
|
|
|
|
|
requires { ofs + len <= a.length }
|
2014-01-27 17:39:34 +01:00
|
|
|
ensures { result.length = len }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < len ->
|
|
|
|
|
result[i] = a[ofs + i] }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val copy (a: array 'a) : array 'a
|
2014-01-27 17:39:34 +01:00
|
|
|
ensures { result.length = a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < result.length -> result[i] = a[i] }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2021-03-12 20:56:41 +01:00
|
|
|
val fill (a: array 'a) (ofs: int31) (len: int31) (v: 'a) : unit writes {a}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs /\ 0 <= len }
|
|
|
|
|
requires { ofs + len <= a.length }
|
2014-01-27 17:39:34 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs \/
|
|
|
|
|
ofs + len <= i < a.length) -> a[i] = (old a)[i] }
|
|
|
|
|
ensures { forall i:int. ofs <= i < ofs + len ->
|
2014-01-27 17:39:34 +01:00
|
|
|
a[i] = v }
|
|
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val blit (a1: array 'a) (ofs1: int31)
|
2014-01-27 17:39:34 +01:00
|
|
|
(a2: array 'a) (ofs2: int31) (len: int31) : unit writes {a2}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs1 /\ 0 <= len }
|
|
|
|
|
requires { ofs1 + len <= a1.length }
|
|
|
|
|
requires { 0 <= ofs2 /\
|
|
|
|
|
ofs2 + len <= a2.length }
|
2014-01-27 17:39:34 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs2 \/
|
|
|
|
|
ofs2 + len <= i < a2.length) ->
|
2014-01-27 17:39:34 +01:00
|
|
|
a2[i] = (old a2)[i] }
|
|
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
ofs2 <= i < ofs2 + len ->
|
|
|
|
|
a2[i] = a1[ofs1 + i - ofs2] }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val self_blit (a: array 'a) (ofs1: int31) (ofs2: int31) (len: int31) : unit
|
2014-01-27 17:39:34 +01:00
|
|
|
writes {a}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs1 /\ 0 <= len /\
|
|
|
|
|
ofs1 + len <= a.length }
|
|
|
|
|
requires { 0 <= ofs2 /\ ofs2 + len <= a.length }
|
2014-01-27 17:39:34 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs2 \/
|
|
|
|
|
ofs2 + len <= i < a.length) -> a[i] = (old a)[i] }
|
2014-01-27 17:39:34 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
ofs2 <= i < ofs2 + len ->
|
|
|
|
|
a[i] = (old a)[ofs1 + i - ofs2] }
|
2014-01-27 17:39:34 +01:00
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2018-05-14 15:59:30 +02:00
|
|
|
(** {2 Arrays with 63-bit indices}
|
|
|
|
|
|
2018-06-14 08:10:07 +02:00
|
|
|
Contrary to arrays from module `Array`, the contents of the array
|
2018-05-14 15:59:30 +02:00
|
|
|
is here modeled as a sequence. It makes it easier to resuse existing
|
|
|
|
|
functions over sequences. (We may consider doing this for regular arrays
|
|
|
|
|
as well in the future.)
|
|
|
|
|
|
2018-06-14 08:10:07 +02:00
|
|
|
A coercion is declared so that an array `a` can be used
|
|
|
|
|
as a sequence. As a consequence, notation `a[i]` in the logic is
|
|
|
|
|
directly that of sequences. You have to import module `seq.Seq` to be
|
2018-05-14 15:59:30 +02:00
|
|
|
able to use it.
|
|
|
|
|
*)
|
2014-03-13 14:27:39 +01:00
|
|
|
|
|
|
|
|
module Array63
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int63
|
|
|
|
|
use seq.Seq
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
type array 'a = private {
|
2018-05-14 15:59:30 +02:00
|
|
|
mutable ghost elts : seq 'a;
|
2015-08-24 15:36:41 +02:00
|
|
|
length : int63;
|
2018-05-14 15:59:30 +02:00
|
|
|
} invariant { 0 <= length = Seq.length elts }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2018-05-14 15:59:30 +02:00
|
|
|
meta coercion function elts
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val ([]) (a: array 'a) (i: int63) : 'a
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { result = a[i] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val ([]<-) (a: array 'a) (i: int63) (v: 'a) : unit writes {a}
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { a.elts = (old a.elts)[i <- v] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
|
|
|
|
(** unsafe get/set operations with no precondition *)
|
2017-12-15 18:10:56 +01:00
|
|
|
|
2014-03-13 14:27:39 +01:00
|
|
|
exception OutOfBounds
|
|
|
|
|
|
|
|
|
|
let defensive_get (a: array 'a) (i: int63)
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { 0 <= i < a.length }
|
|
|
|
|
ensures { result = a[i] }
|
|
|
|
|
raises { OutOfBounds -> i < 0 \/ i >= a.length }
|
2018-11-06 16:54:57 +01:00
|
|
|
= if i < 0 || i >= length a then raise OutOfBounds;
|
2014-03-13 14:27:39 +01:00
|
|
|
a[i]
|
|
|
|
|
|
|
|
|
|
let defensive_set (a: array 'a) (i: int63) (v: 'a)
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { 0 <= i < a.length }
|
|
|
|
|
ensures { a.elts = (old a.elts)[i <- v] }
|
2018-02-17 10:46:39 +01:00
|
|
|
raises { OutOfBounds -> (i < 0 \/ i >= a.length) /\ a = old a }
|
2018-11-06 16:54:57 +01:00
|
|
|
= if i < 0 || i >= length a then raise OutOfBounds;
|
2014-03-13 14:27:39 +01:00
|
|
|
a[i] <- v
|
|
|
|
|
|
2016-03-07 18:06:43 +01:00
|
|
|
val make (n: int63) (v: 'a) : array 'a
|
2018-01-12 18:03:45 +01:00
|
|
|
requires { [@expl:array creation size] n >= 0 }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < n -> result[i] = v }
|
2016-03-07 18:06:43 +01:00
|
|
|
ensures { result.length = n }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val append (a1: array 'a) (a2: array 'a) : array 'a
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { result.length = a1.length + a2.length }
|
|
|
|
|
ensures { forall i:int. 0 <= i < a1.length -> result[i] = a1[i] }
|
|
|
|
|
ensures { forall i:int. 0 <= i < a2.length ->
|
|
|
|
|
result[a1.length + i] = a2[i] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val sub (a: array 'a) (ofs: int63) (len: int63) : array 'a
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs /\ 0 <= len }
|
|
|
|
|
requires { ofs + len <= a.length }
|
2014-03-13 14:27:39 +01:00
|
|
|
ensures { result.length = len }
|
2017-06-19 11:08:48 +02:00
|
|
|
ensures { forall i:int. 0 <= i < len -> result[i] = a[ofs + i] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val copy (a: array 'a) : array 'a
|
2014-03-13 14:27:39 +01:00
|
|
|
ensures { result.length = a.length }
|
2017-06-08 13:50:07 +02:00
|
|
|
ensures { forall i:int. 0 <= i < result.length -> result[i] = a[i] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val fill (a: array 'a) (ofs: int63) (len: int63) (v: 'a) : unit
|
2017-01-31 19:18:09 +01:00
|
|
|
writes { a }
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs /\ 0 <= len }
|
|
|
|
|
requires { ofs + len <= a.length }
|
2014-03-13 14:27:39 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs \/
|
|
|
|
|
ofs + len <= i < a.length) -> a[i] = (old a)[i] }
|
|
|
|
|
ensures { forall i:int. ofs <= i < ofs + len ->
|
2014-03-13 14:27:39 +01:00
|
|
|
a[i] = v }
|
|
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val blit (a1: array 'a) (ofs1: int63)
|
2014-03-13 14:27:39 +01:00
|
|
|
(a2: array 'a) (ofs2: int63) (len: int63) : unit writes {a2}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs1 /\ 0 <= len }
|
|
|
|
|
requires { ofs1 + len <= a1.length }
|
|
|
|
|
requires { 0 <= ofs2 /\
|
|
|
|
|
ofs2 + len <= a2.length }
|
2014-03-13 14:27:39 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs2 \/
|
|
|
|
|
ofs2 + len <= i < a2.length) ->
|
2014-03-13 14:27:39 +01:00
|
|
|
a2[i] = (old a2)[i] }
|
|
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
ofs2 <= i < ofs2 + len ->
|
|
|
|
|
a2[i] = a1[ofs1 + i - ofs2] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2015-08-24 15:36:41 +02:00
|
|
|
val self_blit (a: array 'a) (ofs1: int63) (ofs2: int63) (len: int63) : unit
|
2014-03-13 14:27:39 +01:00
|
|
|
writes {a}
|
2017-06-08 13:50:07 +02:00
|
|
|
requires { 0 <= ofs1 /\ 0 <= len /\
|
|
|
|
|
ofs1 + len <= a.length }
|
|
|
|
|
requires { 0 <= ofs2 /\ ofs2 + len <= a.length }
|
2014-03-13 14:27:39 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
(0 <= i < ofs2 \/
|
|
|
|
|
ofs2 + len <= i < a.length) -> a[i] = (old a)[i] }
|
2014-03-13 14:27:39 +01:00
|
|
|
ensures { forall i:int.
|
2017-06-08 13:50:07 +02:00
|
|
|
ofs2 <= i < ofs2 + len ->
|
|
|
|
|
a[i] = (old a)[ofs1 + i - ofs2] }
|
2014-03-13 14:27:39 +01:00
|
|
|
|
2018-05-31 13:20:39 +02:00
|
|
|
let init (n: int63) (f: int63 -> 'a) : array 'a
|
|
|
|
|
requires { [@expl:array creation size] n >= 0 }
|
|
|
|
|
ensures { forall i: int63. 0 <= i < n -> result[i] = f i }
|
|
|
|
|
ensures { length result = n }
|
|
|
|
|
= let a = make n (f 0) in
|
|
|
|
|
for i = 1 to n - 1 do
|
|
|
|
|
invariant { forall j: int63. 0 <= j < i -> a[j] = f j }
|
|
|
|
|
a[i] <- f i
|
|
|
|
|
done;
|
|
|
|
|
a
|
|
|
|
|
|
2014-03-13 14:27:39 +01:00
|
|
|
end
|
|
|
|
|
|
2017-05-04 10:18:18 +02:00
|
|
|
module Array63Exchange
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int63
|
|
|
|
|
use Array63
|
|
|
|
|
use seq.Exchange as SE
|
2017-05-04 10:18:18 +02:00
|
|
|
|
|
|
|
|
predicate exchange (a1 a2: array 'a) (i j: int) =
|
2018-05-14 15:59:30 +02:00
|
|
|
SE.exchange a1.elts a2.elts i j
|
2018-06-14 08:10:07 +02:00
|
|
|
(** `exchange a1 a2 i j` means that arrays `a1` and `a2` only differ
|
|
|
|
|
by the swapping of elements at indices `i` and `j` *)
|
2017-05-04 10:18:18 +02:00
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
module Array63Swap
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int63
|
|
|
|
|
use Array63
|
2017-05-04 10:18:18 +02:00
|
|
|
use export Array63Exchange
|
|
|
|
|
|
|
|
|
|
let swap (a:array 'a) (i j:int63) : unit
|
|
|
|
|
requires { 0 <= i < length a /\ 0 <= j < length a }
|
|
|
|
|
writes { a }
|
|
|
|
|
ensures { exchange (old a) a i j }
|
|
|
|
|
= let v = a[i] in
|
|
|
|
|
a[i] <- a[j];
|
|
|
|
|
a[j] <- v
|
|
|
|
|
|
|
|
|
|
end
|
|
|
|
|
|
2017-04-04 15:57:42 +02:00
|
|
|
module Array63Permut
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int63
|
|
|
|
|
use Array63
|
|
|
|
|
use seq.Seq
|
|
|
|
|
use seq.SeqEq
|
|
|
|
|
use seq.Permut as SP
|
|
|
|
|
use Array63Exchange
|
2017-04-04 15:57:42 +02:00
|
|
|
|
|
|
|
|
predicate permut (a1 a2: array 'a) (l u: int) =
|
2018-05-14 15:59:30 +02:00
|
|
|
SP.permut a1.elts a2.elts l u
|
2018-06-14 08:10:07 +02:00
|
|
|
(** `permut a1 a2 l u` is true when the segment
|
|
|
|
|
`a1(l..u-1)` is a permutation of the segment `a2(l..u-1)`.
|
|
|
|
|
Values outside of the interval `(l..u-1)` are ignored. *)
|
2017-04-04 15:57:42 +02:00
|
|
|
|
|
|
|
|
predicate array_eq (a1 a2: array 'a) (l u: int) =
|
2018-05-14 15:59:30 +02:00
|
|
|
seq_eq_sub a1.elts a2.elts l u
|
2017-04-04 15:57:42 +02:00
|
|
|
|
|
|
|
|
predicate permut_sub (a1 a2: array 'a) (l u: int) =
|
2018-05-14 15:59:30 +02:00
|
|
|
seq_eq_sub a1.elts a2.elts 0 l /\
|
2017-04-04 15:57:42 +02:00
|
|
|
permut a1 a2 l u /\
|
2018-05-14 15:59:30 +02:00
|
|
|
seq_eq_sub a1.elts a2.elts u (length a1)
|
2018-06-14 08:10:07 +02:00
|
|
|
(** `permut_sub a1 a2 l u` is true when the segment
|
|
|
|
|
`a1(l..u-1)` is a permutation of the segment `a2(l..u-1)`
|
|
|
|
|
and values outside of the interval `(l..u-1)` are equal. *)
|
2017-04-04 15:57:42 +02:00
|
|
|
|
|
|
|
|
predicate permut_all (a1 a2: array 'a) =
|
2018-05-14 15:59:30 +02:00
|
|
|
SP.permut a1.elts a2.elts 0 a1.length
|
2018-06-14 08:10:07 +02:00
|
|
|
(** `permut_all a1 a2 l u` is true when array `a1` is a permutation
|
|
|
|
|
of array `a2`. *)
|
2017-04-04 15:57:42 +02:00
|
|
|
|
|
|
|
|
(** we can always enlarge the interval *)
|
|
|
|
|
lemma permut_sub_weakening:
|
|
|
|
|
forall a1 a2: array 'a, l1 u1 l2 u2: int.
|
|
|
|
|
permut_sub a1 a2 l1 u1 -> 0 <= l2 <= l1 -> u1 <= u2 <= length a1 ->
|
|
|
|
|
permut_sub a1 a2 l2 u2
|
|
|
|
|
|
|
|
|
|
lemma exchange_permut_sub:
|
|
|
|
|
forall a1 a2: array 'a, i j l u: int.
|
|
|
|
|
exchange a1 a2 i j -> l <= i < u -> l <= j < u ->
|
|
|
|
|
0 <= l -> u <= length a1 -> permut_sub a1 a2 l u
|
|
|
|
|
|
|
|
|
|
lemma exchange_permut_all:
|
|
|
|
|
forall a1 a2: array 'a, i j: int.
|
|
|
|
|
exchange a1 a2 i j -> permut_all a1 a2
|
|
|
|
|
|
|
|
|
|
end
|
2018-05-14 15:59:30 +02:00
|
|
|
|
2018-05-17 21:41:41 +02:00
|
|
|
(** {2 Arrays of 63-bit integers}
|
|
|
|
|
|
2018-06-14 08:10:07 +02:00
|
|
|
Here the model is simply a sequence of integers (of type `int`),
|
|
|
|
|
instead of being a sequence of values of type `int63`.
|
2018-05-17 21:41:41 +02:00
|
|
|
|
|
|
|
|
As a consequence, we have to provide the additional information
|
|
|
|
|
that each of the element fits within the bounds of 63-bit integers.
|
|
|
|
|
|
2018-06-14 08:10:07 +02:00
|
|
|
Caveat: type `array63` below is not compatible with type
|
|
|
|
|
`Array63.array int63`.
|
2018-05-17 21:41:41 +02:00
|
|
|
*)
|
|
|
|
|
|
|
|
|
|
module ArrayInt63
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use int.Int
|
|
|
|
|
use mach.int.Int63
|
|
|
|
|
use seq.Seq
|
2018-05-17 21:41:41 +02:00
|
|
|
|
|
|
|
|
type array63 = private {
|
|
|
|
|
mutable ghost elts: seq int;
|
|
|
|
|
ghost size: int;
|
|
|
|
|
} invariant { 0 <= size = length elts <= max_int }
|
|
|
|
|
invariant { forall i. 0 <= i < length elts -> in_bounds elts[i] }
|
|
|
|
|
|
|
|
|
|
meta coercion function elts
|
|
|
|
|
|
|
|
|
|
val length (a: array63) : int63
|
|
|
|
|
ensures { to_int result = a.length }
|
|
|
|
|
|
|
|
|
|
val ([]) (a: array63) (i: int63) : int63
|
|
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
|
|
|
|
ensures { to_int result = a[i] }
|
|
|
|
|
|
|
|
|
|
val ([]<-) (a: array63) (i: int63) (v: int63) : unit
|
|
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
|
|
|
|
writes { a }
|
|
|
|
|
ensures { a.elts = (old a.elts)[i <- to_int v] }
|
|
|
|
|
|
2020-07-02 15:46:44 +02:00
|
|
|
val ghost set (a: array63) (i: int63) (v: int63) : array63
|
|
|
|
|
requires { [@expl:index in array bounds] 0 <= i < a.length }
|
|
|
|
|
ensures { result.length = a.length }
|
|
|
|
|
ensures { result.elts = a.elts[i <- to_int v] }
|
|
|
|
|
|
2018-05-17 21:41:41 +02:00
|
|
|
val make (n: int63) (v: int63) : array63
|
|
|
|
|
requires { [@expl:array creation size] n >= 0 }
|
|
|
|
|
ensures { forall i. 0 <= i < n -> result[i] = to_int v }
|
|
|
|
|
ensures { result.length = n }
|
|
|
|
|
|
|
|
|
|
val copy (a: array63) : array63
|
|
|
|
|
ensures { result.length = a.length }
|
|
|
|
|
ensures { forall i. 0 <= i < result.length -> result[i] = a[i] }
|
|
|
|
|
|
2020-06-30 18:31:13 +02:00
|
|
|
let sub (a: array63) (ofs: int63) (len: int63) : array63
|
|
|
|
|
requires { 0 <= ofs /\ 0 <= len /\ ofs + len <= length a }
|
|
|
|
|
ensures { length result = len }
|
|
|
|
|
ensures { forall i. 0 <= i < len -> result[i] = a[ofs + i] }
|
|
|
|
|
=
|
|
|
|
|
let b = make len 0 in
|
|
|
|
|
for i = 0 to len - 1 do
|
|
|
|
|
invariant { forall k. 0 <= k < i -> b[k] = a[ofs+k] }
|
|
|
|
|
b[i] <- a[ofs + i];
|
|
|
|
|
done;
|
|
|
|
|
b
|
|
|
|
|
|
2018-06-15 16:45:31 +02:00
|
|
|
use seq.Exchange
|
2018-05-31 13:20:39 +02:00
|
|
|
|
|
|
|
|
let swap (a:array63) (i j:int63) : unit
|
|
|
|
|
requires { 0 <= i < length a /\ 0 <= j < length a }
|
|
|
|
|
writes { a }
|
|
|
|
|
ensures { exchange (old a) a i j }
|
|
|
|
|
= let v = a[i] in
|
|
|
|
|
a[i] <- a[j];
|
|
|
|
|
a[j] <- v
|
|
|
|
|
|
2020-06-30 18:31:13 +02:00
|
|
|
let init (n: int63) (f: int63 -> int63) : array63
|
|
|
|
|
requires { [@expl:array creation size] n >= 0 }
|
|
|
|
|
ensures { forall i: int63. 0 <= i < n -> result[i] = f i }
|
|
|
|
|
ensures { length result = n }
|
|
|
|
|
=
|
|
|
|
|
let a = make n 0 in
|
|
|
|
|
for i = 0 to n - 1 do
|
|
|
|
|
invariant { forall k: int63. 0 <= k < i -> a[k] = f k }
|
|
|
|
|
a[i] <- f i
|
|
|
|
|
done;
|
|
|
|
|
a
|
|
|
|
|
|
2018-05-17 21:41:41 +02:00
|
|
|
end
|