3 (** {1 A library for arbitrary-precision integer arithmetic} *)
15 (** {2 data type for unbound integers and invariants} *)
17 constant base : int = 10000
18 (** a power of ten whose square fits on 31 bits *)
20 type t = { mutable digits: array int31 }
21 (** an unbounded integer is stored in an array of 31 bits integers,
22 with all values between 0 included and [base] excluded
24 index 0 is the lsb. the msb is never 0.
26 predicate ok_array (a:array int31) =
27 (to_int a.length >= 1 -> to_int a[to_int a.length - 1] <> 0) /\
28 forall i:int. 0 <= i < to_int a.length ->
29 0 <= to_int a[i] < base
31 predicate ok (x:t) = ok_array x.digits
34 (** {2 value stored in an array} *)
36 (* [value_sub x n m] denotes the integer represented by
37 the digits x[n..m-1] with lsb at index n *)
38 function value_sub (x:map int int31) (n:int) (m:int) (l:int): int
40 if 0 <= n < l /\ n < m then
41 x.[n] + base * value_sub x (n+1) m l
47 if 0 <= n < l /\ n < m then
48 to_int (Map.get x n) + base * value_sub x (n+1) m l
53 let rec lemma value_sub_frame (x y:map int int31) (n m l:int)
54 requires { MapEq.map_eq_sub x y n m }
56 ensures { value_sub x n m l = value_sub y n m l }
58 if n < m then value_sub_frame x y (n+1) m l else ()
60 let rec lemma value_sub_tail (x:map int int31) (n m l :int)
61 requires { 0 <= n <= m < l }
64 value_sub x n (m+1) l =
65 value_sub x n m l + to_int (Map.get x m) * power base (m-n) }
66 = if n < m then value_sub_tail x (n+1) m l else ()
68 let rec lemma value_sub_tail_end (x:map int int31) (n m l :int)
69 requires { 0 <= n <= m /\ m >= l }
71 ensures { value_sub x n (m+1) l = value_sub x n m l }
72 = if n < m then value_sub_tail_end x (n+1) m l else ()
75 let rec lemma value_sub_shorten (x:map int int31) (n m l:int)
76 requires { 0 <= n <= m <= l }
78 ensures { value_sub x n m l = value_sub x n m m }
79 = if n < m then value_sub_shorten x (n+1) m l else ()
81 let rec lemma value_sub_leading_zeros (x:map int int31) (n m' m l:int)
82 requires { 0 <= n <= m' <= m <= l }
83 requires { forall i. m' <= i < m -> to_int (Map.get x i) = 0 }
85 ensures { value_sub x n m l = value_sub x n m' l }
86 = if m' < m then value_sub_leading_zeros x n (m'+1) m l else ()
88 function value_array (x:array int31) : int =
89 value_sub x.elts 0 (to_int x.length) (to_int x.length)
91 function value (x:t) : int = value_array x.digits
94 (** {2 general lemmas} *)
97 lemma power_monotonic:
98 forall x y z. 0 <= x <= y -> power z x <= power z y
102 forall x y. x >= 0 /\ y >= 0 -> power x y >= 0
105 forall x:array int31.
106 let l = to_int x.length in
107 l = 0 -> value_array x = 0
109 lemma value_sub_upper_bound:
110 forall x:map int int31, n l:int. 0 <= n <= l ->
111 (forall i:int. 0 <= i < n -> 0 <= to_int (Map.get x i) < base) ->
112 value_sub x 0 n l < power base n
114 lemma value_sub_lower_bound:
115 forall x:map int int31, n l:int. 0 <= n <= l ->
116 (forall i:int. 0 <= i < n -> 0 <= to_int (Map.get x i) < base) ->
117 0 <= value_sub x 0 n l
119 lemma value_sub_lower_bound_tight:
120 forall x:map int int31, n l:int. 0 < n <= l ->
121 (forall i:int. 0 <= i < n-1 -> 0 <= to_int (Map.get x i) < base) ->
122 0 < to_int (Map.get x (n-1)) < base ->
123 power base (n-1) <= value_sub x 0 n l
125 lemma value_bounds_array:
126 forall x:array int31. ok_array x ->
127 let l = to_int x.length in
128 l > 0 -> power base (l-1) <= value_array x < power base l
130 (** {2 conversion from a small integer} *)
133 let from_small_int (n:int31) : t
134 requires { 0 <= to_int n < base }
135 ensures { ok result }
136 ensures { value result = to_int n }
137 = let zero = of_int 0 in
140 Array31.make zero zero
142 Array31.make (of_int 1) n
146 (** {2 Comparisons} *)
152 let compare_array (x y:array int31) : int31
153 requires { ok_array x /\ ok_array y }
154 ensures { -1 <= to_int result <= 1 }
155 ensures { to_int result = -1 -> value_array x < value_array y }
156 ensures { to_int result = 0 -> value_array x = value_array y }
157 ensures { to_int result = 1 -> value_array x > value_array y }
158 = let zero = of_int 0 in
159 let one = of_int 1 in
160 let minus_one = of_int (-1) in
163 if Int31.(<) l1 l2 then minus_one else
164 if Int31.(>) l1 l2 then one else
166 let res = ref zero in
167 let ghost acc = ref 0 in
169 while Int31.(>) !i zero do
170 invariant { to_int !res = 0 }
171 (* needed to be sure it is zero at normal exit ! *)
172 invariant { 0 <= to_int !i <= to_int l1 }
174 value_sub x.elts 0 (to_int !i) (to_int l1) = value_array x - !acc
177 value_sub y.elts 0 (to_int !i) (to_int l1) = value_array y - !acc
179 variant { to_int !i }
180 assert { value_array x - !acc =
181 value_sub x.elts 0 (to_int !i - 1) (to_int l1) +
182 power base (to_int !i - 1) * (to_int x[to_int !i - 1])
184 assert { value_array y - !acc =
185 value_sub y.elts 0 (to_int !i - 1) (to_int l1) +
186 power base (to_int !i - 1) * (to_int y[to_int !i - 1])
188 i := Int31.(-) !i one;
189 if Int31.(<) x[!i] y[!i] then
191 assert { value_sub y.elts 0 (to_int !i) (to_int l1) >= 0 };
192 assert { value_sub x.elts 0 (to_int !i) (to_int l1) <
193 power base (to_int !i)
195 assert { value_array y - !acc >=
196 power base (to_int !i) * (to_int y[to_int !i])
198 assert { to_int y[to_int !i] >= to_int x[to_int !i] + 1 };
199 assert { power base (to_int !i) * (to_int y[to_int !i]) >=
200 power base (to_int !i) * (to_int x[to_int !i] + 1) };
201 assert { power base (to_int !i) * (to_int y[to_int !i]) >=
202 power base (to_int !i) * (to_int x[to_int !i])
203 + power base (to_int !i) };
207 if Int31.(>) x[!i] y[!i] then
209 assert { value_sub x.elts 0 (to_int !i) (to_int l1) >= 0 };
210 assert { value_sub y.elts 0 (to_int !i) (to_int l1) <
211 power base (to_int !i)
213 assert { value_array x - !acc >=
214 power base (to_int !i) * (to_int x[to_int !i])
216 assert { to_int x[to_int !i] >= to_int y[to_int !i] + 1 };
217 assert { power base (to_int !i) * (to_int x[to_int !i]) >=
218 power base (to_int !i) * (to_int y[to_int !i] + 1) };
219 assert { power base (to_int !i) * (to_int x[to_int !i]) >=
220 power base (to_int !i) * (to_int y[to_int !i])
221 + power base (to_int !i) };
225 acc := !acc + power base (to_int !i) * to_int x[!i];
231 let eq (x y:t) : bool
232 requires { ok x /\ ok y }
233 ensures { if result then value x = value y else value x <> value y }
234 = compare_array x.digits y.digits = of_int 0
236 (** {2 arithmetic operations} *)
238 exception TooManyDigits
240 let add_array (x y:array int31) : array int31
241 requires { ok_array x /\ ok_array y }
242 requires { to_int x.length <= to_int y.length }
243 ensures { ok_array result }
244 ensures { value_array result = value_array x + value_array y }
245 raises { TooManyDigits -> true }
247 let zero = of_int 0 in
248 let one = of_int 1 in
249 let minus_one = of_int (-1) in
250 let base31 = of_int 10000 in
251 assert { to_int base31 = base };
254 if Int31.(>=) h (of_int 0x3FFFFFFF) then raise TooManyDigits;
255 let arr = Array31.make (Int31.(+) h one) zero in
256 let carry = ref zero in
258 let non_null_idx = ref minus_one in
259 while Int31.(<) !i l do
260 invariant { 0 <= to_int !i <= to_int l }
261 invariant { 0 <= to_int !carry <= 1 }
263 forall j. 0 <= j < to_int !i -> 0 <= to_int arr[j] < base }
264 invariant { -1 <= to_int !non_null_idx < to_int !i }
266 to_int !non_null_idx >= 0 -> to_int arr[to_int !non_null_idx] <> 0 }
268 forall j. to_int !non_null_idx < j < to_int !i -> to_int arr[j] = 0 }
270 value_sub arr.elts 0 (to_int !i) (to_int h + 1)
271 + (to_int !carry) * power base (to_int !i) =
272 value_sub x.elts 0 (to_int !i) (to_int l)
273 + value_sub y.elts 0 (to_int !i) (to_int h) }
274 variant { to_int l - to_int !i }
276 let sum = Int31.(+) (Int31.(+) x[!i] y[!i]) !carry in
277 if Int31.(>=) sum base31
278 then begin arr[!i] <- Int31.(-) sum base31; carry := one end
279 else begin arr[!i] <- sum; carry := zero end;
280 if arr[!i] <> zero then non_null_idx := !i;
282 MapEq.map_eq_sub arr.elts (arr at L).elts 0 (to_int !i) };
283 assert { value_sub arr.elts 0 (to_int !i) (to_int h + 1) =
284 value_sub (arr at L).elts 0 (to_int !i) (to_int h + 1) };
285 i := Int31.(+) !i one;
287 while Int31.(<) !i h do
288 invariant { to_int l <= to_int !i <= to_int h }
289 invariant { 0 <= to_int !carry <= 1 }
291 forall j. 0 <= j < to_int !i -> 0 <= to_int arr[j] < base }
292 invariant { -1 <= to_int !non_null_idx < to_int !i }
294 to_int !non_null_idx >= 0 -> to_int arr[to_int !non_null_idx] <> 0 }
296 forall j. to_int !non_null_idx < j < to_int !i -> to_int arr[j] = 0 }
298 value_sub arr.elts 0 (to_int !i) (to_int h + 1)
299 + (to_int !carry) * power base (to_int !i) =
300 value_sub x.elts 0 (to_int l) (to_int l)
301 + value_sub y.elts 0 (to_int !i) (to_int h) }
302 variant { to_int h - to_int !i }
304 let sum = Int31.(+) y[!i] !carry in
305 if Int31.(>=) sum base31
306 then begin arr[!i] <- Int31.(-) sum base31; carry := one end
307 else begin arr[!i] <- sum; carry := zero end;
308 if arr[!i] <> zero then non_null_idx := !i;
310 MapEq.map_eq_sub arr.elts (arr at L).elts 0 (to_int !i) };
311 assert { value_sub arr.elts 0 (to_int !i) (to_int h + 1) =
312 value_sub (arr at L).elts 0 (to_int !i) (to_int h + 1) };
313 i := Int31.(+) !i one;
318 MapEq.map_eq_sub arr.elts (arr at L).elts 0 (to_int !i) };
319 assert { value_sub arr.elts 0 (to_int !i) (to_int h + 1) =
320 value_sub (arr at L).elts 0 (to_int !i) (to_int h + 1) };
321 assert { value_array arr = value_array x + value_array y };
323 ensures { -1 <= to_int !non_null_idx <= to_int !i }
324 ensures { to_int !non_null_idx >= 0 -> to_int arr[to_int !non_null_idx] <> 0 }
326 forall j. to_int !non_null_idx < j <= to_int !i -> to_int arr[j] = 0 }
327 (if arr[!i] <> zero then non_null_idx := !i)
329 let len = Int31.(+) !non_null_idx one in
330 assert { value_sub arr.elts 0 (to_int !i + 1) (to_int h + 1) =
331 value_sub arr.elts 0 (to_int len) (to_int h + 1) } ;
332 assert { value_sub arr.elts 0 (to_int !i + 1) (to_int h + 1) =
333 value_sub arr.elts 0 (to_int len) (to_int len) } ;
334 let arr' = Array31.make len zero in
335 Array31.blit arr zero arr' zero len;
337 MapEq.map_eq_sub arr.elts arr'.elts 0 (to_int len) };
338 assert { value_sub arr.elts 0 (to_int len) (to_int len) =
339 value_sub arr'.elts 0 (to_int len) (to_int len) } ;
340 assert { to_int arr'.length >= 1 ->
341 to_int arr'[to_int arr'.length - 1] <> 0 };
342 assert { forall j. 0 <= j < to_int arr'.length ->
343 0 <= to_int arr'[j] < base };
347 requires { ok x /\ ok y }
348 ensures { ok result }
349 ensures { value result = value x + value y }
350 raises { TooManyDigits -> true }
351 = let l1 = x.digits.length in
352 let l2 = y.digits.length in
354 if Int31.(<=) l1 l2 then
355 add_array x.digits y.digits
356 else add_array y.digits x.digits
361 (* Multiplication: school book algorithm *)
363 let rec mul_array (x y:array int31) : array int31
364 requires { ok_array x /\ ok_array y }
365 ensures { ok_array result }
366 ensures { value_array result = value_array x * value_array y }
367 raises { TooManyDigits -> true }
368 = let zero = of_int 0 in
369 let one = of_int 1 in
370 let two = of_int 2 in
371 let base31 = of_int 10000 in
372 assert { to_int base31 = base };
373 let l1 = x.digits.length in
374 let l2 = y.digits.length in
378 (* Multiplication: Karatsuba algorithm
380 let rec mul_array (x y:array int31) : array int31
381 requires { ok_array x /\ ok_array y }
382 ensures { ok_array result }
383 ensures { value_array result = value_array x * value_array y }
384 raises { TooManyDigits -> true }
385 = let zero = of_int 0 in
386 let one = of_int 1 in
387 let two = of_int 2 in
388 let base31 = of_int 10000 in
389 assert { to_int base31 = base };
390 let l1 = x.digits.length in
391 let l2 = y.digits.length in
392 if Int31.(<=) l1 (of_int 1) && Int31.(<=) l1 (of_int 1) then
394 let n = x.digits.[0] * y.digits.[0] in
395 let h = Int31.(/) n base31 in
396 let l = Int31.(-) n (Int31.(*) h base31) in
397 if Int31.eq h zero then
398 if Int31.eq l zero then
399 let arr = Array31.make zero zero in
402 let arr = Array31.make one l in
405 let arr = Array31.make two l in
409 let m = if Int31.(<=) l1 l2 then l2 else l1 in
410 let m2 = Int31.(/) m two in
411 let m' = Int31.(-) m m2 in
412 let low1 = Array31.make m2 zero in
413 Array31.blit x zero low1 zero m2; (* wrong if l1 < m2 ! *)
414 let low2 = Array31.make m2 zero in
415 Array31.blit y zero low2 zero m2; (* wrong if l2 < m2 ! *)
416 let high1 = Array31.make m' zero in
417 Array31.blit x m2 high1 zero m'; (* wrong if l1 < m ! *)
418 let high2 = Array31.make m' zero in
419 Array31.blit y m2 high2 zero m'; (* wrong if l2 < m ! *)
420 assert { value_array x = value_array low1 +
421 power base m2 * value_array high1 };
422 assert { value_array y = value_array low2 +
423 power base m2 * value_array high2 };
424 let z0 = mul_array low1 low2 in
425 let z1 = mul_array (add_array low1 high1) (add_array low2 high2)
426 let z2 = mul_array high1 high2 in
428 return (z2*10^(2*m2))+((z1-z2-z0)*10^(m2))+(z0)
430 -> we need subtraction !
434 requires { ok x /\ ok y }
435 ensures { ok result }
436 ensures { value result = value x * value y }
437 raises { TooManyDigits -> true }
438 = let res = mul_array x.digits y.digits in
450 use mach.array.Array31
455 let constant base : int = 32768
456 let constant max_digit : int = 16384
457 let constant min_digit : int = -16384
459 type t = { mutable digits: array int31 }
461 predicate ok_array (a:array int31) =
462 forall i:int. 0 <= i < to_int a.length ->
463 min_digit <= to_int a[i] < max_digit
465 predicate ok (x:t) = ok_array x.digits
467 (* [value_sub x n m] denotes the integer represented by
468 the digits x[n..m-1] with lsb at index n *)
469 function value_sub (x:map int int31) (n:int) (m:int) (l:int): int
471 if 0 <= n < l /\ n < m then
472 x.[n] + base * value_sub x (n+1) m l
475 axiom value_sub_next:
478 if 0 <= n < l /\ n < m then
479 to_int (Map.get x n) + base * value_sub x (n+1) m l
484 let rec lemma value_sub_frame (x y:map int int31) (n m l:int)
485 requires { MapEq.map_eq_sub x y n m }
487 ensures { value_sub x n m l = value_sub y n m l }
489 if n < m then value_sub_frame x y (n+1) m l else ()
491 let rec lemma value_sub_tail (x:map int int31) (n m l :int)
492 requires { 0 <= n <= m < l }
495 value_sub x n (m+1) l =
496 value_sub x n m l + to_int (Map.get x m) * power base (m-n) }
497 = if n < m then value_sub_tail x (n+1) m l else ()
499 let rec lemma value_sub_tail_end (x:map int int31) (n m l :int)
500 requires { 0 <= n <= m /\ m >= l }
502 ensures { value_sub x n (m+1) l = value_sub x n m l }
503 = if n < m then value_sub_tail_end x (n+1) m l else ()
505 function value_array (x:array int31) : int =
506 value_sub x.elts 0 (to_int x.length) (to_int x.length)
508 function value (x:t) : int = value_array x.digits
510 let from_small_int (n:int31) : t
511 requires { min_digit <= to_int n < max_digit }
512 ensures { ok result }
513 ensures { value result = to_int n }
515 let a = Array31.make (of_int 1) n in
518 exception TooManyDigits
520 let add_array (x y:array int31) : array int31
521 requires { ok_array x /\ ok_array y }
522 requires { to_int x.length <= to_int y.length }
523 ensures { ok_array result }
524 ensures { value_array result = value_array x + value_array y }
525 raises { TooManyDigits -> true }
527 let zero = of_int 0 in
528 let one = of_int 1 in
529 let minusone = of_int (-1) in
530 let base31 = of_int base in
531 let min_digit31 = of_int min_digit in
532 let max_digit31 = of_int max_digit in
535 if Int31.(>=) h (of_int Int31.max_int31) then raise TooManyDigits;
536 let arr = Array31.make (Int31.(+) h one) zero in
537 let carry = ref zero in
539 while Int31.(<) !i l do
540 invariant { 0 <= to_int !i <= to_int l }
541 invariant { -1 <= to_int !carry <= 1 }
543 forall j. 0 <= j < to_int !i -> min_digit <= to_int arr[j] < max_digit }
545 value_sub arr.elts 0 (to_int !i) (to_int h + 1)
546 + (to_int !carry) * power base (to_int !i) =
547 value_sub x.elts 0 (to_int !i) (to_int l)
548 + value_sub y.elts 0 (to_int !i) (to_int h) }
549 variant { to_int l - to_int !i }
551 let sum = Int31.(+) (Int31.(+) x[!i] y[!i]) !carry in
552 if Int31.(>=) sum max_digit31
553 then begin arr[!i] <- Int31.(-) sum base31; carry := one end
555 if Int31.(<) sum min_digit31
556 then begin arr[!i] <- Int31.(+) sum base31; carry := minusone end
557 else begin arr[!i] <- sum; carry := zero end;
559 MapEq.map_eq_sub arr.elts (arr at L).elts 0 (to_int !i) };
560 assert { value_sub arr.elts 0 (to_int !i) (to_int h + 1) =
561 value_sub (arr at L).elts 0 (to_int !i) (to_int h + 1) };
562 i := Int31.(+) !i one;
564 while Int31.(<) !i h do
565 invariant { to_int l <= to_int !i <= to_int h }
566 invariant { -1 <= to_int !carry <= 1 }
567 invariant { forall j. 0 <= j < to_int !i ->
568 min_digit <= to_int arr[j] < max_digit }
570 value_sub arr.elts 0 (to_int !i) (to_int h + 1)
571 + (to_int !carry) * power base (to_int !i) =
572 value_sub x.elts 0 (to_int l) (to_int l)
573 + value_sub y.elts 0 (to_int !i) (to_int h) }
574 variant { to_int h - to_int !i }
576 let sum = Int31.(+) y[!i] !carry in
577 if Int31.(>=) sum max_digit31
578 then begin arr[!i] <- Int31.(-) sum base31; carry := one end
580 if Int31.(<) sum min_digit31
581 then begin arr[!i] <- Int31.(+) sum base31; carry := minusone end
582 else begin arr[!i] <- sum; carry := zero end;
584 MapEq.map_eq_sub arr.elts (arr at L).elts 0 (to_int !i) };
585 assert { value_sub arr.elts 0 (to_int !i) (to_int h + 1) =
586 value_sub (arr at L).elts 0 (to_int !i) (to_int h + 1) };
587 i := Int31.(+) !i one;
592 MapEq.map_eq_sub arr.elts (arr at L).elts 0 (to_int !i) };
593 assert { value_sub arr.elts 0 (to_int !i) (to_int h + 1) =
594 value_sub (arr at L).elts 0 (to_int !i) (to_int h + 1) };
598 requires { ok x /\ ok y }
599 ensures { ok result }
600 ensures { value result = value x + value y }
601 raises { TooManyDigits -> true }
602 = let l1 = x.digits.length in
603 let l2 = y.digits.length in
605 if Int31.(<=) l1 l2 then
606 add_array x.digits y.digits
607 else add_array y.digits x.digits