5 use import mach.int.UInt64GMP as Limb
19 use logical.LogicalUtil
20 use logical.LogicalOld
21 use int.EuclideanDivision
23 (** Based on Niels Möller and Torbjörn Granlund, “Improved
24 division by invariant integers” 2010 *)
28 predicate reciprocal (v d:limb) =
29 v = (div (radix*radix - 1) (d)) - radix
31 let lemma fact_div (x y z:int)
33 ensures { div (x + y * z) y = (div x y) + z }
35 assert { div (x + y * z) y = (div x y) + z
36 by x + y * z = y * (div (x + y * z) y) + mod (x + y * z) y
37 so mod (x + y * z) y = mod (y * z + x) y = mod x y
38 so x + y * z = y * (div (x + y * z) y) + mod x y
39 so x = y * div x y + mod x y
40 so x + y * z = y * div x y + mod x y + y * z
41 so y * (div (x + y * z) y) + mod x y
42 = y * div x y + mod x y + y * z
43 so y * (div (x + y * z) y) = y * div x y + y * z
46 so div (x + y * z) y = div x y + z }
48 let invert_limb (d:limb) : limb
49 requires { d >= div radix 2 }
50 ensures { reciprocal result d }
52 let v = div2by1 Limb.uint64_max
55 fact_div (radix * radix - 1) (l2i d) (- radix);
56 assert { v = (div (radix*radix - 1) (d)) - radix
58 radix - 1 + radix * (radix - 1 - d)
59 = radix - 1 + radix * (radix - 1) - radix * d
60 = radix - 1 + radix * radix - radix - radix * d
61 = radix * radix - 1 - radix * d
63 radix - 1 + radix * (radix - 1 - d)
64 = radix * radix - 1 - radix * d
67 = div ((radix - 1) + radix * (radix - 1 - d)) (d)
68 = div (radix * radix - 1 - radix * d) (d)
69 = div (radix * radix - 1) (d) - radix
73 (** Divide a two-word integer by a one-word integer given the
74 reciprocal of the divisor. *)
75 let div2by1_inv (uh ul d v:limb) : (limb,limb)
76 requires { d >= div radix 2 }
78 requires { reciprocal v d }
79 returns { q, r -> l2i q * d + l2i r = ul + radix * uh }
80 returns { _q, r -> 0 <= l2i r < d }
82 let ghost k = radix * radix - (radix + l2i v) * l2i d in
83 let ghost u = l2i ul + radix * l2i uh in
84 assert { 1 <= k <= d };
85 let l,h = mul_double v uh in
86 let sl,c = add_with_carry l ul 0 in
87 let (sh,ghost c') = add_with_carry uh h c in (* <c',sh,sl> = <uh, ul> + <h,l> *)
88 assert { sl + radix * sh + radix * radix * c'
89 = l + radix * h + ul + radix * uh };
94 so k = radix * radix - (radix + v) * d
95 = radix * radix - radix * d - v * d
96 so v * d = radix * radix - radix * d - k
97 = radix * (radix - d) - k
99 so v * d < radix * (radix - d)
100 so v * uh < radix * (radix - d)
101 so l + radix * h = v * uh
102 so l + radix * h < radix * (radix - d)
104 so radix * uh <= radix * (d - 1) = radix * d - radix
105 so l + radix * h + radix * uh
106 < radix * (radix - d) + radix * uh
107 <= radix * (radix - d) + radix * d - radix
108 <= radix * (radix - d + d) - radix = radix * radix - radix
110 so l + radix * h + ul + radix * uh
111 = l + radix * h + radix * uh + ul
112 < radix * radix - radix + ul
113 < radix * radix - radix + radix = radix * radix
114 so sl + radix * sh + radix * radix * c'
115 = l + radix * h + ul + radix * uh
117 so radix * radix * c' <= sl + radix * sh + radix * radix * c'
118 so radix * radix * c' < radix * radix
120 assert { sl + radix * sh = l + radix * h + ul + radix * uh
121 = v * uh + ul + radix * uh
122 = ul + (radix + v) * uh };
123 let qh = ref (sh:limb) in
125 let ghost q0 = l2i !ql in
126 let ghost cq = l2i sh + 1 in (*candidate quotient*)
127 let ghost cr = l2i ul - cq * l2i d + radix * l2i uh in (*candidate remainder*)
128 assert { cq * d + cr = u};
130 assert { !qh = mod cq radix };
131 let p = mul_mod !qh d in
132 let r = ref (sub_mod ul p) in
134 assert { r' = mod cr radix
136 let a = (- div (!qh * d) radix) in
139 = mod (ul - mod (!qh * d) radix) radix
141 + ul - mod (!qh * d) radix) radix
142 = mod (ul - mod (!qh * d) radix
143 - radix * div (!qh * d) radix) radix
144 = mod (ul - !qh * d) radix
145 = mod (ul - mod cq radix * d) radix
146 = mod (radix * (- (div cq radix)) * d + ul - mod cq radix * d) radix
147 = mod (ul - (mod cq radix + radix * div cq radix) * d) radix
148 = mod (ul - cq * d) radix
149 = mod (radix * uh + ul - cq * d) radix
150 = mod (ul - cq * d + radix * uh) radix
152 assert { radix * cr = uh * k + ul * (radix - d) + q0 * d - radix * d };
153 prod_compat_strict_r (l2i ul) radix (radix - l2i d);
154 prod_compat_strict_r (l2i d) radix (radix - q0);
155 assert { (* Theorem 2 of Möller&Granlund 2010 *)
156 (MM.max (radix - d) (q0 + 1)) - radix <= cr < MM.max (radix - d) q0
157 by radix * cr = uh * k + ul * (radix - d) + q0 * d - radix * d
158 so (uh * k + ul * (radix - d) >= 0
159 by uh >= 0 /\ k >= 0 /\ ul >= 0 /\ radix - d >= 0)
160 so radix * cr >= q0 * d - radix * d
161 so radix * cr >= - radix * d
163 so radix * cr >= q0 * d - radix * d = (q0 - radix) * d
166 so d * (radix-q0) < radix * (radix - q0)
167 so (q0 - radix) * d > (q0 - radix) * radix
168 so radix * cr > (q0 - radix) * radix
170 so (let m = MM.max (radix - d) (q0 +1) in
172 by (cr + radix >= - d + radix
173 /\ (cr + radix > q0 so cr + radix >= q0 + 1))
175 so 0 < k <= d so 0 <= uh < d
176 so k * uh < k * d <= d * d
177 so radix * cr < d * d + ul * (radix - d) + q0 * d - radix * d
178 so ul * (radix - d) < radix * (radix - d)
179 so radix * cr < d * d + radix * (radix - d) + q0 * d - radix * d
180 so (radix * cr < (radix - d) * (radix - d) + q0 * d
182 d * d + radix * (radix - d) + q0 * d - radix * d
183 = radix * (radix - d) + d * d - radix * d + q0 * d
184 = radix * (radix - d) + (d - radix) * d + q0 * d
185 = radix * (radix - d) - d * (radix - d) + q0 * d
186 = (radix - d) * (radix - d) + q0 * d)
187 so let m = MM.max (radix - d) q0 in
189 so (radix - d) * (radix - d) <= m* (radix - d)
190 so (q0 * d <= m * d by 0 <= q0 <= m /\ 0 < d)
191 so radix * cr < (radix - d) * (radix - d) + q0 * d
192 <= m* (radix - d) + q0 * d
193 <= m* (radix - d) + m * d
197 assert { cr >= 0 -> r' = cr };
200 by cr >= MM.max (radix - d) (q0 + 1) - radix
202 so cr + radix >= radix - d >= 0
203 so 0 <= cr + radix < radix
204 so mod (cr + radix) radix = mod cr radix
205 so r' = mod (cr + radix) radix ) };
208 by MM.max (radix - d) (q0 + 1) >= q0 + 1 > q0
209 so cr >= (MM.max (radix - d) (q0 +1)) - radix > q0 - radix
210 so r' = cr + radix > q0 - radix + radix = q0 ) };
211 assert { 1 <= cq <= radix };
212 assert { (!qh = cq \/ (!qh = 0 /\ cq = radix)
213 by (1 <= cq < radix -> !qh = mod cq radix = cq)
214 so (cq = radix -> !qh = 0) ) };
215 assert { cq = radix ->
221 so u = ul + radix * uh
226 so radix * d + cr = u
227 so radix * d + cr < radix * d
229 assert { 1 <= cq < radix -> !qh = cq /\ !qh * d + cr = u };
238 so r' < MM.max (radix - d) q0
240 so 0 <= r' < radix - d
241 so d <= r' + d < radix
242 so !r = mod (r' + d) radix = r' + d) };
246 so !r = r' + d >= d ) };
248 ( !r = r' + d - radix
249 by r' = cr + radix < radix
250 so cr >= MM.max (radix - d) (q0 + 1) - radix
251 >= radix - d - radix = - d
252 so r' = cr + radix >= radix - d
253 so !r = mod (r' + d) radix
254 so radix + radix >= r' + d >= radix
255 so !r = mod (r' + d) radix = r' + d - radix ) };
258 by r' = cr + radix < radix
259 so !r = mod (r' + d) radix = r' + d - radix
261 so !r = r' + d - radix < d ) };
262 assert { cq = radix ->
267 so u = radix * d + cr
268 = (radix - 1) * d + d + cr
269 = (radix - 1) * d + d + r' - radix
270 so r' = cr + radix >= MM.max (radix - d) (q0 + 1)
272 so radix + radix >= d + r' >= radix
273 so !r = mod (d + r') radix = d + r' - radix
274 so (radix - 1) * d + !r = u
275 so !qh = mod ((mod cq radix) - 1) radix
280 assert { !r = cr + d by [@case_split] cr >= 0 \/ cr < 0 };
281 assert { 1 <= cq <= radix ->
285 so !qh * d + cr + d = u
291 assert { 1 <= cq < radix };
293 assert { !qh * d + !r = ul + radix * uh
294 by [@case_split] cq = radix \/ 1 <= cq < radix };
298 assert { !qh < radix - 1
300 !qh * d = ul + radix * uh - !r
302 so ul + radix * uh - !r
303 <= ul + radix * (d - 1) - !r
304 = ul + radix * d - radix - !r
305 = (ul - radix) + radix * d - !r
309 so !qh * d < (radix - 1) * d
311 so !qh < radix - 1 };
314 assert { 0 <= !r < d };
315 assert { !qh * d + !r = ul + radix * uh };
317 assert { 0 <= !r < d };
318 assert { !qh * d + !r = ul + radix * uh };
321 (** `wmpn_divrem_1 q x sz y` divides `(x, sz)` by `y`, writes the quotient
322 in `(q, sz)` and returns the remainder. Corresponds to
324 (* TODO develop further decimal points (qxn) *)
325 let wmpn_divrem_1 (q x:t) (sz:int32) (y:limb) : limb
326 requires { valid x sz }
327 requires { valid q sz }
328 requires { writable q }
332 = value q sz * y + result }
333 ensures { result < y }
339 (*normalize divisor*)
340 let clz = count_leading_zeros y in
343 let ghost mult = power 2 (p2i clz) in
344 let ry = lsl y (Limb.of_int32 clz) in
345 assert { ry = mult * y };
346 let ghost tlum = power 2 (Limb.length - p2i clz) in
347 assert { tlum * mult = radix };
348 let v = invert_limb ry in
351 invariant { -1 <= !i <= msb }
352 invariant { !r < ry }
353 invariant { mult * value_sub (pelts x) (x.offset + !i + 1) (x.offset + sz)
354 = value_sub (pelts q) (q.offset + !i + 1)
358 invariant { !r <= radix - mult }
359 invariant { mod (!r) mult = 0 }
362 lx := C.get_ofs x !i;
363 (*TODO lshift in place would simplify things*)
364 let l,h = lsld_ext !lx (Limb.of_int32 clz) in
365 mod_mult mult (l2i y) 0;
368 let drm = div (!r) mult in
369 let dym = div (ry) mult in
373 = mod (mult * (y) + 0) mult
379 = mult * dym - mult * drm
385 so !r + h = mult * drm + h
388 <= mult * dym = l2i ry };
389 assert { !r + h < radix by
390 !r + h < ry < radix };
391 let (qu,rem) = div2by1_inv (!r + h) l ry v in
392 mod_mult mult (l2i y * l2i qu) (l2i rem);
393 mod_mult mult (tlum * (l2i !r + l2i h)) (l2i l);
394 assert { mod (rem) mult = 0
397 = (radix * (!r + h) + l)
400 = (mult * tlum * (!r + h) + l)
401 so mod (mult * y * qu + rem) mult
402 = mod (mult * tlum * (!r + h) + l) mult
404 so mod (mult * (y * qu) + rem) mult
406 so mod (mult * tlum * (!r + h) + l) mult
410 let ghost mer = div (l2i rem) mult in
411 assert { rem <= radix - mult
414 so mult * mer = l2i rem < radix = mult * tlum
416 so 0 < mult * tlum - mult * mer = mult * (tlum - mer)
419 so rem = mult * mer <= mult * (tlum - 1) = radix - mult
422 assert { qu * ry + !r = l + radix * h + radix * (!r at StartLoop) };
423 (* coerced div2by1 postcondition *)
424 value_sub_update_no_change (pelts q) (q.offset + p2i !i)
425 (q.offset + 1 + p2i !i)
426 (q.offset + p2i sz) qu;
428 assert { mult * value_sub (pelts x) (x.offset + !i + 1) (x.offset + sz)
429 = value_sub (pelts q) (q.offset + !i + 1)
432 + (!r at StartLoop) }; (* previous invariant is still true *)
433 value_sub_head (pelts x) (x.offset + int32'int !i) (x.offset + p2i sz);
434 value_sub_head (pelts q) (q.offset + int32'int !i) (q.offset + p2i sz);
435 assert { l + radix * h = mult * !lx }; (*lsld_ext postcondition *)
436 assert { mult * value_sub (pelts x) (x.offset + !i)
439 + radix * (mult * value_sub (pelts x) (x.offset + !i + 1)
441 by (pelts x)[x.offset + !i] = !lx
442 so value_sub (pelts x) (x.offset + !i) (x.offset + sz)
443 = !lx + radix * value_sub (pelts x) (x.offset + !i + 1)
444 (x.offset + sz) }; (*nonlinear*)
445 assert { value_sub (pelts q) (q.offset + !i) (q.offset + sz) * ry
448 * (value_sub (pelts q) (q.offset + !i + 1) (q.offset + sz)
450 by (pelts q)[q.offset + !i] = qu
451 so value_sub (pelts q) (q.offset + !i) (q.offset + sz)
452 = qu + radix * value_sub (pelts q) (q.offset + !i + 1)
453 (q.offset + sz) }; (*nonlinear*)
454 assert { mult * value_sub (pelts x) (x.offset + !i)
456 = value_sub (pelts q) (q.offset + !i) (q.offset + sz) * ry
460 let ghost res = lsr !r (Limb.of_int32 clz) in
461 assert { value x sz = value q sz * y + res
464 = value q sz * ry + !r
465 = value q sz * y * mult + !r
466 = value q sz * y * mult + res * mult
467 = (value q sz * y + res) * mult };
468 lsr !r (Limb.of_int32 clz) end
470 let v = invert_limb y in
473 invariant { -1 <= !i <= msb }
475 invariant { value_sub (pelts x) (x.offset + !i + 1) (x.offset + sz)
476 = value_sub (pelts q) (q.offset + !i + 1)
482 let ghost k = p2i !i in
483 lx := C.get_ofs x !i;
484 let (qu, rem) = div2by1_inv !r !lx y v in
486 value_sub_update_no_change (pelts q) (q.offset + p2i !i)
487 (q.offset + 1 + p2i !i)
488 (q.offset + p2i sz) qu;
491 value_sub_head (pelts x) (x.offset + k) (x.offset + p2i sz);
492 value_sub_head (pelts q) (q.offset + k) (q.offset + p2i sz);
493 assert { value_sub (pelts x) (x.offset + !i + 1) (x.offset + sz)
494 = value_sub (pelts q) (q.offset + !i + 1)
498 by (pelts q)[q.offset + k] = qu
499 so (pelts x)[x.offset + k] = !lx
500 so value_sub (pelts x) (x.offset + !i + 1) (x.offset + sz)
501 = value_sub (pelts x) (x.offset + k) (x.offset + sz)
502 = !lx + radix * value_sub (pelts x) (x.offset + k + 1)
504 = !lx + radix * (value_sub (pelts q) (q.offset + k + 1)
506 * y + (!r at StartLoop))
507 = !lx + radix * (!r at StartLoop)
508 + radix * (value_sub (pelts q) (q.offset + k + 1)
512 + radix * (value_sub (pelts q) (q.offset + k + 1)
515 = (qu + radix * value_sub (pelts q) (q.offset + k + 1)
519 = value_sub (pelts q) (q.offset + !i + 1)
528 predicate reciprocal_3by2 (v dh dl:limb) =
529 v = div (radix*radix*radix -1) (dl + radix * dh) - radix
531 let div3by2_inv (uh um ul dh dl v: limb) : (limb,limb,limb)
532 requires { dh >= div radix 2 }
533 requires { reciprocal_3by2 v dh dl }
534 requires { um + radix * uh < dl + radix * dh }
535 returns { q, rl, rh -> uint64'int q * dl + radix * q * dh
536 + uint64'int rl + radix * uint64'int rh
537 = ul + radix * um + radix * radix * uh }
538 returns { _q, rl, rh -> 0 <= uint64'int rl + radix * uint64'int rh < dl + radix * dh }
539 = [@vc:do_not_keep_trace] (* traceability info breaks the proof *)
540 let ghost d = l2i dl + radix * l2i dh in
541 let ghost u = l2i ul + radix * (l2i um + radix * l2i uh) in
545 let l,h = mul_double v uh in
546 let sl, c = add_with_carry um l 0 in
547 let sh, ghost c' = add_with_carry uh h c in
548 assert { sl + radix * sh + radix * radix * c'
549 = um + radix * uh + v * uh };
554 so radix * radix * radix - 1
555 = d * (div (radix * radix * radix - 1) d)
556 + mod (radix * radix * radix - 1) d
557 >= d * (div (radix * radix * radix - 1) d)
558 so radix * (um + radix * uh + v * uh)
559 < radix * (d + v * uh)
560 = radix * d + v * radix * uh
562 = (div (radix * radix * radix - 1) d) * d
563 <= radix * radix * radix - 1
564 < radix * radix * radix
565 so um + radix * uh + v * uh < radix * radix
566 so sl + radix * sh + radix * radix * c' < radix * radix
567 so radix * radix * c' < radix * radix
570 let ghost q0 = l2i sl in
571 let ghost cq = l2i !q1 + 1 in (*candidate quotient*)
573 assert { !q1 = mod cq radix };
574 let p = mul_mod dh sh in
577 let ghost a = div (l2i um - l2i dh * l2i sh) radix in
578 let tl, th = mul_double sh dl in
579 let il, b = sub_with_borrow ul tl 0 in
580 let (ih, ghost b') = sub_with_borrow !r1 th b in
581 assert { il + radix * ih - radix * radix * b'
582 = ul + radix * !r1 - sh * dl };
583 let bl,b2 = sub_with_borrow il dl 0 in
584 let bh, ghost b2' = sub_with_borrow ih dh b2 in
585 assert { bl + radix * bh - radix * radix * b2'
586 = il + radix * ih - dl - radix * dh };
587 mod_mult (radix * radix) (uint64'int b')
588 (uint64'int ul + radix * uint64'int !r1
589 - uint64'int sh * uint64'int dl - uint64'int dl
590 - radix * uint64'int dh);
591 assert { bl + radix * bh
592 = mod (ul + radix * !r1
594 - radix * dh) (radix * radix)
596 mod (il + radix * ih - dl - radix * dh) (radix * radix)
597 = mod (radix * radix * (-b2') + bl + radix * bh) (radix * radix)
598 = mod (bl + radix * bh) (radix * radix)
602 = mod (il + radix * ih
603 - dl - radix * dh) (radix * radix)
605 = radix * radix * b' + ul + radix * !r1
607 so mod (il + radix * ih
608 - dl - radix * dh) (radix * radix)
609 = mod (radix * radix * b' + ul + radix * !r1
610 - sh * dl - dl - radix * dh)
612 = mod (ul + radix * !r1
614 - radix * dh) (radix * radix) };
617 let ghost r' = l2i !r0 + radix * l2i !r1 in
618 let ghost cr = u - d * cq in
619 assert { r' = mod cr(radix * radix)
621 (!r1 at CQuot = mod (um - dh * sh) radix
622 by let a' = div (dh * sh) radix in
623 dh * sh = p + radix * a'
624 so !r1 at CQuot = mod (um - p) radix
625 = mod (radix * a' + um - dh * sh) radix
626 = mod (um - dh * sh) radix )
627 so um - dh * sh = a * radix + !r1 at CQuot
629 = mod (ul + radix * (!r1 at CQuot)
631 - radix * dh) (radix * radix)
632 so ul + radix * (!r1 at CQuot)
633 - sh * dl - dl - radix * dh
634 = ul + radix * (um - dh * sh - a * radix)
635 - sh * dl - dl - radix * dh
636 = ul + radix * um - radix * dh * sh
637 - radix * radix * a - sh * dl - dl
639 = ul + radix * um - radix * dh * (sh + 1)
640 - radix * radix * a - sh * dl - dl
641 = ul + radix * um - radix * dh * (sh + 1)
642 - radix * radix * a - dl * (sh + 1)
644 - (dl + radix * dh) * (sh + 1)
646 = ul + radix * um - d * cq - radix * radix * a
647 = u - radix * radix * uh - d * cq - radix * radix * a
648 = cr + radix * radix * (- a - uh)
649 so (*let y = - a - uh in*)
650 mod (ul + radix * (!r1 at CQuot)
652 - radix * dh) (radix * radix)
653 = mod (radix * radix * (-a - uh) + cr)
655 = mod cr (radix*radix)
657 let ghost m = MM.max (radix * radix - d) (q0 * radix) in
658 assert { (* Theorem 3 of Moller&Granlund 2010 *)
659 m - radix * radix <= cr < m
661 let k = radix * radix * radix - (radix + v) * d in
662 reciprocal_3by2 v dh dl
663 so let m3 = radix * radix * radix - 1 in
664 (radix + v) * d = d * div m3 d = m3 - mod m3 d
666 by k = radix * radix * radix - (radix + v) * d
667 = m3 + 1 - (radix + v) * d
668 = m3 + 1 - m3 + mod m3 d
671 so q0 + radix * sh = (radix + v) * uh + um
673 so radix * cq = radix * sh + radix
674 = (radix + v) * uh + um - q0 + radix
675 so (radix * cr = k * uh + (radix * radix - d) * um
676 + radix * ul + d * q0 - d * radix
677 by radix * cr = radix * (u - cq * d)
679 - ((radix + v) * uh + um - q0 + radix) * d
680 = radix * u - d * (radix + v) * uh
681 - d * um + d * q0 - d * radix
682 = radix * u - (radix * radix * radix - k) * uh
683 - d * um + d * q0 - d * radix
684 = (radix * radix * radix * uh + radix * radix * um
685 + radix * ul) - (radix * radix * radix - k) * uh
686 - d * um + d * q0 - d * radix
687 = k * uh + radix * radix * um + radix * ul
688 - d * um + d * q0 - d * radix
689 = k * uh + (radix * radix - d) * um + radix * ul
690 + d * q0 - d * radix )
691 so (cr >= m - radix * radix
693 k >= 0 so radix * radix - d >= 0
694 so uh >= 0 so um >= 0 so ul >= 0
695 so k * uh + (radix * radix - d) * um + radix * ul
697 so radix * cr >= d * q0 - d * radix
700 so radix * cr >= - d * radix
701 so cr >= -d = radix * radix - d - radix * radix
702 so radix * cr >= d * (q0 - radix)
704 (radix - q0) * d < (radix - q0) * radix * radix
705 by let rq = radix - q0 in let r2 = radix * radix in
709 so d * (q0 - radix) > radix * radix * (q0 - radix)
710 so radix * cr > radix * radix * (q0 - radix)
711 so cr > radix * (q0 - radix) = radix * q0 - radix * radix
715 let bbd = radix * radix - d in
716 bbd > 0 /\ bbd <= m /\ q0 * radix <= m
717 so (bbd * bbd <= bbd * m
719 (bbd = m \/ (bbd < m so bbd * bbd < bbd * m)))
720 so (d*(radix * q0) <= d * m
722 (radix * q0 = m \/ (radix * q0 < m so d > 0 so d * (radix * q0) < d * m)))
731 so [@case_split] (k = d \/ dm = 0 \/
732 (k < d /\ dm > 0 so k * dm < d * dm)))
735 bbd * um <= bbd * (radix - 1)
738 = k * uh + (radix * radix - d) * um
739 + radix * ul + d * q0 - radix * d
741 + radix * ul + d * q0 - radix * d
742 <= d * dm + bbd * (radix - 1)
743 + radix * ul + d * q0 - radix * d
744 < d * dm + bbd * (radix - 1)
745 + radix * radix + d * q0 - radix * d
746 so radix * radix * cr
747 < radix * (d * dm + bbd * (radix - 1)
748 + radix * radix + d * q0 - radix * d)
749 = d * radix * (dh - 1) + bbd * radix * (radix - 1)
750 + radix * radix * radix + radix * d * q0 - radix * radix * d
751 = d * radix * dh - d * radix + bbd * radix * (radix - 1)
752 + radix * radix * radix + radix * d * q0 - radix * radix * d
753 = d * (d - dl) - d * radix + bbd * radix * (radix - 1)
754 + radix * radix * radix + radix * d * q0 - radix * radix * d
755 = d * d - d * radix + bbd * radix * (radix - 1)
756 + radix * radix * radix + radix * d * q0 - radix * radix * d - d * dl
757 so (d * dl >= 0 by d >= 0 /\ dl >= 0)
758 so radix * radix * cr
759 < d * d - d * radix + bbd * radix * (radix - 1)
760 + radix * radix * radix + radix * d * q0 - radix * radix * d - d * dl
761 <= d * d - d * radix + bbd * radix * (radix - 1)
762 + radix * radix * radix + radix * d * q0 - radix * radix * d
763 = d * d - d * radix + bbd * (radix * radix - radix)
764 + radix * radix * radix + radix * d * q0 - radix * radix * d
765 = d * d - d * radix + bbd * radix * radix - (radix * radix - d) * radix
766 + radix * radix * radix + radix * d * q0 - radix * radix * d
767 = d * d - d * radix + bbd * radix * radix
768 + radix * d - radix * radix * radix
769 + radix * radix * radix + radix * d * q0 - radix * radix * d
770 = d * d + bbd * radix * radix - radix * radix * d + radix * d * q0
771 = bbd * radix * radix - d * (radix * radix - d) + radix * d * q0
772 = bbd * radix * radix - d * bbd + radix * d * q0
773 = bbd * bbd + d * (radix * q0)
774 <= bbd * m + d * (radix * q0)
782 by um + radix * uh < dl + radix * dh)
783 so (radix * radix - d) * um <= (radix * radix - d) * (dl - 1)
787 - (radix - dl) * (radix * radix * radix - d * (1+ radix))
789 = k * dh + (radix * radix - d) * um
790 + radix * ul + d * q0 - radix * d
791 <= d * dh + (radix * radix - d) * um
792 + radix * ul + d * q0 - radix * d
793 <= d * dh + (radix * radix - d) * (dl - 1)
794 + radix * ul + d * q0 - radix * d
795 < d * dh + (radix * radix - d) * (dl - 1)
796 + radix * radix + d * q0 - radix * d
797 so radix * radix * cr
798 < radix * (d * dh + (radix * radix - d) * (dl - 1)
799 + radix * radix + d * q0 - radix * d)
801 + (radix * radix - d) * (dl - 1) * radix
802 + radix * radix * radix + d * q0 * radix - radix * radix * d
804 + (radix * radix - d) * (radix * dl - radix)
805 + radix * radix * radix + d * q0 * radix - radix * radix * d
806 = d * d - d * dl + radix * radix * radix * dl
807 - d * radix * dl + d * radix - radix * radix * radix
808 + radix * radix * radix + d * q0 * radix - radix * radix * d
809 = d * d - d * dl + radix * radix * radix * dl
810 - d * radix * dl + d * radix + d * q0 * radix
812 = d * d - radix * radix * d + d * radix + d * q0 * radix
813 + dl * (radix * radix * radix - d - d * radix)
814 = d * (d - radix * radix) + d * radix + d * q0 * radix
815 + dl * (radix * radix * radix - d - d * radix)
816 = bbd * (-d) + d * radix + d * q0 * radix
817 + dl * (radix * radix * radix - d - d * radix)
818 = bbd * (bbd - radix * radix) + d * radix + d * q0 * radix
819 + dl * (radix * radix * radix - d - d * radix)
820 = bbd * bbd + d * q0 * radix
821 - bbd * radix * radix + d * radix
822 + dl * (radix * radix * radix - d * (1 + radix))
823 = bbd * bbd + d * q0 * radix
824 - (radix * radix - d) * radix * radix + d * radix
825 + dl * (radix * radix * radix - d * (1 + radix))
826 = bbd * bbd + d * q0 * radix
827 - radix * ((radix * radix - d) * radix - d)
828 + dl * (radix * radix * radix - d * (1 + radix))
829 = bbd * bbd + d * q0 * radix
830 - radix * (radix * radix * radix - d * radix - d)
831 + dl * (radix * radix * radix - d * (1 + radix))
832 = bbd * bbd + d * q0 * radix
833 - radix * (radix * radix * radix - d * (1+ radix))
834 + dl * (radix * radix * radix - d * (1 + radix))
835 = bbd * bbd + d * q0 * radix
836 - (radix - dl) * (radix * radix * radix - d * (1+ radix))
837 <= bbd * m + d * q0 * radix
838 - (radix - dl) * (radix * radix * radix - d * (1+ radix))
840 - (radix - dl) * (radix * radix * radix - d * (1+ radix))
842 - (radix - dl) * (radix * radix * radix - d * (1+ radix))
844 - (radix - dl) * (radix * radix * radix - d * (1+ radix))
848 if d <= radix * (radix - 1)
849 then (radix + 1) * d <= radix * (radix - 1) * (radix + 1)
850 = radix * (radix * radix - 1)
851 = radix * radix * radix - radix
852 < radix * radix * radix
853 so (radix * radix * radix - d * (1+ radix)) > 0
855 so (radix - dl) * (radix * radix * radix
861 - (radix - dl) * (radix * radix * radix
864 so radix * radix * cr < radix * radix * m
866 dl + radix * dh = d > radix * (radix - 1)
868 so dl + radix * dh < radix * (1 + dh)
869 so radix - 1 < 1 + dh
873 so d >= radix * (radix - 1) +1
875 >= (radix * (radix - 1) + 1) * (radix +1)
876 = radix * (radix * radix - 1) + radix + 1
877 = radix * radix * radix - radix + radix + 1
878 = radix * radix * radix + 1
880 (d * div (radix * radix * radix - 1) d
882 by d * div (radix * radix * radix - 1) d
883 <= radix * radix * radix - 1
884 < radix * radix * radix + 1
886 so (let a = div (radix * radix * radix - 1) d in
889 so (forall x y z. x * z < y * z /\ z > 0 -> x < y)
890 so (forall x y. x * d < y * d -> x < y)
891 so let r = radix + 1 in
894 so v = div (radix * radix * radix - 1) d - radix
895 < radix + 1 - radix = 1
897 so sh = uh = radix - 1
898 so cq = sh + 1 = radix
901 = ul + radix * (um + radix * dh)
902 - radix * (dl + radix * dh)
903 = ul + radix * (um - dl)
907 so cr = ul + radix * (um - dl)
908 < radix + radix * (um - dl)
909 = radix * (1 + um - dl) <= 0
914 assert { cr >= 0 -> r' = cr };
915 assert { cr < 0 -> r' = radix * radix + cr
917 m >= radix * radix - d
918 so cr >= m - radix * radix >= -d
919 so cr + radix * radix >= radix * radix - d >= 0
920 so 0 <= cr + radix * radix < radix * radix
921 so mod (radix * radix + cr) (radix*radix) = mod cr (radix*radix)
922 so r' = mod (radix * radix + cr) (radix*radix) };
923 assert { cr < 0 -> !r1 >= sl
925 so cr >= m - radix * radix >= radix * q0 - radix * radix
926 so r' = radix * radix + cr >= radix * q0
927 so r' = radix * !r1 + !r0 >= radix * q0
929 so r' < radix * !r1 + radix = radix * (!r1 + 1)
930 so radix * q0 < radix * (!r1 + 1)
931 so sl = q0 < !r1 + 1 };
932 assert { 1 <= cq <= radix };
933 assert { 1 <= cq < radix -> !q1 = cq so !q1 * d + cr = u };
934 assert { cq = radix ->
937 so um + radix * uh <= d - 1
938 so radix * d + cr = ul
939 + radix * (um + radix * uh)
940 <= ul + radix * (d - 1)
941 = ul - radix + radix * d
945 label PreCorrections in
949 assert { !q1 = cq - 1
953 (!q1 at PreCorrections)
954 = mod cq radix = mod radix radix= 0
955 so !q1 = mod (0 - 1) radix = radix - 1 = cq - 1
957 0 <= cq - 1 < radix - 1
958 so (!q1 at PreCorrections) = cq
959 so !q1 = mod (cq - 1) radix = cq - 1
961 let rl, c = add_with_carry !r0 dl 0 in
962 let rh, ghost c' = add_with_carry !r1 dh c in
963 assert { rl + radix * rh = mod (r' + d) (radix * radix)
964 by radix * radix * c' + rl + radix * rh
966 so mod (r' + d) (radix * radix)
967 = mod (radix * radix * c' + rl + radix * rh)
969 = mod (rl + radix * rh) (radix * radix) };
970 assert { rl + radix * rh = cr + d
974 so rl + radix * rh = mod (cr + d) (radix * radix)
975 so cr < MM.max (radix * radix - d) (q0*radix)
978 r' = radix * !r1 + !r0
981 so cr < radix * radix - d
982 so cr + d < radix * radix
983 so (cr + d >= 0 by cr + d >= cr)
984 so mod (cr + d) (radix * radix) = cr + d
986 r' = cr + radix * radix
987 so cr >= m - radix * radix
988 so r' >= m >= radix * radix - d
989 so r' + d >= radix * radix
990 so r' < radix * radix
992 so r' + d < radix * radix + radix * radix
993 so mod (r' + d) (radix * radix)
994 = r' + d - radix * radix
999 assert { !q1 * d + !r0 + radix * !r1 = u
1003 so !r0 + radix * !r1 = cr + d
1004 so !q1 * d + !r0 + radix * !r1
1005 = (cq - 1) * d + cr + d
1006 = cq * d - d + cr + d
1009 else assert { !q1 * d + r' = u
1013 so !q1 * d + cr = u };
1014 assert { !q1 * d + !r0 + radix * !r1 = u };
1015 label PreRemAdjust in
1016 if [@extraction:unlikely] (!r1 > dh) || (!r1 = dh && !r0 >= dl)
1018 let bl, b = sub_with_borrow !r0 dl 0 in
1019 let bh, ghost b'= sub_with_borrow !r1 dh b in
1021 assert { bl + radix * bh = !r0 + radix * !r1 - d };
1022 assert { !q1 < radix - 1
1023 by !q1 * d + !r0 + radix * !r1 = u
1024 so !r0 + radix * !r1 >= d
1025 so um + radix * uh <= d - 1
1026 so u = ul + radix * (um + radix * uh)
1027 <= ul + radix * (d - 1)
1028 < radix + radix * (d-1)
1030 so (!q1 * d < (radix - 1) * d
1032 !q1 * d = u - (!r0 + radix * !r1)
1037 q1 := add_mod !q1 1;
1038 assert { !q1 = (!q1 at PreRemAdjust) + 1 };
1041 assert { !q1 * d + !r0 + radix * !r1 = u
1043 !q1 * d + !r0 + radix * !r1
1044 = ((!q1 at PreRemAdjust) + 1) * d
1045 + (!r0 + radix * !r1 at PreRemAdjust) - d
1046 = (!q1 * d + !r0 + radix * !r1 at PreRemAdjust)
1049 assert { 0 <= !r0 + radix * !r1 < d };
1052 let lemma bounds_imply_rec3by2 (v dh dl:limb)
1053 requires { radix * radix * radix - (dl + radix * dh)
1054 <= (radix + v) * (dl + radix * dh)
1055 < radix * radix * radix }
1056 ensures { reciprocal_3by2 v dh dl }
1059 let reciprocal_word_3by2 (dh dl:limb) : limb
1060 requires { dh >= div radix 2 }
1061 ensures { reciprocal_3by2 result dh dl }
1063 let ghost d = l2i dl + radix * l2i dh in
1064 let v = ref (invert_limb dh) in
1065 assert { radix * radix - dh
1066 <= (radix + !v) * dh
1069 radix + !v = div (radix * radix - 1) (dh) };
1070 let p = ref (mul_mod dh !v) in
1071 assert { (radix + !v) * dh
1075 mod ((radix + !v) * dh) radix
1076 = mod (radix * dh + dh * !v) radix
1077 = mod (dh * !v) radix = l2i !p
1079 div ((radix + !v) * dh) radix = radix - 1
1082 = radix * div ((radix + !v) * dh) radix
1083 + mod (dh * !v) radix
1084 = radix * (radix - 1) + !p
1088 if !p < dl (* carry out *)
1090 assert { (!p at Estimate) + dl >= radix };
1091 assert { (!p at Estimate) + dl = radix + !p };
1094 (!p at Estimate) + dl >= radix
1095 so (!p at Estimate) > 0
1097 assert { (radix + !v) * dh + dl
1098 = radix * (radix - 1) + radix + !p };
1104 assert { (radix + !v) * dh + dl
1105 = radix * (radix - 1) + radix + !p
1112 assert { !p = radix + !p at Borrow - dh };
1114 assert { (radix + !v) * dh * radix + radix * dl
1115 = radix * radix * (radix - 1) + radix * !p
1116 by (radix + !v) * dh + dl
1117 = radix * (radix - 1) + !p };
1118 assert { radix * radix - dh
1119 <= (radix + !v) * dh + dl
1121 let tl, th = mul_double !v dl in
1124 if !p < th (* carry out *)
1126 assert { (!p at Adjust) + th >= radix };
1127 assert { (!p at Adjust) + th = radix + !p
1128 by (!p at Adjust) + th < radix + radix
1129 so div ((!p at Adjust) + th) radix = 1
1130 so !p = mod ((!p at Adjust) + th) radix
1131 so (!p at Adjust) + th
1132 = radix * div ((!p at Adjust) + th) radix
1133 + mod ((!p at Adjust) + th) radix
1141 if !p > dh || (!p = dh && tl >= dl)
1143 assert { tl + radix * !p >= d };
1145 assert { (radix + !v) * dh * radix + radix * dl
1147 = radix * radix * radix
1148 + radix * !p + tl - d
1150 (radix + !v) * dh * radix + radix * dl
1152 = (radix + !v at Adjust - 1) * dh * radix
1154 + (!v at Adjust - 1) * dl
1155 = (radix + !v at Adjust) * dh * radix
1157 + (!v at Adjust) * dl - radix * dh
1159 = radix * radix * (radix - 1) + radix * (!p at Adjust)
1160 + (!v at Adjust) * dl - radix * dh
1162 = radix * radix * (radix - 1) + radix * (!p at Adjust)
1163 + radix * th + tl - d
1164 = radix * radix * (radix - 1) + radix * (radix + !p)
1166 = radix * radix * (radix - 1) + radix * radix + radix * !p
1168 = radix * radix * radix + radix * !p + tl - d
1171 assert { radix * radix * radix
1172 <= (radix + !v) * dh * radix + radix * dl
1174 < radix * radix * radix + d };
1177 bounds_imply_rec3by2 !v dh dl;
1180 (* `(x, sz)` is normalized if its most significant bit is set. *)
1181 predicate normalized (x:t) (sz:int32) =
1183 /\ (pelts x)[x.offset + sz - 1] >= div radix 2
1187 let div_sb_qr (q x:t) (sx:int32) (y:t) (sy:int32) : limb
1188 requires { 3 <= sy <= sx }
1189 requires { valid x sx }
1190 requires { valid y sy }
1191 requires { valid q (sx - sy) }
1192 requires { writable q }
1193 requires { writable x }
1194 requires { normalized y sy }
1195 ensures { value (old x) sx =
1197 + power radix (sx - sy) * result)
1200 ensures { value x sy < value y sy }
1201 ensures { 0 <= result <= 1 }
1202 = [@vc:do_not_keep_trace] (* traceability info breaks the proof *)
1203 let xp = ref (C.incr x (sx - 2)) in
1204 let qp = ref (C.incr q (sx - sy)) in
1205 let dh = C.get_ofs y (sy - 1) in
1206 assert { dh >= div radix 2 by normalized y sy };
1207 let dl = C.get_ofs y (sy - 2) in
1208 let v = reciprocal_word_3by2 dh dl in
1209 let i = ref (sx - sy) in
1212 let xd = C.incr !xp mdn in
1213 let ghost vy = value y (p2i sy) in
1216 let r = wmpn_cmp xd y sy in
1218 ensures { r >= 0 -> result = 1 }
1219 ensures { r < 0 -> result = 0 }*)
1226 ensures { value (old x) sx =
1227 (value !qp (sx - sy - !i)
1228 + qh * power radix (sx - sy - !i))
1229 * vy * power radix !i
1230 + value x (sy + !i - 1)
1231 + power radix (sy + !i - 1) * !x1 }
1232 ensures { value_sub (pelts x) (!xp.offset + mdn)
1233 (!xp.offset + mdn + sy - 1)
1234 + power radix (sy - 1) * !x1
1236 ensures { dl + radix * dh
1237 >= (pelts x)[(!xp).offset] + radix * !x1 }
1238 let ghost ox = pelts x in
1243 let ghost b = wmpn_sub_n_in_place xd y sy in
1245 ensures { value (x at PreAdjust) sx =
1246 (value !qp (sx - sy - !i)
1247 + qh * power radix (sx - sy - !i))
1248 * vy * power radix !i
1250 ensures { value_sub (pelts x) (!xp.offset + mdn)
1251 (!xp.offset + mdn + sy)
1253 value_sub_upper_bound (pelts x) xd.offset (xd.offset + p2i sy);
1255 assert { value (xd at PreAdjust) sy
1256 = value xd sy + vy };
1257 value_sub_concat (pelts x) x.offset xd.offset (xd.offset + p2i sy);
1258 value_sub_concat ox x.offset xd.offset (xd.offset + p2i sy);
1259 value_sub_frame (pelts x) ox x.offset xd.offset;
1260 assert { value (x at PreAdjust) sx
1262 + power radix (sx - sy) * vy
1264 value_sub (pelts (x at PreAdjust)) x.offset xd.offset
1265 = value_sub (pelts x) x.offset xd.offset
1266 so pelts (xd at PreAdjust) = pelts (x at PreAdjust)
1267 so value_sub (pelts (x at PreAdjust)) xd.offset (xd.offset + sy)
1268 = value (xd at PreAdjust) sy
1269 so value (x at PreAdjust) sx
1270 = value_sub (pelts (x at PreAdjust)) x.offset xd.offset
1271 + power radix (sx - sy)
1272 * value_sub (pelts (x at PreAdjust)) xd.offset (xd.offset + sy)
1273 = value_sub (pelts x) x.offset xd.offset
1274 + power radix (sx - sy)
1275 * value (xd at PreAdjust) sy
1276 = value_sub (pelts x) x.offset xd.offset
1277 + power radix (sx - sy)
1278 * (value xd sy + vy)
1279 = value_sub (pelts x) x.offset xd.offset
1280 + power radix (sx - sy)
1281 * (value_sub (pelts x) (xd.offset) (xd.offset + sy) + vy)
1282 = value_sub (pelts x) x.offset xd.offset
1283 + power radix (sx - sy)
1284 * value_sub (pelts x) (xd.offset) (xd.offset + sy)
1285 + power radix (sx - sy) * vy
1287 + power radix (sx - sy) * vy
1289 value_sub_tail (pelts x) x.offset (x.offset + p2i sy + p2i !i - 1);
1290 assert { value (x at PreAdjust) sx =
1291 (value !qp (sx - sy - !i)
1292 + qh * power radix (sx - sy - !i))
1293 * vy * power radix !i
1297 so power radix (sx - sy - !i) = 1
1298 so value !qp (sx - sy - !i) = 0 };
1299 value_sub_lower_bound_tight (pelts y) y.offset (y.offset + p2i sy);
1300 assert { value_sub (pelts x) (!xp.offset + mdn)
1301 (!xp.offset + mdn + sy)
1304 value_sub (pelts x) (!xp.offset + mdn)
1305 (!xp.offset + mdn + sy)
1307 = value (xd at PreAdjust) sy - vy
1308 so value (xd at PreAdjust) sy
1310 so vy >= dh * power radix (sy - 1)
1311 so 2 * vy >= 2 * dh * power radix (sy - 1)
1313 so 2 * dh * power radix (sy - 1) >= radix * power radix (sy - 1)
1314 so 2 * vy >= radix * power radix (sy - 1) = power radix sy
1315 so value (xd at PreAdjust) sy < 2 * vy
1316 so value (xd at PreAdjust) sy - vy < vy };
1320 assert { value_sub (pelts x) (!xp.offset + mdn)
1321 (!xp.offset + mdn + sy)
1324 assert { value (x at PreAdjust) sx =
1325 (value !qp (sx - sy - !i)
1326 + qh * power radix (sx - sy - !i))
1327 * vy * power radix !i
1331 so (value !qp (sx - sy - !i)
1332 + qh * power radix (sx - sy - !i)) = 0 };
1335 let ghost gx1 = (C.get_ofs !xp 1) in
1336 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
1337 value_sub_upper_bound_tight (pelts y) y.offset (y.offset + p2i sy - 1);
1338 value_sub_tail (pelts x) (!xp.offset) (!xp.offset + p2i sy - 1);
1339 value_sub_lower_bound_tight (pelts x) (!xp.offset) (!xp.offset + p2i sy - 1);
1340 assert { dl + radix * dh
1341 >= (pelts x)[(!xp).offset] + radix * gx1
1342 by value_sub (pelts x) (!xp.offset + mdn)
1343 (!xp.offset + mdn + sy)
1345 so value y (sy - 1) < (dl + 1) * power radix (sy - 1 - 1)
1346 so vy = dh * power radix (sy - 1)
1348 < dh * power radix (sy - 1)
1349 + (dl + 1) * power radix (sy - 1 - 1)
1350 = power radix (sy - 2) * (dl+1 + radix * dh)
1351 so !xp.offset + mdn + sy - 1 = !xp.offset + 1
1352 so (pelts x)[!xp.offset + mdn + sy - 1]
1353 = (pelts x)[!xp.offset + 1] = gx1
1354 so value_sub (pelts x) (!xp.offset + mdn) (!xp.offset + mdn + sy)
1355 = gx1 * power radix (sy - 1)
1356 + value_sub (pelts x) (!xp.offset + mdn)
1357 (!xp.offset + mdn + sy - 1)
1358 >= gx1 * power radix (sy - 1)
1359 + (pelts x)[!xp.offset] * power radix (sy - 1 - 1)
1360 = power radix (sy - 2)
1361 * ((pelts x) [!xp.offset] + radix * gx1)
1362 so power radix (sy - 2) * ((pelts x) [!xp.offset] + radix * gx1)
1363 < power radix (sy - 2) * (dl+1 + radix * dh)
1364 so (pelts x) [!xp.offset] + radix * gx1
1365 < dl + 1 + radix * dh
1367 value_sub_tail (pelts x) (!xp.offset + p2i mdn)
1368 (!xp.offset + p2i mdn + p2i sy - 1);
1369 value_sub_tail (pelts x) x.offset (x.offset + p2i sy + p2i !i - 1);
1370 x1 := (C.get_ofs !xp 1);
1371 assert { value_sub (pelts x) (!xp.offset + mdn)
1372 (!xp.offset + mdn + sy - 1)
1373 + power radix (sy - 1) * !x1
1376 !xp.offset + mdn + sy - 1 = !xp.offset + 1
1377 so value_sub (pelts x) (!xp.offset + mdn)
1378 (!xp.offset + mdn + sy - 1)
1379 + power radix (sy - 1) * !x1
1380 = value_sub (pelts x) (!xp.offset + mdn)
1381 (!xp.offset + mdn + sy - 1)
1382 + power radix (sy - 1) * (pelts x)[!xp.offset + 1]
1383 = value_sub (pelts x) (!xp.offset + mdn)
1384 (!xp.offset + mdn + sy - 1)
1385 + power radix (sy - 1)
1386 * (pelts x)[!xp.offset + mdn + sy - 1]
1387 = value_sub (pelts x) (!xp.offset + mdn)
1388 (!xp.offset + mdn + sy)
1390 assert { value (x at PreAdjust) sx =
1391 (value !qp (sx - sy - !i)
1392 + qh * power radix (sx - sy - !i))
1393 * vy * power radix !i
1394 + value x (sy + !i - 1)
1395 + power radix (sy + !i - 1) * !x1
1396 by value (x at PreAdjust) sx =
1397 (value !qp (sx - sy - !i)
1398 + qh * power radix (sx - sy - !i))
1399 * vy * power radix !i
1402 so x.offset + sy + !i - 1 = !xp.offset + 1
1403 so (pelts x)[x.offset + sy + !i - 1] =
1404 (pelts x)[!xp.offset + 1]= !x1
1407 + power radix (sx -1) * (pelts x)[x.offset + sx - 1]
1408 = value x (sy + !i - 1)
1409 + power radix (sy + !i - 1) * (pelts x)[x.offset + sy + !i - 1]
1410 so value x (sy + !i - 1)
1411 + power radix (sy + !i - 1) * !x1
1417 invariant { 0 <= !i <= sx - sy }
1418 invariant { (!qp).offset = q.offset + !i }
1419 invariant { (!xp).offset = x.offset + sy + !i - 2 }
1420 invariant { plength !qp = plength q }
1421 invariant { !qp.min = q.min }
1422 invariant { !qp.max = q.max }
1423 invariant { plength !xp = plength x }
1424 invariant { !xp.min = x.min }
1425 invariant { !xp.max = x.max }
1426 invariant { pelts !qp = pelts q }
1427 invariant { pelts !xp = pelts x }
1428 invariant { writable !qp /\ writable !xp }
1429 invariant { value (old x) sx =
1430 (value !qp (sx - sy - !i)
1431 + qh * power radix (sx - sy - !i))
1432 * vy * power radix !i
1433 + value x (sy + !i - 1)
1434 + power radix (sy + !i - 1) * !x1 }
1435 invariant { value_sub (pelts x) (!xp.offset + mdn)
1436 (!xp.offset + mdn + sy - 1)
1437 + power radix (sy - 1) * !x1
1439 invariant { dl + radix * dh
1440 >= (pelts x)[(!xp).offset] + radix * !x1 }
1442 let ghost k = int32'int !i in
1444 let ghost s = int32'int sy + int32'int !i - 1 in
1445 xp.contents <- C.incr !xp (-1);
1446 let xd = C.incr !xp mdn in
1447 let nx0 = C.get_ofs !xp 1 in
1448 if [@extraction:unlikely] (!x1 = dh && nx0 = dl)
1450 ql := Limb.uint64_max;
1451 value_sub_concat (pelts x) x.offset xd.offset (xd.offset + p2i sy);
1452 value_sub_tail (pelts xd) xd.offset (xd.offset + p2i sy - 1);
1453 let ghost vlx = value xd (p2i sy - 1) in
1454 assert { value xd sy
1455 = vlx + power radix (sy - 1) * dl
1457 = vlx + power radix (sy - 1)
1458 * (pelts xd)[xd.offset + sy - 1]
1459 so xd.offset + sy - 1 = !xp.offset + mdn + sy - 1
1461 so pelts xd = pelts !xp
1462 so (pelts xd)[xd.offset + sy - 1]
1463 = (pelts !xp)[!xp.offset + 1] = dl
1465 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
1466 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 2);
1467 let ghost vly = value y (p2i sy - 2) in
1468 assert { vy = vly + power radix (sy - 2) * dl
1469 + power radix (sy - 1) * dh
1470 by (pelts y)[y.offset + sy - 1] = dh
1471 so (pelts y)[y.offset + sy - 2] = dl
1473 vy = value y (sy - 1)
1474 + power radix (sy - 1) * dh
1475 = vly + power radix (sy - 2) * dl
1476 + power radix (sy - 1) * dh };
1478 ensures { value_sub (pelts xd) (xd.offset+1) (xd.offset + p2i sy - 1)
1479 + power radix (sy - 2) * dl
1480 + power radix (sy - 1) * dh
1482 value_sub_tail (pelts xd) (xd.offset + 1) (xd.offset + p2i sy - 2);
1483 assert { value_sub (pelts x) (!xp.offset at StartLoop + mdn)
1484 (!xp.offset at StartLoop + mdn + sy - 1)
1485 = value_sub (pelts xd) (xd.offset+1) (xd.offset + p2i sy - 1)
1486 + power radix (sy - 2) * dl
1489 so !xp.offset at StartLoop + mdn = xd.offset + 1
1490 so !xp.offset at StartLoop + mdn + sy - 1 = xd.offset + sy
1491 so xd.offset + sy - 1 = !xp.offset + 1
1492 so pelts xd = pelts !xp
1493 so (pelts xd)[xd.offset + sy - 1] = (pelts !xp)[!xp.offset+1] = dl
1494 so value_sub (pelts x) (!xp.offset at StartLoop + mdn)
1495 (!xp.offset at StartLoop + mdn + sy - 1)
1496 = value_sub (pelts xd) (xd.offset+1) (xd.offset + sy)
1497 = value_sub (pelts xd) (xd.offset+1) (xd.offset + p2i sy - 1)
1498 + power radix (sy - 2)
1499 * (pelts xd)[xd.offset + p2i sy - 1]
1500 = value_sub (pelts xd) (xd.offset+1) (xd.offset + p2i sy - 1)
1501 + power radix (sy - 2) * dl
1503 assert { !x1 = dh };
1506 let ghost xc = Array.copy (x.data) in
1507 value_sub_frame (pelts x) xc.elts x.offset (x.offset + p2i !i);
1508 let ghost b = wmpn_submul_1 xd y sy !ql in
1510 ensures { value x !i
1511 = value (x at SubMax) !i }
1512 assert { forall j. x.offset <= j < x.offset + !i
1513 -> (pelts x)[j] = xc.elts[j]
1515 (pelts x)[j] = (pelts x at SubMax)[j]
1517 ((pelts x at SubMax)[j] = xc.elts[j]
1519 0 <= j /\ j < xc.Array.length
1521 value_sub_frame (pelts x) xc.elts x.offset (x.offset + p2i !i);
1523 value_sub_upper_bound (pelts xd) xd.offset (xd.offset + p2i sy);
1524 value_sub_lower_bound (pelts xd) xd.offset (xd.offset + p2i sy);
1525 value_sub_head (pelts xd) xd.offset (xd.offset + p2i sy - 1);
1526 assert { vlx < radix * vly
1528 vlx = value_sub (pelts xd at SubMax) xd.offset
1529 (xd.offset + sy - 1)
1530 = (pelts xd at SubMax)[xd.offset]
1531 + radix * value_sub (pelts xd at SubMax)
1533 (xd.offset + sy - 1)
1534 so value_sub (pelts xd at SubMax) (xd.offset + 1)
1535 (xd.offset + sy - 1)
1536 + power radix (sy - 2) * dl
1537 + power radix (sy - 1) * dh
1539 = vly + power radix (sy - 2) * dl
1540 + power radix (sy - 1) * dh
1541 so value_sub (pelts xd at SubMax) (xd.offset + 1)
1542 (xd.offset + sy - 1)
1544 so value_sub (pelts xd at SubMax) (xd.offset + 1)
1545 (xd.offset + sy - 1)
1547 so vlx = (pelts xd at SubMax)[xd.offset]
1548 + radix * value_sub (pelts xd at SubMax)
1550 (xd.offset + sy - 1)
1551 <= (pelts xd at SubMax)[xd.offset]
1553 < radix + radix * (vly - 1)
1559 = value (xd at SubMax) sy
1561 + power radix sy * b
1563 so 0 <= value xd sy < power radix sy
1564 so radix * power radix (sy - 2) = power radix (sy - 1)
1565 so radix * power radix (sy - 1) = power radix sy
1567 = power radix (sy - 1) * dl + vlx
1569 + power radix sy * b
1570 = power radix (sy - 1) * dl + vlx
1571 - radix * (vly + power radix (sy - 2) * dl
1572 + power radix (sy - 1) * dh)
1573 + vy + power radix sy * b
1574 = power radix (sy - 1) * dl + vlx
1575 - radix * vly - radix * power radix (sy - 2) * dl
1576 - radix * power radix (sy - 1) * dh
1577 + vy + power radix sy * b
1578 = power radix (sy - 1) * dl + vlx
1579 - radix * vly - power radix (sy - 1) * dl
1580 - power radix sy * dh
1581 + vy + power radix sy * b
1582 = power radix sy * (b - dh)
1583 + vlx - radix * vly + vy
1584 so vlx < radix * vly
1585 so (0 <= vlx - radix * vly + vy < power radix sy
1588 = vly + power radix (sy - 2) * dl
1589 + power radix (sy - 1) * dh
1591 = power radix (sy - 2) * (dl + radix * dh)
1593 so let pr2 = power radix (sy - 2) in
1595 so 0 <= vly * (radix - 1) < pr2 * (radix - 1)
1597 >= pr2 * (dl + radix * dh)
1599 = pr2 * (dl + radix * dh - (radix - 1))
1600 so dh + radix * dh - (radix - 1) >= 0
1603 >= pr2 * (dl + radix * dh - (radix - 1)) >= 0
1604 so vlx - radix * vly < 0
1605 so vlx - radix * vly + vy < vy < power radix sy
1607 so - (power radix sy)
1608 < power radix sy * (b - dh)
1612 value_sub_concat (pelts x) x.offset xd.offset (x.offset + s);
1613 x1 := C.get_ofs !xp 1;
1614 qp.contents <- C.incr !qp (-1);
1615 value_sub_update_no_change (pelts q) (!qp).offset
1617 ((!qp).offset + p2i sx - p2i sy - p2i !i)
1621 assert { value_sub (pelts q) ((!qp).offset + 1)
1622 ((!qp).offset + sx - sy - !i)
1623 = value (!qp at StartLoop)
1625 by value_sub (pelts q) ((!qp).offset + 1)
1626 ((!qp).offset + sx - sy - !i)
1627 = value_sub (pelts q at QUp) (!qp.offset + 1)
1628 ((!qp).offset + sx - sy - !i)
1629 = value (!qp at StartLoop) (sx - sy - k) };
1630 value_sub_head (pelts q) (!qp).offset
1631 ((!qp).offset + p2i sx - p2i sy - p2i !i);
1632 value_sub_tail (pelts x) x.offset (x.offset + p2i sy + p2i !i - 1);
1633 assert { value xd (sy - 1)
1634 + power radix (sy - 1) * !x1
1635 = value (xd at SubMax) sy
1636 + power radix sy * (!x1 at StartLoop)
1640 = value (xd at SubMax) sy
1642 + power radix sy * b
1643 so b = dh = !x1 at StartLoop
1644 so pelts !xp = pelts x = pelts xd
1645 so ((pelts xd)[xd.offset + sy - 1] = !x1
1647 xd.offset = x.offset + !i
1648 so (!xp).offset = x.offset + !i + sy - 2
1649 so (!xp).offset + 1 = xd.offset + sy - 1
1650 so (pelts xd)[xd.offset + sy - 1]
1651 = (pelts !xp)[(!xp).offset + 1]
1656 + power radix (sy - 1) * (pelts xd)[xd.offset + sy - 1]
1658 + power radix (sy - 1) * !x1
1661 assert { value (old x) sx =
1662 (value !qp (sx - sy - !i)
1663 + qh * power radix (sx - sy - !i))
1664 * vy * power radix !i
1665 + value x (sy + !i - 1)
1666 + power radix (sy + !i - 1) * !x1
1668 pelts !xp = pelts x = pelts xd
1671 = value (xd at SubMax) sy
1673 + power radix sy * b
1674 = value (xd at SubMax) sy
1676 + power radix sy * dh
1682 xd.offset = x.offset + !i
1683 so x.offset + s = xd.offset + sy - 1
1684 so value_sub (pelts x) (x.offset + !i) (x.offset + s)
1689 * value_sub (pelts x) (x.offset + !i)
1693 * value xd (sy - 1))
1695 = power radix !i * power radix (sy - 1)
1700 power x s = power x (n + m)
1701 so (power x (n + m) = power x n * power x m
1704 so forall x:int, n:int, m:int.
1706 power x (n + m) = (power x n * power x m)))
1707 so (value x s + power radix s * !x1
1709 + power radix !i * (value xd sy)
1711 value x s + power radix s * !x1
1715 + power radix (!i + sy - 1) * !x1
1719 + power radix (sy - 1) * !x1)
1721 + power radix !i * (value xd sy)
1723 so (value (x at StartLoop) (sy + k - 1)
1724 = value (x at SubMax) !i
1726 * value (xd at SubMax) sy
1728 pelts xd at SubMax = pelts x at SubMax
1729 so x.offset at SubMax + !i = xd.offset at SubMax
1731 value (x at StartLoop) (sy + k - 1)
1732 = value_sub (pelts x at SubMax) (x at SubMax).offset
1733 (xd.offset at SubMax)
1735 * value_sub (pelts x at SubMax)
1736 (xd.offset at SubMax)
1737 (xd.offset at SubMax + sy)
1738 so value_sub (pelts x at SubMax) (x at SubMax).offset
1739 (xd at SubMax).offset
1740 = value (x at SubMax) !i
1741 so value_sub (pelts x at SubMax) (xd.offset at SubMax)
1742 (xd.offset at SubMax + sy)
1743 = value (xd at SubMax) sy
1746 = value (x at SubMax) !i
1747 so value x s + power radix s * !x1
1748 = value (x at StartLoop) (sy + k - 1)
1751 - value (xd at SubMax) sy)
1752 = value (x at StartLoop) (sy + k - 1)
1755 + power radix sy * b)
1756 = value (x at StartLoop) (sy + k - 1)
1759 + power radix sy * (!x1 at StartLoop))
1760 so value !qp (sx - sy - !i)
1762 value_sub (pelts q) ((!qp).offset + 1)
1763 ((!qp).offset + sx - sy - !i)
1764 so (value_sub (pelts q) ((!qp).offset + 1)
1765 ((!qp).offset + sx - sy - !i)
1766 = value (!qp at StartLoop)
1768 by value (!qp at StartLoop) (sx - sy - k)
1769 = value_sub (pelts q at StartLoop)
1770 (!qp.offset + 1) (!qp.offset + sx - sy - !i))
1771 so value !qp (sx - sy - !i)
1772 = !ql + radix * value (!qp at StartLoop)
1774 so power radix (sx - sy - !i)
1775 = radix * power radix (sx - sy - k)
1776 so radix * power radix !i = power radix k
1777 so (power radix !i * power radix sy
1778 = power radix (sy + k - 1)
1779 by !i + sy = sy + k - 1
1780 so power radix !i * power radix sy
1781 = power radix (!i + sy))
1782 so (value !qp (sx - sy - !i)
1783 + qh * power radix (sx - sy - !i))
1784 * vy * power radix !i
1785 + value x (sy + !i - 1)
1786 + power radix (sy + !i - 1) * !x1
1787 = (!ql + radix * value (!qp at StartLoop)
1789 + qh * power radix (sx - sy - !i))
1790 * vy * power radix !i
1791 + value x (sy + !i - 1)
1792 + power radix (sy + !i - 1) * !x1
1793 = (!ql + radix * value (!qp at StartLoop)
1795 + radix * qh * power radix (sx - sy - k))
1796 * vy * power radix !i
1797 + value x (sy + !i - 1)
1798 + power radix (sy + !i - 1) * !x1
1799 = (!ql + radix * value (!qp at StartLoop)
1801 + radix * qh * power radix (sx - sy - k))
1802 * vy * power radix !i
1804 + power radix s * !x1
1805 = !ql * vy * power radix !i
1806 + radix * (value (!qp at StartLoop)
1808 + qh * power radix (sx - sy - k))
1809 * vy * power radix !i
1811 + power radix s * !x1
1812 = !ql * vy * power radix !i
1813 + (value (!qp at StartLoop)
1815 + qh * power radix (sx - sy - k))
1816 * vy * radix * power radix !i
1818 + power radix s * !x1
1819 = !ql * vy * power radix !i
1820 + (value (!qp at StartLoop)
1822 + qh * power radix (sx - sy - k))
1823 * vy * power radix k
1825 + power radix s * !x1
1826 = !ql * vy * power radix !i
1827 + (value (!qp at StartLoop)
1829 + qh * power radix (sx - sy - k))
1830 * vy * power radix k
1831 + value (x at StartLoop) (sy + k - 1)
1834 + power radix sy * (!x1 at StartLoop))
1835 = (value (!qp at StartLoop)
1837 + qh * power radix (sx - sy - k))
1838 * vy * power radix k
1839 + value (x at StartLoop) (sy + k - 1)
1840 + power radix !i * power radix sy
1841 * (!x1 at StartLoop)
1842 = (value (!qp at StartLoop)
1844 + qh * power radix (sx - sy - k))
1845 * vy * power radix k
1846 + value (x at StartLoop) (sy + k - 1)
1847 + power radix (sy + k - 1) * (!x1 at StartLoop)
1850 assert { value_sub (pelts x) (!xp.offset + mdn)
1851 (!xp.offset + mdn + sy - 1)
1852 + power radix (sy - 1) * !x1
1856 so xd.offset = !xp.offset + mdn
1857 so !xp.offset + mdn + sy - 1 = xd.offset + sy - 1
1860 = value_sub (pelts xd) xd.offset (xd.offset + sy - 1)
1861 = value_sub (pelts x) (!xp.offset + mdn)
1862 (!xp.offset + mdn + sy - 1)
1863 so value_sub (pelts x) (!xp.offset + mdn)
1864 (!xp.offset + mdn + sy - 1)
1865 + power radix (sy - 1) * !x1
1866 = value (xd at SubMax) sy
1867 + power radix sy * (!x1 at StartLoop)
1869 so value (xd at SubMax) sy =
1870 vlx + power radix (sy - 1) * dl
1871 so vlx < radix * vly
1872 so (value (xd at SubMax) sy
1873 + power radix sy * (!x1 at StartLoop)
1876 !x1 at StartLoop = dh
1877 so power radix sy = radix * power radix (sy - 1)
1878 so power radix (sy - 1) = radix * power radix (sy - 2)
1879 so value (xd at SubMax) sy
1880 + power radix sy * (!x1 at StartLoop)
1881 = vlx + power radix (sy - 1) * dl
1882 + power radix sy * dh
1883 < radix * vly + power radix (sy - 1) * dl
1884 + power radix sy * dh
1885 = radix * vly + radix * power radix (sy - 2) * dl
1886 + radix * power radix (sy - 1) * dh
1887 = radix * (vly + power radix (sy - 2) * dl
1888 + power radix (sy - 1) * dh)
1892 so value (xd at SubMax) sy
1893 + power radix sy * (!x1 at StartLoop)
1895 < radix * vy - (radix - 1) * vy
1898 value_sub_tail (pelts x) (!xp.offset + p2i mdn) (!xp.offset);
1899 value_sub_upper_bound (pelts y) (y.offset) (y.offset + p2i sy - 2);
1900 value_sub_lower_bound (pelts x) (!xp.offset + p2i mdn) (!xp.offset);
1901 assert { dl + radix * dh
1902 >= (pelts x)[(!xp).offset] + radix * !x1
1904 vy = vly + power radix (sy - 2)
1906 so value_sub (pelts x) (!xp.offset + mdn)
1907 (!xp.offset + mdn + sy - 1)
1908 + power radix (sy - 1) * !x1
1910 so !xp.offset + mdn + sy - 1 = !xp.offset + 1
1911 so power radix (sy - 1) = power radix (sy - 2) * radix
1914 > value_sub (pelts x) (!xp.offset + mdn)
1915 (!xp.offset + mdn + sy - 1)
1916 + power radix (sy - 1) * !x1
1917 = value_sub (pelts x) (!xp.offset + mdn)
1919 + power radix (sy - 1) * !x1
1920 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
1921 + power radix (- mdn) * (pelts x)[(!xp).offset]
1922 + power radix (sy - 1) * !x1
1923 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
1924 + power radix (sy - 2) * (pelts x)[(!xp).offset]
1925 + power radix (sy - 1) * !x1
1926 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
1927 + power radix (sy - 2) * (pelts x)[(!xp).offset]
1928 + power radix (sy - 2) * radix * !x1
1929 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
1930 + power radix (sy - 2)
1931 * ((pelts x)[(!xp).offset] + radix * !x1)
1932 >= power radix (sy - 2)
1933 * ((pelts x)[(!xp).offset] + radix * !x1)
1934 so vly < power radix (sy - 2)
1935 so vy < power radix (sy - 2)
1936 + power radix (sy - 2)
1938 = power radix (sy - 2)
1939 * (1 + dl + radix * dh)
1940 so power radix (sy - 2)
1941 * ((pelts x)[(!xp).offset] + radix * !x1)
1942 < power radix (sy - 2) * (1 + dl + radix * dh)
1943 so power radix (sy - 2)
1944 * ((pelts x)[(!xp).offset] + radix * !x1
1945 - (1 + dl + radix * dh))
1947 so (pelts x)[(!xp).offset] + radix * !x1
1948 - (1 + dl + radix * dh)
1953 assert { dl + radix * dh
1954 > (pelts x)[(!xp).offset + 1] + radix * !x1
1957 >= (pelts x)[(!xp).offset + 1] + radix * !x1
1959 so [@case_split] dh <> !x1
1961 /\ dl <> (pelts x)[(!xp).offset + 1])
1963 [@case_split] dh > !x1 \/
1964 (dh = !x1 /\ dl > (pelts x)[(!xp).offset + 1])
1967 let ghost vlx = value xd (p2i sy - 2) in
1968 let xp0 = C.get !xp in
1969 let xp1 = C.get_ofs !xp 1 in
1971 ensures { value xd sy =
1973 + power radix (sy - 2) * (xp0 + radix * xp1) }
1974 value_sub_tail (pelts xd) xd.offset (xd.offset + p2i sy - 1);
1975 value_sub_tail (pelts xd) xd.offset (xd.offset + p2i sy - 2);
1976 value_sub_upper_bound (pelts xd) xd.offset (xd.offset + p2i sy - 2);
1977 assert { value xd sy
1978 = vlx + power radix (sy - 2)
1979 * (xp0 + radix * xp1)
1980 by xd.offset + sy - 2 = !xp.offset
1981 so (pelts xd)[xd.offset + sy - 1] = xp1
1982 so (pelts xd)[xd.offset + sy - 2] = xp0
1983 so pelts xd = pelts !xp
1986 + power radix (sy - 1)
1987 * (pelts xd)[xd.offset + sy - 1]
1989 + power radix (sy - 2)
1990 * (pelts xd)[xd.offset + sy - 2]
1991 + power radix (sy - 1)
1992 * (pelts xd)[xd.offset + sy - 1]
1994 + power radix (sy - 2) * xp0
1995 + power radix (sy - 1) * xp1
1997 + power radix (sy - 2) * xp0
1998 + power radix (sy - 2) * radix * xp1
1999 = vlx + power radix (sy - 2)
2000 * (xp0 + radix * xp1)
2004 div3by2_inv !x1 xp1 xp0 dh dl v in
2009 value_sub_concat (pelts x) x.offset xd.offset
2010 (x.offset + p2i sy + k - 1);
2011 let ghost xc = Array.copy (x.data) in
2012 value_sub_frame (pelts x) xc.elts x.offset (x.offset + p2i !i);
2013 let cy = wmpn_submul_1 xd y (sy - 2) !ql in
2016 ensures { value x !i
2017 = value (x at SubProd) !i }
2018 assert { forall j. x.offset <= j < x.offset + !i
2019 -> (pelts x)[j] = xc.elts[j]
2021 (pelts x)[j] = (pelts x at SubProd)[j]
2023 ((pelts x at SubProd)[j] = xc.elts[j]
2025 0 <= j /\ j < xc.Array.length
2027 value_sub_frame (pelts x) xc.elts x.offset (x.offset + p2i !i);
2029 let (cy1:limb) = [@vc:sp] if (!x0 < cy) then 1 else 0 in
2030 x0 := sub_mod !x0 cy;
2031 let (cy2:limb) = [@vc:sp] if (!x1 < cy1) then 1 else 0 in
2032 x1 := sub_mod !x1 cy1;
2033 assert { 0 <= cy2 <= 1 };
2034 (* assert { cy2 = 1 -> rh = 0 }; (* and cy > rl *)*)
2035 value_sub_update (pelts x) (!xp).offset xd.offset
2036 (xd.offset + p2i sy - 1) !x0;
2037 value_sub_update_no_change (pelts x) (!xp).offset
2038 x.offset (x.offset + p2i !i) !x0;
2039 value_sub_update_no_change (pelts x) (!xp).offset
2040 xd.offset (xd.offset + p2i sy - 2) !x0;
2043 = value (x at SubProd) !i
2046 = value (x at PostSub) !i
2047 = value (x at SubProd) !i };
2048 value_sub_tail (pelts x) xd.offset (xd.offset + p2i sy - 1);
2050 ensures { value xd (sy - 1)
2051 + power radix (sy - 1) * !x1
2052 - power radix sy * cy2
2053 = value (xd at SubProd) sy
2054 + power radix sy * (!x1 at StartLoop)
2056 assert { value xd (sy - 2)
2057 = value (xd at PostSub) (sy - 2) };
2058 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
2059 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 2);
2060 let ghost vly = value y (p2i sy - 2) in
2061 assert { vy = vly + power radix (sy - 2)
2063 by (pelts y)[y.offset + sy - 1] = dh
2064 so (pelts y)[y.offset + sy - 2] = dl
2066 vy = value y (sy - 1)
2067 + power radix (sy - 1) * dh
2068 = vly + power radix (sy - 2) * dl
2069 + power radix (sy - 1) * dh
2070 so power radix (sy - 1)
2071 = power radix (sy - 2) * radix };
2072 assert { value xd (sy - 2)
2073 - power radix (sy - 2) * cy
2077 - power radix (sy - 2) * cy
2078 = value (xd at PostSub) (sy - 2)
2079 - power radix (sy - 2) * cy
2082 assert { power radix sy
2083 = power radix (sy - 2) * radix * radix };
2084 assert { xp0 + radix * xp1
2085 + radix * radix * !x1 at StartLoop
2086 - !ql * (dl + radix * dh)
2087 = rl + radix * rh };
2088 begin ensures { value (xd at SubProd) sy
2089 + power radix sy * (!x1 at StartLoop)
2092 - power radix (sy - 2) * cy
2093 + power radix (sy - 2) *
2095 assert { value (xd at SubProd) sy
2096 = vlx + power radix (sy - 2) * xp0
2097 + power radix (sy - 1) * xp1 }; (*nonlinear*)
2098 assert { !ql * vy = !ql * vly
2099 + power radix (sy - 2)
2100 * (!ql * (dl + radix * dh)) }; (*nonlinear*)
2102 begin ensures { value xd (sy - 2)
2103 - power radix (sy - 2) * cy
2104 + power radix (sy - 2) * (rl + radix * rh)
2106 + power radix (sy - 1) * !x1
2107 - power radix sy * cy2 }
2108 value_sub_tail (pelts xd) xd.offset (xd.offset + p2i sy - 2);
2109 assert { value xd (sy - 1)
2111 + power radix (sy - 2) * !x0
2112 by (pelts xd)[xd.offset + sy - 2] = !x0
2113 so value xd (sy - 1)
2114 = value_sub (pelts xd) xd.offset (xd.offset + sy - 1)
2115 = value_sub (pelts xd) xd.offset (xd.offset + sy - 2)
2116 + power radix (sy - 2) * !x0
2118 + power radix (sy - 2) * !x0 };
2119 assert { rl + radix * rh - cy
2120 = !x0 + radix * !x1 - power radix 2 * cy2
2122 (!x0 - radix * cy1 = rl - cy
2124 !x0 = mod (rl - cy) radix
2125 so - radix < rl - cy < radix
2128 /\ (- radix < rl - cy < 0
2130 div (rl - cy) radix = - 1
2132 = radix * div (rl - cy) radix
2133 + mod (rl - cy) radix
2135 = !x0 - radix * cy1)
2136 else cy1 = 0 /\ rl - cy = l2i !x0)) }
2140 if [@extraction:unlikely] (not (cy2 = 0))
2144 begin ensures { !ql > 0 }
2145 value_sub_lower_bound (pelts y) y.offset (y.offset + p2i sy - 1);
2146 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
2147 value_sub_upper_bound (pelts xd) xd.offset (xd.offset + p2i sy - 1);
2151 + power radix (sy - 1) * !x1
2152 - power radix sy * cy2
2155 value xd (sy - 1) < power radix (sy - 1)
2157 so value xd (sy - 1)
2158 + power radix (sy - 1) * !x1
2159 < power radix (sy - 1)
2160 + power radix (sy - 1) * !x1
2161 = power radix (sy - 1) * (1 + !x1)
2162 <= power radix (sy - 1) * radix
2164 so value xd (sy - 1)
2165 + power radix (sy - 1) * !x1
2166 - power radix sy * cy2
2167 < power radix sy - power radix sy * cy2
2170 so value (xd at SubProd) sy
2171 + power radix sy * (!x1 at StartLoop)
2174 so (value (xd at SubProd) sy
2175 + power radix sy * (!x1 at StartLoop) >= 0
2176 by value (xd at SubProd) sy >= 0
2177 so !x1 at StartLoop >= 0
2178 so power radix sy * (!x1 at StartLoop) >= 0
2181 so vy = value_sub (pelts y)
2182 y.offset (y.offset + sy - 1)
2183 + power radix (sy - 1) * dh
2188 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
2189 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 2);
2190 let ghost vly = value y (p2i sy - 2) in
2191 assert { vy = vly + power radix (sy - 2) * dl
2192 + power radix (sy - 1) * dh
2193 by (pelts y)[y.offset + sy - 1] = dh
2194 so (pelts y)[y.offset + sy - 2] = dl
2196 vy = value y (sy - 1)
2197 + power radix (sy - 1) * dh
2198 = vly + power radix (sy - 2) * dl
2199 + power radix (sy - 1) * dh };
2201 ensures { value xd (sy - 1)
2202 + power radix (sy - 1) * !x1
2203 >= power radix sy - vy }
2204 assert { value xd (sy - 1)
2205 + power radix (sy - 1) * !x1
2206 = power radix sy + value (xd at SubProd) sy
2207 + power radix sy * (!x1 at StartLoop)
2209 assert { value (xd at SubProd) sy
2210 + power radix sy * (!x1 at StartLoop)
2214 value (xd at SubProd) sy
2215 = vlx + power radix (sy - 2) * (xp0 + radix * xp1)
2216 so xp0 + radix * xp1 + radix * radix * (!x1 at StartLoop)
2217 = !ql * (dl + radix * dh) + rl + radix * rh
2218 so power radix (sy - 1) = power radix (sy - 2) * radix
2219 so vy = vly + power radix (sy - 2) * (dl + radix * dh)
2222 vly <= power radix (sy - 2)
2224 so !ql * vly <= !ql * power radix (sy - 2)
2225 < radix * power radix (sy - 2)
2226 = power radix (sy - 1)
2227 so vy = vly + power radix (sy - 2) * (dl + radix * dh)
2228 so dh >= div radix 2 > 1
2231 so vy >= power radix (sy - 2) * radix * dh
2232 > power radix (sy - 2) * radix * 1
2233 = power radix (sy - 1)
2235 so - !ql * vly > - vy
2237 so power radix sy = power radix (sy - 2) * radix * radix
2238 so value (xd at SubProd) sy
2239 + power radix sy * (!x1 at StartLoop)
2241 = vlx + power radix (sy - 2) * (xp0 + radix * xp1)
2242 + power radix sy * (!x1 at StartLoop)
2244 = vlx + power radix (sy - 2) * (xp0 + radix * xp1)
2245 + power radix (sy - 2)
2246 * radix * radix * (!x1 at StartLoop)
2248 = vlx + power radix (sy - 2)
2249 * (xp0 + radix * xp1
2250 + radix * radix * (!x1 at StartLoop))
2252 = vlx + power radix (sy - 2) *
2253 (!ql * (dl + radix * dh) + rl + radix * rh)
2255 = vlx + power radix (sy - 2) *
2256 (!ql * (dl + radix * dh) + rl + radix * rh)
2258 + power radix (sy - 2) * (dl + radix * dh))
2259 = vlx + power radix (sy - 2) * (rl + radix * rh)
2261 >= power radix (sy - 2) * (rl + radix * rh)
2263 >= - !ql * vly > - vy
2266 let ghost xc = Array.copy (x.data) in
2267 assert { forall j. x.offset <= j < x.offset + !i
2268 -> (pelts x)[j] = xc.elts[j]
2270 0 <= x.offset <= j /\ j < x.offset + !i <= xc.Array.length
2271 so 0 <= j < xc.Array.length
2273 value_sub_frame (pelts x) xc.elts x.offset (x.offset + p2i !i);
2274 let c = wmpn_add_n_in_place xd y (sy - 1) in
2276 ensures { value x !i
2277 = value (x at Adjust) !i }
2278 assert { forall j. x.offset <= j < x.offset + !i
2279 -> (pelts x)[j] = xc.elts[j]
2281 pelts (xd at Adjust) = pelts (x at Adjust)
2282 so pelts x = pelts xd
2283 so (pelts x)[j] = (pelts x at Adjust)[j]
2285 ((pelts x at Adjust)[j] = xc.elts[j]
2287 0 <= j /\ j < xc.Array.length
2289 value_sub_frame (pelts x) xc.elts x.offset (x.offset + p2i !i);
2293 ensures { value xd (sy - 1) + power radix (sy - 1) * !x1
2294 = value (xd at Adjust) (sy - 1)
2295 + power radix (sy - 1) * (!x1 at Adjust)
2298 assert { 0 <= c <= 1
2300 value xd (sy - 1) + c * power radix (sy - 1)
2301 = value (xd at Adjust) (sy - 1)
2304 value (xd at Adjust) (sy - 1)
2305 < power radix (sy - 1)
2306 so value y (sy - 1) < power radix (sy - 1)
2307 so value xd (sy - 1) >= 0
2308 so c * power radix (sy - 1) < 2 * power radix (sy - 1)
2309 so let p = power radix (sy - 1) in
2310 (c < 2 by c * p < 2 * p so p > 0)
2312 let ghost c' = div (l2i !x1 + l2i dh + l2i c) radix in
2313 x1 := add_mod !x1 (add_mod dh c);
2314 assert { !x1 + c' * radix = !x1 at Adjust + dh + c
2316 (!x1 = mod (!x1 at Adjust + dh + c) radix
2318 !x1 = mod (!x1 at Adjust + (mod (dh + c) radix)) radix
2319 so mod (div (dh + c) radix * radix + !x1 at Adjust
2320 + mod (dh + c) radix) radix
2321 = mod (!x1 at Adjust + (mod (dh + c) radix)) radix
2322 so !x1 = mod (div (dh + c) radix * radix + !x1 at Adjust
2323 + mod (dh + c) radix) radix
2324 = mod (!x1 at Adjust + dh + c) radix
2326 so (!x1 at Adjust) + dh + c
2327 = div (!x1 at Adjust + dh + c) radix * radix
2328 + mod (!x1 at Adjust + dh + c) radix
2331 assert { 0 <= c' <= 1 };
2332 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
2333 assert { value xd (sy - 1) + power radix (sy - 1) * !x1
2334 = value (xd at Adjust) (sy - 1)
2335 + power radix (sy - 1) * (!x1 at Adjust)
2339 value xd (sy - 1) + power radix (sy - 1) * c
2340 = value (xd at Adjust) (sy - 1)
2342 so vy = value y (sy - 1)
2343 + power radix (sy - 1) * dh
2344 so value xd (sy - 1) + power radix (sy - 1) * c
2345 + power radix (sy - 1) * (!x1 at Adjust)
2346 + power radix (sy - 1) * dh
2347 = value (xd at Adjust) (sy - 1)
2349 + power radix (sy - 1) * (!x1 at Adjust)
2350 + power radix (sy - 1) * dh
2351 = value (xd at Adjust) (sy - 1)
2352 + power radix (sy - 1) * (!x1 at Adjust)
2354 so value xd (sy - 1) + power radix (sy - 1) * c
2355 + power radix (sy - 1) * (!x1 at Adjust)
2356 + power radix (sy - 1) * dh
2358 + power radix (sy - 1) * (c + dh + !x1 at Adjust)
2360 + power radix (sy - 1) * (!x1 + radix * c')
2362 + power radix (sy - 1) * !x1
2363 + power radix sy * c'
2364 so value xd (sy - 1)
2365 + power radix (sy - 1) * !x1
2366 + power radix sy * c'
2367 = value (xd at Adjust) (sy - 1)
2368 + power radix (sy - 1) * (!x1 at Adjust)
2370 so value (xd at Adjust) (sy - 1)
2371 + power radix (sy - 1) * (!x1 at Adjust)
2372 >= power radix sy - vy
2373 so value xd (sy - 1) < power radix (sy - 1)
2375 so power radix (sy - 1) * !x1
2376 <= power radix (sy - 1) * (radix - 1)
2377 so value xd (sy - 1)
2378 + power radix (sy - 1) * !x1
2379 <= value xd (sy - 1)
2380 + power radix (sy - 1) * (radix - 1)
2381 < power radix (sy - 1)
2382 + power radix (sy - 1) * (radix - 1)
2390 assert { value xd (sy - 1) + power radix (sy - 1) * !x1
2391 = value (xd at SubProd) sy
2392 + power radix sy * (!x1 at StartLoop)
2395 value xd (sy - 1) + power radix (sy - 1) * !x1
2396 = value (xd at Adjust) (sy - 1)
2397 + power radix (sy - 1) * (!x1 at Adjust)
2400 = value (xd at SubProd) sy
2401 + power radix sy * (!x1 at StartLoop)
2402 - (!ql at Adjust) * vy
2404 = value (xd at SubProd) sy
2405 + power radix sy * (!x1 at StartLoop)
2408 = value (xd at SubProd) sy
2409 + power radix sy * (!x1 at StartLoop)
2411 qp.contents <- C.incr !qp (-1);
2412 value_sub_update_no_change (pelts q) (!qp).offset
2414 ((!qp).offset + p2i sx - p2i sy - p2i !i)
2417 value_sub_head (pelts q) (!qp).offset
2418 ((!qp).offset + p2i sx - p2i sy - p2i !i);
2419 value_sub_tail (pelts x) x.offset (x.offset + p2i sy + p2i !i - 1);
2420 value_sub_concat (pelts x) x.offset xd.offset (x.offset + s);
2422 assert { value (old x) sx =
2423 (value !qp (sx - sy - !i)
2424 + qh * power radix (sx - sy - !i))
2425 * vy * power radix !i
2426 + value x (sy + !i - 1)
2427 + power radix (sy + !i - 1) * !x1
2429 value !qp (sx - sy - !i)
2431 value_sub (pelts q) ((!qp).offset + 1)
2432 ((!qp).offset + sx - sy - !i)
2433 so (value_sub (pelts q) ((!qp).offset + 1)
2434 ((!qp).offset + sx - sy - !i)
2435 = value (!qp at StartLoop)
2438 (!qp at StartLoop).offset = (!qp).offset + 1
2439 so ((!qp).offset + sx - sy - !i)
2440 - ((!qp).offset + 1)
2443 so value !qp (sx - sy - !i)
2444 = !ql + radix * value (!qp at StartLoop)
2451 xd.offset = x.offset + !i
2452 so x.offset + s = xd.offset + sy - 1
2453 so pelts x = pelts xd
2454 so x.offset + s - xd.offset = sy - 1
2455 so value_sub (pelts x) xd.offset (x.offset + s)
2458 = value_sub (pelts x) x.offset xd.offset
2459 + power radix !i * value_sub (pelts x) xd.offset (x.offset + s)
2461 + power radix !i * value xd (sy - 1)
2464 = power radix !i * power radix (sy - 1)
2469 power x s = power x (n + m)
2470 so (power x (n + m) = power x n * power x m
2473 so forall x:int, n:int, m:int.
2474 0 <= n -> 0 <= m -> power x (n + m) = (power x n * power x m)))
2475 so (value x s + power radix s * !x1
2478 (value (xd at SubProd) sy
2479 + power radix sy * (!x1 at StartLoop)
2481 by value xd (sy - 1)
2482 + power radix (sy - 1) * !x1
2483 = value (xd at SubProd) sy
2484 + power radix sy * (!x1 at StartLoop)
2486 so value x s + power radix s * !x1
2490 + power radix (!i + sy - 1) * !x1
2495 * power radix (sy - 1) * !x1
2499 + power radix (sy - 1) * !x1)
2502 (value (xd at SubProd) sy
2503 + power radix sy * (!x1 at StartLoop)
2506 so (value (x at StartLoop) (sy + k - 1)
2507 = value (x at SubProd) !i
2509 * value (xd at SubProd) sy
2511 value (x at StartLoop) (sy + k - 1)
2512 = value_sub (pelts x at SubProd) (x at SubProd).offset
2513 ((x at SubProd).offset + sy + k - 1)
2514 = value_sub (pelts x at SubProd) (x at SubProd).offset xd.offset
2515 + power radix (xd.offset - (x at SubProd).offset)
2516 * value_sub (pelts x at SubProd) xd.offset
2517 ((x at SubProd).offset + sy + k - 1)
2518 so (x at SubProd).offset = x.offset
2519 so xd.offset = x.offset + !i
2520 so value_sub (pelts x at SubProd) (x at SubProd).offset xd.offset
2521 = value (x at SubProd) !i
2522 so power radix (xd.offset - x.offset) = power radix !i
2523 so x.offset + sy + k - 1 - xd.offset = p2i sy
2524 so value_sub (pelts x at SubProd) xd.offset
2525 (x.offset + sy + k - 1)
2526 = value (xd at SubProd) sy
2529 = value (x at SubProd) !i
2532 = value (x at Adjust) !i
2533 = value (x at SubProd) !i
2535 so power radix !i * power radix sy = power radix (!i + sy)
2536 so value x s + power radix s * !x1
2537 - value (x at StartLoop) (sy + k - 1)
2540 (value (xd at SubProd) sy
2541 + power radix sy * (!x1 at StartLoop)
2543 - (value (x at SubProd) !i
2545 * value (xd at SubProd) sy)
2548 (value (xd at SubProd) sy
2549 + power radix sy * (!x1 at StartLoop)
2553 * value (xd at SubProd) sy)
2555 * (power radix sy * (!x1 at StartLoop)
2557 = power radix !i * power radix sy * (!x1 at StartLoop)
2558 - power radix !i * !ql * vy
2559 = power radix (!i + sy) * (!x1 at StartLoop)
2560 - power radix !i * !ql * vy
2561 = power radix (sy + k - 1) * (!x1 at StartLoop)
2562 - power radix !i * !ql * vy
2563 so value x s + power radix s * !x1
2564 = value (x at StartLoop) (sy + k - 1)
2565 + power radix (sy + k - 1) * (!x1 at StartLoop)
2566 - power radix !i * !ql * vy
2567 so power radix (sx - sy - !i)
2568 = radix * power radix (sx - sy - k)
2569 so radix * power radix !i = power radix k
2570 so (value !qp (sx - sy - !i)
2571 + qh * power radix (sx - sy - !i))
2572 * vy * power radix !i
2573 + value x (sy + !i - 1)
2574 + power radix (sy + !i - 1) * !x1
2575 = (!ql + radix * value (!qp at StartLoop)
2577 + qh * power radix (sx - sy - !i))
2578 * vy * power radix !i
2579 + value x (sy + !i - 1)
2580 + power radix (sy + !i - 1) * !x1
2581 = (!ql + radix * value (!qp at StartLoop)
2583 + qh * radix * power radix (sx - sy - k))
2584 * vy * power radix !i
2585 + value x (sy + !i - 1)
2586 + power radix (sy + !i - 1) * !x1
2587 = !ql * vy * power radix !i
2588 + (value (!qp at StartLoop)
2590 + qh * power radix (sx - sy - k))
2591 * vy * radix * power radix !i
2592 + value x (sy + !i - 1)
2593 + power radix (sy + !i - 1) * !x1
2594 = !ql * vy * power radix !i
2595 + (value (!qp at StartLoop)
2597 + qh * power radix (sx - sy - k))
2598 * vy * power radix k
2599 + value x (sy + !i - 1)
2600 + power radix (sy + !i - 1) * !x1
2601 = !ql * vy * power radix !i
2602 + (value (!qp at StartLoop)
2604 + qh * power radix (sx - sy - k))
2605 * vy * power radix k
2607 + power radix s * !x1
2608 = !ql * vy * power radix !i
2609 + (value (!qp at StartLoop)
2611 + qh * power radix (sx - sy - k))
2612 * vy * power radix k
2613 + value (x at StartLoop) (sy + k - 1)
2614 + power radix (sy + k - 1) * (!x1 at StartLoop)
2615 - power radix !i * !ql * vy
2616 = (value (!qp at StartLoop)
2618 + qh * power radix (sx - sy - k))
2619 * vy * power radix k
2620 + value (x at StartLoop) (sy + k - 1)
2621 + power radix (sy + k - 1) * (!x1 at StartLoop)
2624 assert { value_sub (pelts x) (!xp.offset + mdn)
2625 (!xp.offset + mdn + sy - 1)
2626 + power radix (sy - 1) * !x1
2629 (value xd (sy - 1) + power radix (sy - 1) * !x1 < vy
2631 value xd (sy - 1) + power radix (sy - 1) * !x1
2632 = value (xd at Adjust) (sy - 1)
2633 + power radix (sy - 1) * (!x1 at Adjust)
2636 so value (xd at Adjust) (sy - 1)
2637 < power radix (sy - 1)
2638 so 1 + (!x1 at Adjust) <= radix
2639 so value (xd at Adjust) (sy - 1)
2640 + power radix (sy - 1) * (!x1 at Adjust)
2643 < power radix (sy - 1)
2644 + power radix (sy - 1) * (!x1 at Adjust)
2647 = power radix (sy - 1) * (1 + !x1 at Adjust)
2650 <= power radix (sy - 1) * radix
2655 so pelts x = pelts xd
2656 so xd.offset = !xp.offset + mdn
2657 so value xd (sy - 1)
2658 = value_sub (pelts x) (!xp.offset + mdn)
2659 (!xp.offset + mdn + sy - 1)
2661 assert { dl + radix * dh
2662 >= (pelts x)[(!xp).offset] + radix * !x1
2664 vy = vly + power radix (sy - 2)
2666 so value_sub (pelts x) (!xp.offset + mdn)
2667 (!xp.offset + mdn + sy - 1)
2668 + power radix (sy - 1) * !x1
2670 so !xp.offset + mdn + sy - 1 = !xp.offset + 1
2671 so power radix (sy - 1) = power radix (sy - 2) * radix
2674 > value_sub (pelts x) (!xp.offset + mdn)
2675 (!xp.offset + mdn + sy - 1)
2676 + power radix (sy - 1) * !x1
2677 = value_sub (pelts x) (!xp.offset + mdn)
2679 + power radix (sy - 1) * !x1
2680 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2681 + power radix (- mdn) * (pelts x)[(!xp).offset]
2682 + power radix (sy - 1) * !x1
2683 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2684 + power radix (sy - 2) * (pelts x)[(!xp).offset]
2685 + power radix (sy - 1) * !x1
2686 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2687 + power radix (sy - 2) * (pelts x)[(!xp).offset]
2688 + power radix (sy - 2) * radix * !x1
2689 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2690 + power radix (sy - 2)
2691 * ((pelts x)[(!xp).offset] + radix * !x1)
2692 >= power radix (sy - 2)
2693 * ((pelts x)[(!xp).offset] + radix * !x1)
2694 so vly < power radix (sy - 2)
2695 so vy < power radix (sy - 2)
2696 + power radix (sy - 2)
2698 = power radix (sy - 2)
2699 * (1 + dl + radix * dh)
2700 so power radix (sy - 2)
2701 * ((pelts x)[(!xp).offset] + radix * !x1)
2702 < power radix (sy - 2) * (1 + dl + radix * dh)
2703 so power radix (sy - 2)
2704 * ((pelts x)[(!xp).offset] + radix * !x1
2705 - (1 + dl + radix * dh))
2707 so (pelts x)[(!xp).offset] + radix * !x1
2708 - (1 + dl + radix * dh)
2713 qp.contents <- C.incr !qp (-1);
2714 value_sub_update_no_change (pelts q) (!qp).offset
2716 ((!qp).offset + p2i sx - p2i sy - p2i !i)
2719 value_sub_head (pelts q) (!qp).offset
2720 ((!qp).offset + p2i sx - p2i sy - p2i !i);
2721 assert { value !qp (sx - sy - !i) * vy
2722 = !ql * vy + radix *
2723 (value_sub (pelts q) ((!qp).offset + 1)
2724 ((!qp).offset + sx - sy - !i) * vy) }; (*nonlinear*)
2725 assert { value_sub (pelts q) ((!qp).offset + 1)
2726 ((!qp).offset + sx - sy - !i) * vy
2727 = (value !qp (sx - sy - !i) * vy at StartLoop) }; (*nonlinear*)
2728 value_tail x (sy + !i - 1);
2729 value_sub_concat (pelts x) x.offset xd.offset (x.offset + s);
2732 assert { value x !i = value (x at SubProd) !i };
2733 assert { value x s = value x !i + power radix !i * value xd (sy-1)
2734 by xd.offset = x.offset + !i
2735 so x.offset + s = xd.offset + sy - 1
2736 so pelts x = pelts xd
2737 so x.offset + s - xd.offset = sy - 1
2738 so value_sub (pelts x) xd.offset (x.offset + s)
2741 = value_sub (pelts x) x.offset xd.offset
2742 + power radix !i * value_sub (pelts x) xd.offset (x.offset + s)
2744 + power radix !i * value xd (sy - 1)}; (*lifted from assertion*)
2745 assert { (value !qp (sx - sy - !i) + qh * power radix (sx - sy - !i))
2747 = value !qp (sx - sy - !i) * vy
2748 + qh * vy * power radix (sx - sy - !i) }; (*nonlinear*)
2749 assert { ((value !qp (sx - sy - !i) + qh * power radix (sx - sy - !i))
2751 = (value !qp (sx - sy - !i) * vy
2752 + qh * vy * power radix (sx - sy - !i) at StartLoop) }; (*nonlinear*)
2753 assert { value x s = value x (sy + !i - 1) };
2754 assert { value (xd at SmallDiv) sy =
2755 vlx + power radix (sy - 2) * xp0
2756 + power radix (sy - 1) * xp1 }; (*nonlinear*)
2757 assert { value (x at SubProd) (sy + (!i at StartLoop) - 1)
2758 = value (x at SubProd) !i + power radix !i * value (xd at SubProd) sy };
2759 assert { value (old x) sx =
2760 (value !qp (sx - sy - !i)
2761 + qh * power radix (sx - sy - !i))
2762 * vy * power radix !i
2763 + value x (sy + !i - 1)
2764 + power radix (sy + !i - 1) * !x1 };
2765 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
2766 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 2);
2767 let ghost vly = value y (p2i sy - 2) in
2768 assert { vy = vly + power radix (sy - 2) * dl
2769 + power radix (sy - 1) * dh
2770 by (pelts y)[y.offset + sy - 1] = dh
2771 so (pelts y)[y.offset + sy - 2] = dl
2773 vy = value y (sy - 1)
2774 + power radix (sy - 1) * dh
2775 = vly + power radix (sy - 2) * dl
2776 + power radix (sy - 1) * dh };
2777 assert { value_sub (pelts x) (!xp.offset + mdn)
2778 (!xp.offset + mdn + sy - 1)
2779 + power radix (sy - 1) * !x1
2783 so xd.offset = !xp.offset + mdn
2784 so !xp.offset + mdn + sy - 1 = xd.offset + sy - 1
2787 = value_sub (pelts xd) xd.offset (xd.offset + sy - 1)
2788 = value_sub (pelts x) (!xp.offset + mdn)
2789 (!xp.offset + mdn + sy - 1)
2790 so value xd (sy - 1)
2791 + power radix (sy - 1) * !x1
2792 - power radix sy * cy2
2793 = value (xd at SubProd) sy
2794 + power radix sy * (!x1 at StartLoop)
2797 so value xd (sy - 1)
2798 + power radix (sy - 1) * !x1
2799 = value (xd at SubProd) sy
2800 + power radix sy * (!x1 at StartLoop)
2802 so !ql * (dl + radix * dh)
2806 + radix * radix * (!x1 at StartLoop)
2807 so vy = vly + power radix (sy - 2)
2810 = power radix (sy - 2) *
2813 + radix * radix * (!x1 at StartLoop))
2814 - power radix (sy - 2) * (rl + radix * rh)
2816 so value (xd at SubProd) sy
2818 + power radix (sy - 2) * (xp0 + radix * xp1)
2820 = power radix (sy - 2) * radix * radix
2821 so (value (xd at SubProd) sy
2822 + power radix sy * (!x1 at StartLoop)
2827 by !ql >= 0 so vly >= 0)
2828 so (power radix (sy - 2) * (rl + radix * rh)
2829 <= power radix (sy - 2)
2831 - power radix (sy - 2)
2833 rl + radix * rh <= dl + radix * dh - 1
2834 so power radix (sy - 2) >= 0
2835 so power radix (sy - 2) * (rl + radix * rh)
2836 <= power radix (sy - 2)
2837 * (dl + radix * dh - 1)
2838 = power radix (sy - 2)
2840 - power radix (sy - 2)
2842 so vlx < power radix (sy - 2)
2843 so value (xd at SubProd) sy
2844 + power radix sy * (!x1 at StartLoop)
2847 + power radix (sy - 2) * (xp0 + radix * xp1)
2848 + power radix sy * (!x1 at StartLoop)
2851 + power radix (sy - 2) *
2853 + radix * radix * (!x1 at StartLoop))
2856 + power radix (sy - 2) *
2858 + radix * radix * (!x1 at StartLoop))
2859 - (power radix (sy - 2) *
2862 + radix * radix * (!x1 at StartLoop))
2863 - power radix (sy - 2) * (rl + radix * rh)
2866 + power radix (sy - 2) * (rl + radix * rh)
2869 + power radix (sy - 2) * (rl + radix * rh)
2871 + power radix (sy - 2)
2873 - power radix (sy - 2)
2874 < power radix (sy - 2)
2875 + power radix (sy - 2)
2877 - power radix (sy - 2)
2878 = power radix (sy - 2) * (dl + radix * dh)
2881 so value_sub (pelts x) (!xp.offset + mdn)
2882 (!xp.offset + mdn + sy - 1)
2883 + power radix (sy - 1) * !x1
2885 + power radix (sy - 1) * !x1
2886 = value (xd at SubProd) sy
2887 + power radix sy * (!x1 at StartLoop)
2891 value_sub_tail (pelts x) (!xp.offset + p2i mdn) (!xp.offset);
2892 value_sub_upper_bound (pelts y) (y.offset) (y.offset + p2i sy - 2);
2893 value_sub_lower_bound (pelts x) (!xp.offset + p2i mdn) (!xp.offset);
2894 assert { dl + radix * dh
2895 >= (pelts x)[(!xp).offset] + radix * !x1
2897 vy = vly + power radix (sy - 2)
2899 so value_sub (pelts x) (!xp.offset + mdn)
2900 (!xp.offset + mdn + sy - 1)
2901 + power radix (sy - 1) * !x1
2903 so !xp.offset + mdn + sy - 1 = !xp.offset + 1
2904 so power radix (sy - 1) = power radix (sy - 2) * radix
2907 > value_sub (pelts x) (!xp.offset + mdn)
2908 (!xp.offset + mdn + sy - 1)
2909 + power radix (sy - 1) * !x1
2910 = value_sub (pelts x) (!xp.offset + mdn)
2912 + power radix (sy - 1) * !x1
2913 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2914 + power radix (- mdn) * (pelts x)[(!xp).offset]
2915 + power radix (sy - 1) * !x1
2916 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2917 + power radix (sy - 2) * (pelts x)[(!xp).offset]
2918 + power radix (sy - 1) * !x1
2919 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2920 + power radix (sy - 2) * (pelts x)[(!xp).offset]
2921 + power radix (sy - 2) * radix * !x1
2922 = value_sub (pelts x) (!xp.offset + mdn) (!xp.offset)
2923 + power radix (sy - 2)
2924 * ((pelts x)[(!xp).offset] + radix * !x1)
2925 >= power radix (sy - 2)
2926 * ((pelts x)[(!xp).offset] + radix * !x1)
2927 so vly < power radix (sy - 2)
2928 so vy < power radix (sy - 2)
2929 + power radix (sy - 2)
2931 = power radix (sy - 2)
2932 * (1 + dl + radix * dh)
2933 so power radix (sy - 2)
2934 * ((pelts x)[(!xp).offset] + radix * !x1)
2935 < power radix (sy - 2) * (1 + dl + radix * dh)
2936 so power radix (sy - 2)
2937 * ((pelts x)[(!xp).offset] + radix * !x1
2938 - (1 + dl + radix * dh))
2940 so (pelts x)[(!xp).offset] + radix * !x1
2941 - (1 + dl + radix * dh)
2949 assert { !xp.offset = x.offset + sy - 2 };
2950 value_sub_update_no_change (pelts x) (!xp.offset + 1)
2951 x.offset (!xp.offset) !x1;
2952 C.set_ofs !xp 1 !x1;
2953 assert { value x (sy - 1) =
2954 value (x at EndLoop) (sy - 1)
2955 by pelts x = Map.set (pelts x at EndLoop) (x.offset + sy - 1) !x1 };
2956 value_sub_tail (pelts x) x.offset (!xp.offset+1);
2958 assert { value (old x) sx =
2960 + power radix (sx - sy) * qh)
2966 + power radix (sy - 1) * !x1
2969 = (value !qp (sx - sy - !i)
2970 + qh * power radix (sx - sy - !i))
2971 * vy * power radix !i
2972 + value x (sy + !i - 1)
2973 + power radix (sy + !i - 1) * !x1
2974 = (value !qp (sx - sy)
2975 + qh * power radix (sx - sy))
2978 + power radix (sy - 1) * !x1
2979 = (value !qp (sx - sy)
2980 + qh * power radix (sx - sy))
2985 let wmpn_divrem_2 (q x y:t) (sx:int32) : limb
2986 requires { 2 <= sx }
2987 requires { valid x sx }
2988 requires { valid y 2 }
2989 requires { valid q (sx - 2) }
2990 requires { (pelts y)[y.offset + 1] >= div radix 2 }
2991 requires { writable q /\ writable x }
2992 ensures { value (old x) sx =
2994 + power radix (sx - 2) * result)
2997 ensures { value x 2 < value y 2 }
2998 ensures { 0 <= result <= 1 }
3000 let xp = ref (C.incr x (sx - 2)) in
3001 let dh = C.get_ofs y 1 in
3003 let rh = ref (C.get_ofs !xp 1) in
3004 let rl = ref (C.get !xp) in
3007 assert { value y 2 = dl + radix * dh };
3008 let i = ref (sx - 2) in
3009 let dinv = reciprocal_word_3by2 dh dl in
3010 ([@vc:sp] if (!rh >= dh && ([@vc:sp] !rh > dh || !rl >= dl))
3014 ensures { value x sx
3015 = (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3016 + !qh * power radix (sx - 2 - !i))
3017 * value y 2 * power radix !i
3019 + power radix !i * (!rl + radix * !rh) }
3020 ensures { !rl + radix * !rh < dl + radix * dh }
3022 let (r0, b) = sub_with_borrow !rl dl 0 in
3023 let (r1, ghost b') = sub_with_borrow !rh dh b in
3025 assert { r0 + radix * r1 = !rl + radix * !rh - (dl + radix * dh) };
3026 value_sub_tail (pelts x) x.offset (x.offset + p2i sx - 1);
3027 value_sub_tail (pelts x) x.offset (x.offset + p2i sx - 2);
3032 = (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3033 + !qh * power radix (sx - 2 - !i))
3034 * value y 2 * power radix !i
3036 + power radix !i * (!rl + radix * !rh)
3038 value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2) = 0
3039 so (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3040 + !qh * power radix (sx - 2 - !i))
3041 * value y 2 * power radix !i
3043 + power radix !i * (!rl + radix * !rh)
3044 = value y 2 * power radix !i
3046 + power radix !i * (!rl + radix * !rh)
3048 + power radix !i * (dl + radix * dh + !rl + radix * !rh)
3050 + power radix !i * (!rl at Adjust + radix * !rh at Adjust)
3052 + power radix !i * !rl at Adjust
3053 + power radix (!i+1) * !rh at Adjust
3059 ensures { value x sx
3060 = (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3061 + !qh * power radix (sx - 2 - !i))
3062 * value y 2 * power radix !i
3064 + power radix !i * (!rl + radix * !rh) }
3065 ensures { !rl + radix * !rh < dl + radix * dh }
3067 value_sub_tail (pelts x) x.offset (x.offset + p2i sx - 1);
3068 value_sub_tail (pelts x) x.offset (x.offset + p2i sx - 2);
3072 invariant { 0 <= !i <= sx - 2 }
3073 invariant { !xp.offset = x.offset + !i }
3074 invariant { plength !xp = plength x }
3075 invariant { !xp.min = x.min }
3076 invariant { !xp.max = x.max }
3077 invariant { pelts !xp = pelts x }
3078 invariant { writable !xp }
3079 invariant { value x sx
3080 = (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3081 + !qh * power radix (sx - 2 - !i))
3082 * value y 2 * power radix !i
3084 + power radix !i * (!rl + radix * !rh) }
3085 invariant { !rl + radix * !rh < dl + radix * dh }
3087 let ghost k = p2i !i in
3088 xp.contents <- C.incr !xp (-1);
3091 let (qu, r0, r1) = div3by2_inv !rh !rl !lx dh dl dinv in
3096 assert { qu * (dl + radix * dh) + r0 + radix * r1
3097 = !lx + radix * (!rl at StartLoop)
3098 + radix * radix * (!rh at StartLoop)
3100 radix * ((!rl at StartLoop) + radix * (!rh at StartLoop))
3101 = radix * (!rl at StartLoop) + radix * radix * (!rh at StartLoop)
3103 qu * (dl + radix * dh) + r0 + radix * r1
3104 = !lx + radix * ((!rl at StartLoop) + radix * (!rh at StartLoop))
3105 = !lx + radix * (!rl at StartLoop)
3106 + radix * radix * (!rh at StartLoop)
3108 value_sub_head (pelts q) (q.offset + p2i !i) (q.offset + p2i sx - 2);
3109 value_sub_tail (pelts x) x.offset (x.offset + p2i !i);
3111 = (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3112 + !qh * power radix (sx - 2 - !i))
3113 * value y 2 * power radix !i
3115 + power radix !i * (!rl + radix * !rh)
3117 value x k = value x !i + power radix !i * !lx
3118 so value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3120 * value_sub (pelts q) (q.offset + k) (q.offset + sx - 2)
3121 so power radix (sx - 2 - !i) = radix * power radix (sx - 2 - k)
3123 (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3124 + !qh * power radix (sx - 2 - !i))
3126 * (value_sub (pelts q) (q.offset + k) (q.offset + sx - 2)
3127 + !qh * power radix (sx - 2 - k))
3128 so power radix !i * radix = power radix k
3129 so ((value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3130 + !qh * power radix (sx - 2 - !i))
3131 * value y 2 * power radix !i
3132 = power radix !i * qu * (dl + radix * dh)
3133 + (value_sub (pelts q) (q.offset + k)
3135 + !qh * power radix (sx - 2 - k))
3136 * value y 2 * power radix k
3138 (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3139 + !qh * power radix (sx - 2 - !i))
3140 * value y 2 * power radix !i
3142 * (value_sub (pelts q) (q.offset + k)
3144 + !qh * power radix (sx - 2 - k)))
3145 * value y 2 * power radix !i
3146 = power radix !i * qu * (dl + radix * dh)
3147 + radix * (value_sub (pelts q) (q.offset + k)
3149 + !qh * power radix (sx - 2 - k))
3150 * value y 2 * power radix !i
3151 = power radix !i * qu * (dl + radix * dh)
3152 + (value_sub (pelts q) (q.offset + k)
3154 + !qh * power radix (sx - 2 - k))
3155 * value y 2 * power radix k)
3156 so (value_sub (pelts q) (q.offset + !i) (q.offset + sx - 2)
3157 + !qh * power radix (sx - 2 - !i))
3158 * value y 2 * power radix !i
3160 + power radix !i * (!rl + radix * !rh)
3161 = power radix !i * qu * (dl + radix * dh)
3162 + (value_sub (pelts q) (q.offset + k)
3164 + !qh * power radix (sx - 2 - k))
3165 * value y 2 * power radix k
3167 + power radix !i * (!rl + radix * !rh)
3168 = (value_sub (pelts q) (q.offset + k)
3170 + !qh * power radix (sx - 2 - k))
3171 * value y 2 * power radix k
3173 + power radix !i * (qu * (dl + radix * dh)
3174 + !rl + radix * !rh)
3175 = (value_sub (pelts q) (q.offset + k)
3177 + !qh * power radix (sx - 2 - k))
3178 * value y 2 * power radix k
3181 * (!lx + radix * (!rl at StartLoop)
3182 + radix * radix * (!rh at StartLoop))
3183 = (value_sub (pelts q) (q.offset + k)
3185 + !qh * power radix (sx - 2 - k))
3186 * value y 2 * power radix k
3188 + power radix !i * !lx
3189 + power radix !i * (radix * (!rl at StartLoop
3190 + radix * !rh at StartLoop))
3191 = (value_sub (pelts q) (q.offset + k)
3193 + !qh * power radix (sx - 2 - k))
3194 * value y 2 * power radix k
3196 + power radix !i * (radix * (!rl at StartLoop
3197 + radix * !rh at StartLoop))
3198 = (value_sub (pelts q) (q.offset + k)
3200 + !qh * power radix (sx - 2 - k))
3201 * value y 2 * power radix k
3203 + power radix k * (!rl at StartLoop
3204 + radix * !rh at StartLoop)
3210 = (value_sub (pelts q) q.offset (q.offset + sx - 2)
3211 + !qh * power radix (sx - 2))
3214 by power radix !i = 1 };
3217 assert { value x 2 = !rl + radix * !rh
3218 by (pelts x)[x.offset] = !rl
3219 /\ (pelts x)[x.offset + 1] = !rh};
3222 (** `div_qr q r x y sx sy` divides `(x, sx)` by `(y, sy)`, writes the quotient
3223 in `(q, (sx-sy))` and the remainder in `(r, sy)`. Corresponds to
3225 let div_qr (q r x y nx ny:t) (sx sy:int32) : unit
3226 requires { 1 <= sy <= sx <= (Int32.max_int32 - 1) }
3227 requires { valid x sx }
3228 requires { valid y sy }
3229 requires { valid q (sx - sy + 1) }
3230 requires { valid r sy }
3231 requires { valid nx (sx + 1) }
3232 requires { valid ny sy }
3233 requires { writable nx /\ writable ny }
3234 requires { (pelts y)[y.offset + sy - 1] > 0 }
3235 requires { writable q /\ writable r }
3236 ensures { value x sx
3237 = value q (sx - sy + 1) * value y sy
3239 ensures { value r sy < value y sy }
3242 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
3243 value_sub_lower_bound (pelts y) y.offset (y.offset + p2i sy - 1);
3244 assert { value y sy >= power radix (sy - 1) };
3247 let lr = wmpn_divrem_1 q x sx (C.get y) in
3252 let clz = clz_ext (C.get_ofs y (sy - 1)) in
3253 let ghost p = power 2 (p2i clz) in
3257 value_sub_shift_no_change (pelts x) x.offset (p2i sx) (p2i sx) 0;
3259 value_sub_frame_shift (pelts x) (pelts nx) x.offset nx.offset (p2i sx);
3261 let ghost _qh = wmpn_divrem_2 q nx y (sx + 1) in
3264 = value q (sx - sy + 1) * value y sy
3266 by value r sy = value nx sy
3267 so value (nx at Div2_ns) (sx + 1) < power radix sx
3268 so value (nx at Div2_ns) (sx + 1)
3269 = value (nx at Div2_ns) sx
3273 > value (nx at Div2_ns) (sx + 1)
3274 = (value q (sx - 1) + power radix (sx - 1) * _qh)
3278 so value y 2 >= radix
3279 so value q (sx - 1) >= 0
3281 so (value q (sx - 1)
3282 + power radix (sx - 1) * _qh) >= 0
3283 so (value q (sx - 1) + power radix (sx - 1) * _qh)
3286 >= (value q (sx - 1)
3287 + power radix (sx - 1) * _qh)
3289 >= (value q (sx - 1)
3290 + power radix (sx - 1) * _qh)
3292 >= power radix (sx - 1) * _qh * radix
3293 = power radix sx * _qh
3294 so power radix sx > power radix sx * _qh
3296 so value x sx = value (nx at Div2_ns) sx
3301 let ghost _c = wmpn_lshift ny y sy (Limb.of_int32 clz) in
3303 ensures { normalized ny sy }
3304 ensures { value ny sy = power 2 clz * value y sy }
3305 let ghost dh = (pelts y)[y.offset + p2i sy - 1] in
3307 = value y (sy - 1) + power radix (sy - 1) * dh };
3308 value_sub_upper_bound (pelts y) y.offset (y.offset + p2i sy - 1);
3309 value_sub_tail (pelts ny) ny.offset (ny.offset + p2i sy - 1);
3310 value_sub_upper_bound (pelts ny) ny.offset (ny.offset + p2i sy - 1);
3311 let ghost ndh = (pelts ny)[ny.offset + p2i sy - 1] in
3312 assert { normalized ny sy
3313 /\ value ny sy = power 2 clz * value y sy
3315 value y sy < (dh + 1) * power radix (sy - 1)
3316 so value ny sy + (power radix sy) * _c
3317 = power 2 clz * value y sy
3320 + dh * power radix (sy - 1))
3321 so power 2 clz * dh <= radix - power 2 clz
3322 so value ny sy + (power radix sy) * _c
3323 = power 2 clz * value y (sy - 1)
3324 + power 2 clz * dh * power radix (sy - 1)
3325 < power 2 clz * power radix (sy - 1)
3326 + power 2 clz * dh * power radix (sy - 1)
3327 <= power 2 clz * power radix (sy - 1)
3328 + (radix - power 2 clz) * power radix (sy - 1)
3329 = radix * power radix (sy - 1)
3333 = power 2 clz * value y sy
3334 so value y sy >= dh * power radix (sy - 1)
3336 >= power 2 clz * dh * power radix (sy - 1)
3338 value ny (sy - 1) + power radix (sy - 1) * ndh
3339 < power radix (sy - 1) + power radix (sy - 1) * ndh
3340 = power radix (sy - 1) * (ndh + 1)
3341 so power radix (sy - 1) * (ndh + 1)
3342 > power radix (sy - 1) * (power 2 clz * dh)
3343 so ndh + 1 > power 2 clz * dh
3344 so ndh >= power 2 clz * dh
3345 so 2 * power 2 clz * dh >= radix
3347 so ndh >= div radix 2
3350 let h = wmpn_lshift nx x sx (Limb.of_int32 clz) in
3353 ensures { value nx (sx + 1)
3355 value_sub_tail (pelts nx) nx.offset (nx.offset + p2i sx);
3356 assert { value nx (sx + 1)
3359 value nx sx + power radix sx * h
3361 so value nx (sx + 1)
3362 = value nx sx + power radix sx * h
3366 (* TODO don't add 1 when not needed, cf "adjust" in GMP algo *)
3367 let ghost _qh = wmpn_divrem_2 q nx ny (sx + 1) in
3368 let ghost _l = wmpn_rshift r nx sy (Limb.of_int32 clz) in
3369 begin ensures { value nx 2 = p * value r 2 }
3372 (mod (value nx sy) p = 0
3374 value (nx at Div2_s) (sx + 1)
3375 = (value q (sx - 1) + power radix (sx - 1) * _qh)
3378 so value (nx at Div2_s) (sx + 1)
3380 so value ny sy = p * value y sy
3382 = value (nx at Div2_s) (sx + 1)
3384 + power radix (sx - 1) * _qh)
3387 - p * (value q (sx - 1)
3388 + power radix (sx - 1) * _qh)
3392 + power radix (sx - 1) * _qh)
3394 so let n = (value x sx
3396 + power radix (sx - 1) * _qh)
3403 so mod (value nx sy) p
3409 so _l + radix * value r sy
3410 = power 2 (Limb.length - clz) * (value nx sy)
3411 so let a = div (value nx sy) p in
3413 so power 2 (Limb.length - clz) * p = radix
3414 so power 2 (Limb.length - clz) * (value nx sy)
3415 = power 2 (Limb.length - clz) * (p * a)
3416 = (power 2 (Limb.length - clz) * p) * a
3418 so mod (radix * value r sy + _l) radix
3420 so mod (radix * value r sy + _l) radix
3421 = mod (radix * a) radix = 0
3425 assert { value nx 2 = p * value r 2
3428 = power 2 (Limb.length - clz) * value nx 2
3429 so p * power 2 (Limb.length - clz)
3431 so p * radix * value r 2
3432 = p * power 2 (Limb.length - clz) * value nx 2
3433 = radix * value nx 2
3434 so p * value r 2 = value nx 2
3438 = value q (sx - sy + 1) * value y sy
3441 value (nx at Div2_s) (sx + 1)
3442 = (value q (sx - 1) + power radix (sx - 1) * _qh)
3445 so value (nx at Div2_s) (sx + 1)
3447 so value ny 2 = p * value y 2
3450 value x sx < power radix sx
3451 so value y 2 >= radix
3452 so value ny 2 >= p * radix
3453 so value q (sx - 1) >= 0
3455 so (value q (sx - 1) + power radix (sx - 1) * _qh)
3457 so (value q (sx - 1) + power radix (sx - 1) * _qh)
3460 >= (value q (sx - 1)
3461 + power radix (sx - 1) * _qh)
3463 >= (value q (sx - 1)
3464 + power radix (sx - 1) * _qh)
3466 >= power radix (sx - 1) * _qh * p * radix
3467 = power radix sx * p * _qh
3468 so power radix sx * p
3469 > value (nx at Div2_s) (sx + 1)
3470 >= power radix sx * p * _qh
3472 so value nx 2 = p * value r 2
3474 = value q (sx - 1) * p * value y 2
3476 = p * (value q (sx - 1) * value y 2
3482 (* let qn = ref (Int32.(-) (Int32.(+) sx 1) sy) in
3483 if (Int32.(>=) (Int32.(+) !qn !qn) sx)
3486 if (get_ofs x (sx - 1)) >= (get_ofs y (sy - 1))
3490 let clz = clz_ext (C.get_ofs y (sy - 1)) in
3491 let ghost p = power 2 (p2i clz) in
3495 value_sub_shift_no_change (pelts x) x.offset
3496 (p2i sx) (p2i sx) 0;
3498 value_sub_frame_shift (pelts x) (pelts nx) x.offset nx.offset (p2i sx);
3499 assert { value y sy * (power radix (sx - sy + adjust))
3500 > value nx (sx + adjust)
3502 let dh = (pelts y)[y.offset + sy - 1] in
3503 value y sy >= dh * power radix (sy - 1)
3504 so value nx (sx + adjust) = value nx sx = value x sx
3507 so value x sx < power radix sx
3508 so value y sy * power radix (sx - sy + adjust)
3509 >= dh * power radix (sy - 1)
3510 * power radix (sx - sy + adjust)
3511 = dh * power radix ((sy - 1) + (sx - sy + adjust))
3512 = dh * power radix sx
3513 so dh >= div radix 2 > 1
3514 so dh * power radix sx > power radix sx )
3517 so let ah = (pelts x)[x.offset + sx - 1] in
3518 value x sx < (ah + 1) * power radix (sx - 1)
3520 so value x sx < dh * power radix (sx - 1)
3521 so value y sy * power radix (sx - sy + adjust)
3522 = value y sy * power radix (sx - sy)
3523 >= dh * power radix (sy - 1)
3524 * power radix (sx - sy)
3525 = dh * power radix (sy - 1 + sx - sy)
3526 = dh * power radix (sx - 1))) };
3528 let ghost _qh = div_sb_qr q nx (sx + adjust) y sy in
3531 = value q (sx - sy + adjust) * value y sy
3533 by value r sy = value nx sy
3534 so value (nx at Div_ns) (sx + adjust) = value x sx < power radix sx
3535 so value (nx at Div_ns) (sx + adjust)
3536 = value (nx at Div_ns) sx
3539 value (nx at Div_ns) (sx + adjust)
3540 = (value q (sx - sy + adjust)
3541 + power radix (sx - sy + adjust) * _qh)
3545 so value q (sx - sy + adjust) >= 0
3547 so (value q (sx - sy + adjust)
3548 + power radix (sx - sy + adjust) * _qh) >= 0
3549 so (value q (sx - sy + adjust)
3550 + power radix (sx - sy + adjust) * _qh)
3553 >= (value q (sx - sy + adjust)
3554 + power radix (sx - sy + adjust) * _qh)
3556 >= power radix (sx - sy + adjust) * _qh * value y sy
3558 so value x sx = value (nx at Div_ns) sx
3562 ensures { value q (sx - sy + 1)
3563 = value (q at Ret_ns) (sx - sy + adjust) }
3566 value_sub_shift_no_change (pelts x) x.offset
3567 (p2i sx) (p2i sx) 0;
3568 set_ofs q (sx - sy) 0;
3569 value_sub_tail (pelts q) q.offset (q.offset + p2i sx - p2i sy);
3575 let ghost _c = wmpn_lshift ny y sy (Limb.of_int32 clz) in
3577 ensures { normalized ny sy }
3578 ensures { value ny sy
3579 = power 2 clz * value y sy }
3580 let ghost dh = (pelts y)[y.offset + p2i sy - 1] in
3582 = value y (sy - 1) + power radix (sy - 1) * dh };
3583 value_sub_upper_bound (pelts y) y.offset (y.offset + p2i sy - 1);
3584 value_sub_tail (pelts ny) ny.offset (ny.offset + p2i sy - 1);
3585 value_sub_upper_bound (pelts ny) ny.offset (ny.offset + p2i sy - 1);
3586 let ghost ndh = (pelts ny)[ny.offset + p2i sy - 1] in
3587 assert { normalized ny sy
3589 = power 2 clz * value y sy
3591 value y sy < (dh + 1) * power radix (sy - 1)
3592 so value ny sy + (power radix sy) * _c
3593 = power 2 clz * value y sy
3596 + dh * power radix (sy - 1))
3597 so power 2 clz * dh <= radix - power 2 clz
3600 value ny sy + (power radix sy) * _c
3601 = power 2 clz * value y (sy - 1)
3602 + power 2 clz * dh * power radix (sy - 1)
3603 < power 2 clz * power radix (sy - 1)
3604 + power 2 clz * dh * power radix (sy - 1)
3605 <= power 2 clz * power radix (sy - 1)
3606 + (radix - power 2 clz) * power radix (sy - 1)
3607 = radix * power radix (sy - 1)
3610 so power radix sy * _c < power radix sy
3611 so power radix sy > 0
3615 = power 2 clz * value y sy
3616 so value y sy >= dh * power radix (sy - 1)
3618 >= power 2 clz * dh * power radix (sy - 1)
3620 value ny (sy - 1) + power radix (sy - 1) * ndh
3621 < power radix (sy - 1) + power radix (sy - 1) * ndh
3622 = power radix (sy - 1) * (ndh + 1)
3623 so power radix (sy - 1) * (ndh + 1)
3624 > power radix (sy - 1) * (power 2 clz * dh)
3625 so ndh + 1 > power 2 clz * dh
3626 so ndh >= power 2 clz * dh
3627 so 2 * power 2 clz * dh >= radix
3629 so ndh >= div radix 2
3632 let h = wmpn_lshift nx x sx (Limb.of_int32 clz) in
3636 ensures { value nx (sx + adjust)
3640 value_sub_tail (pelts nx) nx.offset (nx.offset + p2i sx);
3641 assert { value nx (sx + 1)
3644 value nx sx + power radix sx * h
3646 so value nx (sx + 1)
3647 = value nx sx + power radix sx * h
3650 assert { adjust = 0 };
3653 let dh = (pelts y)[y.offset + sy - 1] in
3654 let ah = (pelts x)[x.offset + sx - 1] in
3658 so (p * ah <= radix - p
3660 let q = power 2 (Limb.length - clz) in
3665 so p * ah <= p * (q - 1) = radix - p
3667 so p * (ah + 1) <= radix
3668 so let s = power radix (sx - 1) in
3669 value x sx < (ah + 1) * s
3670 so p * value x sx < p * (ah + 1) * s
3671 so (p * (ah + 1) * s
3675 (p * (ah + 1) = radix
3676 \/ (p * (ah + 1) < radix
3680 so radix * power radix (sx - 1) = power radix sx
3681 so value (nx at Shifted) sx + power radix sx * h
3683 so power radix sx * h < power radix sx * 1
3684 so (h < 1 by power radix sx > 0)
3689 assert { value ny sy * (power radix (sx - sy + adjust))
3690 > value nx (sx + adjust)
3692 let dh = (pelts y)[y.offset + sy - 1] in
3693 value ny sy >= p * dh * power radix (sy - 1)
3694 so value nx (sx + adjust) = p * value x sx
3698 so value x sx < power radix sx
3699 so p * value x sx < p * power radix sx
3700 so value ny sy * power radix (sx - sy + adjust)
3701 >= p * dh * power radix (sy - 1)
3702 * power radix (sx - sy + adjust)
3703 = p * dh * power radix ((sy - 1) + (sx - sy + adjust))
3704 = p * dh * power radix sx
3706 so p * dh * power radix sx >= p * power radix sx )
3709 so let ah = (pelts x)[x.offset + sx - 1] in
3710 value x sx < (ah + 1) * power radix (sx - 1)
3712 so value x sx < dh * power radix (sx - 1)
3713 so p * value x sx < p * dh * power radix (sx - 1)
3714 so value ny sy * power radix (sx - sy + adjust)
3715 = value ny sy * power radix (sx - sy)
3716 >= p * dh * power radix (sy - 1)
3717 * power radix (sx - sy)
3718 = p * dh * power radix (sy - 1 + sx - sy)
3719 = p * dh * power radix (sx - 1))) };
3720 let ghost _qh = div_sb_qr q nx (sx + adjust) ny sy in
3721 let ghost _l = wmpn_rshift r nx sy (Limb.of_int32 clz) in
3722 begin ensures { value nx sy = p * value r sy }
3725 (mod (value nx sy) p = 0
3727 value (nx at Div_s) (sx + adjust)
3728 = (value q (sx - sy + adjust)
3729 + power radix (sx - sy + adjust) * _qh)
3732 so value (nx at Div_s) (sx + adjust)
3734 so value ny sy = p * value y sy
3736 = value (nx at Div_s) (sx + adjust)
3737 - (value q (sx - sy + adjust)
3738 + power radix (sx - sy + adjust) * _qh)
3741 - p * (value q (sx - sy + adjust)
3742 + power radix (sx - sy + adjust) * _qh)
3745 - (value q (sx - sy + adjust)
3746 + power radix (sx - sy + adjust) * _qh)
3748 so let n = (value x sx
3749 - (value q (sx - sy + adjust)
3750 + power radix (sx - sy + adjust) * _qh)
3757 so mod (value nx sy) p
3763 so _l + radix * value r sy
3764 = power 2 (Limb.length - clz) * (value nx sy)
3765 so let a = div (value nx sy) p in
3767 so power 2 (Limb.length - clz) * p = radix
3768 so power 2 (Limb.length - clz) * (value nx sy)
3769 = power 2 (Limb.length - clz) * (p * a)
3770 = (power 2 (Limb.length - clz) * p) * a
3772 so mod (radix * value r sy + _l) radix
3774 so mod (radix * value r sy + _l) radix
3775 = mod (radix * a) radix = 0
3779 assert { value nx sy = p * value r sy
3782 = power 2 (Limb.length - clz) * value nx sy
3783 so p * power 2 (Limb.length - clz)
3785 so p * radix * value r sy
3786 = p * power 2 (Limb.length - clz) * value nx sy
3787 = radix * value nx sy
3788 so p * value r sy = value nx sy
3792 = value q (sx - sy + adjust) * value y sy
3795 value (nx at Div_s) (sx + adjust)
3796 = (value q (sx - sy + adjust)
3797 + power radix (sx - sy + adjust) * _qh)
3800 so value (nx at Div_s) (sx + adjust)
3802 so power radix (sx - sy + 1) * power radix (sy - 1)
3804 so value ny sy = p * value y sy
3807 value (nx at Div_s) (sx + adjust)
3808 = (value q (sx - sy + adjust)
3809 + power radix (sx - sy + adjust) * _qh)
3813 so value q (sx - sy + adjust) >= 0
3815 so (value q (sx - sy + adjust)
3816 + power radix (sx - sy + adjust) * _qh) >= 0
3817 so (value q (sx - sy + adjust)
3818 + power radix (sx - sy + adjust) * _qh)
3821 >= (value q (sx - sy + adjust)
3822 + power radix (sx - sy + adjust) * _qh)
3824 >= power radix (sx - sy + adjust) * _qh * value ny sy
3826 so value nx sy = p * value r sy
3828 = value q (sx - sy + adjust) * p * value y sy
3830 = p * (value q (sx - sy + adjust)
3836 ensures { value q (sx - sy + 1)
3837 = value (q at Ret_s) (sx - sy + adjust) }
3840 value_sub_shift_no_change (pelts x) x.offset
3841 (p2i sx) (p2i sx) 0;
3842 set_ofs q (sx - sy) 0;
3843 value_sub_tail (pelts q) q.offset (q.offset + p2i sx - p2i sy);
3844 assert { value q (sx - sy + 1) = value (q at Ret_s) (sx - sy)
3845 by value q (sx - sy + 1)
3846 = value (q at Ret_s) (sx - sy) + power radix (sx - sy) * 0
3847 = value (q at Ret_s) (sx - sy) }
3854 let wmpn_tdiv_qr (q r:t) (qxn:int32) (x:t) (sx:int32) (y:t) (sy:int32) : unit
3855 requires { 1 <= sy <= sx <= (Int32.max_int32 - 1) }
3856 requires { valid x sx }
3857 requires { valid y sy }
3858 requires { valid q (sx - sy + 1) }
3859 requires { valid r sy }
3860 requires { writable q /\ writable r }
3861 requires { qxn = 0 }
3862 requires { (pelts y)[y.offset + sy - 1] > 0 }
3863 ensures { value x sx
3864 = value q (sx - sy + 1) * value y sy
3866 ensures { value r sy < value y sy }
3868 let nx = malloc (UInt32.(+) (UInt32.of_int32 sx) 1) in
3869 c_assert (is_not_null nx);
3870 let ny = malloc (UInt32.of_int32 sy) in
3871 c_assert (is_not_null ny);
3872 div_qr q r x y nx ny sx sy;
3876 let div_qr_in_place (q x y nx ny:t) (sx sy:int32) : unit
3877 requires { 1 <= sy <= sx <= (Int32.max_int32 - 1) }
3878 requires { valid x sx }
3879 requires { valid y sy }
3880 requires { valid q (sx - sy + 1) }
3881 requires { valid nx (sx + 1) }
3882 requires { valid ny sy }
3883 requires { writable q /\ writable x }
3884 requires { writable nx /\ writable ny }
3885 requires { (pelts y)[y.offset + sy - 1] > 0 }
3886 ensures { value (old x) sx
3887 = value q (sx - sy + 1) * value y sy
3889 ensures { value x sy < value y sy }
3892 value_sub_tail (pelts y) y.offset (y.offset + p2i sy - 1);
3893 value_sub_lower_bound (pelts y) y.offset (y.offset + p2i sy - 1);
3894 assert { value y sy >= power radix (sy - 1) };
3895 let ghost ox = pure { x } in
3898 let lr = wmpn_divrem_1 q x sx (C.get y) in
3903 let clz = clz_ext (C.get_ofs y (sy - 1)) in
3904 let ghost p = power 2 (p2i clz) in
3908 value_sub_shift_no_change (pelts x) x.offset (p2i sx) (p2i sx) 0;
3910 value_sub_frame_shift (pelts x) (pelts nx) x.offset nx.offset (p2i sx);
3912 let ghost _qh = wmpn_divrem_2 q nx y (sx + 1) in
3914 assert { value ox sx
3915 = value q (sx - sy + 1) * value y sy
3917 by value x sy = value nx sy
3918 so value (nx at Div2_ns) (sx + 1) < power radix sx
3919 so value (nx at Div2_ns) (sx + 1)
3920 = value (nx at Div2_ns) sx
3924 > value (nx at Div2_ns) (sx + 1)
3925 = (value q (sx - 1) + power radix (sx - 1) * _qh)
3929 so value y 2 >= radix
3930 so value q (sx - 1) >= 0
3932 so (value q (sx - 1)
3933 + power radix (sx - 1) * _qh) >= 0
3934 so (value q (sx - 1) + power radix (sx - 1) * _qh)
3937 >= (value q (sx - 1)
3938 + power radix (sx - 1) * _qh)
3940 >= (value q (sx - 1)
3941 + power radix (sx - 1) * _qh)
3943 >= power radix (sx - 1) * _qh * radix
3944 = power radix sx * _qh
3945 so power radix sx > power radix sx * _qh
3947 so value ox sx = value (nx at Div2_ns) sx
3952 let ghost _c = wmpn_lshift ny y sy (Limb.of_int32 clz) in
3954 ensures { normalized ny sy }
3955 ensures { value ny sy = power 2 clz * value y sy }
3956 let ghost dh = (pelts y)[y.offset + p2i sy - 1] in
3958 = value y (sy - 1) + power radix (sy - 1) * dh };
3959 value_sub_upper_bound (pelts y) y.offset (y.offset + p2i sy - 1);
3960 value_sub_tail (pelts ny) ny.offset (ny.offset + p2i sy - 1);
3961 value_sub_upper_bound (pelts ny) ny.offset (ny.offset + p2i sy - 1);
3962 let ghost ndh = (pelts ny)[ny.offset + p2i sy - 1] in
3963 assert { normalized ny sy
3964 /\ value ny sy = power 2 clz * value y sy
3966 value y sy < (dh + 1) * power radix (sy - 1)
3967 so value ny sy + (power radix sy) * _c
3968 = power 2 clz * value y sy
3971 + dh * power radix (sy - 1))
3972 so power 2 clz * dh <= radix - power 2 clz
3973 so value ny sy + (power radix sy) * _c
3974 = power 2 clz * value y (sy - 1)
3975 + power 2 clz * dh * power radix (sy - 1)
3976 < power 2 clz * power radix (sy - 1)
3977 + power 2 clz * dh * power radix (sy - 1)
3978 <= power 2 clz * power radix (sy - 1)
3979 + (radix - power 2 clz) * power radix (sy - 1)
3980 = radix * power radix (sy - 1)
3984 = power 2 clz * value y sy
3985 so value y sy >= dh * power radix (sy - 1)
3987 >= power 2 clz * dh * power radix (sy - 1)
3989 value ny (sy - 1) + power radix (sy - 1) * ndh
3990 < power radix (sy - 1) + power radix (sy - 1) * ndh
3991 = power radix (sy - 1) * (ndh + 1)
3992 so power radix (sy - 1) * (ndh + 1)
3993 > power radix (sy - 1) * (power 2 clz * dh)
3994 so ndh + 1 > power 2 clz * dh
3995 so ndh >= power 2 clz * dh
3996 so 2 * power 2 clz * dh >= radix
3998 so ndh >= div radix 2
4001 let h = wmpn_lshift nx x sx (Limb.of_int32 clz) in
4004 ensures { value nx (sx + 1)
4006 value_sub_tail (pelts nx) nx.offset (nx.offset + p2i sx);
4007 assert { value nx (sx + 1)
4010 value nx sx + power radix sx * h
4012 so value nx (sx + 1)
4013 = value nx sx + power radix sx * h
4017 (* TODO don't add 1 when not needed, cf "adjust" in GMP algo *)
4018 let ghost _qh = wmpn_divrem_2 q nx ny (sx + 1) in
4019 let ghost _l = wmpn_rshift x nx sy (Limb.of_int32 clz) in
4020 begin ensures { value nx 2 = p * value x 2 }
4023 (mod (value nx sy) p = 0
4025 value (nx at Div2_s) (sx + 1)
4026 = (value q (sx - 1) + power radix (sx - 1) * _qh)
4029 so value (nx at Div2_s) (sx + 1)
4031 so value ny sy = p * value y sy
4033 = value (nx at Div2_s) (sx + 1)
4035 + power radix (sx - 1) * _qh)
4038 - p * (value q (sx - 1)
4039 + power radix (sx - 1) * _qh)
4043 + power radix (sx - 1) * _qh)
4045 so let n = (value ox sx
4047 + power radix (sx - 1) * _qh)
4054 so mod (value nx sy) p
4060 so _l + radix * value x sy
4061 = power 2 (Limb.length - clz) * (value nx sy)
4062 so let a = div (value nx sy) p in
4064 so power 2 (Limb.length - clz) * p = radix
4065 so power 2 (Limb.length - clz) * (value nx sy)
4066 = power 2 (Limb.length - clz) * (p * a)
4067 = (power 2 (Limb.length - clz) * p) * a
4069 so mod (radix * value x sy + _l) radix
4071 so mod (radix * value x sy + _l) radix
4072 = mod (radix * a) radix = 0
4076 assert { value nx 2 = p * value x 2
4079 = power 2 (Limb.length - clz) * value nx 2
4080 so p * power 2 (Limb.length - clz)
4082 so p * radix * value x 2
4083 = p * power 2 (Limb.length - clz) * value nx 2
4084 = radix * value nx 2
4085 so p * value x 2 = value nx 2
4088 assert { value ox sx
4089 = value q (sx - sy + 1) * value y sy
4092 value (nx at Div2_s) (sx + 1)
4093 = (value q (sx - 1) + power radix (sx - 1) * _qh)
4096 so value (nx at Div2_s) (sx + 1)
4098 so value ny 2 = p * value y 2
4101 value ox sx < power radix sx
4102 so value y 2 >= radix
4103 so value ny 2 >= p * radix
4104 so value q (sx - 1) >= 0
4106 so (value q (sx - 1) + power radix (sx - 1) * _qh)
4108 so (value q (sx - 1) + power radix (sx - 1) * _qh)
4111 >= (value q (sx - 1)
4112 + power radix (sx - 1) * _qh)
4114 >= (value q (sx - 1)
4115 + power radix (sx - 1) * _qh)
4117 >= power radix (sx - 1) * _qh * p * radix
4118 = power radix sx * p * _qh
4119 so power radix sx * p
4120 > value (nx at Div2_s) (sx + 1)
4121 >= power radix sx * p * _qh
4123 so value nx 2 = p * value x 2
4125 = value q (sx - 1) * p * value y 2
4127 = p * (value q (sx - 1) * value y 2
4133 (* let qn = ref (Int32.(-) (Int32.(+) sx 1) sy) in
4134 if (Int32.(>=) (Int32.(+) !qn !qn) sx)
4137 if (get_ofs x (sx - 1)) >= (get_ofs y (sy - 1))
4141 let clz = clz_ext (C.get_ofs y (sy - 1)) in
4142 let ghost p = power 2 (p2i clz) in
4146 value_sub_shift_no_change (pelts x) x.offset
4147 (p2i sx) (p2i sx) 0;
4149 value_sub_frame_shift (pelts x) (pelts nx) x.offset nx.offset (p2i sx);
4150 assert { value y sy * (power radix (sx - sy + adjust))
4151 > value nx (sx + adjust)
4153 let dh = (pelts y)[y.offset + sy - 1] in
4154 value y sy >= dh * power radix (sy - 1)
4155 so value nx (sx + adjust) = value nx sx = value ox sx
4158 so value ox sx < power radix sx
4159 so value y sy * power radix (sx - sy + adjust)
4160 >= dh * power radix (sy - 1)
4161 * power radix (sx - sy + adjust)
4162 = dh * power radix ((sy - 1) + (sx - sy + adjust))
4163 = dh * power radix sx
4164 so dh >= div radix 2 > 1
4165 so dh * power radix sx > power radix sx )
4168 so let ah = (pelts x)[x.offset + sx - 1] in
4169 value ox sx < (ah + 1) * power radix (sx - 1)
4171 so value ox sx < dh * power radix (sx - 1)
4172 so value y sy * power radix (sx - sy + adjust)
4173 = value y sy * power radix (sx - sy)
4174 >= dh * power radix (sy - 1)
4175 * power radix (sx - sy)
4176 = dh * power radix (sy - 1 + sx - sy)
4177 = dh * power radix (sx - 1))) };
4179 let ghost _qh = div_sb_qr q nx (sx + adjust) y sy in
4181 assert { value ox sx
4182 = value q (sx - sy + adjust) * value y sy
4184 by value x sy = value nx sy
4185 so value (nx at Div_ns) (sx + adjust) = value ox sx < power radix sx
4186 so value (nx at Div_ns) (sx + adjust)
4187 = value (nx at Div_ns) sx
4190 value (nx at Div_ns) (sx + adjust)
4191 = (value q (sx - sy + adjust)
4192 + power radix (sx - sy + adjust) * _qh)
4196 so value q (sx - sy + adjust) >= 0
4198 so (value q (sx - sy + adjust)
4199 + power radix (sx - sy + adjust) * _qh) >= 0
4200 so (value q (sx - sy + adjust)
4201 + power radix (sx - sy + adjust) * _qh)
4204 >= (value q (sx - sy + adjust)
4205 + power radix (sx - sy + adjust) * _qh)
4207 >= power radix (sx - sy + adjust) * _qh * value y sy
4209 so value ox sx = value (nx at Div_ns) sx
4213 ensures { value q (sx - sy + 1)
4214 = value (q at Ret_ns) (sx - sy + adjust) }
4217 value_sub_shift_no_change (pelts x) x.offset
4218 (p2i sx) (p2i sx) 0;
4219 set_ofs q (sx - sy) 0;
4220 value_sub_tail (pelts q) q.offset (q.offset + p2i sx - p2i sy);
4226 let ghost _c = wmpn_lshift ny y sy (Limb.of_int32 clz) in
4228 ensures { normalized ny sy }
4229 ensures { value ny sy
4230 = power 2 clz * value y sy }
4231 let ghost dh = (pelts y)[y.offset + p2i sy - 1] in
4233 = value y (sy - 1) + power radix (sy - 1) * dh };
4234 value_sub_upper_bound (pelts y) y.offset (y.offset + p2i sy - 1);
4235 value_sub_tail (pelts ny) ny.offset (ny.offset + p2i sy - 1);
4236 value_sub_upper_bound (pelts ny) ny.offset (ny.offset + p2i sy - 1);
4237 let ghost ndh = (pelts ny)[ny.offset + p2i sy - 1] in
4238 assert { normalized ny sy
4240 = power 2 clz * value y sy
4242 value y sy < (dh + 1) * power radix (sy - 1)
4243 so value ny sy + (power radix sy) * _c
4244 = power 2 clz * value y sy
4247 + dh * power radix (sy - 1))
4248 so power 2 clz * dh <= radix - power 2 clz
4251 value ny sy + (power radix sy) * _c
4252 = power 2 clz * value y (sy - 1)
4253 + power 2 clz * dh * power radix (sy - 1)
4254 < power 2 clz * power radix (sy - 1)
4255 + power 2 clz * dh * power radix (sy - 1)
4256 <= power 2 clz * power radix (sy - 1)
4257 + (radix - power 2 clz) * power radix (sy - 1)
4258 = radix * power radix (sy - 1)
4261 so power radix sy * _c < power radix sy
4262 so power radix sy > 0
4266 = power 2 clz * value y sy
4267 so value y sy >= dh * power radix (sy - 1)
4269 >= power 2 clz * dh * power radix (sy - 1)
4271 value ny (sy - 1) + power radix (sy - 1) * ndh
4272 < power radix (sy - 1) + power radix (sy - 1) * ndh
4273 = power radix (sy - 1) * (ndh + 1)
4274 so power radix (sy - 1) * (ndh + 1)
4275 > power radix (sy - 1) * (power 2 clz * dh)
4276 so ndh + 1 > power 2 clz * dh
4277 so ndh >= power 2 clz * dh
4278 so 2 * power 2 clz * dh >= radix
4280 so ndh >= div radix 2
4283 let h = wmpn_lshift nx x sx (Limb.of_int32 clz) in
4287 ensures { value nx (sx + adjust)
4291 value_sub_tail (pelts nx) nx.offset (nx.offset + p2i sx);
4292 assert { value nx (sx + 1)
4295 value nx sx + power radix sx * h
4297 so value nx (sx + 1)
4298 = value nx sx + power radix sx * h
4301 assert { adjust = 0 };
4304 let dh = (pelts y)[y.offset + sy - 1] in
4305 let ah = (pelts x)[x.offset + sx - 1] in
4309 so (p * ah <= radix - p
4311 let q = power 2 (Limb.length - clz) in
4316 so p * ah <= p * (q - 1) = radix - p
4318 so p * (ah + 1) <= radix
4319 so let s = power radix (sx - 1) in
4320 value ox sx < (ah + 1) * s
4321 so p * value ox sx < p * (ah + 1) * s
4322 so (p * (ah + 1) * s
4326 (p * (ah + 1) = radix
4327 \/ (p * (ah + 1) < radix
4331 so radix * power radix (sx - 1) = power radix sx
4332 so value (nx at Shifted) sx + power radix sx * h
4334 so power radix sx * h < power radix sx * 1
4335 so (h < 1 by power radix sx > 0)
4340 assert { value ny sy * (power radix (sx - sy + adjust))
4341 > value nx (sx + adjust)
4343 let dh = (pelts y)[y.offset + sy - 1] in
4344 value ny sy >= p * dh * power radix (sy - 1)
4345 so value nx (sx + adjust) = p * value ox sx
4349 so value ox sx < power radix sx
4350 so p * value ox sx < p * power radix sx
4351 so value ny sy * power radix (sx - sy + adjust)
4352 >= p * dh * power radix (sy - 1)
4353 * power radix (sx - sy + adjust)
4354 = p * dh * power radix ((sy - 1) + (sx - sy + adjust))
4355 = p * dh * power radix sx
4357 so p * dh * power radix sx >= p * power radix sx )
4360 so let ah = (pelts x)[x.offset + sx - 1] in
4361 value ox sx < (ah + 1) * power radix (sx - 1)
4363 so value ox sx < dh * power radix (sx - 1)
4364 so p * value ox sx < p * dh * power radix (sx - 1)
4365 so value ny sy * power radix (sx - sy + adjust)
4366 = value ny sy * power radix (sx - sy)
4367 >= p * dh * power radix (sy - 1)
4368 * power radix (sx - sy)
4369 = p * dh * power radix (sy - 1 + sx - sy)
4370 = p * dh * power radix (sx - 1))) };
4371 let ghost _qh = div_sb_qr q nx (sx + adjust) ny sy in
4372 let ghost _l = wmpn_rshift x nx sy (Limb.of_int32 clz) in
4373 begin ensures { value nx sy = p * value x sy }
4376 (mod (value nx sy) p = 0
4378 value (nx at Div_s) (sx + adjust)
4379 = (value q (sx - sy + adjust)
4380 + power radix (sx - sy + adjust) * _qh)
4383 so value (nx at Div_s) (sx + adjust)
4385 so value ny sy = p * value y sy
4387 = value (nx at Div_s) (sx + adjust)
4388 - (value q (sx - sy + adjust)
4389 + power radix (sx - sy + adjust) * _qh)
4392 - p * (value q (sx - sy + adjust)
4393 + power radix (sx - sy + adjust) * _qh)
4396 - (value q (sx - sy + adjust)
4397 + power radix (sx - sy + adjust) * _qh)
4399 so let n = (value ox sx
4400 - (value q (sx - sy + adjust)
4401 + power radix (sx - sy + adjust) * _qh)
4408 so mod (value nx sy) p
4414 so _l + radix * value x sy
4415 = power 2 (Limb.length - clz) * (value nx sy)
4416 so let a = div (value nx sy) p in
4418 so power 2 (Limb.length - clz) * p = radix
4419 so power 2 (Limb.length - clz) * (value nx sy)
4420 = power 2 (Limb.length - clz) * (p * a)
4421 = (power 2 (Limb.length - clz) * p) * a
4423 so mod (radix * value x sy + _l) radix
4425 so mod (radix * value x sy + _l) radix
4426 = mod (radix * a) radix = 0
4430 assert { value nx sy = p * value x sy
4433 = power 2 (Limb.length - clz) * value nx sy
4434 so p * power 2 (Limb.length - clz)
4436 so p * radix * value x sy
4437 = p * power 2 (Limb.length - clz) * value nx sy
4438 = radix * value nx sy
4439 so p * value x sy = value nx sy
4442 assert { value ox sx
4443 = value q (sx - sy + adjust) * value y sy
4446 value (nx at Div_s) (sx + adjust)
4447 = (value q (sx - sy + adjust)
4448 + power radix (sx - sy + adjust) * _qh)
4451 so value (nx at Div_s) (sx + adjust)
4453 so power radix (sx - sy + 1) * power radix (sy - 1)
4455 so value ny sy = p * value y sy
4458 value (nx at Div_s) (sx + adjust)
4459 = (value q (sx - sy + adjust)
4460 + power radix (sx - sy + adjust) * _qh)
4464 so value q (sx - sy + adjust) >= 0
4466 so (value q (sx - sy + adjust)
4467 + power radix (sx - sy + adjust) * _qh) >= 0
4468 so (value q (sx - sy + adjust)
4469 + power radix (sx - sy + adjust) * _qh)
4472 >= (value q (sx - sy + adjust)
4473 + power radix (sx - sy + adjust) * _qh)
4475 >= power radix (sx - sy + adjust) * _qh * value ny sy
4477 so value nx sy = p * value x sy
4479 = value q (sx - sy + adjust) * p * value y sy
4481 = p * (value q (sx - sy + adjust)
4487 ensures { value q (sx - sy + 1)
4488 = value (q at Ret_s) (sx - sy + adjust) }
4491 value_sub_shift_no_change (pelts x) x.offset
4492 (p2i sx) (p2i sx) 0;
4493 set_ofs q (sx - sy) 0;
4494 value_sub_tail (pelts q) q.offset (q.offset + p2i sx - p2i sy);
4495 assert { value q (sx - sy + 1) = value (q at Ret_s) (sx - sy)
4496 by value q (sx - sy + 1)
4497 = value (q at Ret_s) (sx - sy) + power radix (sx - sy) * 0
4498 = value (q at Ret_s) (sx - sy) }
4505 let wmpn_tdiv_qr_in_place (q:t) (qxn:int32) (x:t) (sx:int32) (y:t) (sy:int32)
4507 requires { 1 <= sy <= sx <= (Int32.max_int32 - 1) }
4508 requires { valid x sx }
4509 requires { valid y sy }
4510 requires { valid q (sx - sy + 1) }
4511 requires { writable x /\ writable q }
4512 requires { qxn = 0 }
4513 requires { (pelts y)[y.offset + sy - 1] > 0 }
4514 ensures { value (old x) sx
4515 = value q (sx - sy + 1) * value y sy
4517 ensures { value x sy < value y sy }
4519 let nx = malloc (UInt32.(+) (UInt32.of_int32 sx) 1) in
4520 c_assert (is_not_null nx);
4521 let ny = malloc (UInt32.of_int32 sy) in
4522 c_assert (is_not_null ny);
4523 div_qr_in_place q x y nx ny sx sy;