10 use import mach.int.UInt64GMP as Limb
17 use stringlemmas.String_lemmas
20 use int.ComputerDivision as CD
21 use int.EuclideanDivision
22 use base_info.BaseInfo
24 let wmpn_set_str_bits (rp: ptr limb) (ghost sz: int32)
25 (sp: ptr uchar) (sn: uint32)
26 (bits: uint32) : int32
27 requires { 0 < sn <= max_int32 }
29 requires { valid rp sz }
30 requires { valid sp sn }
31 requires { 1 <= bits <= 8 }
32 requires { power 2 (bits * sn) <= power radix sz }
33 requires { writable rp }
34 requires { in_base (power 2 bits) (pelts sp)
35 (offset sp) (offset sp + sn) }
36 ensures { 0 <= result <= sz }
37 ensures { value rp result = svalue (power 2 bits) sp sn }
38 ensures { result > 0 -> (pelts rp)[offset rp + result - 1] > 0 }
42 let ghost ref rdone : int = 0 in
43 let ref j = UInt32.to_int32 sn in
44 let ghost b = power 2 (uint32'int bits) in
45 assert { bits * sn <= 64 * sz
46 by power 2 (bits * sn) <= power radix sz
47 = power (power 2 64) sz
48 = power 2 (64 * sz) };
49 assert { 2 <= b <= 256
56 invariant { 0 <= j <= sn }
57 invariant { 0 <= rn <= sz }
58 invariant { (sn - j) * bits = rdone }
59 invariant { j > 0 -> if shift = 0 then rdone = 64 * rn
60 else rdone = 64 * rn - 64 + shift }
61 invariant { 0 <= shift < 64 }
62 invariant { shift > 0 ->
63 (pelts rp)[offset rp + rn - 1] < power 2 shift }
64 invariant { rn = 0 -> shift = 0 }
65 invariant { value rp rn
66 = svalue_sub b (pelts sp) (offset sp + j)
70 let ghost orp = pure { rp } in
72 let sj = UChar.to_uint64 (C.get_ofs sp j) in
73 svalue_sub_tail b (pelts sp) (offset sp + int32'int j + 1)
74 (offset sp + uint32'int sn);
75 assert { svalue_sub b (pelts sp) (offset sp + j) (offset sp + sn)
76 = svalue_sub b (pelts sp) (offset sp + j + 1)
78 + power b (sn - (j+1)) * sj
79 = svalue_sub b (pelts sp) (offset sp + j + 1)
82 by power b (sn - (j+1))
83 = power (power 2 bits) (sn - (j+1))
84 = power 2 (bits * (sn - (j+1)))
89 by (sn - (j+1)) * bits = 64 * rn + shift
90 so (sn - (j+1)) * bits
91 = bits * sn - (j+1) * bits
92 <= 64 * sz - (j+1) * bits
94 so 64 * rn < 64 * sz };
96 value_sub_frame (pelts rp) (pelts orp)
97 (offset rp) (offset rp + int32'int rn);
98 assert { value rp rn = value rp rn at StartLoop };
102 assert { (pelts rp)[offset rp + rn - 1]
105 assert { power b (sn - (j+1)) = power radix (rn-1)
106 by power b (sn - (j+1))
107 = power 2 (bits * (sn - (j+1)))
109 = power 2 (64 * (rn-1))
110 = power radix (rn-1) };
111 assert { value rp rn = svalue_sub b (pelts sp) (offset sp + j)
114 = value rp (rn - 1) + power radix (rn - 1) * sj
115 = value orp (rn - 1) + power radix (rn - 1) * sj
116 = svalue_sub b (pelts sp) (offset sp + j + 1)
118 + power radix (rn - 1) * sj
119 = svalue_sub b (pelts sp) (offset sp + j)
123 let rlow = C.get_ofs rp (rn - 1) in
124 assert { rlow < power 2 shift };
125 assert { radix = power 2 (64 - shift) * power 2 shift };
126 let slow = lsl_mod sj (Limb.of_uint32 shift) in
127 assert { slow = power 2 shift * mod sj (power 2 (64 - shift))
128 by slow = mod (sj * power 2 shift) radix
129 = mod (sj * power 2 shift)
130 (power 2 (64 - shift) * power 2 shift)
131 = power 2 shift * mod sj (power 2 (64 - shift)) };
132 assert { rlow + slow < radix
133 by slow = power 2 shift * mod sj (power 2 (64 - shift))
134 <= power 2 shift * (power 2 (64 - shift) - 1)
135 = power 2 shift * power 2 (64 - shift)
137 = radix - power 2 shift };
138 let nr = rlow + slow in
139 C.set_ofs rp (rn-1) nr;
140 let ghost oshift = pure { shift } in
141 shift <- shift + bits;
142 assert { power radix (rn - 1) * power 2 oshift
143 = power b (sn - (j+1))
144 by power radix (rn - 1) = power 2 (64 * (rn - 1))
145 so power radix (rn - 1) * power 2 oshift
146 = power 2 (64 * (rn - 1) + oshift)
147 = power 2 (bits * (sn - (j+1)))
148 = power b (sn - (j+1)) };
154 assert { rdone = 64 * rn + shift - bits };
156 by (sn - (j+1)) * bits = rdone
157 = 64 * rn + shift - bits
158 so bits * sn <= 64 * sz
159 so 64 * rn + shift - bits
160 = sn * bits - (j+1) * bits
161 <= 64 * sz - (j+1) * bits
163 so 64 * rn + shift <= 64 * sz
164 so 64 * rn < 64 * rn + shift };
165 let shigh = lsr_mod sj (Limb.of_uint32 (bits - shift)) in
166 assert { shigh < power 2 shift
167 by shigh = div sj (power 2 (bits - shift))
168 so sj = (power 2 (bits - shift))
169 * div sj (power 2 (bits - shift))
170 + mod sj (power 2 (bits - shift))
171 so power 2 (bits - shift) * shigh
172 = sj - mod sj (power 2 (bits - shift))
174 = power 2 (bits - shift) * power 2 shift
175 so shigh < power 2 shift };
176 assert { slow + radix * shigh = power 2 oshift * sj
177 by slow = mod (power 2 oshift * sj) radix
178 so shigh = div sj (power 2 (bits - shift))
179 so shift = oshift + bits - 64
180 so shigh = div sj (power 2 (64 - oshift))
181 so let m = mod sj (power 2 (64 - oshift)) in
182 sj = power 2 (64 - oshift) * shigh + m
183 so power 2 oshift * sj
184 = power 2 oshift * power 2 (64 - oshift) * shigh
186 = radix * shigh + power 2 oshift * m
187 so 0 <= m < power 2 (64 - oshift)
188 so 0 <= power 2 oshift * m
189 < power 2 oshift * power 2 (64 - oshift)
191 so mod (power 2 oshift * sj) radix
192 = mod (radix * shigh + power 2 oshift * m) radix
193 = mod (power 2 oshift * m) radix
195 so power 2 oshift * m = slow
196 so power 2 oshift * sj = radix * shigh + slow };
197 C.set_ofs rp rn shigh;
198 value_tail rp (rn - 1);
199 value_sub_frame (pelts rp) (pelts orp)
200 (offset rp) (offset rp + int32'int rn - 1);
202 = value orp (rn - 1) + power radix (rn - 1) * nr
203 by (pelts rp)[offset rp + rn - 1] = nr
205 = value rp (rn - 1) + power radix (rn - 1) * nr };
206 value_tail orp (rn - 1);
208 assert { value rp (rn + 1)
209 = svalue_sub b (pelts sp) (offset sp + j) (offset sp + sn)
211 = value rp rn + power radix rn * shigh
212 = value orp (rn - 1) + power radix (rn - 1) * nr
213 + power radix rn * shigh
214 = value orp (rn - 1) + power radix (rn - 1) * rlow
215 + power radix (rn - 1) * slow
216 + power radix rn * shigh
218 + power radix (rn - 1) * slow
219 + power radix rn * shigh
221 + power radix (rn - 1) * (slow + radix * shigh)
223 + power radix (rn - 1) * power 2 oshift * sj
224 = value orp rn + power b (sn - (j+1)) * sj
225 = svalue_sub b (pelts sp)
226 (offset sp + j) (offset sp + sn) };
229 value_tail rp (rn - 1);
230 value_tail orp (rn - 1);
231 assert { slow = power 2 oshift * sj
232 by slow = power 2 oshift * mod sj (power 2 (64 - oshift))
233 so 64 - oshift = bits
234 so 0 <= sj < power 2 bits
235 so mod sj (power 2 (64 - oshift))
236 = mod sj (power 2 bits)
239 = svalue_sub b (pelts sp) (offset sp + j) (offset sp + sn)
241 = value rp (rn - 1) + power radix (rn - 1) * nr
242 = value rp (rn - 1) + power radix (rn - 1) * rlow
243 + power radix (rn - 1) * slow
244 = value orp (rn - 1) + power radix (rn - 1) * rlow
245 + power radix (rn - 1) * slow
246 = value orp rn + power radix (rn - 1) * slow
248 + power radix (rn - 1) * power 2 oshift * sj
249 = value orp rn + power b (sn - (j+1)) * sj
250 = svalue_sub b (pelts sp) (offset sp + j)
254 assert { slow = power 2 oshift * sj
255 by slow = power 2 oshift * mod sj (power 2 (64 - oshift))
256 so oshift + bits < 64
257 so sj < power 2 bits <= power 2 (64 - oshift)
258 so mod sj (power 2 (64 - oshift)) = sj };
259 assert { nr < power 2 shift
261 so rlow < power 2 oshift
262 so rlow + slow < power 2 oshift + power 2 oshift * sj
263 = power 2 oshift * (1 + sj)
264 <= power 2 oshift * power 2 bits
266 value_tail rp (rn - 1);
267 value_tail orp (rn - 1);
269 = svalue_sub b (pelts sp) (offset sp + j) (offset sp + sn)
271 = value rp (rn - 1) + power radix (rn - 1) * nr
272 = value rp (rn - 1) + power radix (rn - 1) * rlow
273 + power radix (rn - 1) * slow
274 = value orp (rn - 1) + power radix (rn - 1) * rlow
275 + power radix (rn - 1) * slow
276 = value orp rn + power radix (rn - 1) * slow
278 + power radix (rn - 1) * power 2 oshift * sj
279 = value orp rn + power b (sn - (j+1)) * sj
280 = svalue_sub b (pelts sp) (offset sp + j)
284 rdone <- rdone + uint32'int bits;
292 let wmpn_set_str_other (rp: ptr limb) (ghost sz: int32)
293 (sp: ptr uchar) (sn: uint32) (b:limb)
294 (info: wmpn_base_info) : int32
295 requires { 0 < sn <= max_int32 }
297 requires { valid rp sz }
298 requires { valid sp sn }
299 requires { 2 <= b <= 256 }
300 requires { power b sn <= power radix sz }
301 requires { writable rp }
302 requires { in_base b (pelts sp) (offset sp) (offset sp + sn) }
303 requires { info.b = b }
304 ensures { svalue b sp sn > 0 -> 1 <= result <= sz }
305 ensures { value rp result = svalue b sp sn }
306 ensures { svalue b sp sn > 0 -> (pelts rp)[offset rp + result - 1] > 0 }
307 ensures { svalue b sp sn = 0 -> result = 1 }
308 ensures { 0 < result }
310 let ref k = 1 + (sn - 1) % info.exp in
312 let ref w = UChar.to_uint64 (C.get sp) in
314 while (k <- k - 1; k) > 0 do
316 invariant { 1 <= k <= sn }
317 invariant { 1 <= j <= sn }
318 invariant { w = svalue_sub b (pelts sp) (offset sp) (offset sp + j) }
319 invariant { 0 <= w < power b j }
320 invariant { j + k - 1 = 1 + mod (sn - 1) info.exp }
321 invariant { int32'int j = uint32'int sn -> k = 1 }
324 assert { j < info.exp };
325 let sj = UChar.to_uint64 (C.get_ofs sp j) in
326 svalue_sub_head (uint64'int b) (pelts sp)
327 (offset sp) (offset sp + int32'int j + 1);
329 = svalue_sub b (pelts sp) (offset sp) (offset sp + j + 1) };
330 assert { w * b + sj < radix
332 = svalue_sub b (pelts sp) (offset sp) (offset sp + j + 1)
335 so power b (j+1) <= power b (info.exp) < radix };
343 = svalue_sub b (pelts sp) (offset sp) (offset sp + j) };
344 assert { j = 1 + mod (sn - 1) info.exp };
345 assert { mod (sn - j) info.exp = 0
347 so mod 1 info.exp = 1
349 = mod (mod 1 info.exp + mod (sn - 1) info.exp) info.exp
351 so let ds = div sn info.exp in
352 let dj = div j info.exp in
353 sn = ds * info.exp + mod sn info.exp
354 so j = dj * info.exp + mod j info.exp
355 so sn - j = (ds - dj) * info.exp
356 so mod (sn - j) info.exp = 0 };
357 while j < UInt32.to_int32 sn do
359 invariant { 0 <= j <= sn }
360 invariant { value rp rn
361 = svalue_sub b (pelts sp) (offset sp)
362 (offset sp + int32'int j) }
363 invariant { j <= sn }
364 invariant { 0 <= rn <= sz }
365 invariant { svalue b sp j > 0 -> (pelts rp)[offset rp + rn - 1] > 0 }
366 invariant { svalue b sp j = 0 -> rn = 1 }
367 invariant { mod (sn - j) info.exp = 0 }
368 w <- UChar.to_uint64 (C.get_ofs sp j);
369 let oj = pure { j } in
370 assert { j + info.exp <= sn };
372 for k = 1 to info.exp - 1 do
373 invariant { w = svalue_sub b (pelts sp) (offset sp + oj)
375 invariant { 1 <= k <= info.exp }
376 invariant { j = oj + k }
377 let sj = UChar.to_uint64 (C.get_ofs sp j) in
378 svalue_sub_head (uint64'int b) (pelts sp) (offset sp + int32'int oj)
379 (offset sp + int32'int j + 1);
380 assert { w * b + sj = svalue_sub b (pelts sp) (offset sp + oj)
381 (offset sp + j + 1) };
382 assert { w * b + sj < radix
383 by svalue_sub b (pelts sp) (offset sp + oj) (offset sp + j + 1)
384 < power b (j + 1 - oj)
385 = power b (k+1) <= power b info.exp < radix };
389 assert { mod (sn - j) info.exp = 0
391 so mod (sn - j) info.exp
392 = mod (sn - oj - info.exp) info.exp
393 = mod (mod (sn - oj) info.exp
394 + mod (- info.exp) info.exp) info.exp
395 = mod (0 + 0) info.exp = 0 };
396 svalue_sub_concat (uint64'int b) (pelts sp) (offset sp)
397 (offset sp + int32'int oj) (offset sp + int32'int j);
398 assert { svalue b sp j
399 = svalue b sp oj * power b (j - oj) + w
400 = value rp rn * power b info.exp + w
401 = value rp rn * info.bb + w };
402 let ghost orp = pure { rp } in
403 let ref cy = wmpn_mul_1_in_place rp rn info.bb in
404 assert { cy < radix - 1
405 by value rp rn <= (power radix rn - 1)
406 so info.bb <= radix - 1
407 so info.bb * value orp rn <= (radix - 1) * (power radix rn - 1)
408 < (radix - 1) * (power radix rn)
409 so value orp rn * info.bb = value rp rn + power radix rn * cy
410 >= power radix rn * cy
411 so power radix rn * cy < power radix rn * (radix - 1) };
412 let cy1 = wmpn_add_1_in_place rp rn w in
414 assert { value rp rn + power radix rn * cy
415 = svalue_sub b (pelts sp) (offset sp) (offset sp + j) };
417 value_sub_update_no_change (pelts rp) (offset rp + int32'int rn)
418 (offset rp) (offset rp + int32'int rn)
420 value_tail orp (rn - 1);
422 by power b sn <= power radix sz
423 so value rp rn + power radix rn * cy
424 = svalue_sub b (pelts sp) (offset sp) (offset sp + j)
425 < power b j <= power b sn <= power radix sz
426 so power radix rn * cy >= power radix rn
428 so power radix rn < power radix sz };
434 value_tail rp (rn - 1);
435 value_tail orp (rn - 1);
436 assert { svalue b sp j > 0 -> (pelts rp)[offset rp + rn - 1] > 0
438 so value rp rn = value orp rn * info.bb + w
439 >= value orp rn * info.bb
441 so if svalue b sp oj > 0
442 then (pelts orp)[offset rp + rn - 1] > 0
445 + power radix (rn - 1)
446 * (pelts orp)[offset rp + rn - 1]
447 >= power radix (rn - 1) * (pelts orp)[offset rp + rn - 1]
448 >= power radix (rn - 1)
449 so value rp rn >= value orp rn
450 so power radix (rn - 1) * 1
451 = power radix (rn - 1) <= value rp rn
453 + power radix (rn - 1) * (pelts rp)[offset rp + rn - 1]
454 < power radix (rn - 1)
455 + power radix (rn - 1) * (pelts rp)[offset rp + rn - 1]
456 = power radix (rn - 1)
457 * (1 + (pelts rp)[offset rp + rn - 1])
458 so 1 < 1 + (pelts rp)[offset rp + rn - 1]
459 else rn = 1 /\ value rp rn = svalue b sp j = w
461 so (pelts rp)[offset rp + rn - 1] > 0 };
464 value_tail rp (rn - 1);
467 let wmpn_set_str (rp: ptr limb) (ghost sz: int32) (sp: ptr uchar) (sn:uint32)
468 (base: int32) : int32
469 requires { valid sp sn }
470 requires { valid rp sz }
473 requires { power base sn <= power radix (sz - 1) }
474 requires { 2 <= base <= 256 }
475 requires { writable rp }
476 requires { in_base base (pelts sp) (offset sp) (offset sp + sn) }
477 writes { rp.data.elts }
478 ensures { result <= sz - 1 }
479 ensures { value rp result = svalue base sp sn }
480 ensures { sn > 0 -> (pelts sp)[offset sp] > 0
481 -> (pelts rp)[offset rp + result - 1] > 0 }
483 ghost (if sn > 0 then
484 svalue_sub_tail (int32'int base) (pelts sp) (offset sp + 1)
485 (offset sp + uint32'int sn));
486 assert { sn > 0 -> (pelts sp)[offset sp] > 0 -> svalue base sp sn > 0
488 = svalue_sub base (pelts sp) (offset sp + 1) (offset sp + sn)
489 + power base (sn - 1) * (pelts sp)[offset sp]
490 >= power base (sn - 1) * (pelts sp)[offset sp]
492 if sn = 0 then return 0;
493 let bits = wmpn_base_power_of_two_p (Limb.of_int32 base) in
495 then return wmpn_set_str_bits rp (sz-1) sp sn bits
497 let info = wmpn_get_base_info (Limb.of_int32 base) in
498 return wmpn_set_str_other rp (sz-1) sp sn (Limb.of_int32 base) info