9 (** {3 Complements to map standard library} *)
11 predicate map_eq_sub_shift (x y:map int 'a) (xi yi sz:int) =
12 forall i. 0 <= i < sz -> x[xi+i] = y[yi+i]
14 let lemma map_eq_shift (x y:map int 'a) (xi yi sz k:int)
15 requires { map_eq_sub_shift x y xi yi sz }
16 requires { 0 <= k < sz }
17 ensures { x[xi+k] = y[yi+k] }
20 let rec lemma map_eq_shift_zero (x y: map int 'a) (n m: int)
21 requires { map_eq_sub_shift x y n n (m-n) }
23 ensures { MapEq.map_eq_sub x y n m }
27 assert { forall i. 0 <= i < m-n -> x[n+i] = y[n+i] };
28 assert { forall i. n <= i < m ->
29 let j = i - n in 0 <= j < m-n ->
30 x[n+j] = y[n+j] -> x[i] = y[i]};
31 map_eq_shift_zero x y (n+1) m;
37 use import mach.int.UInt64GMP as Limb
45 meta compute_max_steps 0x100000
47 (** {3 Long integers as arrays of libs} *)
49 lemma limb_max_bound: 1 <= max_uint64
51 function l2i (x:limb) : int = Limb.to_int x
53 function p2i (i:int32) : int = int32'int i
55 let lemma prod_compat_strict_r (a b c:int)
56 requires { 0 <= a < b }
58 ensures { c * a < c * b }
61 let lemma prod_compat_r (a b c:int)
62 requires { 0 <= a <= b }
64 ensures { c * a <= c * b }
67 let lemma prod_compat_strict_lr (a b c d:int)
68 requires { 0 <= a < b }
69 requires { 0 <= c < d }
70 ensures { a * c < b * d }
71 = () (* assert { a * c < a * d = d * a < d * b = b * d } *)
73 meta remove_prop axiom prod_compat_strict_lr
75 let lemma prod_compat_lr (a b c d:int)
76 requires { 0 <= a <= b }
77 requires { 0 <= c <= d }
78 ensures { a * c <= b * d }
81 meta remove_prop axiom prod_compat_lr
83 let lemma simp_compat_strict_l (a b c:int)
84 requires { 0 <= a * b < a * c }
89 meta remove_prop axiom simp_compat_strict_l
91 (** {3 Integer value of a natural number} *)
93 (** `value_sub x n m` denotes the integer represented by
94 the digits `x[n..m-1]` with lsb at index n *)
95 let rec ghost function value_sub (x:map int limb) (n:int) (m:int) : int
99 l2i x[n] + radix * value_sub x (n+1) m
102 let rec lemma value_sub_frame (x y:map int limb) (n m:int)
103 requires { MapEq.map_eq_sub x y n m }
105 ensures { value_sub x n m = value_sub y n m }
107 if n < m then value_sub_frame x y (n+1) m else ()
109 let rec lemma value_sub_frame_shift (x y:map int limb) (xi yi sz:int)
110 requires { map_eq_sub_shift x y xi yi sz }
112 ensures { value_sub x xi (xi+sz) = value_sub y yi (yi+sz) }
116 map_eq_shift x y xi yi sz 0;
117 assert { forall i. 0 <= i < sz-1 ->
118 let j = 1+i in x[xi+j] = y[yi+j] };
119 value_sub_frame_shift x y (xi+1) (yi+1) (sz-1)
121 else assert { 1+2 = 3 }
123 let rec lemma value_sub_tail (x:map int limb) (n m:int)
127 value_sub x n (m+1) =
128 value_sub x n m + (Map.get x m) * power radix (m-n) }
129 = [@vc:sp] if n < m then value_sub_tail x (n+1) m else ()
131 let rec lemma value_sub_concat (x:map int limb) (n m l:int)
132 requires { n <= m <= l}
136 value_sub x n m + value_sub x m l * power radix (m-n) }
141 value_sub_concat x (n+1) m l
145 let lemma value_sub_head (x:map int limb) (n m:int)
147 ensures { value_sub x n m = x[n] + radix * value_sub x (n+1) m }
148 = value_sub_concat x n (n+1) m
150 let lemma value_sub_update (x:map int limb) (i n m:int) (v:limb)
151 requires { n <= i < m }
153 value_sub (Map.set x i v) n m =
154 value_sub x n m + power radix (i - n) * (v -(Map.get x i))
156 = assert { MapEq.map_eq_sub x (Map.set x i v) n i };
157 assert { MapEq.map_eq_sub x (Map.set x i v) (i+1) m };
158 value_sub_concat x n i m;
159 value_sub_concat (Map.set x i v) n i m;
160 value_sub_head x i m;
161 value_sub_head (Map.set x i v) i m
163 let rec lemma value_zero (x:map int limb) (n m:int)
164 requires { MapEq.map_eq_sub x (Const.const Limb.zero_unsigned) n m }
166 ensures { value_sub x n m = 0 }
167 = if n < m then value_zero x (n+1) m else ()
169 let lemma value_sub_update_no_change (x: map int limb) (i n m: int) (v:limb)
171 requires { i < n \/ m <= i }
172 ensures { value_sub x n m = value_sub (Map.set x i v) n m }
173 = value_sub_frame x (Map.set x i v) n m
175 let lemma value_sub_shift_no_change (x:map int limb) (ofs i sz:int) (v:limb)
176 requires { i < 0 \/ sz <= i }
178 ensures { value_sub x ofs (ofs + sz) =
179 value_sub (Map.set x (ofs+i) v) ofs (ofs+sz) }
180 = value_sub_frame_shift x (Map.set x (ofs+i) v) ofs ofs sz
182 (** {3 Comparisons} *)
184 let rec lemma value_sub_lower_bound (x:map int limb) (x1 x2:int)
186 ensures { 0 <= value_sub x x1 x2 }
187 = if x2 <= x1 then () else
189 value_sub_head x x1 x2;
190 value_sub_lower_bound x (x1+1) x2
193 let rec lemma value_sub_upper_bound (x:map int limb) (x1 x2:int)
194 requires { x1 <= x2 }
196 ensures { value_sub x x1 x2 < power radix (x2 - x1) }
197 = if x1 = x2 then () else
199 value_sub_tail x x1 (x2-1);
200 assert { value_sub x x1 x2
201 <= value_sub x x1 (x2-1) + power radix (x2-x1-1) * (radix - 1) };
202 value_sub_upper_bound x x1 (x2-1)
205 let lemma value_sub_lower_bound_tight (x:map int limb) (x1 x2:int)
207 ensures { power radix (x2-x1-1) * l2i (Map.get x (x2-1)) <= value_sub x x1 x2 }
208 = assert { value_sub x x1 x2 = value_sub x x1 (x2-1)
209 + power radix (x2-x1-1) * l2i (Map.get x (x2-1)) }
211 let lemma value_sub_upper_bound_tight (x:map int limb) (x1 x2:int)
213 ensures { value_sub x x1 x2 < power radix (x2-x1-1) * (l2i (Map.get x (x2-1)) + 1) }
214 = value_sub_upper_bound x x1 (x2-1)
216 function value (x:t) (sz:int) : int =
217 value_sub (pelts x) x.offset (x.offset + sz)
219 let lemma value_tail (x:t) (sz:int32)
221 ensures { value x (sz+1) = value x sz + (pelts x)[x.offset + sz] * power radix sz }
222 = value_sub_tail (pelts x) x.offset (x.offset + p2i sz)
224 meta remove_prop axiom value_tail
226 let lemma value_concat (x:t) (n m:int32)
227 requires { 0 <= n <= m }
229 = value x n + power radix n
230 * value_sub (pelts x) (x.offset + n) (x.offset + m) }
232 = value_sub_concat (pelts x) x.offset (x.offset + p2i n) (x.offset + p2i m)
235 let lemma value_sub_eq (x1 x2: map int limb) (n1 n2 m1 m2: int)
239 ensures { value_sub x1 n1 m1 = value_sub x2 n2 m2 }
242 meta remove_prop axiom value_sub_eq