1 ------------------------------------------------------------------------------
3 -- GNAT RUN-TIME COMPONENTS --
5 -- S Y S T E M . A R I T H _ D O U B L E --
9 -- Copyright (C) 1992-2023, Free Software Foundation, Inc. --
11 -- GNAT is free software; you can redistribute it and/or modify it under --
12 -- terms of the GNU General Public License as published by the Free Soft- --
13 -- ware Foundation; either version 3, or (at your option) any later ver- --
14 -- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
15 -- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
16 -- or FITNESS FOR A PARTICULAR PURPOSE. --
18 -- As a special exception under Section 7 of GPL version 3, you are granted --
19 -- additional permissions described in the GCC Runtime Library Exception, --
20 -- version 3.1, as published by the Free Software Foundation. --
22 -- You should have received a copy of the GNU General Public License and --
23 -- a copy of the GCC Runtime Library Exception along with this program; --
24 -- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
25 -- <http://www.gnu.org/licenses/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 with Ada
.Unchecked_Conversion
;
33 with System
.SPARK
.Cut_Operations
; use System
.SPARK
.Cut_Operations
;
35 package body System
.Arith_Double
38 -- Contracts, ghost code, loop invariants and assertions in this unit are
39 -- meant for analysis only, not for run-time checking, as it would be too
40 -- costly otherwise. This is enforced by setting the assertion policy to
43 pragma Assertion_Policy
(Pre
=> Ignore
,
45 Contract_Cases
=> Ignore
,
47 Loop_Invariant
=> Ignore
,
50 pragma Suppress
(Overflow_Check
);
51 pragma Suppress
(Range_Check
);
53 function To_Uns
is new Ada
.Unchecked_Conversion
(Double_Int
, Double_Uns
);
54 function To_Int
is new Ada
.Unchecked_Conversion
(Double_Uns
, Double_Int
);
56 Double_Size
: constant Natural := Double_Int
'Size;
57 Single_Size
: constant Natural := Double_Int
'Size / 2;
59 -- Log of Single_Size in base 2, so that Single_Size = 2 ** Log_Single_Size
60 Log_Single_Size
: constant Natural :=
65 when others => raise Program_Error
)
68 -- Power-of-two constants
71 (Off
, "non-preelaborable call not allowed in preelaborated unit",
72 Reason
=> "Ghost code is not compiled");
74 (Off
, "non-static constant in preelaborated unit",
75 Reason
=> "Ghost code is not compiled");
76 Big_0
: constant Big_Integer
:=
79 Big_2xxSingle : constant Big_Integer :=
80 Big (Double_Int'(2 ** Single_Size
))
82 Big_2xxDouble_Minus_1
: constant Big_Integer
:=
83 Big
(Double_Uns
'(2 ** (Double_Size - 1)))
85 Big_2xxDouble : constant Big_Integer :=
86 Big (Double_Uns'(2 ** Double_Size
- 1)) + 1
89 (On
, "non-preelaborable call not allowed in preelaborated unit");
90 pragma Warnings
(On
, "non-static constant in preelaborated unit");
92 -----------------------
93 -- Local Subprograms --
94 -----------------------
96 function "+" (A
, B
: Single_Uns
) return Double_Uns
is
97 (Double_Uns
(A
) + Double_Uns
(B
));
98 function "+" (A
: Double_Uns
; B
: Single_Uns
) return Double_Uns
is
100 -- Length doubling additions
102 function "*" (A
, B
: Single_Uns
) return Double_Uns
is
103 (Double_Uns
(A
) * Double_Uns
(B
));
104 -- Length doubling multiplication
106 function "/" (A
: Double_Uns
; B
: Single_Uns
) return Double_Uns
is
110 -- Length doubling division
112 function "&" (Hi
, Lo
: Single_Uns
) return Double_Uns
is
113 (Shift_Left
(Double_Uns
(Hi
), Single_Size
) or Double_Uns
(Lo
));
114 -- Concatenate hi, lo values to form double result
116 function "abs" (X
: Double_Int
) return Double_Uns
is
117 (if X
= Double_Int
'First
118 then Double_Uns
'(2 ** (Double_Size - 1))
119 else Double_Uns (Double_Int'(abs X
)));
120 -- Convert absolute value of X to unsigned. Note that we can't just use
121 -- the expression of the Else since it overflows for X = Double_Int'First.
123 function "rem" (A
: Double_Uns
; B
: Single_Uns
) return Double_Uns
is
124 (A
rem Double_Uns
(B
))
127 -- Length doubling remainder
129 function Big_2xx
(N
: Natural) return Big_Positive
is
130 (Big
(Double_Uns
'(2 ** N)))
133 Pre => N < Double_Size,
134 Post => Big_2xx'Result > 0;
135 -- 2**N as a big integer
137 function Big3 (X1, X2, X3 : Single_Uns) return Big_Natural is
138 (Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (X1))
139 + Big_2xxSingle * Big (Double_Uns (X2))
140 + Big (Double_Uns (X3)))
142 -- X1&X2&X3 as a big integer
144 function Big3 (X1, X2, X3 : Big_Integer) return Big_Integer is
145 (Big_2xxSingle * Big_2xxSingle * X1
149 -- Version of Big3 on big integers
151 function Le3 (X1, X2, X3, Y1, Y2, Y3 : Single_Uns) return Boolean
153 Post => Le3'Result = (Big3 (X1, X2, X3) <= Big3 (Y1, Y2, Y3));
154 -- Determines if (3 * Single_Size)-bit value X1&X2&X3 <= Y1&Y2&Y3
156 function Lo (A : Double_Uns) return Single_Uns is
157 (Single_Uns (A and (2 ** Single_Size - 1)));
158 -- Low order half of double value
160 function Hi (A : Double_Uns) return Single_Uns is
161 (Single_Uns (Shift_Right (A, Single_Size)));
162 -- High order half of double value
164 procedure Sub3 (X1, X2, X3 : in out Single_Uns; Y1, Y2, Y3 : Single_Uns)
166 Pre => Big3 (X1, X2, X3) >= Big3 (Y1, Y2, Y3),
167 Post => Big3 (X1, X2, X3) = Big3 (X1, X2, X3)'Old - Big3 (Y1, Y2, Y3);
168 -- Computes X1&X2&X3 := X1&X2&X3 - Y1&Y1&Y3 mod 2 ** (3 * Single_Size)
170 function To_Neg_Int (A : Double_Uns) return Double_Int
172 Annotate => (GNATprove, Always_Return),
173 Pre => In_Double_Int_Range (-Big (A)),
174 Post => Big (To_Neg_Int'Result) = -Big (A);
175 -- Convert to negative integer equivalent. If the input is in the range
176 -- 0 .. 2 ** (Double_Size - 1), then the corresponding nonpositive signed
177 -- integer (obtained by negating the given value) is returned, otherwise
178 -- constraint error is raised.
180 function To_Pos_Int (A : Double_Uns) return Double_Int
182 Annotate => (GNATprove, Always_Return),
183 Pre => In_Double_Int_Range (Big (A)),
184 Post => Big (To_Pos_Int'Result) = Big (A);
185 -- Convert to positive integer equivalent. If the input is in the range
186 -- 0 .. 2 ** (Double_Size - 1) - 1, then the corresponding non-negative
187 -- signed integer is returned, otherwise constraint error is raised.
189 procedure Raise_Error;
190 pragma No_Return (Raise_Error);
191 -- Raise constraint error with appropriate message
197 procedure Inline_Le3 (X1, X2, X3, Y1, Y2, Y3 : Single_Uns)
200 Pre => Le3 (X1, X2, X3, Y1, Y2, Y3),
201 Post => Big3 (X1, X2, X3) <= Big3 (Y1, Y2, Y3);
203 procedure Lemma_Abs_Commutation (X : Double_Int)
206 Post => abs (Big (X)) = Big (Double_Uns'(abs X
));
208 procedure Lemma_Abs_Div_Commutation
(X
, Y
: Big_Integer
)
212 Post
=> abs (X
/ Y
) = abs X
/ abs Y
;
214 procedure Lemma_Abs_Mult_Commutation
(X
, Y
: Big_Integer
)
217 Post
=> abs (X
* Y
) = abs X
* abs Y
;
219 procedure Lemma_Abs_Range
(X
: Big_Integer
)
222 Pre
=> In_Double_Int_Range
(X
),
223 Post
=> abs (X
) <= Big_2xxDouble_Minus_1
224 and then In_Double_Int_Range
(-abs (X
));
226 procedure Lemma_Abs_Rem_Commutation
(X
, Y
: Big_Integer
)
230 Post
=> abs (X
rem Y
) = (abs X
) rem (abs Y
);
232 procedure Lemma_Add_Commutation
(X
: Double_Uns
; Y
: Single_Uns
)
235 Pre
=> X
<= 2 ** Double_Size
- 2 ** Single_Size
,
236 Post
=> Big
(X
) + Big
(Double_Uns
(Y
)) = Big
(X
+ Double_Uns
(Y
));
238 procedure Lemma_Add_One
(X
: Double_Uns
)
241 Pre
=> X
/= Double_Uns
'Last,
242 Post
=> Big
(X
+ Double_Uns
'(1)) = Big (X) + 1;
244 procedure Lemma_Big_Of_Double_Uns (X : Double_Uns)
247 Post => Big (X) < Big_2xxDouble;
249 procedure Lemma_Big_Of_Double_Uns_Of_Single_Uns (X : Single_Uns)
252 Post => Big (Double_Uns (X)) >= 0
253 and then Big (Double_Uns (X)) < Big_2xxSingle;
255 procedure Lemma_Bounded_Powers_Of_2_Increasing (M, N : Natural)
258 Pre => M < N and then N < Double_Size,
259 Post => Double_Uns'(2)**M
< Double_Uns
'(2)**N;
261 procedure Lemma_Concat_Definition (X, Y : Single_Uns)
264 Post => Big (X & Y) = Big_2xxSingle * Big (Double_Uns (X))
265 + Big (Double_Uns (Y));
267 procedure Lemma_Deep_Mult_Commutation
268 (Factor : Big_Integer;
273 Factor * Big (Double_Uns (X)) * Big (Double_Uns (Y)) =
274 Factor * Big (Double_Uns (X) * Double_Uns (Y));
276 procedure Lemma_Div_Commutation (X, Y : Double_Uns)
280 Post => Big (X) / Big (Y) = Big (X / Y);
282 procedure Lemma_Div_Definition
289 Pre => B /= 0 and then Q = A / B and then R = A rem B,
290 Post => Big (A) = Big (Double_Uns (B)) * Big (Q) + Big (R);
292 procedure Lemma_Div_Ge (X, Y, Z : Big_Integer)
295 Pre => Z > 0 and then X >= Y * Z,
298 procedure Lemma_Div_Lt (X, Y, Z : Big_Natural)
301 Pre => Z > 0 and then X < Y * Z,
304 procedure Lemma_Div_Eq (A, B, S, R : Big_Integer)
307 Pre => A * S = B * S + R and then S /= 0,
308 Post => A = B + R / S;
310 procedure Lemma_Double_Big_2xxSingle
313 Post => Big_2xxSingle * Big_2xxSingle = Big_2xxDouble;
315 procedure Lemma_Double_Shift (X : Double_Uns; S, S1 : Double_Uns)
318 Pre => S <= Double_Uns (Double_Size)
319 and then S1 <= Double_Uns (Double_Size),
320 Post => Shift_Left (Shift_Left (X, Natural (S)), Natural (S1)) =
321 Shift_Left (X, Natural (S + S1));
323 procedure Lemma_Double_Shift (X : Single_Uns; S, S1 : Natural)
326 Pre => S <= Single_Size - S1,
327 Post => Shift_Left (Shift_Left (X, S), S1) = Shift_Left (X, S + S1);
329 procedure Lemma_Double_Shift (X : Double_Uns; S, S1 : Natural)
332 Pre => S <= Double_Size - S1,
333 Post => Shift_Left (Shift_Left (X, S), S1) = Shift_Left (X, S + S1);
335 procedure Lemma_Double_Shift_Left (X : Double_Uns; S, S1 : Double_Uns)
338 Pre => S <= Double_Uns (Double_Size)
339 and then S1 <= Double_Uns (Double_Size),
340 Post => Shift_Left (Shift_Left (X, Natural (S)), Natural (S1)) =
341 Shift_Left (X, Natural (S + S1));
343 procedure Lemma_Double_Shift_Left (X : Double_Uns; S, S1 : Natural)
346 Pre => S <= Double_Size - S1,
347 Post => Shift_Left (Shift_Left (X, S), S1) = Shift_Left (X, S + S1);
349 procedure Lemma_Double_Shift_Right (X : Double_Uns; S, S1 : Double_Uns)
352 Pre => S <= Double_Uns (Double_Size)
353 and then S1 <= Double_Uns (Double_Size),
354 Post => Shift_Right (Shift_Right (X, Natural (S)), Natural (S1)) =
355 Shift_Right (X, Natural (S + S1));
357 procedure Lemma_Double_Shift_Right (X : Double_Uns; S, S1 : Natural)
360 Pre => S <= Double_Size - S1,
361 Post => Shift_Right (Shift_Right (X, S), S1) = Shift_Right (X, S + S1);
363 procedure Lemma_Ge_Commutation (A, B : Double_Uns)
367 Post => Big (A) >= Big (B);
369 procedure Lemma_Ge_Mult (A, B, C, D : Big_Integer)
372 Pre => A >= B and then B * C >= D and then C > 0,
375 procedure Lemma_Gt_Commutation (A, B : Double_Uns)
379 Post => Big (A) > Big (B);
381 procedure Lemma_Gt_Mult (A, B, C, D : Big_Integer)
384 Pre => A >= B and then B * C > D and then C > 0,
387 procedure Lemma_Hi_Lo (Xu : Double_Uns; Xhi, Xlo : Single_Uns)
390 Pre => Xhi = Hi (Xu) and Xlo = Lo (Xu),
392 Big_2xxSingle * Big (Double_Uns (Xhi)) + Big (Double_Uns (Xlo));
394 procedure Lemma_Hi_Lo_3 (Xu : Double_Uns; Xhi, Xlo : Single_Uns)
397 Pre => Xhi = Hi (Xu) and then Xlo = Lo (Xu),
398 Post => Big (Xu) = Big3 (0, Xhi, Xlo);
400 procedure Lemma_Lo_Is_Ident (X : Double_Uns)
403 Pre => Big (X) < Big_2xxSingle,
404 Post => Double_Uns (Lo (X)) = X;
406 procedure Lemma_Lt_Commutation (A, B : Double_Uns)
410 Post => Big (A) < Big (B);
412 procedure Lemma_Lt_Mult (A, B, C, D : Big_Integer)
415 Pre => A < B and then B * C <= D and then C > 0,
418 procedure Lemma_Mult_Commutation (X, Y : Single_Uns)
422 Big (Double_Uns (X)) * Big (Double_Uns (Y)) =
423 Big (Double_Uns (X) * Double_Uns (Y));
425 procedure Lemma_Mult_Commutation (X, Y : Double_Int)
428 Pre => In_Double_Int_Range (Big (X) * Big (Y)),
429 Post => Big (X) * Big (Y) = Big (X * Y);
431 procedure Lemma_Mult_Commutation (X, Y, Z : Double_Uns)
434 Pre => Big (X) * Big (Y) < Big_2xxDouble and then Z = X * Y,
435 Post => Big (X) * Big (Y) = Big (Z);
437 procedure Lemma_Mult_Decomposition
440 Xhi, Xlo, Yhi, Ylo : Single_Uns)
443 Pre => Mult = Big (Xu) * Big (Yu)
444 and then Xhi = Hi (Xu)
445 and then Xlo = Lo (Xu)
446 and then Yhi = Hi (Yu)
447 and then Ylo = Lo (Yu),
449 Big_2xxSingle * Big_2xxSingle * (Big (Double_Uns'(Xhi
* Yhi
)))
450 + Big_2xxSingle
* (Big
(Double_Uns
'(Xhi * Ylo)))
451 + Big_2xxSingle * (Big (Double_Uns'(Xlo
* Yhi
)))
452 + (Big
(Double_Uns
'(Xlo * Ylo)));
454 procedure Lemma_Mult_Distribution (X, Y, Z : Big_Integer)
457 Post => X * (Y + Z) = X * Y + X * Z;
459 procedure Lemma_Mult_Div (A, B : Big_Integer)
463 Post => A * B / B = A;
465 procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer)
468 Pre => (X >= 0 and then Y >= 0)
469 or else (X <= 0 and then Y <= 0),
472 procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer)
475 Pre => (X <= Big_0 and then Y >= Big_0)
476 or else (X >= Big_0 and then Y <= Big_0),
477 Post => X * Y <= Big_0;
479 procedure Lemma_Mult_Positive (X, Y : Big_Integer)
482 Pre => (X > Big_0 and then Y > Big_0)
483 or else (X < Big_0 and then Y < Big_0),
484 Post => X * Y > Big_0;
486 procedure Lemma_Neg_Div (X, Y : Big_Integer)
490 Post => X / Y = (-X) / (-Y);
492 procedure Lemma_Neg_Rem (X, Y : Big_Integer)
496 Post => X rem Y = X rem (-Y);
498 procedure Lemma_Not_In_Range_Big2xx64
500 Post => not In_Double_Int_Range (Big_2xxDouble)
501 and then not In_Double_Int_Range (-Big_2xxDouble);
503 procedure Lemma_Powers (A : Big_Natural; B, C : Natural)
506 Pre => B <= Natural'Last - C,
507 Post => A**B * A**C = A**(B + C);
509 procedure Lemma_Powers_Of_2 (M, N : Natural)
512 Pre => M < Double_Size
513 and then N < Double_Size
514 and then M + N <= Double_Size,
516 Big_2xx (M) * Big_2xx (N) =
517 (if M + N = Double_Size then Big_2xxDouble else Big_2xx (M + N));
519 procedure Lemma_Powers_Of_2_Commutation (M : Natural)
522 Subprogram_Variant => (Decreases => M),
523 Pre => M <= Double_Size,
524 Post => Big (Double_Uns'(2))**M
=
525 (if M
< Double_Size
then Big_2xx
(M
) else Big_2xxDouble
);
527 procedure Lemma_Powers_Of_2_Increasing
(M
, N
: Natural)
530 Subprogram_Variant
=> (Increases
=> M
),
532 Post
=> Big
(Double_Uns
'(2))**M < Big (Double_Uns'(2))**N
;
534 procedure Lemma_Rem_Abs
(X
, Y
: Big_Integer
)
538 Post
=> X
rem Y
= X
rem (abs Y
);
539 pragma Unreferenced
(Lemma_Rem_Abs
);
541 procedure Lemma_Rem_Commutation
(X
, Y
: Double_Uns
)
545 Post
=> Big
(X
) rem Big
(Y
) = Big
(X
rem Y
);
547 procedure Lemma_Rem_Is_Ident
(X
, Y
: Big_Integer
)
550 Pre
=> abs X
< abs Y
,
552 pragma Unreferenced
(Lemma_Rem_Is_Ident
);
554 procedure Lemma_Rem_Sign
(X
, Y
: Big_Integer
)
558 Post
=> Same_Sign
(X
rem Y
, X
);
559 pragma Unreferenced
(Lemma_Rem_Sign
);
561 procedure Lemma_Rev_Div_Definition
(A
, B
, Q
, R
: Big_Natural
)
564 Pre
=> A
= B
* Q
+ R
and then R
< B
,
565 Post
=> Q
= A
/ B
and then R
= A
rem B
;
567 procedure Lemma_Shift_Left
(X
: Double_Uns
; Shift
: Natural)
570 Pre
=> Shift
< Double_Size
571 and then Big
(X
) * Big_2xx
(Shift
) < Big_2xxDouble
,
572 Post
=> Big
(Shift_Left
(X
, Shift
)) = Big
(X
) * Big_2xx
(Shift
);
574 procedure Lemma_Shift_Right
(X
: Double_Uns
; Shift
: Natural)
577 Pre
=> Shift
< Double_Size
,
578 Post
=> Big
(Shift_Right
(X
, Shift
)) = Big
(X
) / Big_2xx
(Shift
);
580 procedure Lemma_Shift_Without_Drop
586 Pre
=> (Hi
(X
) and Mask
) = 0 -- X has the first Shift bits off
587 and then Shift
<= Single_Size
588 and then Mask
= Shift_Left
(Single_Uns
'Last, Single_Size
- Shift
)
589 and then Y
= Shift_Left
(X
, Shift
),
590 Post
=> Big
(Y
) = Big_2xx
(Shift
) * Big
(X
);
592 procedure Lemma_Simplify
(X
, Y
: Big_Integer
)
596 Post
=> X
* Y
/ Y
= X
;
598 procedure Lemma_Substitution
(A
, B
, C
, C1
, D
: Big_Integer
)
601 Pre
=> C
= C1
and then A
= B
* C
+ D
,
602 Post
=> A
= B
* C1
+ D
;
604 procedure Lemma_Subtract_Commutation
(X
, Y
: Double_Uns
)
608 Post
=> Big
(X
) - Big
(Y
) = Big
(X
- Y
);
610 procedure Lemma_Subtract_Double_Uns
(X
, Y
: Double_Int
)
613 Pre
=> X
>= 0 and then X
<= Y
,
614 Post
=> Double_Uns
(Y
- X
) = Double_Uns
(Y
) - Double_Uns
(X
);
616 procedure Lemma_Word_Commutation
(X
: Single_Uns
)
619 Post
=> Big_2xxSingle
* Big
(Double_Uns
(X
))
620 = Big
(2**Single_Size
* Double_Uns
(X
));
622 -----------------------------
623 -- Local lemma null bodies --
624 -----------------------------
626 procedure Inline_Le3
(X1
, X2
, X3
, Y1
, Y2
, Y3
: Single_Uns
) is null;
627 procedure Lemma_Abs_Commutation
(X
: Double_Int
) is null;
628 procedure Lemma_Abs_Mult_Commutation
(X
, Y
: Big_Integer
) is null;
629 procedure Lemma_Abs_Range
(X
: Big_Integer
) is null;
630 procedure Lemma_Add_Commutation
(X
: Double_Uns
; Y
: Single_Uns
) is null;
631 procedure Lemma_Add_One
(X
: Double_Uns
) is null;
632 procedure Lemma_Big_Of_Double_Uns
(X
: Double_Uns
) is null;
633 procedure Lemma_Big_Of_Double_Uns_Of_Single_Uns
(X
: Single_Uns
) is null;
634 procedure Lemma_Bounded_Powers_Of_2_Increasing
(M
, N
: Natural) is null;
635 procedure Lemma_Deep_Mult_Commutation
636 (Factor
: Big_Integer
;
639 procedure Lemma_Div_Commutation
(X
, Y
: Double_Uns
) is null;
640 procedure Lemma_Div_Definition
646 procedure Lemma_Div_Ge
(X
, Y
, Z
: Big_Integer
) is null;
647 procedure Lemma_Div_Lt
(X
, Y
, Z
: Big_Natural
) is null;
648 procedure Lemma_Double_Big_2xxSingle
is null;
649 procedure Lemma_Double_Shift
(X
: Double_Uns
; S
, S1
: Double_Uns
) is null;
650 procedure Lemma_Double_Shift
(X
: Single_Uns
; S
, S1
: Natural) is null;
651 procedure Lemma_Double_Shift_Left
(X
: Double_Uns
; S
, S1
: Double_Uns
)
653 procedure Lemma_Double_Shift_Right
(X
: Double_Uns
; S
, S1
: Double_Uns
)
655 procedure Lemma_Ge_Commutation
(A
, B
: Double_Uns
) is null;
656 procedure Lemma_Ge_Mult
(A
, B
, C
, D
: Big_Integer
) is null;
657 procedure Lemma_Gt_Commutation
(A
, B
: Double_Uns
) is null;
658 procedure Lemma_Gt_Mult
(A
, B
, C
, D
: Big_Integer
) is null;
659 procedure Lemma_Lo_Is_Ident
(X
: Double_Uns
) is null;
660 procedure Lemma_Lt_Commutation
(A
, B
: Double_Uns
) is null;
661 procedure Lemma_Lt_Mult
(A
, B
, C
, D
: Big_Integer
) is null;
662 procedure Lemma_Mult_Commutation
(X
, Y
: Single_Uns
) is null;
663 procedure Lemma_Mult_Commutation
(X
, Y
: Double_Int
) is null;
664 procedure Lemma_Mult_Commutation
(X
, Y
, Z
: Double_Uns
) is null;
665 procedure Lemma_Mult_Distribution
(X
, Y
, Z
: Big_Integer
) is null;
666 procedure Lemma_Mult_Non_Negative
(X
, Y
: Big_Integer
) is null;
667 procedure Lemma_Mult_Non_Positive
(X
, Y
: Big_Integer
) is null;
668 procedure Lemma_Mult_Positive
(X
, Y
: Big_Integer
) is null;
669 procedure Lemma_Neg_Rem
(X
, Y
: Big_Integer
) is null;
670 procedure Lemma_Not_In_Range_Big2xx64
is null;
671 procedure Lemma_Powers
(A
: Big_Natural
; B
, C
: Natural) is null;
672 procedure Lemma_Rem_Commutation
(X
, Y
: Double_Uns
) is null;
673 procedure Lemma_Rem_Is_Ident
(X
, Y
: Big_Integer
) is null;
674 procedure Lemma_Rem_Sign
(X
, Y
: Big_Integer
) is null;
675 procedure Lemma_Rev_Div_Definition
(A
, B
, Q
, R
: Big_Natural
) is null;
676 procedure Lemma_Simplify
(X
, Y
: Big_Integer
) is null;
677 procedure Lemma_Substitution
(A
, B
, C
, C1
, D
: Big_Integer
) is null;
678 procedure Lemma_Subtract_Commutation
(X
, Y
: Double_Uns
) is null;
679 procedure Lemma_Subtract_Double_Uns
(X
, Y
: Double_Int
) is null;
680 procedure Lemma_Word_Commutation
(X
: Single_Uns
) is null;
682 --------------------------
683 -- Add_With_Ovflo_Check --
684 --------------------------
686 function Add_With_Ovflo_Check
(X
, Y
: Double_Int
) return Double_Int
is
687 R
: constant Double_Int
:= To_Int
(To_Uns
(X
) + To_Uns
(Y
));
691 procedure Prove_Negative_X
694 Pre
=> X
< 0 and then (Y
> 0 or else R
< 0),
697 procedure Prove_Non_Negative_X
700 Pre
=> X
>= 0 and then (Y
< 0 or else R
>= 0),
703 procedure Prove_Overflow_Case
707 (if X
>= 0 then Y
>= 0 and then R
< 0
708 else Y
<= 0 and then R
>= 0),
709 Post
=> not In_Double_Int_Range
(Big
(X
) + Big
(Y
));
711 ----------------------
712 -- Prove_Negative_X --
713 ----------------------
715 procedure Prove_Negative_X
is
717 if X
= Double_Int
'First then
722 (To_Uns
(X
) + To_Uns
(Y
) =
723 2 ** (Double_Size
- 1) - Double_Uns
(-Y
));
724 pragma Assert
-- as R < 0
725 (To_Uns
(X
) + To_Uns
(Y
) >= 2 ** (Double_Size
- 1));
726 pragma Assert
(Y
= 0);
729 elsif Y
= Double_Int
'First then
731 (To_Uns
(X
) + To_Uns
(Y
) =
732 2 ** (Double_Size
- 1) - Double_Uns
(-X
));
733 pragma Assert
(False);
737 (To_Uns
(X
) + To_Uns
(Y
) = -Double_Uns
(-X
) - Double_Uns
(-Y
));
739 else -- Y > 0, 0 > X > Double_Int'First
741 Ru
: constant Double_Uns
:= To_Uns
(X
) + To_Uns
(Y
);
743 pragma Assert
(Ru
= -Double_Uns
(-X
) + Double_Uns
(Y
));
744 if Ru
< 2 ** (Double_Size
- 1) then -- R >= 0
745 Lemma_Subtract_Double_Uns
(-X
, Y
);
746 pragma Assert
(Ru
= Double_Uns
(X
+ Y
));
748 elsif Ru
= 2 ** (Double_Size
- 1) then
749 pragma Assert
(Double_Uns
(Y
) < 2 ** (Double_Size
- 1));
750 pragma Assert
(Double_Uns
(-X
) < 2 ** (Double_Size
- 1));
751 pragma Assert
(False);
755 (R
= -Double_Int
(-(-Double_Uns
(-X
) + Double_Uns
(Y
))));
757 (R
= -Double_Int
(-Double_Uns
(Y
) + Double_Uns
(-X
)));
761 end Prove_Negative_X
;
763 --------------------------
764 -- Prove_Non_Negative_X --
765 --------------------------
767 procedure Prove_Non_Negative_X
is
769 if Y
>= 0 or else Y
= Double_Int
'First then
773 (To_Uns
(X
) + To_Uns
(Y
) = Double_Uns
(X
) - Double_Uns
(-Y
));
775 end Prove_Non_Negative_X
;
777 -------------------------
778 -- Prove_Overflow_Case --
779 -------------------------
781 procedure Prove_Overflow_Case
is
783 if X
< 0 and then X
/= Double_Int
'First and then Y
/= Double_Int
'First
786 (To_Uns
(X
) + To_Uns
(Y
) = -Double_Uns
(-X
) - Double_Uns
(-Y
));
788 end Prove_Overflow_Case
;
790 -- Start of processing for Add_With_Ovflo_Check
794 if Y
< 0 or else R
>= 0 then
795 Prove_Non_Negative_X
;
800 if Y
> 0 or else R
< 0 then
808 end Add_With_Ovflo_Check
;
814 procedure Double_Divide
815 (X
, Y
, Z
: Double_Int
;
816 Q
, R
: out Double_Int
;
819 Xu
: constant Double_Uns
:= abs X
;
820 Yu
: constant Double_Uns
:= abs Y
;
822 Yhi
: constant Single_Uns
:= Hi
(Yu
);
823 Ylo
: constant Single_Uns
:= Lo
(Yu
);
825 Zu
: constant Double_Uns
:= abs Z
;
826 Zhi
: constant Single_Uns
:= Hi
(Zu
);
827 Zlo
: constant Single_Uns
:= Lo
(Zu
);
830 Du
, Qu
, Ru
: Double_Uns
;
831 Den_Pos
: constant Boolean := (Y
< 0) = (Z
< 0);
833 -- Local ghost variables
835 Mult
: constant Big_Integer
:= abs (Big
(Y
) * Big
(Z
)) with Ghost
;
836 Quot
: Big_Integer
with Ghost
;
837 Big_R
: Big_Integer
with Ghost
;
838 Big_Q
: Big_Integer
with Ghost
;
842 procedure Prove_Overflow_Case
845 Pre
=> X
= Double_Int
'First and then Big
(Y
) * Big
(Z
) = -1,
846 Post
=> not In_Double_Int_Range
(Big
(X
) / (Big
(Y
) * Big
(Z
)))
847 and then not In_Double_Int_Range
848 (Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
),
849 Big
(X
) / (Big
(Y
) * Big
(Z
)),
850 Big
(X
) rem (Big
(Y
) * Big
(Z
))));
851 -- Proves the special case where -2**(Double_Size - 1) is divided by -1,
852 -- generating an overflow.
854 procedure Prove_Quotient_Zero
857 Pre
=> Mult
>= Big_2xxDouble
859 not (Mult
= Big_2xxDouble
860 and then X
= Double_Int
'First
864 Post
=> Big
(R
) = Big
(X
) rem (Big
(Y
) * Big
(Z
))
867 Big
(Q
) = Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
),
868 Big
(X
) / (Big
(Y
) * Big
(Z
)),
870 else Big
(Q
) = Big
(X
) / (Big
(Y
) * Big
(Z
)));
871 -- Proves the general case where divisor doesn't fit in Double_Uns and
874 procedure Prove_Round_To_One
877 Pre
=> Mult
= Big_2xxDouble
878 and then X
= Double_Int
'First
879 and then Q
= (if Den_Pos
then -1 else 1)
882 Post
=> Big
(R
) = Big
(X
) rem (Big
(Y
) * Big
(Z
))
883 and then Big
(Q
) = Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
),
884 Big
(X
) / (Big
(Y
) * Big
(Z
)),
886 -- Proves the special case where the divisor doesn't fit in Double_Uns
887 -- but quotient is still 1 or -1 due to rounding
888 -- (abs (Y*Z) = 2**Double_Size and X = -2**(Double_Size - 1) and Round).
890 procedure Prove_Rounding_Case
894 and then Quot
= Big
(X
) / (Big
(Y
) * Big
(Z
))
895 and then Big_R
= Big
(X
) rem (Big
(Y
) * Big
(Z
))
897 Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
), Quot
, Big_R
)
898 and then Big
(Ru
) = abs Big_R
899 and then Big
(Du
) = Mult
901 (if Ru
> (Du
- Double_Uns
'(1)) / Double_Uns'(2)
904 Post
=> abs Big_Q
= Big
(Qu
);
905 -- Proves correctness of the rounding of the unsigned quotient
907 procedure Prove_Sign_Quotient
911 and then Quot
= Big
(X
) / (Big
(Y
) * Big
(Z
))
912 and then Big_R
= Big
(X
) rem (Big
(Y
) * Big
(Z
))
915 Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
), Quot
, Big_R
)
919 (if Den_Pos
then Big_Q
>= 0 else Big_Q
<= 0)
921 (if Den_Pos
then Big_Q
<= 0 else Big_Q
>= 0));
922 -- Proves the correct sign of the signed quotient Big_Q
924 procedure Prove_Signs
928 and then Quot
= Big
(X
) / (Big
(Y
) * Big
(Z
))
929 and then Big_R
= Big
(X
) rem (Big
(Y
) * Big
(Z
))
932 Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
), Quot
, Big_R
)
934 and then Big
(Ru
) = abs Big_R
935 and then Big
(Qu
) = abs Big_Q
936 and then R
= (if X
>= 0 then To_Int
(Ru
) else To_Int
(-Ru
))
938 Q
= (if (X
>= 0) = Den_Pos
then To_Int
(Qu
) else To_Int
(-Qu
))
939 and then not (X
= Double_Int
'First and then Big
(Y
) * Big
(Z
) = -1),
940 Post
=> Big
(R
) = Big
(X
) rem (Big
(Y
) * Big
(Z
))
943 Big
(Q
) = Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
),
944 Big
(X
) / (Big
(Y
) * Big
(Z
)),
946 else Big
(Q
) = Big
(X
) / (Big
(Y
) * Big
(Z
)));
947 -- Proves final signs match the intended result after the unsigned
950 -----------------------------
951 -- Local lemma null bodies --
952 -----------------------------
954 procedure Prove_Overflow_Case
is null;
955 procedure Prove_Quotient_Zero
is null;
956 procedure Prove_Round_To_One
is null;
957 procedure Prove_Sign_Quotient
is null;
959 -------------------------
960 -- Prove_Rounding_Case --
961 -------------------------
963 procedure Prove_Rounding_Case
is
965 if Same_Sign
(Big
(X
), Big
(Y
) * Big
(Z
)) then
968 end Prove_Rounding_Case
;
974 procedure Prove_Signs
is
976 if (X
>= 0) = Den_Pos
then
977 pragma Assert
(Quot
>= 0);
978 pragma Assert
(Big_Q
>= 0);
979 pragma Assert
(Q
>= 0);
980 pragma Assert
(Big
(Q
) = Big_Q
);
982 pragma Assert
((X
>= 0) /= (Big
(Y
) * Big
(Z
) >= 0));
983 pragma Assert
(Quot
<= 0);
984 pragma Assert
(Big_Q
<= 0);
985 pragma Assert
(if X
>= 0 then R
>= 0);
986 pragma Assert
(if X
< 0 then R
<= 0);
987 pragma Assert
(Big
(R
) = Big_R
);
991 -- Start of processing for Double_Divide
994 if Yu
= 0 or else Zu
= 0 then
998 pragma Assert
(Mult
/= 0);
999 pragma Assert
(Den_Pos
= (Big
(Y
) * Big
(Z
) > 0));
1000 Quot
:= Big
(X
) / (Big
(Y
) * Big
(Z
));
1001 Big_R
:= Big
(X
) rem (Big
(Y
) * Big
(Z
));
1003 Big_Q
:= Round_Quotient
(Big
(X
), Big
(Y
) * Big
(Z
), Quot
, Big_R
);
1007 Lemma_Abs_Mult_Commutation
(Big
(Y
), Big
(Z
));
1008 Lemma_Mult_Decomposition
(Mult
, Yu
, Zu
, Yhi
, Ylo
, Zhi
, Zlo
);
1010 -- Compute Y * Z. Note that if the result overflows Double_Uns, then
1011 -- the rounded result is zero, except for the very special case where
1012 -- X = -2 ** (Double_Size - 1) and abs (Y * Z) = 2 ** Double_Size, when
1019 -- Handle the special case when Round is True
1025 and then X
= Double_Int
'First
1028 Q
:= (if Den_Pos
then -1 else 1);
1035 pragma Assert
(Double_Uns
'(Yhi * Zhi) >= Double_Uns (Yhi));
1036 pragma Assert (Double_Uns'(Yhi
* Zhi
) >= Double_Uns
(Zhi
));
1037 pragma Assert
(Big
(Double_Uns
'(Yhi * Zhi)) >= 1);
1038 if Yhi > 1 or else Zhi > 1 then
1039 pragma Assert (Big (Double_Uns'(Yhi
* Zhi
)) > 1);
1040 pragma Assert
(if X
= Double_Int
'First and then Round
then
1041 Mult
> Big_2xxDouble
);
1043 pragma Assert
(Big
(Double_Uns
'(Yhi * Zlo)) > 0);
1044 pragma Assert (if X = Double_Int'First and then Round then
1045 Mult > Big_2xxDouble);
1047 pragma Assert (Double_Uns'(Ylo
* Zhi
) > 0);
1048 pragma Assert
(Big
(Double_Uns
'(Ylo * Zhi)) > 0);
1049 pragma Assert (if X = Double_Int'First and then Round then
1050 Mult > Big_2xxDouble);
1052 pragma Assert (not (X = Double_Int'First and then Round));
1054 Prove_Quotient_Zero;
1060 pragma Assert (Big (T2) = Big (Double_Uns'(Yhi
* Zlo
)));
1061 pragma Assert
(Big_0
= Big
(Double_Uns
'(Ylo * Zhi)));
1066 pragma Assert (Big (T2) = Big (Double_Uns'(Ylo
* Zhi
)));
1067 pragma Assert
(Big_0
= Big
(Double_Uns
'(Yhi * Zlo)));
1072 pragma Assert (Big (T2) = Big (Double_Uns'(Yhi
* Zlo
))
1073 + Big
(Double_Uns
'(Ylo * Zhi)));
1074 Lemma_Mult_Distribution (Big_2xxSingle,
1075 Big (Double_Uns'(Yhi
* Zlo
)),
1076 Big
(Double_Uns
'(Ylo * Zhi)));
1077 pragma Assert (Mult = Big_2xxSingle * Big (T2) + Big (T1));
1078 Lemma_Hi_Lo (T1, Hi (T1), Lo (T1));
1080 (Mult = Big_2xxSingle * Big (T2)
1081 + Big_2xxSingle * Big (Double_Uns (Hi (T1)))
1082 + Big (Double_Uns (Lo (T1))));
1083 Lemma_Mult_Distribution (Big_2xxSingle,
1085 Big (Double_Uns (Hi (T1))));
1086 Lemma_Add_Commutation (T2, Hi (T1));
1091 (Mult = Big_2xxSingle * Big (T2) + Big (Double_Uns (Lo (T1))));
1092 Lemma_Hi_Lo (T2, Hi (T2), Lo (T2));
1093 Lemma_Mult_Distribution (Big_2xxSingle,
1094 Big (Double_Uns (Hi (T2))),
1095 Big (Double_Uns (Lo (T2))));
1096 Lemma_Double_Big_2xxSingle;
1098 (Mult = Big_2xxDouble * Big (Double_Uns (Hi (T2)))
1099 + Big_2xxSingle * Big (Double_Uns (Lo (T2)))
1100 + Big (Double_Uns (Lo (T1))));
1102 if Hi (T2) /= 0 then
1105 -- Handle the special case when Round is True
1108 and then Lo (T2) = 0
1109 and then Lo (T1) = 0
1110 and then X = Double_Int'First
1113 Q := (if Den_Pos then -1 else 1);
1120 pragma Assert (Big (Double_Uns (Hi (T2))) >= 1);
1121 pragma Assert (Big (Double_Uns (Lo (T2))) >= 0);
1122 pragma Assert (Big (Double_Uns (Lo (T1))) >= 0);
1123 pragma Assert (Big_2xxSingle * Big (Double_Uns (Lo (T2)))
1124 + Big (Double_Uns (Lo (T1))) >= 0);
1125 pragma Assert (Mult >= Big_2xxDouble * Big (Double_Uns (Hi (T2))));
1126 pragma Assert (Mult >= Big_2xxDouble);
1128 pragma Assert (Big (Double_Uns (Hi (T2))) > 1);
1129 pragma Assert (if X = Double_Int'First and then Round then
1130 Mult > Big_2xxDouble);
1131 elsif Lo (T2) > 0 then
1132 pragma Assert (Big (Double_Uns (Lo (T2))) > 0);
1133 pragma Assert (Big_2xxSingle > 0);
1134 pragma Assert (Big_2xxSingle * Big (Double_Uns (Lo (T2))) > 0);
1135 pragma Assert (Big_2xxSingle * Big (Double_Uns (Lo (T2)))
1136 + Big (Double_Uns (Lo (T1))) > 0);
1137 pragma Assert (if X = Double_Int'First and then Round then
1138 Mult > Big_2xxDouble);
1139 elsif Lo (T1) > 0 then
1140 pragma Assert (Double_Uns (Lo (T1)) > 0);
1141 Lemma_Gt_Commutation (Double_Uns (Lo (T1)), 0);
1142 pragma Assert (Big (Double_Uns (Lo (T1))) > 0);
1143 pragma Assert (if X = Double_Int'First and then Round then
1144 Mult > Big_2xxDouble);
1146 pragma Assert (not (X = Double_Int'First and then Round));
1148 Prove_Quotient_Zero;
1154 Du := Lo (T2) & Lo (T1);
1156 Lemma_Hi_Lo (Du, Lo (T2), Lo (T1));
1157 pragma Assert (Mult = Big (Du));
1158 pragma Assert (Du /= 0);
1159 -- Multiplication of 2-limb arguments Yu and Zu leads to 4-limb result
1160 -- (where each limb is a single value). Cases where 4 limbs are needed
1161 -- require Yhi /= 0 and Zhi /= 0 and lead to early exit. Remaining cases
1162 -- where 3 limbs are needed correspond to Hi(T2) /= 0 and lead to early
1163 -- exit. Thus, at this point, the result fits in 2 limbs which are
1164 -- exactly Lo (T2) and Lo (T1), which corresponds to the value of Du.
1165 -- As the case where one of Yu or Zu is null also led to early exit,
1166 -- we have Du /= 0 here.
1168 -- Check overflow case of largest negative number divided by -1
1170 if X = Double_Int'First and then Du = 1 and then not Den_Pos then
1171 Prove_Overflow_Case;
1175 -- Perform the actual division
1177 pragma Assert (Du /= 0);
1178 -- Multiplication of 2-limb arguments Yu and Zu leads to 4-limb result
1179 -- (where each limb is a single value). Cases where 4 limbs are needed
1180 -- require Yhi/=0 and Zhi/=0 and lead to early exit. Remaining cases
1181 -- where 3 limbs are needed correspond to Hi(T2)/=0 and lead to early
1182 -- exit. Thus, at this point, the result fits in 2 limbs which are
1183 -- exactly Lo(T2) and Lo(T1), which corresponds to the value of Du.
1184 -- As the case where one of Yu or Zu is null also led to early exit,
1185 -- we have Du/=0 here.
1190 Lemma_Div_Commutation (Xu, Du);
1191 Lemma_Abs_Div_Commutation (Big (X), Big (Y) * Big (Z));
1192 Lemma_Abs_Commutation (X);
1193 pragma Assert (abs Quot = Big (Qu));
1194 Lemma_Rem_Commutation (Xu, Du);
1195 Lemma_Abs_Rem_Commutation (Big (X), Big (Y) * Big (Z));
1196 pragma Assert (abs Big_R = Big (Ru));
1198 -- Deal with rounding case
1201 if Ru > (Du - Double_Uns'(1)) / Double_Uns
'(2) then
1202 Lemma_Add_Commutation (Qu, 1);
1204 Qu := Qu + Double_Uns'(1);
1207 Prove_Rounding_Case
;
1210 pragma Assert
(abs Big_Q
= Big
(Qu
));
1211 Prove_Sign_Quotient
;
1213 -- Set final signs (RM 4.5.5(27-30))
1215 -- Case of dividend (X) sign positive
1219 Q
:= (if Den_Pos
then To_Int
(Qu
) else To_Int
(-Qu
));
1221 -- We perform the unary minus operation on the unsigned value
1222 -- before conversion to signed, to avoid a possible overflow
1223 -- for value -2 ** (Double_Size - 1), both for computing R and Q.
1225 -- Case of dividend (X) sign negative
1229 Q
:= (if Den_Pos
then To_Int
(-Qu
) else To_Int
(Qu
));
1239 function Le3
(X1
, X2
, X3
, Y1
, Y2
, Y3
: Single_Uns
) return Boolean is
1254 -------------------------------
1255 -- Lemma_Abs_Div_Commutation --
1256 -------------------------------
1258 procedure Lemma_Abs_Div_Commutation
(X
, Y
: Big_Integer
) is
1262 pragma Assert
(abs (X
/ Y
) = abs (X
/ (-Y
)));
1264 Lemma_Neg_Div
(X
, Y
);
1265 pragma Assert
(abs (X
/ Y
) = abs ((-X
) / (-Y
)));
1268 end Lemma_Abs_Div_Commutation
;
1270 -------------------------------
1271 -- Lemma_Abs_Rem_Commutation --
1272 -------------------------------
1274 procedure Lemma_Abs_Rem_Commutation
(X
, Y
: Big_Integer
) is
1277 Lemma_Neg_Rem
(X
, Y
);
1279 pragma Assert
(X
rem Y
= -((-X
) rem (-Y
)));
1280 pragma Assert
(abs (X
rem Y
) = (abs X
) rem (abs Y
));
1282 pragma Assert
(abs (X
rem Y
) = (abs X
) rem (abs Y
));
1285 end Lemma_Abs_Rem_Commutation
;
1287 -----------------------------
1288 -- Lemma_Concat_Definition --
1289 -----------------------------
1291 procedure Lemma_Concat_Definition
(X
, Y
: Single_Uns
) is
1292 Hi
: constant Double_Uns
:= Shift_Left
(Double_Uns
(X
), Single_Size
);
1293 Lo
: constant Double_Uns
:= Double_Uns
(Y
);
1295 pragma Assert
(Hi
= Double_Uns
'(2 ** Single_Size) * Double_Uns (X));
1296 pragma Assert ((Hi or Lo) = Hi + Lo);
1297 end Lemma_Concat_Definition;
1303 procedure Lemma_Div_Eq (A, B, S, R : Big_Integer) is
1305 pragma Assert ((A - B) * S = R);
1306 pragma Assert ((A - B) * S / S = R / S);
1307 Lemma_Mult_Div (A - B, S);
1308 pragma Assert (A - B = R / S);
1311 ------------------------
1312 -- Lemma_Double_Shift --
1313 ------------------------
1315 procedure Lemma_Double_Shift (X : Double_Uns; S, S1 : Natural) is
1317 Lemma_Double_Shift (X, Double_Uns (S), Double_Uns (S1));
1318 pragma Assert (Shift_Left (Shift_Left (X, S), S1)
1319 = Shift_Left (Shift_Left (X, S), Natural (Double_Uns (S1))));
1320 pragma Assert (Shift_Left (X, S + S1)
1321 = Shift_Left (X, Natural (Double_Uns (S + S1))));
1322 end Lemma_Double_Shift;
1324 -----------------------------
1325 -- Lemma_Double_Shift_Left --
1326 -----------------------------
1328 procedure Lemma_Double_Shift_Left (X : Double_Uns; S, S1 : Natural) is
1330 Lemma_Double_Shift_Left (X, Double_Uns (S), Double_Uns (S1));
1331 pragma Assert (Shift_Left (Shift_Left (X, S), S1)
1332 = Shift_Left (Shift_Left (X, S), Natural (Double_Uns (S1))));
1333 pragma Assert (Shift_Left (X, S + S1)
1334 = Shift_Left (X, Natural (Double_Uns (S + S1))));
1335 end Lemma_Double_Shift_Left;
1337 ------------------------------
1338 -- Lemma_Double_Shift_Right --
1339 ------------------------------
1341 procedure Lemma_Double_Shift_Right (X : Double_Uns; S, S1 : Natural) is
1343 Lemma_Double_Shift_Right (X, Double_Uns (S), Double_Uns (S1));
1344 pragma Assert (Shift_Right (Shift_Right (X, S), S1)
1345 = Shift_Right (Shift_Right (X, S), Natural (Double_Uns (S1))));
1346 pragma Assert (Shift_Right (X, S + S1)
1347 = Shift_Right (X, Natural (Double_Uns (S + S1))));
1348 end Lemma_Double_Shift_Right;
1354 procedure Lemma_Hi_Lo (Xu : Double_Uns; Xhi, Xlo : Single_Uns) is
1356 pragma Assert (Double_Uns (Xhi) = Xu / Double_Uns'(2 ** Single_Size
));
1357 pragma Assert
(Double_Uns
(Xlo
) = Xu
mod 2 ** Single_Size
);
1364 procedure Lemma_Hi_Lo_3
(Xu
: Double_Uns
; Xhi
, Xlo
: Single_Uns
) is
1366 Lemma_Hi_Lo
(Xu
, Xhi
, Xlo
);
1369 ------------------------------
1370 -- Lemma_Mult_Decomposition --
1371 ------------------------------
1373 procedure Lemma_Mult_Decomposition
1374 (Mult
: Big_Integer
;
1375 Xu
, Yu
: Double_Uns
;
1376 Xhi
, Xlo
, Yhi
, Ylo
: Single_Uns
)
1379 Lemma_Hi_Lo
(Xu
, Xhi
, Xlo
);
1380 Lemma_Hi_Lo
(Yu
, Yhi
, Ylo
);
1384 (Big_2xxSingle
* Big
(Double_Uns
(Xhi
)) + Big
(Double_Uns
(Xlo
))) *
1385 (Big_2xxSingle
* Big
(Double_Uns
(Yhi
)) + Big
(Double_Uns
(Ylo
))));
1386 pragma Assert
(Mult
=
1388 * Big_2xxSingle
* Big
(Double_Uns
(Xhi
)) * Big
(Double_Uns
(Yhi
))
1389 + Big_2xxSingle
* Big
(Double_Uns
(Xhi
)) * Big
(Double_Uns
(Ylo
))
1390 + Big_2xxSingle
* Big
(Double_Uns
(Xlo
)) * Big
(Double_Uns
(Yhi
))
1391 + Big
(Double_Uns
(Xlo
)) * Big
(Double_Uns
(Ylo
)));
1392 Lemma_Deep_Mult_Commutation
(Big_2xxSingle
* Big_2xxSingle
, Xhi
, Yhi
);
1393 Lemma_Deep_Mult_Commutation
(Big_2xxSingle
, Xhi
, Ylo
);
1394 Lemma_Deep_Mult_Commutation
(Big_2xxSingle
, Xlo
, Yhi
);
1395 Lemma_Mult_Commutation
(Xlo
, Ylo
);
1396 pragma Assert
(Mult
=
1397 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
'(Xhi * Yhi))
1398 + Big_2xxSingle * Big (Double_Uns'(Xhi
* Ylo
))
1399 + Big_2xxSingle
* Big
(Double_Uns
'(Xlo * Yhi))
1400 + Big (Double_Uns'(Xlo
* Ylo
)));
1401 end Lemma_Mult_Decomposition
;
1403 --------------------
1404 -- Lemma_Mult_Div --
1405 --------------------
1407 procedure Lemma_Mult_Div
(A
, B
: Big_Integer
) is
1410 pragma Assert
(A
* B
/ B
= A
);
1412 pragma Assert
(A
* (-B
) / (-B
) = A
);
1420 procedure Lemma_Neg_Div
(X
, Y
: Big_Integer
) is
1422 pragma Assert
((-X
) / (-Y
) = -(X
/ (-Y
)));
1423 pragma Assert
(X
/ (-Y
) = -(X
/ Y
));
1426 -----------------------
1427 -- Lemma_Powers_Of_2 --
1428 -----------------------
1430 procedure Lemma_Powers_Of_2
(M
, N
: Natural) is
1432 if M
+ N
< Double_Size
then
1433 pragma Assert
(Double_Uns
'(2**M) * Double_Uns'(2**N
)
1434 = Double_Uns
'(2**(M + N)));
1437 Lemma_Powers_Of_2_Commutation (M);
1438 Lemma_Powers_Of_2_Commutation (N);
1439 Lemma_Powers_Of_2_Commutation (M + N);
1440 Lemma_Powers (Big (Double_Uns'(2)), M
, N
);
1442 if M
+ N
< Double_Size
then
1443 pragma Assert
(Big
(Double_Uns
'(2))**M * Big (Double_Uns'(2))**N
1444 = Big
(Double_Uns
'(2))**(M + N));
1445 Lemma_Powers_Of_2_Increasing (M + N, Double_Size);
1446 Lemma_Mult_Commutation (2 ** M, 2 ** N, 2 ** (M + N));
1448 pragma Assert (Big (Double_Uns'(2))**M
* Big
(Double_Uns
'(2))**N
1449 = Big (Double_Uns'(2))**(M
+ N
));
1451 end Lemma_Powers_Of_2
;
1453 -----------------------------------
1454 -- Lemma_Powers_Of_2_Commutation --
1455 -----------------------------------
1457 procedure Lemma_Powers_Of_2_Commutation
(M
: Natural) is
1460 Lemma_Powers_Of_2_Commutation
(M
- 1);
1461 pragma Assert
(Big
(Double_Uns
'(2))**(M - 1) = Big_2xx (M - 1));
1462 pragma Assert (Big (Double_Uns'(2))**M
= Big_2xx
(M
- 1) * 2);
1463 if M
< Double_Size
then
1464 Lemma_Powers_Of_2_Increasing
(M
- 1, Double_Size
- 1);
1465 Lemma_Bounded_Powers_Of_2_Increasing
(M
- 1, Double_Size
- 1);
1466 pragma Assert
(Double_Uns
'(2 ** (M - 1)) * 2 = Double_Uns'(2**M
));
1467 Lemma_Mult_Commutation
1468 (Double_Uns
'(2 ** (M - 1)), 2, Double_Uns'(2**M
));
1469 pragma Assert
(Big
(Double_Uns
'(2))**M = Big_2xx (M));
1472 end Lemma_Powers_Of_2_Commutation;
1474 ----------------------------------
1475 -- Lemma_Powers_Of_2_Increasing --
1476 ----------------------------------
1478 procedure Lemma_Powers_Of_2_Increasing (M, N : Natural) is
1481 Lemma_Powers_Of_2_Increasing (M + 1, N);
1483 end Lemma_Powers_Of_2_Increasing;
1489 procedure Lemma_Rem_Abs (X, Y : Big_Integer) is
1491 Lemma_Neg_Rem (X, Y);
1494 ----------------------
1495 -- Lemma_Shift_Left --
1496 ----------------------
1498 procedure Lemma_Shift_Left (X : Double_Uns; Shift : Natural) is
1500 procedure Lemma_Mult_Pow2 (X : Double_Uns; I : Natural)
1503 Pre => I < Double_Size - 1,
1504 Post => X * Double_Uns'(2) ** I
* Double_Uns
'(2)
1505 = X * Double_Uns'(2) ** (I
+ 1);
1507 procedure Lemma_Mult_Pow2
(X
: Double_Uns
; I
: Natural) is
1508 Mul1
: constant Double_Uns
:= Double_Uns
'(2) ** I;
1509 Mul2 : constant Double_Uns := Double_Uns'(2);
1510 Left
: constant Double_Uns
:= X
* Mul1
* Mul2
;
1512 pragma Assert
(Left
= X
* (Mul1
* Mul2
));
1513 pragma Assert
(Mul1
* Mul2
= Double_Uns
'(2) ** (I + 1));
1514 end Lemma_Mult_Pow2;
1516 XX : Double_Uns := X;
1519 for J in 1 .. Shift loop
1521 Cur_XX : constant Double_Uns := XX;
1523 XX := Shift_Left (XX, 1);
1524 pragma Assert (XX = Cur_XX * Double_Uns'(2));
1525 Lemma_Mult_Pow2
(X
, J
- 1);
1527 Lemma_Double_Shift_Left
(X
, J
- 1, 1);
1528 pragma Loop_Invariant
(XX
= Shift_Left
(X
, J
));
1529 pragma Loop_Invariant
(XX
= X
* Double_Uns
'(2) ** J);
1531 end Lemma_Shift_Left;
1533 -----------------------
1534 -- Lemma_Shift_Right --
1535 -----------------------
1537 procedure Lemma_Shift_Right (X : Double_Uns; Shift : Natural) is
1539 procedure Lemma_Div_Pow2 (X : Double_Uns; I : Natural)
1542 Pre => I < Double_Size - 1,
1543 Post => X / Double_Uns'(2) ** I
/ Double_Uns
'(2)
1544 = X / Double_Uns'(2) ** (I
+ 1);
1546 procedure Lemma_Div_Pow2
(X
: Double_Uns
; I
: Natural) is
1547 Div1
: constant Double_Uns
:= Double_Uns
'(2) ** I;
1548 Div2 : constant Double_Uns := Double_Uns'(2);
1549 Left
: constant Double_Uns
:= X
/ Div1
/ Div2
;
1551 pragma Assert
(Left
= X
/ (Div1
* Div2
));
1552 pragma Assert
(Div1
* Div2
= Double_Uns
'(2) ** (I + 1));
1555 XX : Double_Uns := X;
1558 for J in 1 .. Shift loop
1560 Cur_XX : constant Double_Uns := XX;
1562 XX := Shift_Right (XX, 1);
1563 pragma Assert (XX = Cur_XX / Double_Uns'(2));
1564 Lemma_Div_Pow2
(X
, J
- 1);
1566 Lemma_Double_Shift_Right
(X
, J
- 1, 1);
1567 pragma Loop_Invariant
(XX
= Shift_Right
(X
, J
));
1568 pragma Loop_Invariant
(XX
= X
/ Double_Uns
'(2) ** J);
1570 end Lemma_Shift_Right;
1572 ------------------------------
1573 -- Lemma_Shift_Without_Drop --
1574 ------------------------------
1576 procedure Lemma_Shift_Without_Drop
1581 pragma Unreferenced (Mask);
1583 procedure Lemma_Bound
1585 Pre => Shift <= Single_Size
1586 and then X <= 2**Single_Size
1587 * Double_Uns'(2**(Single_Size
- Shift
) - 1)
1588 + Single_Uns
'(2**Single_Size - 1),
1589 Post => X <= 2**(Double_Size - Shift) - 1;
1591 procedure Lemma_Exp_Pos (N : Integer)
1593 Pre => N in 0 .. Double_Size - 1,
1594 Post => Double_Uns'(2**N
) > 0;
1596 -----------------------------
1597 -- Local lemma null bodies --
1598 -----------------------------
1600 procedure Lemma_Bound
is null;
1601 procedure Lemma_Exp_Pos
(N
: Integer) is null;
1603 -- Start of processing for Lemma_Shift_Without_Drop
1607 pragma Assert
(Big
(Y
) = Big_2xx
(Shift
) * Big
(X
));
1612 Lemma_Exp_Pos
(Double_Size
- Shift
);
1613 pragma Assert
(X
< 2**(Double_Size
- Shift
));
1614 pragma Assert
(Big
(X
) < Big_2xx
(Double_Size
- Shift
));
1615 pragma Assert
(Y
= 2**Shift
* X
);
1616 Lemma_Lt_Mult
(Big
(X
), Big_2xx
(Double_Size
- Shift
), Big_2xx
(Shift
),
1617 Big_2xx
(Shift
) * Big_2xx
(Double_Size
- Shift
));
1618 pragma Assert
(Big_2xx
(Shift
) * Big
(X
)
1619 < Big_2xx
(Shift
) * Big_2xx
(Double_Size
- Shift
));
1620 Lemma_Powers_Of_2
(Shift
, Double_Size
- Shift
);
1621 Lemma_Mult_Commutation
(2**Shift
, X
, Y
);
1622 pragma Assert
(Big
(Y
) = Big_2xx
(Shift
) * Big
(X
));
1623 end Lemma_Shift_Without_Drop
;
1625 -------------------------------
1626 -- Multiply_With_Ovflo_Check --
1627 -------------------------------
1629 function Multiply_With_Ovflo_Check
(X
, Y
: Double_Int
) return Double_Int
is
1630 Xu
: constant Double_Uns
:= abs X
;
1631 Xhi
: constant Single_Uns
:= Hi
(Xu
);
1632 Xlo
: constant Single_Uns
:= Lo
(Xu
);
1634 Yu
: constant Double_Uns
:= abs Y
;
1635 Yhi
: constant Single_Uns
:= Hi
(Yu
);
1636 Ylo
: constant Single_Uns
:= Lo
(Yu
);
1638 T1
, T2
: Double_Uns
;
1640 -- Local ghost variables
1642 Mult
: constant Big_Integer
:= abs (Big
(X
) * Big
(Y
)) with Ghost
;
1646 procedure Prove_Both_Too_Large
1652 Big_2xxSingle
* Big_2xxSingle
* (Big
(Double_Uns
'(Xhi * Yhi)))
1653 + Big_2xxSingle * (Big (Double_Uns'(Xhi
* Ylo
)))
1654 + Big_2xxSingle
* (Big
(Double_Uns
'(Xlo * Yhi)))
1655 + (Big (Double_Uns'(Xlo
* Ylo
))),
1656 Post
=> not In_Double_Int_Range
(Big
(X
) * Big
(Y
));
1658 procedure Prove_Final_Decomposition
1661 Pre
=> In_Double_Int_Range
(Big
(X
) * Big
(Y
))
1662 and then Mult
= Big_2xxSingle
* Big
(T2
) + Big
(Double_Uns
(Lo
(T1
)))
1663 and then Hi
(T2
) = 0,
1664 Post
=> Mult
= Big
(Lo
(T2
) & Lo
(T1
));
1666 procedure Prove_Neg_Int
1669 Pre
=> In_Double_Int_Range
(Big
(X
) * Big
(Y
))
1670 and then Mult
= Big
(T2
)
1671 and then ((X
>= 0 and then Y
< 0) or else (X
< 0 and then Y
>= 0)),
1672 Post
=> To_Neg_Int
(T2
) = X
* Y
;
1674 procedure Prove_Pos_Int
1677 Pre
=> In_Double_Int_Range
(Big
(X
) * Big
(Y
))
1678 and then Mult
= Big
(T2
)
1679 and then ((X
>= 0 and then Y
>= 0) or else (X
< 0 and then Y
< 0)),
1680 Post
=> In_Double_Int_Range
(Big
(T2
))
1681 and then To_Pos_Int
(T2
) = X
* Y
;
1683 procedure Prove_Result_Too_Large
1686 Pre
=> Mult
= Big_2xxSingle
* Big
(T2
) + Big
(Double_Uns
(Lo
(T1
)))
1687 and then Hi
(T2
) /= 0,
1688 Post
=> not In_Double_Int_Range
(Big
(X
) * Big
(Y
));
1690 procedure Prove_Too_Large
1693 Pre
=> abs (Big
(X
) * Big
(Y
)) >= Big_2xxDouble
,
1694 Post
=> not In_Double_Int_Range
(Big
(X
) * Big
(Y
));
1696 --------------------------
1697 -- Prove_Both_Too_Large --
1698 --------------------------
1700 procedure Prove_Both_Too_Large
is
1702 pragma Assert
(Mult
>=
1703 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
'(Xhi * Yhi)));
1704 pragma Assert (Double_Uns (Xhi) * Double_Uns (Yhi) >= 1);
1705 pragma Assert (Mult >= Big_2xxSingle * Big_2xxSingle);
1707 end Prove_Both_Too_Large;
1709 -------------------------------
1710 -- Prove_Final_Decomposition --
1711 -------------------------------
1713 procedure Prove_Final_Decomposition is
1715 Lemma_Hi_Lo (T2, Hi (T2), Lo (T2));
1716 pragma Assert (Mult = Big_2xxSingle * Big (Double_Uns (Lo (T2)))
1717 + Big (Double_Uns (Lo (T1))));
1718 pragma Assert (Mult <= Big_2xxDouble_Minus_1);
1719 Lemma_Mult_Commutation (X, Y);
1720 pragma Assert (Mult = abs (Big (X * Y)));
1721 Lemma_Word_Commutation (Lo (T2));
1722 pragma Assert (Mult = Big (Double_Uns'(2 ** Single_Size
)
1723 * Double_Uns
(Lo
(T2
)))
1724 + Big
(Double_Uns
(Lo
(T1
))));
1725 Lemma_Add_Commutation
(Double_Uns
'(2 ** Single_Size)
1726 * Double_Uns (Lo (T2)),
1728 pragma Assert (Mult = Big (Double_Uns'(2 ** Single_Size
)
1729 * Double_Uns
(Lo
(T2
)) + Lo
(T1
)));
1730 pragma Assert
(Lo
(T2
) & Lo
(T1
) = Double_Uns
'(2 ** Single_Size)
1731 * Double_Uns (Lo (T2)) + Lo (T1));
1732 end Prove_Final_Decomposition;
1738 procedure Prove_Neg_Int is
1740 pragma Assert (X * Y <= 0);
1741 pragma Assert (Mult = -Big (X * Y));
1748 procedure Prove_Pos_Int is
1750 pragma Assert (X * Y >= 0);
1751 pragma Assert (Mult = Big (X * Y));
1754 ----------------------------
1755 -- Prove_Result_Too_Large --
1756 ----------------------------
1758 procedure Prove_Result_Too_Large is
1760 pragma Assert (Mult >= Big_2xxSingle * Big (T2));
1761 Lemma_Hi_Lo (T2, Hi (T2), Lo (T2));
1762 pragma Assert (Mult >=
1763 Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2))));
1764 pragma Assert (Double_Uns (Hi (T2)) >= 1);
1765 pragma Assert (Mult >= Big_2xxSingle * Big_2xxSingle);
1767 end Prove_Result_Too_Large;
1769 ---------------------
1770 -- Prove_Too_Large --
1771 ---------------------
1773 procedure Prove_Too_Large is null;
1775 -- Start of processing for Multiply_With_Ovflo_Check
1778 Lemma_Mult_Decomposition (Mult, Xu, Yu, Xhi, Xlo, Yhi, Ylo);
1782 Prove_Both_Too_Large;
1786 pragma Assert (Big (T2) = Big (Double_Uns'(Xhi
* Ylo
))
1787 + Big
(Double_Uns
'(Xlo * Yhi)));
1792 pragma Assert (Big (T2) = Big (Double_Uns'(Xhi
* Ylo
))
1793 + Big
(Double_Uns
'(Xlo * Yhi)));
1795 else -- Yhi = Xhi = 0
1799 -- Here we have T2 set to the contribution to the upper half of the
1800 -- result from the upper halves of the input values.
1804 pragma Assert (Big (T2) = Big (Double_Uns'(Xhi
* Ylo
))
1805 + Big
(Double_Uns
'(Xlo * Yhi)));
1806 Lemma_Mult_Distribution (Big_2xxSingle, Big (Double_Uns'(Xhi
* Ylo
)),
1807 Big
(Double_Uns
'(Xlo * Yhi)));
1808 pragma Assert (Mult = Big_2xxSingle * Big (T2) + Big (T1));
1809 Lemma_Add_Commutation (T2, Hi (T1));
1811 (Big (T2 + Hi (T1)) = Big (T2) + Big (Double_Uns (Hi (T1))));
1815 Lemma_Hi_Lo (T1, Hi (T1), Lo (T1));
1817 (Mult = Big_2xxSingle * Big (T2) + Big (Double_Uns (Lo (T1))));
1819 if Hi (T2) /= 0 then
1820 Prove_Result_Too_Large;
1824 Prove_Final_Decomposition;
1826 T2 := Lo (T2) & Lo (T1);
1828 pragma Assert (Mult = Big (T2));
1833 return To_Pos_Int (T2);
1834 pragma Annotate (CodePeer, Intentional, "precondition",
1835 "Intentional Unsigned->Signed conversion");
1838 Lemma_Abs_Range (Big (X) * Big (Y));
1839 return To_Neg_Int (T2);
1844 return To_Pos_Int (T2);
1845 pragma Annotate (CodePeer, Intentional, "precondition",
1846 "Intentional Unsigned->Signed conversion");
1849 Lemma_Abs_Range (Big (X) * Big (Y));
1850 return To_Neg_Int (T2);
1854 end Multiply_With_Ovflo_Check;
1860 procedure Raise_Error is
1862 raise Constraint_Error with "Double arithmetic overflow";
1864 (GNATprove, Intentional, "exception might be raised",
1865 "Procedure Raise_Error is called to signal input errors");
1872 procedure Scaled_Divide
1873 (X, Y, Z : Double_Int;
1874 Q, R : out Double_Int;
1877 Xu : constant Double_Uns := abs X;
1878 Xhi : constant Single_Uns := Hi (Xu);
1879 Xlo : constant Single_Uns := Lo (Xu);
1881 Yu : constant Double_Uns := abs Y;
1882 Yhi : constant Single_Uns := Hi (Yu);
1883 Ylo : constant Single_Uns := Lo (Yu);
1885 Zu : Double_Uns := abs Z;
1886 Zhi : Single_Uns := Hi (Zu);
1887 Zlo : Single_Uns := Lo (Zu);
1889 D : array (1 .. 4) of Single_Uns with Relaxed_Initialization;
1890 -- The dividend, four digits (D(1) is high order)
1892 Qd : array (1 .. 2) of Single_Uns with Relaxed_Initialization;
1893 -- The quotient digits, two digits (Qd(1) is high order)
1895 S1, S2, S3 : Single_Uns;
1896 -- Value to subtract, three digits (S1 is high order)
1900 -- Unsigned quotient and remainder
1903 -- Mask of bits used to compute the scaling factor below
1906 -- Scaling factor used for multiple-precision divide. Dividend and
1907 -- Divisor are multiplied by 2 ** Scale, and the final remainder is
1908 -- divided by the scaling factor. The reason for this scaling is to
1909 -- allow more accurate estimation of quotient digits.
1912 -- Shift factor used to compute the scaling factor above
1914 T1, T2, T3 : Double_Uns;
1917 -- Local ghost variables
1919 Mult : constant Big_Natural := abs (Big (X) * Big (Y)) with Ghost;
1920 Quot : Big_Integer with Ghost;
1921 Big_R : Big_Integer with Ghost;
1922 Big_Q : Big_Integer with Ghost;
1923 Inter : Natural with Ghost;
1925 -- Local ghost functions
1927 function Is_Mult_Decomposition
1928 (D1, D2, D3, D4 : Big_Integer)
1931 (Mult = Big_2xxSingle * Big_2xxSingle * Big_2xxSingle * D1
1932 + Big_2xxSingle * Big_2xxSingle * D2
1933 + Big_2xxSingle * D3
1937 function Is_Scaled_Mult_Decomposition
1938 (D1, D2, D3, D4 : Big_Integer)
1941 (Mult * Big_2xx (Scale)
1942 = Big_2xxSingle * Big_2xxSingle * Big_2xxSingle * D1
1943 + Big_2xxSingle * Big_2xxSingle * D2
1944 + Big_2xxSingle * D3
1948 Pre => Scale < Double_Size;
1952 procedure Prove_Dividend_Scaling
1955 Pre => D'Initialized
1956 and then Scale <= Single_Size
1957 and then Is_Mult_Decomposition (Big (Double_Uns (D (1))),
1958 Big (Double_Uns (D (2))),
1959 Big (Double_Uns (D (3))),
1960 Big (Double_Uns (D (4))))
1961 and then Big (D (1) & D (2)) * Big_2xx (Scale) < Big_2xxDouble
1962 and then T1 = Shift_Left (D (1) & D (2), Scale)
1963 and then T2 = Shift_Left (Double_Uns (D (3)), Scale)
1964 and then T3 = Shift_Left (Double_Uns (D (4)), Scale),
1965 Post => Is_Scaled_Mult_Decomposition
1966 (Big (Double_Uns (Hi (T1))),
1967 Big (Double_Uns (Lo (T1) or Hi (T2))),
1968 Big (Double_Uns (Lo (T2) or Hi (T3))),
1969 Big (Double_Uns (Lo (T3))));
1970 -- Proves the scaling of the 4-digit dividend actually multiplies it by
1973 procedure Prove_Multiplication (Q : Single_Uns)
1976 Pre => T1 = Q * Lo (Zu)
1977 and then T2 = Q * Hi (Zu)
1978 and then S3 = Lo (T1)
1979 and then T3 = Hi (T1) + Lo (T2)
1980 and then S2 = Lo (T3)
1981 and then S1 = Hi (T3) + Hi (T2),
1982 Post => Big3 (S1, S2, S3) = Big (Double_Uns (Q)) * Big (Zu);
1983 -- Proves correctness of the multiplication of divisor by quotient to
1984 -- compute amount to subtract.
1986 procedure Prove_Mult_Decomposition_Split3
1987 (D1, D2, D3, D3_Hi, D3_Lo, D4 : Big_Integer)
1990 Pre => Is_Mult_Decomposition (D1, D2, D3, D4)
1991 and then D3 = Big_2xxSingle * D3_Hi + D3_Lo,
1992 Post => Is_Mult_Decomposition (D1, D2 + D3_Hi, D3_Lo, D4);
1993 -- Proves decomposition of Mult after splitting third component
1995 procedure Prove_Negative_Dividend
1999 and then Big (Qu) = abs Big_Q
2000 and then In_Double_Int_Range (Big_Q)
2001 and then Big (Ru) = abs Big_R
2002 and then ((X >= 0 and Y < 0) or (X < 0 and Y >= 0))
2004 (if Round then Round_Quotient (Big (X) * Big (Y), Big (Z),
2005 Big (X) * Big (Y) / Big (Z),
2006 Big (X) * Big (Y) rem Big (Z))
2007 else Big (X) * Big (Y) / Big (Z))
2008 and then Big_R = Big (X) * Big (Y) rem Big (Z),
2010 (if Z > 0 then Big_Q <= Big_0
2011 and then In_Double_Int_Range (-Big (Qu))
2013 and then In_Double_Int_Range (Big (Qu)))
2014 and then In_Double_Int_Range (-Big (Ru));
2015 -- Proves the sign of rounded quotient when dividend is non-positive
2017 procedure Prove_Overflow
2021 and then Mult >= Big_2xxDouble * Big (Double_Uns'(abs Z
)),
2022 Post
=> not In_Double_Int_Range
(Big
(X
) * Big
(Y
) / Big
(Z
))
2023 and then not In_Double_Int_Range
2024 (Round_Quotient
(Big
(X
) * Big
(Y
), Big
(Z
),
2025 Big
(X
) * Big
(Y
) / Big
(Z
),
2026 Big
(X
) * Big
(Y
) rem Big
(Z
)));
2027 -- Proves overflow case when the quotient has at least 3 digits
2029 procedure Prove_Positive_Dividend
2033 and then Big
(Qu
) = abs Big_Q
2034 and then In_Double_Int_Range
(Big_Q
)
2035 and then Big
(Ru
) = abs Big_R
2036 and then ((X
>= 0 and Y
>= 0) or (X
< 0 and Y
< 0))
2038 (if Round
then Round_Quotient
(Big
(X
) * Big
(Y
), Big
(Z
),
2039 Big
(X
) * Big
(Y
) / Big
(Z
),
2040 Big
(X
) * Big
(Y
) rem Big
(Z
))
2041 else Big
(X
) * Big
(Y
) / Big
(Z
))
2042 and then Big_R
= Big
(X
) * Big
(Y
) rem Big
(Z
),
2044 (if Z
> 0 then Big_Q
>= Big_0
2045 and then In_Double_Int_Range
(Big
(Qu
))
2047 and then In_Double_Int_Range
(-Big
(Qu
)))
2048 and then In_Double_Int_Range
(Big
(Ru
));
2049 -- Proves the sign of rounded quotient when dividend is non-negative
2051 procedure Prove_Qd_Calculation_Part_1
(J
: Integer)
2055 and then D
'Initialized
2056 and then D
(J
) < Zhi
2057 and then Hi
(Zu
) = Zhi
2058 and then Qd
(J
)'Initialized
2059 and then Qd
(J
) = Lo
((D
(J
) & D
(J
+ 1)) / Zhi
),
2060 Post
=> Big
(Double_Uns
(Qd
(J
))) >=
2061 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) / Big
(Zu
);
2062 -- When dividing 3 digits by 2 digits, proves the initial calculation
2063 -- of the quotient given by dividing the first 2 digits of the dividend
2064 -- by the first digit of the divisor is not an underestimate (so
2065 -- readjusting down works).
2067 procedure Prove_Q_Too_Big
2070 Pre
=> In_Double_Int_Range
(Big_Q
)
2071 and then abs Big_Q
= Big_2xxDouble
,
2073 -- Proves the inconsistency when Q is equal to Big_2xx64
2075 procedure Prove_Rescaling
2078 Pre
=> Scale
<= Single_Size
2080 and then Mult
* Big_2xx
(Scale
) = Big
(Zu
) * Big
(Qu
) + Big
(Ru
)
2081 and then Big
(Ru
) < Big
(Zu
)
2082 and then Big
(Zu
) = Big
(Double_Uns
'(abs Z)) * Big_2xx (Scale)
2083 and then Quot = Big (X) * Big (Y) / Big (Z)
2084 and then Big_R = Big (X) * Big (Y) rem Big (Z),
2085 Post => abs Quot = Big (Qu)
2086 and then abs Big_R = Big (Shift_Right (Ru, Scale));
2087 -- Proves scaling back only the remainder is the right thing to do after
2088 -- computing the scaled division.
2090 procedure Prove_Rounding_Case
2094 and then Quot = Big (X) * Big (Y) / Big (Z)
2095 and then Big_R = Big (X) * Big (Y) rem Big (Z)
2097 Round_Quotient (Big (X) * Big (Y), Big (Z), Quot, Big_R)
2098 and then Big (Ru) = abs Big_R
2099 and then Big (Zu) = Big (Double_Uns'(abs Z
)),
2101 (if Ru
> (Zu
- Double_Uns
'(1)) / Double_Uns'(2)
2104 -- Proves correctness of the rounding of the unsigned quotient
2106 procedure Prove_Scaled_Mult_Decomposition_Regroup24
2107 (D1
, D2
, D3
, D4
: Big_Integer
)
2110 Pre
=> Scale
< Double_Size
2111 and then Is_Scaled_Mult_Decomposition
(D1
, D2
, D3
, D4
),
2112 Post
=> Is_Scaled_Mult_Decomposition
2113 (0, Big_2xxSingle
* D1
+ D2
, 0, Big_2xxSingle
* D3
+ D4
);
2114 -- Proves scaled decomposition of Mult after regrouping on second and
2115 -- fourth component.
2117 procedure Prove_Scaled_Mult_Decomposition_Regroup3
2118 (D1
, D2
, D3
, D4
: Big_Integer
)
2121 Pre
=> Scale
< Double_Size
2122 and then Is_Scaled_Mult_Decomposition
(D1
, D2
, D3
, D4
),
2123 Post
=> Is_Scaled_Mult_Decomposition
(0, 0, Big3
(D1
, D2
, D3
), D4
);
2124 -- Proves scaled decomposition of Mult after regrouping on third
2127 procedure Prove_Sign_R
2130 Pre
=> Z
/= 0 and then Big_R
= Big
(X
) * Big
(Y
) rem Big
(Z
),
2131 Post
=> In_Double_Int_Range
(Big_R
);
2133 procedure Prove_Signs
2137 and then Quot
= Big
(X
) * Big
(Y
) / Big
(Z
)
2138 and then Big_R
= Big
(X
) * Big
(Y
) rem Big
(Z
)
2141 Round_Quotient
(Big
(X
) * Big
(Y
), Big
(Z
), Quot
, Big_R
)
2143 and then Big
(Ru
) = abs Big_R
2144 and then Big
(Qu
) = abs Big_Q
2145 and then In_Double_Int_Range
(Big_Q
)
2146 and then In_Double_Int_Range
(Big_R
)
2148 (if (X
>= 0) = (Y
>= 0) then To_Pos_Int
(Ru
) else To_Neg_Int
(Ru
))
2150 (if ((X
>= 0) = (Y
>= 0)) = (Z
>= 0) then To_Pos_Int
(Qu
)
2151 else To_Neg_Int
(Qu
)), -- need to ensure To_Pos_Int precondition
2152 Post
=> Big
(R
) = Big_R
and then Big
(Q
) = Big_Q
;
2153 -- Proves final signs match the intended result after the unsigned
2154 -- division is done.
2156 procedure Prove_Z_Low
2160 and then D
'Initialized
2161 and then Hi
(abs Z
) = 0
2162 and then Lo
(abs Z
) = Zlo
2164 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(D
(2)))
2165 + Big_2xxSingle
* Big
(Double_Uns
(D
(3)))
2166 + Big
(Double_Uns
(D
(4)))
2167 and then D
(2) < Zlo
2168 and then Quot
= (Big
(X
) * Big
(Y
)) / Big
(Z
)
2169 and then Big_R
= (Big
(X
) * Big
(Y
)) rem Big
(Z
)
2170 and then T1
= D
(2) & D
(3)
2171 and then T2
= Lo
(T1
rem Zlo
) & D
(4)
2172 and then Qu
= Lo
(T1
/ Zlo
) & Lo
(T2
/ Zlo
)
2173 and then Ru
= T2
rem Zlo
,
2174 Post
=> Big
(Qu
) = abs Quot
2175 and then Big
(Ru
) = abs Big_R
;
2176 -- Proves the case where the divisor is only one digit
2178 ----------------------------
2179 -- Prove_Dividend_Scaling --
2180 ----------------------------
2182 procedure Prove_Dividend_Scaling
is
2183 Big_D12
: constant Big_Integer
:=
2184 Big_2xx
(Scale
) * Big
(D
(1) & D
(2));
2185 Big_T1
: constant Big_Integer
:= Big
(T1
);
2186 Big_D3
: constant Big_Integer
:=
2187 Big_2xx
(Scale
) * Big
(Double_Uns
(D
(3)));
2188 Big_T2
: constant Big_Integer
:= Big
(T2
);
2189 Big_D4
: constant Big_Integer
:=
2190 Big_2xx
(Scale
) * Big
(Double_Uns
(D
(4)));
2191 Big_T3
: constant Big_Integer
:= Big
(T3
);
2194 Lemma_Shift_Left
(D
(1) & D
(2), Scale
);
2195 Lemma_Ge_Mult
(Big_2xxSingle
, Big_2xx
(Scale
), Big_2xxSingle
,
2196 Big_2xxSingle
* Big_2xx
(Scale
));
2197 Lemma_Lt_Mult
(Big
(Double_Uns
(D
(3))), Big_2xxSingle
,
2198 Big_2xx
(Scale
), Big_2xxDouble
);
2199 Lemma_Shift_Left
(Double_Uns
(D
(3)), Scale
);
2200 Lemma_Lt_Mult
(Big
(Double_Uns
(D
(4))), Big_2xxSingle
,
2201 Big_2xx
(Scale
), Big_2xxDouble
);
2202 Lemma_Shift_Left
(Double_Uns
(D
(4)), Scale
);
2203 Lemma_Hi_Lo
(D
(1) & D
(2), D
(1), D
(2));
2204 pragma Assert
(Mult
* Big_2xx
(Scale
) =
2205 Big_2xxSingle
* Big_2xxSingle
* Big_D12
2206 + Big_2xxSingle
* Big_D3
2208 pragma Assert
(Big_2xx
(Scale
) > 0);
2210 Two_xx_Scale
: constant Double_Uns
:= Double_Uns
'(2 ** Scale);
2211 D12 : constant Double_Uns := D (1) & D (2);
2213 pragma Assert (Big_2xx (Scale) * Big (D12) < Big_2xxDouble);
2214 pragma Assert (Big (Two_xx_Scale) * Big (D12) < Big_2xxDouble);
2215 Lemma_Mult_Commutation (Two_xx_Scale, D12, T1);
2217 pragma Assert (Big_D12 = Big_T1);
2218 pragma Assert (Big_2xxSingle * Big_2xxSingle * Big_D12
2219 = Big_2xxSingle * Big_2xxSingle * Big_T1);
2220 Lemma_Mult_Commutation (2 ** Scale, Double_Uns (D (3)), T2);
2221 pragma Assert (Big_D3 = Big_T2);
2222 pragma Assert (Big_2xxSingle * Big_D3 = Big_2xxSingle * Big_T2);
2223 Lemma_Mult_Commutation (2 ** Scale, Double_Uns (D (4)), T3);
2224 pragma Assert (Big_D4 = Big_T3);
2226 (By (Is_Scaled_Mult_Decomposition (0, Big_T1, Big_T2, Big_T3),
2227 By (Big_2xxSingle * Big_2xxSingle * Big_D12 =
2228 Big_2xxSingle * Big_2xxSingle * Big_T1,
2231 By (Big_2xxSingle * Big_D3 = Big_2xxSingle * Big_T2,
2235 Lemma_Hi_Lo (T1, Hi (T1), Lo (T1));
2236 Lemma_Hi_Lo (T2, Hi (T2), Lo (T2));
2237 Lemma_Hi_Lo (T3, Hi (T3), Lo (T3));
2238 Lemma_Mult_Distribution (Big_2xxSingle * Big_2xxSingle,
2239 Big_2xxSingle * Big (Double_Uns (Hi (T1))),
2240 Big (Double_Uns (Lo (T1))));
2241 Lemma_Mult_Distribution (Big_2xxSingle,
2242 Big_2xxSingle * Big (Double_Uns (Hi (T2))),
2243 Big (Double_Uns (Lo (T2))));
2244 Lemma_Mult_Distribution (Big_2xxSingle * Big_2xxSingle,
2245 Big (Double_Uns (Lo (T1))),
2246 Big (Double_Uns (Hi (T2))));
2247 Lemma_Mult_Distribution (Big_2xxSingle,
2248 Big (Double_Uns (Lo (T2))),
2249 Big (Double_Uns (Hi (T3))));
2251 (By (Is_Scaled_Mult_Decomposition
2252 (Big (Double_Uns (Hi (T1))),
2253 Big (Double_Uns (Lo (T1))) + Big (Double_Uns (Hi (T2))),
2254 Big (Double_Uns (Lo (T2))) + Big (Double_Uns (Hi (T3))),
2255 Big (Double_Uns (Lo (T3)))),
2256 -- Start from stating equality between the expanded values of
2257 -- the right-hand side in the known and desired assertions over
2258 -- Is_Scaled_Mult_Decomposition.
2259 By (Big_2xxSingle * Big_2xxSingle * Big_2xxSingle *
2260 Big (Double_Uns (Hi (T1)))
2261 + Big_2xxSingle * Big_2xxSingle *
2262 (Big (Double_Uns (Lo (T1))) + Big (Double_Uns (Hi (T2))))
2264 (Big (Double_Uns (Lo (T2))) + Big (Double_Uns (Hi (T3))))
2265 + Big (Double_Uns (Lo (T3))) =
2266 Big_2xxSingle * Big_2xxSingle * Big_2xxSingle * 0
2267 + Big_2xxSingle * Big_2xxSingle * Big_T1
2268 + Big_2xxSingle * Big_T2
2270 -- Now list all known equalities that contribute
2271 Big_2xxSingle * Big_2xxSingle * Big_2xxSingle *
2272 Big (Double_Uns (Hi (T1)))
2273 + Big_2xxSingle * Big_2xxSingle *
2274 (Big (Double_Uns (Lo (T1))) + Big (Double_Uns (Hi (T2))))
2276 (Big (Double_Uns (Lo (T2))) + Big (Double_Uns (Hi (T3))))
2277 + Big (Double_Uns (Lo (T3))) =
2278 Big_2xxSingle * Big_2xxSingle * Big_2xxSingle *
2279 Big (Double_Uns (Hi (T1)))
2280 + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Lo (T1)))
2281 + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2)))
2282 + Big_2xxSingle * Big (Double_Uns (Lo (T2)))
2283 + Big_2xxSingle * Big (Double_Uns (Hi (T3)))
2284 + Big (Double_Uns (Lo (T3)))
2286 By (Big_2xxSingle * Big_2xxSingle * Big (T1)
2287 = Big_2xxSingle * Big_2xxSingle * Big_2xxSingle
2288 * Big (Double_Uns (Hi (T1)))
2289 + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Lo (T1))),
2290 Big_2xxSingle * Big_2xxSingle * Big (T1)
2291 = Big_2xxSingle * Big_2xxSingle
2292 * (Big_2xxSingle * Big (Double_Uns (Hi (T1)))
2293 + Big (Double_Uns (Lo (T1)))))
2295 By (Big_2xxSingle * Big (T2)
2296 = Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2)))
2297 + Big_2xxSingle * Big (Double_Uns (Lo (T2))),
2298 Big_2xxSingle * Big (T2)
2299 = Big_2xxSingle * (Big_2xxSingle * Big (Double_Uns (Hi (T2)))
2300 + Big (Double_Uns (Lo (T2)))))
2302 Big (T3) = Big_2xxSingle * Big (Double_Uns (Hi (T3)))
2303 + Big (Double_Uns (Lo (T3))))));
2304 Lemma_Mult_Distribution (Big_2xxSingle * Big_2xxSingle,
2305 Big (Double_Uns (Lo (T1))),
2306 Big (Double_Uns (Hi (T2))));
2307 pragma Assert (Double_Uns (Lo (T1) or Hi (T2)) =
2308 Double_Uns (Lo (T1)) + Double_Uns (Hi (T2)));
2309 pragma Assert (Double_Uns (Lo (T2) or Hi (T3)) =
2310 Double_Uns (Lo (T2)) + Double_Uns (Hi (T3)));
2311 Lemma_Add_Commutation (Double_Uns (Lo (T1)), Hi (T2));
2312 Lemma_Add_Commutation (Double_Uns (Lo (T2)), Hi (T3));
2314 (By (Is_Scaled_Mult_Decomposition
2315 (Big (Double_Uns (Hi (T1))),
2316 Big (Double_Uns (Lo (T1) or Hi (T2))),
2317 Big (Double_Uns (Lo (T2) or Hi (T3))),
2318 Big (Double_Uns (Lo (T3)))),
2319 By (Big_2xxSingle * Big_2xxSingle
2320 * Big (Double_Uns (Lo (T1) or Hi (T2))) =
2321 Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Lo (T1)))
2322 + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2))),
2323 Big_2xxSingle * Big_2xxSingle
2324 * Big (Double_Uns (Lo (T1)) + Double_Uns (Hi (T2))) =
2325 Big_2xxSingle * Big_2xxSingle
2326 * (Big (Double_Uns (Lo (T1))) + Big (Double_Uns (Hi (T2)))))
2328 Big_2xxSingle * Big (Double_Uns (Lo (T2) or Hi (T3))) =
2329 Big_2xxSingle * Big (Double_Uns (Lo (T2)))
2330 + Big_2xxSingle * Big (Double_Uns (Hi (T3)))));
2331 end Prove_Dividend_Scaling;
2333 --------------------------
2334 -- Prove_Multiplication --
2335 --------------------------
2337 procedure Prove_Multiplication (Q : Single_Uns) is
2339 Lemma_Hi_Lo (Zu, Hi (Zu), Lo (Zu));
2340 Lemma_Hi_Lo (T1, Hi (T1), S3);
2341 Lemma_Hi_Lo (T2, Hi (T2), Lo (T2));
2342 Lemma_Hi_Lo (T3, Hi (T3), S2);
2343 Lemma_Mult_Commutation (Double_Uns (Q), Double_Uns (Lo (Zu)), T1);
2344 Lemma_Mult_Commutation (Double_Uns (Q), Double_Uns (Hi (Zu)), T2);
2345 pragma Assert (Big (Double_Uns (Q)) * Big (Zu) =
2346 Big_2xxSingle * Big (T2) + Big (T1));
2347 pragma Assert (Big (Double_Uns (Q)) * Big (Zu) =
2348 Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2)))
2349 + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T3)))
2350 + Big_2xxSingle * Big (Double_Uns (S2))
2351 + Big (Double_Uns (S3)));
2352 pragma Assert (Double_Uns (Hi (T3)) + Hi (T2) = Double_Uns (S1));
2353 Lemma_Add_Commutation (Double_Uns (Hi (T3)), Hi (T2));
2355 (Big (Double_Uns (Hi (T3))) + Big (Double_Uns (Hi (T2))) =
2356 Big (Double_Uns (S1)));
2357 Lemma_Mult_Distribution (Big_2xxSingle * Big_2xxSingle,
2358 Big (Double_Uns (Hi (T3))),
2359 Big (Double_Uns (Hi (T2))));
2361 (Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2)))
2362 + Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T3)))
2363 = Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (S1)));
2364 pragma Assert (Big (Double_Uns (Q)) * Big (Zu) =
2365 Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (S1))
2366 + Big_2xxSingle * Big (Double_Uns (S2))
2367 + Big (Double_Uns (S3)));
2369 (By (Big (Double_Uns (Q)) * Big (Zu) = Big3 (S1, S2, S3),
2371 Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (S1))
2372 + Big_2xxSingle * Big (Double_Uns (S2))
2373 + Big (Double_Uns (S3))));
2374 end Prove_Multiplication;
2376 -------------------------------------
2377 -- Prove_Mult_Decomposition_Split3 --
2378 -------------------------------------
2380 procedure Prove_Mult_Decomposition_Split3
2381 (D1, D2, D3, D3_Hi, D3_Lo, D4 : Big_Integer)
2384 -----------------------------
2385 -- Prove_Negative_Dividend --
2386 -----------------------------
2388 procedure Prove_Negative_Dividend is
2390 Lemma_Mult_Non_Positive (Big (X), Big (Y));
2391 end Prove_Negative_Dividend;
2393 --------------------
2394 -- Prove_Overflow --
2395 --------------------
2397 procedure Prove_Overflow is
2399 Lemma_Div_Ge (Mult, Big_2xxDouble, Big (Double_Uns'(abs Z
)));
2400 Lemma_Abs_Commutation
(Z
);
2401 Lemma_Abs_Div_Commutation
(Big
(X
) * Big
(Y
), Big
(Z
));
2404 -----------------------------
2405 -- Prove_Positive_Dividend --
2406 -----------------------------
2408 procedure Prove_Positive_Dividend
is
2410 Lemma_Mult_Non_Negative
(Big
(X
), Big
(Y
));
2411 end Prove_Positive_Dividend
;
2413 ---------------------------------
2414 -- Prove_Qd_Calculation_Part_1 --
2415 ---------------------------------
2417 procedure Prove_Qd_Calculation_Part_1
(J
: Integer) is
2419 Lemma_Hi_Lo
(D
(J
) & D
(J
+ 1), D
(J
), D
(J
+ 1));
2420 Lemma_Lt_Commutation
(Double_Uns
(D
(J
)), Double_Uns
(Zhi
));
2421 Lemma_Gt_Mult
(Big
(Double_Uns
(Zhi
)),
2422 Big
(Double_Uns
(D
(J
))) + 1,
2423 Big_2xxSingle
, Big
(D
(J
) & D
(J
+ 1)));
2425 (Big
(D
(J
) & D
(J
+ 1)), Big_2xxSingle
, Big
(Double_Uns
(Zhi
)));
2426 Lemma_Div_Commutation
(D
(J
) & D
(J
+ 1), Double_Uns
(Zhi
));
2427 Lemma_Lo_Is_Ident
((D
(J
) & D
(J
+ 1)) / Zhi
);
2428 Lemma_Div_Definition
(D
(J
) & D
(J
+ 1), Zhi
, Double_Uns
(Qd
(J
)),
2429 (D
(J
) & D
(J
+ 1)) rem Zhi
);
2430 Lemma_Lt_Commutation
2431 ((D
(J
) & D
(J
+ 1)) rem Zhi
, Double_Uns
(Zhi
));
2433 ((Big
(Double_Uns
(Qd
(J
))) + 1) * Big
(Double_Uns
(Zhi
)),
2434 Big
(D
(J
) & D
(J
+ 1)) + 1, Big_2xxSingle
,
2435 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)));
2436 Lemma_Hi_Lo
(Zu
, Zhi
, Lo
(Zu
));
2437 Lemma_Gt_Mult
(Big
(Zu
), Big_2xxSingle
* Big
(Double_Uns
(Zhi
)),
2438 Big
(Double_Uns
(Qd
(J
))) + 1,
2439 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)));
2440 Lemma_Div_Lt
(Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)),
2441 Big
(Double_Uns
(Qd
(J
))) + 1, Big
(Zu
));
2442 end Prove_Qd_Calculation_Part_1
;
2444 ---------------------
2445 -- Prove_Q_Too_Big --
2446 ---------------------
2448 procedure Prove_Q_Too_Big
is
2450 pragma Assert
(Big_Q
= Big_2xxDouble
or Big_Q
= -Big_2xxDouble
);
2451 Lemma_Not_In_Range_Big2xx64
;
2452 end Prove_Q_Too_Big
;
2454 ---------------------
2455 -- Prove_Rescaling --
2456 ---------------------
2458 procedure Prove_Rescaling
is
2460 Lemma_Div_Lt
(Big
(Ru
), Big
(Double_Uns
'(abs Z)), Big_2xx (Scale));
2461 Lemma_Div_Eq (Mult, Big (Double_Uns'(abs Z
)) * Big
(Qu
),
2462 Big_2xx
(Scale
), Big
(Ru
));
2463 Lemma_Rev_Div_Definition
(Mult
, Big
(Double_Uns
'(abs Z)),
2464 Big (Qu), Big (Ru) / Big_2xx (Scale));
2465 Lemma_Abs_Div_Commutation (Big (X) * Big (Y), Big (Z));
2466 Lemma_Abs_Rem_Commutation (Big (X) * Big (Y), Big (Z));
2467 Lemma_Abs_Commutation (Z);
2468 Lemma_Shift_Right (Ru, Scale);
2469 end Prove_Rescaling;
2471 -------------------------
2472 -- Prove_Rounding_Case --
2473 -------------------------
2475 procedure Prove_Rounding_Case is
2477 if Same_Sign (Big (X) * Big (Y), Big (Z)) then
2480 end Prove_Rounding_Case;
2482 -----------------------------------------------
2483 -- Prove_Scaled_Mult_Decomposition_Regroup24 --
2484 -----------------------------------------------
2486 procedure Prove_Scaled_Mult_Decomposition_Regroup24
2487 (D1, D2, D3, D4 : Big_Integer)
2490 ----------------------------------------------
2491 -- Prove_Scaled_Mult_Decomposition_Regroup3 --
2492 ----------------------------------------------
2494 procedure Prove_Scaled_Mult_Decomposition_Regroup3
2495 (D1, D2, D3, D4 : Big_Integer)
2502 procedure Prove_Sign_R is
2504 pragma Assert (In_Double_Int_Range (Big (Z)));
2511 procedure Prove_Signs is null;
2517 procedure Prove_Z_Low is
2519 Lemma_Hi_Lo (T1, D (2), D (3));
2520 Lemma_Add_Commutation (Double_Uns (D (2)), 1);
2522 (Big (Double_Uns (D (2))) + 1 <= Big (Double_Uns (Zlo)));
2523 Lemma_Div_Definition (T1, Zlo, T1 / Zlo, T1 rem Zlo);
2524 pragma Assert (Double_Uns (Lo (T1 rem Zlo)) = T1 rem Zlo);
2525 Lemma_Hi_Lo (T2, Lo (T1 rem Zlo), D (4));
2526 pragma Assert (T1 rem Zlo < Double_Uns (Zlo));
2527 pragma Assert (T1 rem Zlo + Double_Uns'(1) <= Double_Uns
(Zlo
));
2528 Lemma_Ge_Commutation
(Double_Uns
(Zlo
), T1
rem Zlo
+ Double_Uns
'(1));
2529 Lemma_Add_Commutation (T1 rem Zlo, 1);
2530 pragma Assert (Big (T1 rem Zlo) + 1 <= Big (Double_Uns (Zlo)));
2531 Lemma_Div_Definition (T2, Zlo, T2 / Zlo, Ru);
2533 (Mult = Big (Double_Uns (Zlo)) *
2534 (Big_2xxSingle * Big (T1 / Zlo) + Big (T2 / Zlo)) + Big (Ru));
2535 pragma Assert (Big_2xxSingle * Big (Double_Uns (D (2)))
2536 + Big (Double_Uns (D (3)))
2537 < Big_2xxSingle * (Big (Double_Uns (D (2))) + 1));
2538 Lemma_Div_Lt (Big (T1), Big_2xxSingle, Big (Double_Uns (Zlo)));
2539 Lemma_Div_Commutation (T1, Double_Uns (Zlo));
2540 Lemma_Lo_Is_Ident (T1 / Zlo);
2542 (Big (T2) <= Big_2xxSingle * (Big (Double_Uns (Zlo)) - 1)
2543 + Big (Double_Uns (D (4))));
2544 Lemma_Div_Lt (Big (T2), Big_2xxSingle, Big (Double_Uns (Zlo)));
2545 Lemma_Div_Commutation (T2, Double_Uns (Zlo));
2546 Lemma_Lo_Is_Ident (T2 / Zlo);
2547 Lemma_Hi_Lo (Qu, Lo (T1 / Zlo), Lo (T2 / Zlo));
2548 Lemma_Substitution (Mult, Big (Double_Uns (Zlo)),
2549 Big_2xxSingle * Big (T1 / Zlo) + Big (T2 / Zlo),
2550 Big (Qu), Big (Ru));
2551 Lemma_Lt_Commutation (Ru, Double_Uns (Zlo));
2552 Lemma_Rev_Div_Definition
2553 (Mult, Big (Double_Uns (Zlo)), Big (Qu), Big (Ru));
2554 pragma Assert (Double_Uns (Zlo) = abs Z);
2555 Lemma_Abs_Commutation (Z);
2556 Lemma_Abs_Div_Commutation (Big (X) * Big (Y), Big (Z));
2557 Lemma_Abs_Rem_Commutation (Big (X) * Big (Y), Big (Z));
2560 -- Start of processing for Scaled_Divide
2567 Quot := Big (X) * Big (Y) / Big (Z);
2568 Big_R := Big (X) * Big (Y) rem Big (Z);
2570 Big_Q := Round_Quotient (Big (X) * Big (Y), Big (Z), Quot, Big_R);
2575 -- First do the multiplication, giving the four digit dividend
2577 Lemma_Abs_Mult_Commutation (Big (X), Big (Y));
2578 Lemma_Abs_Commutation (X);
2579 Lemma_Abs_Commutation (Y);
2580 Lemma_Mult_Decomposition (Mult, Xu, Yu, Xhi, Xlo, Yhi, Ylo);
2582 (Is_Mult_Decomposition
2584 D2 => Big (Double_Uns'(Xhi
* Yhi
)),
2585 D3
=> Big
(Double_Uns
'(Xhi * Ylo)) + Big (Double_Uns'(Xlo
* Yhi
)),
2586 D4
=> Big
(Double_Uns
'(Xlo * Ylo))));
2592 Lemma_Hi_Lo (T1, D (3), D (4));
2594 (Is_Mult_Decomposition
2596 D2 => Big (Double_Uns'(Xhi
* Yhi
)),
2597 D3
=> Big
(Double_Uns
'(Xhi * Ylo)) + Big (Double_Uns'(Xlo
* Yhi
))
2598 + Big
(Double_Uns
(D
(3))),
2599 D4
=> Big
(Double_Uns
(D
(4)))));
2604 Lemma_Hi_Lo
(T1
, Hi
(T1
), Lo
(T1
));
2606 (Is_Mult_Decomposition
2608 D2
=> Big
(Double_Uns
'(Xhi * Yhi)) + Big (Double_Uns (Hi (T1))),
2609 D3 => Big (Double_Uns'(Xhi
* Ylo
)) + Big
(Double_Uns
(Lo
(T1
)))
2610 + Big
(Double_Uns
(D
(3))),
2611 D4
=> Big
(Double_Uns
(D
(4)))));
2613 T2
:= D
(3) + Lo
(T1
);
2615 Lemma_Add_Commutation
(Double_Uns
(Lo
(T1
)), D
(3));
2617 (Is_Mult_Decomposition
2619 D2
=> Big
(Double_Uns
'(Xhi * Yhi)) + Big (Double_Uns (Hi (T1))),
2620 D3 => Big (Double_Uns'(Xhi
* Ylo
)) + Big
(T2
),
2621 D4
=> Big
(Double_Uns
(D
(4)))));
2622 Lemma_Mult_Distribution
(Big_2xxSingle
,
2623 Big
(Double_Uns
(D
(3))),
2624 Big
(Double_Uns
(Lo
(T1
))));
2625 Lemma_Hi_Lo
(T2
, Hi
(T2
), Lo
(T2
));
2627 (Is_Mult_Decomposition
2629 D2
=> Big
(Double_Uns
'(Xhi * Yhi)) + Big (Double_Uns (Hi (T1)))
2630 + Big (Double_Uns (Hi (T2))),
2631 D3 => Big (Double_Uns'(Xhi
* Ylo
)) + Big
(Double_Uns
(Lo
(T2
))),
2632 D4
=> Big
(Double_Uns
(D
(4)))));
2635 D
(2) := Hi
(T1
) + Hi
(T2
);
2637 pragma Assert
(Double_Uns
(Hi
(T1
)) + Hi
(T2
) = Double_Uns
(D
(2)));
2638 Lemma_Add_Commutation
(Double_Uns
(Hi
(T1
)), Hi
(T2
));
2640 (Big
(Double_Uns
(Hi
(T1
))) + Big
(Double_Uns
(Hi
(T2
))) =
2641 Big
(Double_Uns
(D
(2))));
2643 (Is_Mult_Decomposition
2645 D2
=> Big
(Double_Uns
'(Xhi * Yhi)) + Big (Double_Uns (D (2))),
2646 D3 => Big (Double_Uns'(Xhi
* Ylo
)) + Big
(Double_Uns
(D
(3))),
2647 D4
=> Big
(Double_Uns
(D
(4)))));
2652 Lemma_Hi_Lo
(T1
, Hi
(T1
), Lo
(T1
));
2654 (By
(Is_Mult_Decomposition
2656 D2
=> Big
(Double_Uns
'(Xhi * Yhi)) + Big (Double_Uns (D (2)))
2657 + Big (Double_Uns (Hi (T1))),
2658 D3 => Big (Double_Uns (Lo (T1))) + Big (Double_Uns (D (3))),
2659 D4 => Big (Double_Uns (D (4)))),
2660 (By (Big_2xxSingle * Big (T1) =
2661 Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T1)))
2662 + Big_2xxSingle * Big (Double_Uns (Lo (T1))),
2663 Big_2xxSingle * Big (T1) =
2664 Big_2xxSingle * (Big_2xxSingle * Big (Double_Uns (Hi (T1)))
2665 + Big (Double_Uns (Lo (T1))))))));
2667 T2 := D (3) + Lo (T1);
2669 Lemma_Add_Commutation (Double_Uns (D (3)), Lo (T1));
2670 Lemma_Hi_Lo (T2, Hi (T2), Lo (T2));
2671 Prove_Mult_Decomposition_Split3
2673 D2 => Big (Double_Uns'(Xhi
* Yhi
)) + Big
(Double_Uns
(D
(2)))
2674 + Big
(Double_Uns
(Hi
(T1
))),
2676 D3_Hi
=> Big
(Double_Uns
(Hi
(T2
))),
2677 D3_Lo
=> Big
(Double_Uns
(Lo
(T2
))),
2678 D4
=> Big
(Double_Uns
(D
(4))));
2681 T3
:= D
(2) + Hi
(T1
);
2683 Lemma_Add_Commutation
(Double_Uns
(D
(2)), Hi
(T1
));
2685 (Is_Mult_Decomposition
2687 D2
=> Big
(Double_Uns
'(Xhi * Yhi)) + Big (T3)
2688 + Big (Double_Uns (Hi (T2))),
2689 D3 => Big (Double_Uns (D (3))),
2690 D4 => Big (Double_Uns (D (4)))));
2691 Lemma_Add_Commutation (T3, Hi (T2));
2694 T2 := Double_Uns'(Xhi
* Yhi
);
2697 (Is_Mult_Decomposition
2699 D2
=> Big
(T2
) + Big
(T3
),
2700 D3
=> Big
(Double_Uns
(D
(3))),
2701 D4
=> Big
(Double_Uns
(D
(4)))));
2702 Lemma_Hi_Lo
(T2
, Hi
(T2
), Lo
(T2
));
2704 (By
(Is_Mult_Decomposition
2705 (D1
=> Big
(Double_Uns
(Hi
(T2
))),
2706 D2
=> Big
(Double_Uns
(Lo
(T2
))) + Big
(T3
),
2707 D3
=> Big
(Double_Uns
(D
(3))),
2708 D4
=> Big
(Double_Uns
(D
(4)))),
2709 By
(Big_2xxSingle
* Big_2xxSingle
* Big
(T2
) =
2710 Big_2xxSingle
* Big_2xxSingle
* Big_2xxSingle
2711 * Big
(Double_Uns
(Hi
(T2
)))
2712 + Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(Lo
(T2
))),
2713 Big_2xxSingle
* Big_2xxSingle
*
2714 (Big_2xxSingle
* Big
(Double_Uns
(Hi
(T2
)))
2715 + Big
(Double_Uns
(Lo
(T2
))))
2716 = Big_2xxSingle
* Big_2xxSingle
* Big_2xxSingle
2717 * Big
(Double_Uns
(Hi
(T2
)))
2718 + Big_2xxSingle
* Big_2xxSingle
2719 * Big
(Double_Uns
(Lo
(T2
))))));
2724 Lemma_Add_Commutation
(T3
, Lo
(T2
));
2726 (Is_Mult_Decomposition
2727 (D1
=> Big
(Double_Uns
(Hi
(T2
))),
2729 D3
=> Big
(Double_Uns
(D
(3))),
2730 D4
=> Big
(Double_Uns
(D
(4)))));
2731 Lemma_Hi_Lo
(T1
, Hi
(T1
), Lo
(T1
));
2733 (By
(Is_Mult_Decomposition
2734 (D1
=> Big
(Double_Uns
(Hi
(T2
))) + Big
(Double_Uns
(Hi
(T1
))),
2735 D2
=> Big
(Double_Uns
(D
(2))),
2736 D3
=> Big
(Double_Uns
(D
(3))),
2737 D4
=> Big
(Double_Uns
(D
(4)))),
2738 By
(Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(Lo
(T1
))) =
2739 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(D
(2))),
2742 By
(Big_2xxSingle
* Big_2xxSingle
* Big
(T1
) =
2743 Big_2xxSingle
* Big_2xxSingle
* Big_2xxSingle
2744 * Big
(Double_Uns
(Hi
(T1
)))
2745 + Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(Lo
(T1
))),
2746 Big_2xxSingle
* Big_2xxSingle
*
2747 (Big_2xxSingle
* Big
(Double_Uns
(Hi
(T1
)))
2748 + Big
(Double_Uns
(Lo
(T1
))))
2749 = Big_2xxSingle
* Big_2xxSingle
* Big_2xxSingle
2750 * Big
(Double_Uns
(Hi
(T1
)))
2751 + Big_2xxSingle
* Big_2xxSingle
2752 * Big
(Double_Uns
(Lo
(T1
))))));
2754 D
(1) := Hi
(T2
) + Hi
(T1
);
2757 (Double_Uns
(Hi
(T2
)) + Hi
(T1
) = Double_Uns
(D
(1)));
2758 Lemma_Add_Commutation
(Double_Uns
(Hi
(T2
)), Hi
(T1
));
2760 (Big
(Double_Uns
(Hi
(T2
))) + Big
(Double_Uns
(Hi
(T1
))) =
2761 Big
(Double_Uns
(D
(1))));
2764 (By
(Is_Mult_Decomposition
2765 (D1
=> Big
(Double_Uns
(D
(1))),
2766 D2
=> Big
(Double_Uns
(D
(2))),
2767 D3
=> Big
(Double_Uns
(D
(3))),
2768 D4
=> Big
(Double_Uns
(D
(4)))),
2769 Big_2xxSingle
* Big_2xxSingle
* Big_2xxSingle
*
2770 Big
(Double_Uns
(D
(1)))
2771 = Big_2xxSingle
* Big_2xxSingle
* Big_2xxSingle
*
2772 (Big
(Double_Uns
(Hi
(T2
)) + Double_Uns
(Hi
(T1
))))));
2777 (By
(Is_Mult_Decomposition
2778 (D1
=> Big
(Double_Uns
(D
(1))),
2779 D2
=> Big
(Double_Uns
(D
(2))),
2780 D3
=> Big
(Double_Uns
(D
(3))),
2781 D4
=> Big
(Double_Uns
(D
(4)))),
2782 Big
(Double_Uns
'(Xhi * Yhi)) = 0
2783 and then Big (Double_Uns'(Xhi
* Ylo
)) = 0
2784 and then Big
(Double_Uns
(D
(1))) = 0));
2788 (Is_Mult_Decomposition
(D1
=> Big
(Double_Uns
(D
(1))),
2789 D2
=> Big
(Double_Uns
(D
(2))),
2790 D3
=> Big
(Double_Uns
(D
(3))),
2791 D4
=> Big
(Double_Uns
(D
(4)))));
2794 (By
(Is_Mult_Decomposition
2797 D3
=> Big
(Double_Uns
'(Xhi * Ylo)) + Big (Double_Uns (D (3))),
2798 D4 => Big (Double_Uns (D (4)))),
2799 Big (Double_Uns'(Xhi
* Yhi
)) = 0
2800 and then Big
(Double_Uns
'(Xlo * Yhi)) = 0));
2805 Lemma_Hi_Lo (T1, Hi (T1), Lo (T1));
2807 (By (Is_Mult_Decomposition
2809 D2 => Big (Double_Uns (Hi (T1))),
2810 D3 => Big (Double_Uns (Lo (T1))) + Big (Double_Uns (D (3))),
2811 D4 => Big (Double_Uns (D (4)))),
2812 Big_2xxSingle * Big (Double_Uns'(Xhi
* Ylo
)) =
2813 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(Hi
(T1
)))
2814 + Big_2xxSingle
* Big
(Double_Uns
(Lo
(T1
)))));
2816 T2
:= D
(3) + Lo
(T1
);
2818 Lemma_Add_Commutation
(Double_Uns
(Lo
(T1
)), D
(3));
2820 (By
(Is_Mult_Decomposition
2822 D2
=> Big
(Double_Uns
(Hi
(T1
))),
2824 D4
=> Big
(Double_Uns
(D
(4)))),
2825 Big_2xxSingle
* Big
(T2
) =
2827 (Big
(Double_Uns
(Lo
(T1
))) + Big
(Double_Uns
(D
(3))))));
2828 Lemma_Mult_Distribution
(Big_2xxSingle
,
2829 Big
(Double_Uns
(D
(3))),
2830 Big
(Double_Uns
(Lo
(T1
))));
2831 Lemma_Hi_Lo
(T2
, Hi
(T2
), Lo
(T2
));
2834 D
(2) := Hi
(T1
) + Hi
(T2
);
2837 (Double_Uns
(Hi
(T1
)) + Hi
(T2
) = Double_Uns
(D
(2)));
2838 Lemma_Add_Commutation
(Double_Uns
(Hi
(T1
)), Hi
(T2
));
2840 (Big
(Double_Uns
(Hi
(T1
))) + Big
(Double_Uns
(Hi
(T2
))) =
2841 Big
(Double_Uns
(D
(2))));
2843 (Is_Mult_Decomposition
2845 D2
=> Big
(Double_Uns
(D
(2))),
2846 D3
=> Big
(Double_Uns
(D
(3))),
2847 D4
=> Big
(Double_Uns
(D
(4)))));
2852 (By
(Is_Mult_Decomposition
2854 D2
=> Big
(Double_Uns
(D
(2))),
2855 D3
=> Big
(Double_Uns
(D
(3))),
2856 D4
=> Big
(Double_Uns
(D
(4)))),
2857 Big
(Double_Uns
'(Xhi * Ylo)) = 0
2858 and then Big (Double_Uns (D (2))) = 0));
2864 pragma Assert (Is_Mult_Decomposition (D1 => Big (Double_Uns (D (1))),
2865 D2 => Big (Double_Uns (D (2))),
2866 D3 => Big (Double_Uns (D (3))),
2867 D4 => Big (Double_Uns (D (4)))));
2869 -- Now it is time for the dreaded multiple precision division. First an
2870 -- easy case, check for the simple case of a one digit divisor.
2873 if D (1) /= 0 or else D (2) >= Zlo then
2876 (Mult >= Big_2xxSingle * Big_2xxSingle * Big_2xxSingle
2877 * Big (Double_Uns (D (1))));
2878 Lemma_Double_Big_2xxSingle;
2879 Lemma_Mult_Positive (Big_2xxDouble, Big_2xxSingle);
2880 Lemma_Ge_Mult (Big (Double_Uns (D (1))),
2882 Big_2xxDouble * Big_2xxSingle,
2883 Big_2xxDouble * Big_2xxSingle);
2884 Lemma_Mult_Positive (Big_2xxSingle, Big (Double_Uns (D (1))));
2885 Lemma_Ge_Mult (Big_2xxSingle * Big_2xxSingle, Big_2xxDouble,
2886 Big_2xxSingle * Big (Double_Uns (D (1))),
2887 Big_2xxDouble * Big_2xxSingle);
2888 pragma Assert (Mult >= Big_2xxDouble * Big_2xxSingle);
2889 Lemma_Ge_Commutation (2 ** Single_Size, Zu);
2890 Lemma_Ge_Mult (Big_2xxSingle, Big (Zu), Big_2xxDouble,
2891 Big_2xxDouble * Big (Zu));
2892 pragma Assert (Mult >= Big_2xxDouble * Big (Zu));
2894 Lemma_Ge_Commutation (Double_Uns (D (2)), Zu);
2895 pragma Assert (Mult >= Big_2xxDouble * Big (Zu));
2901 -- Here we are dividing at most three digits by one digit
2904 T1 := D (2) & D (3);
2905 T2 := Lo (T1 rem Zlo) & D (4);
2907 Qu := Lo (T1 / Zlo) & Lo (T2 / Zlo);
2913 -- If divisor is double digit and dividend is too large, raise error
2915 elsif (D (1) & D (2)) >= Zu then
2916 Lemma_Hi_Lo (D (1) & D (2), D (1), D (2));
2917 Lemma_Ge_Commutation (D (1) & D (2), Zu);
2921 -- This is the complex case where we definitely have a double digit
2922 -- divisor and a dividend of at least three digits. We use the classical
2923 -- multiple-precision division algorithm (see section (4.3.1) of Knuth's
2924 -- "The Art of Computer Programming", Vol. 2 for a description
2928 -- First normalize the divisor so that it has the leading bit on.
2929 -- We do this by finding the appropriate left shift amount.
2931 Lemma_Lt_Commutation (D (1) & D (2), Zu);
2932 pragma Assert (Mult < Big_2xxDouble * Big (Zu));
2934 Shift := Single_Size;
2935 Mask := Single_Uns'Last;
2939 pragma Assert (Big_2xx (Scale) = 1);
2941 while Shift > 1 loop
2942 pragma Loop_Invariant (Scale <= Single_Size - Shift);
2943 pragma Loop_Invariant ((Hi (Zu) and Mask) /= 0);
2944 pragma Loop_Invariant
2945 (Mask = Shift_Left (Single_Uns'Last, Single_Size - Shift));
2946 pragma Loop_Invariant (Zu = Shift_Left (abs Z, Scale));
2947 pragma Loop_Invariant (Big (Zu) =
2948 Big (Double_Uns'(abs Z
)) * Big_2xx
(Scale
));
2949 pragma Loop_Invariant
(Inter
in 0 .. Log_Single_Size
- 1);
2950 pragma Loop_Invariant
(Shift
= 2 ** (Log_Single_Size
- Inter
));
2951 pragma Loop_Invariant
(Shift
mod 2 = 0);
2954 -- Local ghost variables
2956 Shift_Prev
: constant Natural := Shift
with Ghost
;
2957 Mask_Prev
: constant Single_Uns
:= Mask
with Ghost
;
2958 Zu_Prev
: constant Double_Uns
:= Zu
with Ghost
;
2962 procedure Prove_Power
2965 Pre
=> Inter
in 0 .. Log_Single_Size
- 1
2966 and then Shift
= 2 ** (Log_Single_Size
- Inter
),
2967 Post
=> Shift
/ 2 = 2 ** (Log_Single_Size
- (Inter
+ 1))
2968 and then (Shift
= 2 or (Shift
/ 2) mod 2 = 0);
2970 procedure Prove_Prev_And_Mask
(Prev
, Mask
: Single_Uns
)
2974 and then (Prev
and Mask
) = 0,
2975 Post
=> (Prev
and not Mask
) /= 0;
2977 procedure Prove_Shift_Progress
2980 Pre
=> Shift
<= Single_Size
/ 2
2981 and then Shift_Prev
= 2 * Shift
2982 and then Mask_Prev
=
2983 Shift_Left
(Single_Uns
'Last, Single_Size
- Shift_Prev
)
2985 Shift_Left
(Single_Uns
'Last,
2986 Single_Size
- Shift_Prev
+ Shift
),
2988 Shift_Left
(Single_Uns
'Last, Single_Size
- 2 * Shift
)
2990 Shift_Left
(Single_Uns
'Last, Single_Size
- Shift
);
2992 procedure Prove_Shifting
2995 Pre
=> Shift
<= Single_Size
/ 2
2996 and then Zu
= Shift_Left
(Zu_Prev
, Shift
)
2997 and then Mask_Prev
=
2998 Shift_Left
(Single_Uns
'Last, Single_Size
- 2 * Shift
)
3000 Shift_Left
(Single_Uns
'Last, Single_Size
- Shift
)
3001 and then (Hi
(Zu_Prev
) and Mask_Prev
and not Mask
) /= 0,
3002 Post
=> (Hi
(Zu
) and Mask
) /= 0;
3004 -----------------------------
3005 -- Local lemma null bodies --
3006 -----------------------------
3008 procedure Prove_Prev_And_Mask
(Prev
, Mask
: Single_Uns
) is null;
3009 procedure Prove_Power
is null;
3010 procedure Prove_Shifting
is null;
3011 procedure Prove_Shift_Progress
is null;
3014 pragma Assert
(Mask
= Shift_Left
(Single_Uns
'Last,
3015 Single_Size
- Shift_Prev
));
3021 pragma Assert
(Shift_Prev
= 2 * Shift
);
3023 Mask
:= Shift_Left
(Mask
, Shift
);
3026 (Single_Uns
'Last, Single_Size
- Shift_Prev
, Shift
);
3027 Prove_Shift_Progress
;
3029 if (Hi
(Zu
) and Mask
) = 0 then
3030 Zu
:= Shift_Left
(Zu
, Shift
);
3032 pragma Assert
((Hi
(Zu_Prev
) and Mask_Prev
) /= 0);
3034 (By
((Hi
(Zu_Prev
) and Mask_Prev
and Mask
) = 0,
3035 (Hi
(Zu_Prev
) and Mask
) = 0
3037 (Hi
(Zu_Prev
) and Mask_Prev
and Mask
)
3038 = (Hi
(Zu_Prev
) and Mask
and Mask_Prev
)
3040 Prove_Prev_And_Mask
(Hi
(Zu_Prev
) and Mask_Prev
, Mask
);
3042 pragma Assert
(Big
(Zu_Prev
) =
3043 Big
(Double_Uns
'(abs Z)) * Big_2xx (Scale));
3044 Lemma_Shift_Without_Drop (Zu_Prev, Zu, Mask, Shift);
3046 (Big (Zu), Big_2xx (Shift),
3047 Big (Zu_Prev), Big (Double_Uns'(abs Z
)) * Big_2xx
(Scale
),
3049 Lemma_Powers_Of_2
(Shift
, Scale
);
3051 (Big
(Zu
), Big
(Double_Uns
'(abs Z)),
3052 Big_2xx (Shift) * Big_2xx (Scale),
3053 Big_2xx (Shift + Scale), 0);
3054 Lemma_Double_Shift (abs Z, Scale, Shift);
3056 Scale := Scale + Shift;
3058 pragma Assert (Zu = Shift_Left (abs Z, Scale));
3060 (Big (Zu) = Big (Double_Uns'(abs Z
)) * Big_2xx
(Scale
));
3064 (Big
(Zu
) = Big
(Double_Uns
'(abs Z)) * Big_2xx (Scale));
3071 pragma Assert (Shift = 1);
3072 pragma Assert (Mask = Shift_Left (Single_Uns'Last, Single_Size - 1));
3073 pragma Assert ((Zhi and Mask) /= 0);
3074 pragma Assert (Zhi >= 2 ** (Single_Size - 1));
3075 pragma Assert (Big (Zu) = Big (Double_Uns'(abs Z
)) * Big_2xx
(Scale
));
3076 -- We have Hi (Zu) /= 0 before normalization. The sequence of
3077 -- Shift_Left operations results in the leading bit of Zu being 1 by
3078 -- moving the leftmost 1-bit in Zu to leading position, thus
3079 -- Zhi = Hi (Zu) >= 2 ** (Single_Size - 1) here.
3081 -- Note that when we scale up the dividend, it still fits in four
3082 -- digits, since we already tested for overflow, and scaling does
3083 -- not change the invariant that (D (1) & D (2)) < Zu.
3085 Lemma_Lt_Commutation
(D
(1) & D
(2), abs Z
);
3086 Lemma_Big_Of_Double_Uns
(Zu
);
3087 Lemma_Lt_Mult
(Big
(D
(1) & D
(2)),
3088 Big
(Double_Uns
'(abs Z)), Big_2xx (Scale),
3091 T1 := Shift_Left (D (1) & D (2), Scale);
3092 T2 := Shift_Left (Double_Uns (D (3)), Scale);
3093 T3 := Shift_Left (Double_Uns (D (4)), Scale);
3095 Prove_Dividend_Scaling;
3098 D (2) := Lo (T1) or Hi (T2);
3099 D (3) := Lo (T2) or Hi (T3);
3102 pragma Assert (Big (Double_Uns (Hi (T1))) = Big (Double_Uns (D (1))));
3104 (Big_2xxSingle * Big_2xxSingle * Big_2xxSingle
3105 * Big (Double_Uns (Hi (T1)))
3106 = Big_2xxSingle * Big_2xxSingle * Big_2xxSingle
3107 * Big (Double_Uns (D (1))));
3108 Lemma_Substitution (Big_2xxDouble * Big (Zu), Big_2xxDouble, Big (Zu),
3109 Big (Double_Uns'(abs Z
)) * Big_2xx
(Scale
), 0);
3110 Lemma_Lt_Mult
(Mult
, Big_2xxDouble
* Big
(Double_Uns
'(abs Z)),
3111 Big_2xx (Scale), Big_2xxDouble * Big (Zu));
3112 pragma Assert (Mult >= Big_0);
3113 pragma Assert (Big_2xx (Scale) >= Big_0);
3114 Lemma_Mult_Non_Negative (Mult, Big_2xx (Scale));
3115 Lemma_Div_Lt (Mult * Big_2xx (Scale), Big (Zu), Big_2xxDouble);
3116 Lemma_Concat_Definition (D (1), D (2));
3117 Lemma_Double_Big_2xxSingle;
3118 Prove_Scaled_Mult_Decomposition_Regroup24
3119 (Big (Double_Uns (D (1))),
3120 Big (Double_Uns (D (2))),
3121 Big (Double_Uns (D (3))),
3122 Big (Double_Uns (D (4))));
3124 (Mult * Big_2xx (Scale), Big_2xxSingle * Big_2xxSingle,
3125 Big_2xxSingle * Big (Double_Uns (D (1)))
3126 + Big (Double_Uns (D (2))),
3127 Big (D (1) & D (2)),
3128 Big_2xxSingle * Big (Double_Uns (D (3)))
3129 + Big (Double_Uns (D (4))));
3130 pragma Assert (Big (D (1) & D (2)) < Big (Zu));
3132 -- Loop to compute quotient digits, runs twice for Qd (1) and Qd (2)
3137 procedure Prove_First_Iteration (X1, X2, X3, X4 : Single_Uns)
3142 Big_2xxSingle * Big3 (X1, X2, X3) + Big (Double_Uns (X4))
3143 = Big3 (X2, X3, X4);
3145 ---------------------------
3146 -- Prove_First_Iteration --
3147 ---------------------------
3149 procedure Prove_First_Iteration (X1, X2, X3, X4 : Single_Uns) is
3152 -- Local ghost variables
3154 Qd1 : Single_Uns := 0 with Ghost;
3155 D234 : Big_Integer := 0 with Ghost;
3156 D123 : constant Big_Integer := Big3 (D (1), D (2), D (3))
3158 D4 : constant Big_Integer := Big (Double_Uns (D (4)))
3162 Prove_Scaled_Mult_Decomposition_Regroup3
3163 (Big (Double_Uns (D (1))),
3164 Big (Double_Uns (D (2))),
3165 Big (Double_Uns (D (3))),
3166 Big (Double_Uns (D (4))));
3167 pragma Assert (Mult * Big_2xx (Scale) = Big_2xxSingle * D123 + D4);
3169 for J in 1 .. 2 loop
3170 Lemma_Hi_Lo (D (J) & D (J + 1), D (J), D (J + 1));
3171 pragma Assert (Big (D (J) & D (J + 1)) < Big (Zu));
3173 -- Compute next quotient digit. We have to divide three digits
3174 -- by two digits. We estimate the quotient by dividing the
3175 -- leading two digits by the leading digit. Given the scaling
3176 -- we did above which ensured the first bit of the divisor is
3177 -- set, this gives an estimate of the quotient that is at most
3181 Lemma_Lt_Commutation (Zu, D (J) & D (J + 1));
3182 pragma Assert (False);
3184 elsif D (J) = Zhi then
3185 Qd (J) := Single_Uns'Last;
3187 Lemma_Concat_Definition (D (J), D (J + 1));
3188 Lemma_Big_Of_Double_Uns_Of_Single_Uns (D (J + 2));
3189 pragma Assert (Big_2xxSingle > Big (Double_Uns (D (J + 2))));
3190 pragma Assert (Big3 (D (J), D (J + 1), 0) + Big_2xxSingle
3191 > Big3 (D (J), D (J + 1), D (J + 2)));
3192 pragma Assert (Big (Double_Uns'(0)) = 0);
3193 pragma Assert
(Big
(D
(J
) & D
(J
+ 1)) * Big_2xxSingle
=
3194 Big_2xxSingle
* (Big_2xxSingle
* Big
(Double_Uns
(D
(J
)))
3195 + Big
(Double_Uns
(D
(J
+ 1)))));
3196 pragma Assert
(Big
(D
(J
) & D
(J
+ 1)) * Big_2xxSingle
=
3197 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(D
(J
)))
3198 + Big_2xxSingle
* Big
(Double_Uns
(D
(J
+ 1))));
3199 pragma Assert
(Big
(D
(J
) & D
(J
+ 1)) * Big_2xxSingle
3200 = Big3
(D
(J
), D
(J
+ 1), 0));
3201 pragma Assert
((Big
(D
(J
) & D
(J
+ 1)) + 1) * Big_2xxSingle
3202 = Big3
(D
(J
), D
(J
+ 1), 0) + Big_2xxSingle
);
3203 Lemma_Gt_Mult
(Big
(Zu
), Big
(D
(J
) & D
(J
+ 1)) + 1,
3205 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)));
3207 (Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)),
3208 Big_2xxSingle
, Big
(Zu
));
3209 pragma Assert
(Big
(Double_Uns
(Qd
(J
))) >=
3210 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) / Big
(Zu
));
3213 Qd
(J
) := Lo
((D
(J
) & D
(J
+ 1)) / Zhi
);
3215 Prove_Qd_Calculation_Part_1
(J
);
3218 pragma Assert
(for all K
in 1 .. J
=> Qd
(K
)'Initialized);
3220 (Big
(Double_Uns
(Qd
(J
))),
3221 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) / Big
(Zu
),
3222 Big
(Zu
), Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) - Big
(Zu
));
3224 -- Compute amount to subtract
3229 T3
:= Hi
(T1
) + Lo
(T2
);
3231 S1
:= Hi
(T3
) + Hi
(T2
);
3233 Prove_Multiplication
(Qd
(J
));
3235 -- Adjust quotient digit if it was too high
3237 -- We use the version of the algorithm in the 2nd Edition
3238 -- of "The Art of Computer Programming". This had a bug not
3239 -- discovered till 1995, see Vol 2 errata:
3240 -- http://www-cs-faculty.stanford.edu/~uno/err2-2e.ps.gz.
3241 -- Under rare circumstances the expression in the test could
3242 -- overflow. This version was further corrected in 2005, see
3244 -- http://www-cs-faculty.stanford.edu/~uno/all2-pre.ps.gz.
3245 -- This implementation is not impacted by these bugs, due
3246 -- to the use of a word-size comparison done in function Le3
3247 -- instead of a comparison on two-word integer quantities in
3248 -- the original algorithm.
3250 Lemma_Hi_Lo_3
(Zu
, Zhi
, Zlo
);
3252 while not Le3
(S1
, S2
, S3
, D
(J
), D
(J
+ 1), D
(J
+ 2)) loop
3253 pragma Loop_Invariant
3254 (for all K
in 1 .. J
=> Qd
(K
)'Initialized);
3255 pragma Loop_Invariant
(if J
= 2 then Qd
(1) = Qd1
);
3256 pragma Loop_Invariant
3257 (Big3
(S1
, S2
, S3
) = Big
(Double_Uns
(Qd
(J
))) * Big
(Zu
));
3258 pragma Loop_Invariant
3259 (Big3
(S1
, S2
, S3
) > Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)));
3260 pragma Assert
(Big3
(S1
, S2
, S3
) > 0);
3262 pragma Assert
(Big3
(S1
, S2
, S3
) = 0);
3263 pragma Assert
(False);
3265 Lemma_Ge_Commutation
(Double_Uns
(Qd
(J
)), 1);
3267 (Big
(Double_Uns
(Qd
(J
))), 1, Big
(Zu
), Big
(Zu
));
3269 Sub3
(S1
, S2
, S3
, 0, Zhi
, Zlo
);
3272 (Big3
(S1
, S2
, S3
) >
3273 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) - Big
(Zu
));
3274 Lemma_Subtract_Commutation
(Double_Uns
(Qd
(J
)), 1);
3275 pragma Assert
(Double_Uns
(Qd
(J
)) - Double_Uns
'(1)
3276 = Double_Uns (Qd (J) - 1));
3277 pragma Assert (Big (Double_Uns'(1)) = 1);
3278 Lemma_Substitution
(Big3
(S1
, S2
, S3
), Big
(Zu
),
3279 Big
(Double_Uns
(Qd
(J
))) - 1,
3280 Big
(Double_Uns
(Qd
(J
) - 1)), 0);
3283 Prev
: constant Single_Uns
:= Qd
(J
) - 1 with Ghost
;
3285 Qd
(J
) := Qd
(J
) - 1;
3287 pragma Assert
(Qd
(J
) = Prev
);
3291 (Big3
(S1
, S2
, S3
) = Big
(Double_Uns
(Qd
(J
))) * Big
(Zu
));
3294 -- Now subtract S1&S2&S3 from D1&D2&D3 ready for next step
3296 pragma Assert
(for all K
in 1 .. J
=> Qd
(K
)'Initialized);
3298 (Big3
(S1
, S2
, S3
) = Big
(Double_Uns
(Qd
(J
))) * Big
(Zu
));
3299 pragma Assert
(Big3
(S1
, S2
, S3
) >
3300 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) - Big
(Zu
));
3301 Inline_Le3
(S1
, S2
, S3
, D
(J
), D
(J
+ 1), D
(J
+ 2));
3303 Sub3
(D
(J
), D
(J
+ 1), D
(J
+ 2), S1
, S2
, S3
);
3305 pragma Assert
(Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) < Big
(Zu
));
3307 Lemma_Double_Big_2xxSingle
;
3308 pragma Assert
(Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) =
3310 * Big_2xxSingle
* Big
(Double_Uns
(D
(J
)))
3311 + Big_2xxSingle
* Big
(Double_Uns
(D
(J
+ 1)))
3312 + Big
(Double_Uns
(D
(J
+ 2))));
3313 pragma Assert
(Big_2xxSingle
>= 0);
3314 Lemma_Big_Of_Double_Uns_Of_Single_Uns
(D
(J
+ 1));
3315 pragma Assert
(Big
(Double_Uns
(D
(J
+ 1))) >= 0);
3316 Lemma_Mult_Non_Negative
3317 (Big_2xxSingle
, Big
(Double_Uns
(D
(J
+ 1))));
3319 (By
(Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) >=
3320 Big_2xxSingle
* Big_2xxSingle
3321 * Big
(Double_Uns
(D
(J
))),
3322 By
(Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2))
3323 - Big_2xxSingle
* Big_2xxSingle
3324 * Big
(Double_Uns
(D
(J
)))
3325 = Big_2xxSingle
* Big
(Double_Uns
(D
(J
+ 1)))
3326 + Big
(Double_Uns
(D
(J
+ 2))),
3327 Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) =
3329 * Big_2xxSingle
* Big
(Double_Uns
(D
(J
)))
3330 + Big_2xxSingle
* Big
(Double_Uns
(D
(J
+ 1)))
3331 + Big
(Double_Uns
(D
(J
+ 2))))
3333 By
(Big_2xxSingle
* Big
(Double_Uns
(D
(J
+ 1)))
3334 + Big
(Double_Uns
(D
(J
+ 2))) >= 0,
3335 Big_2xxSingle
* Big
(Double_Uns
(D
(J
+ 1))) >= 0
3337 Big
(Double_Uns
(D
(J
+ 2))) >= 0
3339 Lemma_Ge_Commutation
(Double_Uns
(D
(J
)), Double_Uns
'(1));
3340 Lemma_Ge_Mult (Big (Double_Uns (D (J))),
3341 Big (Double_Uns'(1)),
3343 Big
(Double_Uns
'(1)) * Big_2xxDouble);
3345 (Big_2xxDouble * Big (Double_Uns'(1)) = Big_2xxDouble
);
3347 (Big3
(D
(J
), D
(J
+ 1), D
(J
+ 2)) >= Big_2xxDouble
);
3348 pragma Assert
(False);
3353 D234
:= Big3
(D
(2), D
(3), D
(4));
3354 pragma Assert
(D4
= Big
(Double_Uns
(D
(4))));
3356 (Mult
* Big_2xx
(Scale
), Big_2xxSingle
, D123
,
3357 Big3
(D
(1), D
(2), D
(3)) + Big3
(S1
, S2
, S3
),
3358 Big
(Double_Uns
(D
(4))));
3359 Prove_First_Iteration
(D
(1), D
(2), D
(3), D
(4));
3360 Lemma_Substitution
(Mult
* Big_2xx
(Scale
), Big_2xxSingle
,
3362 Big
(Double_Uns
(Qd1
)) * Big
(Zu
),
3365 pragma Assert
(Qd1
= Qd
(1));
3367 (By
(Mult
* Big_2xx
(Scale
) =
3368 Big_2xxSingle
* Big
(Double_Uns
(Qd1
)) * Big
(Zu
)
3370 + Big3
(D
(2), D
(3), D
(4)),
3371 Big3
(D
(2), D
(3), D
(4)) = D234
- Big3
(S1
, S2
, S3
)));
3373 (By
(Mult
* Big_2xx
(Scale
) =
3374 Big_2xxSingle
* Big
(Double_Uns
(Qd
(1))) * Big
(Zu
)
3375 + Big
(Double_Uns
(Qd
(2))) * Big
(Zu
)
3376 + Big_2xxSingle
* Big
(Double_Uns
(D
(3)))
3377 + Big
(Double_Uns
(D
(4))),
3378 Big_2xxSingle
* Big
(Double_Uns
(Qd
(1))) * Big
(Zu
)
3379 = Big_2xxSingle
* Big
(Double_Uns
(Qd1
)) * Big
(Zu
)
3381 Big3
(S1
, S2
, S3
) = Big
(Double_Uns
(Qd
(2))) * Big
(Zu
)
3383 By
(Big3
(D
(2), D
(3), D
(4))
3384 = Big_2xxSingle
* Big
(Double_Uns
(D
(3)))
3385 + Big
(Double_Uns
(D
(4))),
3386 Big3
(D
(2), D
(3), D
(4))
3387 = Big_2xxSingle
* Big_2xxSingle
*
3388 Big
(Double_Uns
(D
(2)))
3389 + Big_2xxSingle
* Big
(Double_Uns
(D
(3)))
3390 + Big
(Double_Uns
(D
(4)))
3392 Big_2xxSingle
* Big_2xxSingle
* Big
(Double_Uns
(D
(2)))
3399 -- The two quotient digits are now set, and the remainder of the
3400 -- scaled division is in D3&D4. To get the remainder for the
3401 -- original unscaled division, we rescale this dividend.
3403 -- We rescale the divisor as well, to make the proper comparison
3404 -- for rounding below.
3406 pragma Assert
(for all K
in 1 .. 2 => Qd
(K
)'Initialized);
3407 Qu
:= Qd
(1) & Qd
(2);
3408 Ru
:= D
(3) & D
(4);
3411 (Mult
* Big_2xx
(Scale
) =
3412 Big_2xxSingle
* Big
(Double_Uns
(Qd
(1))) * Big
(Zu
)
3413 + Big
(Double_Uns
(Qd
(2))) * Big
(Zu
)
3414 + Big_2xxSingle
* Big
(Double_Uns
(D
(3)))
3415 + Big
(Double_Uns
(D
(4))));
3416 Lemma_Hi_Lo
(Qu
, Qd
(1), Qd
(2));
3417 Lemma_Hi_Lo
(Ru
, D
(3), D
(4));
3419 (Mult
* Big_2xx
(Scale
), Big
(Zu
),
3420 Big_2xxSingle
* Big
(Double_Uns
(Qd
(1)))
3421 + Big
(Double_Uns
(Qd
(2))),
3422 Big
(Qu
), Big
(Ru
));
3425 Ru
:= Shift_Right
(Ru
, Scale
);
3427 Lemma_Shift_Right
(Zu
, Scale
);
3429 Zu
:= Shift_Right
(Zu
, Scale
);
3431 Lemma_Simplify
(Big
(Double_Uns
'(abs Z)), Big_2xx (Scale));
3434 pragma Assert (Big (Ru) = abs Big_R);
3435 pragma Assert (Big (Qu) = abs Quot);
3436 pragma Assert (Big (Zu) = Big (Double_Uns'(abs Z
)));
3438 -- Deal with rounding case
3441 Prove_Rounding_Case
;
3443 if Ru
> (Zu
- Double_Uns
'(1)) / Double_Uns'(2) then
3444 pragma Assert
(abs Big_Q
= Big
(Qu
) + 1);
3446 -- Protect against wrapping around when rounding, by signaling
3447 -- an overflow when the quotient is too large.
3449 if Qu
= Double_Uns
'Last then
3456 Qu
:= Qu
+ Double_Uns
'(1);
3460 pragma Assert (Big (Qu) = abs Big_Q);
3462 -- Set final signs (RM 4.5.5(27-30))
3464 -- Case of dividend (X * Y) sign positive
3466 if (X >= 0 and then Y >= 0) or else (X < 0 and then Y < 0) then
3467 Prove_Positive_Dividend;
3469 R := To_Pos_Int (Ru);
3470 Q := (if Z > 0 then To_Pos_Int (Qu) else To_Neg_Int (Qu));
3472 -- Case of dividend (X * Y) sign negative
3475 Prove_Negative_Dividend;
3477 R := To_Neg_Int (Ru);
3478 Q := (if Z > 0 then To_Neg_Int (Qu) else To_Pos_Int (Qu));
3489 procedure Sub3 (X1, X2, X3 : in out Single_Uns; Y1, Y2, Y3 : Single_Uns) is
3491 -- Local ghost variables
3493 XX1 : constant Single_Uns := X1 with Ghost;
3494 XX2 : constant Single_Uns := X2 with Ghost;
3495 XX3 : constant Single_Uns := X3 with Ghost;
3499 procedure Lemma_Add3_No_Carry (X1, X2, X3, Y1, Y2, Y3 : Single_Uns)
3502 Pre => X1 <= Single_Uns'Last - Y1
3503 and then X2 <= Single_Uns'Last - Y2
3504 and then X3 <= Single_Uns'Last - Y3,
3505 Post => Big3 (X1 + Y1, X2 + Y2, X3 + Y3)
3506 = Big3 (X1, X2, X3) + Big3 (Y1, Y2, Y3);
3508 procedure Lemma_Ge_Expand (X1, X2, X3, Y1, Y2, Y3 : Single_Uns)
3511 Pre => Big3 (X1, X2, X3) >= Big3 (Y1, Y2, Y3),
3513 or else (X1 = Y1 and then X2 > Y2)
3514 or else (X1 = Y1 and then X2 = Y2 and then X3 >= Y3);
3516 procedure Lemma_Sub3_No_Carry (X1, X2, X3, Y1, Y2, Y3 : Single_Uns)
3519 Pre => X1 >= Y1 and then X2 >= Y2 and then X3 >= Y3,
3520 Post => Big3 (X1 - Y1, X2 - Y2, X3 - Y3)
3521 = Big3 (X1, X2, X3) - Big3 (Y1, Y2, Y3);
3523 procedure Lemma_Sub3_With_Carry2 (X1, X2, X3, Y2 : Single_Uns)
3527 Post => Big3 (X1, X2 - Y2, X3)
3528 = Big3 (X1, X2, X3) + Big3 (Single_Uns'(1), 0, 0) - Big3
(0, Y2
, 0);
3530 procedure Lemma_Sub3_With_Carry3
(X1
, X2
, X3
, Y3
: Single_Uns
)
3534 Post
=> Big3
(X1
, X2
, X3
- Y3
)
3535 = Big3
(X1
, X2
, X3
) + Big3
(Single_Uns
'(0), 1, 0) - Big3 (0, 0, Y3);
3537 -------------------------
3538 -- Lemma_Add3_No_Carry --
3539 -------------------------
3541 procedure Lemma_Add3_No_Carry (X1, X2, X3, Y1, Y2, Y3 : Single_Uns) is
3543 Lemma_Add_Commutation (Double_Uns (X1), Y1);
3544 Lemma_Add_Commutation (Double_Uns (X2), Y2);
3545 Lemma_Add_Commutation (Double_Uns (X3), Y3);
3546 pragma Assert (Double_Uns (Single_Uns'(X1
+ Y1
))
3547 = Double_Uns
(X1
) + Double_Uns
(Y1
));
3548 pragma Assert
(Double_Uns
(Single_Uns
'(X2 + Y2))
3549 = Double_Uns (X2) + Double_Uns (Y2));
3550 pragma Assert (Double_Uns (Single_Uns'(X3
+ Y3
))
3551 = Double_Uns
(X3
) + Double_Uns
(Y3
));
3552 end Lemma_Add3_No_Carry
;
3554 ---------------------
3555 -- Lemma_Ge_Expand --
3556 ---------------------
3558 procedure Lemma_Ge_Expand
(X1
, X2
, X3
, Y1
, Y2
, Y3
: Single_Uns
) is null;
3560 -------------------------
3561 -- Lemma_Sub3_No_Carry --
3562 -------------------------
3564 procedure Lemma_Sub3_No_Carry
(X1
, X2
, X3
, Y1
, Y2
, Y3
: Single_Uns
) is
3566 Lemma_Subtract_Commutation
(Double_Uns
(X1
), Double_Uns
(Y1
));
3567 Lemma_Subtract_Commutation
(Double_Uns
(X2
), Double_Uns
(Y2
));
3568 Lemma_Subtract_Commutation
(Double_Uns
(X3
), Double_Uns
(Y3
));
3569 end Lemma_Sub3_No_Carry
;
3571 ----------------------------
3572 -- Lemma_Sub3_With_Carry2 --
3573 ----------------------------
3575 procedure Lemma_Sub3_With_Carry2
(X1
, X2
, X3
, Y2
: Single_Uns
) is
3576 pragma Unreferenced
(X1
, X3
);
3578 Lemma_Add_Commutation
3579 (Double_Uns
'(2 ** Single_Size) - Double_Uns (Y2), X2);
3580 Lemma_Subtract_Commutation
3581 (Double_Uns'(2 ** Single_Size
), Double_Uns
(Y2
));
3582 end Lemma_Sub3_With_Carry2
;
3584 ----------------------------
3585 -- Lemma_Sub3_With_Carry3 --
3586 ----------------------------
3588 procedure Lemma_Sub3_With_Carry3
(X1
, X2
, X3
, Y3
: Single_Uns
) is
3589 pragma Unreferenced
(X1
, X2
);
3591 Lemma_Add_Commutation
3592 (Double_Uns
'(2 ** Single_Size) - Double_Uns (Y3), X3);
3593 Lemma_Subtract_Commutation
3594 (Double_Uns'(2 ** Single_Size
), Double_Uns
(Y3
));
3595 end Lemma_Sub3_With_Carry3
;
3597 -- Start of processing for Sub3
3600 Lemma_Ge_Expand
(X1
, X2
, X3
, Y1
, Y2
, Y3
);
3604 pragma Assert
(X1
>= 1);
3605 Lemma_Sub3_No_Carry
(X1
, X2
, X3
, 1, 0, 0);
3610 (Big3
(X1
, X2
, X3
) =
3611 Big3
(XX1
, XX2
, XX3
) - Big3
(Single_Uns
'(1), 0, 0));
3613 (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3)
3614 - Big3 (Single_Uns'(0), Single_Uns
'Last, 0)
3615 - Big3
(Single_Uns
'(0), 1, 0));
3616 Lemma_Add3_No_Carry (X1, X2, X3, 0, Single_Uns'Last, 0);
3618 Lemma_Sub3_No_Carry (X1, X2, X3, 0, 1, 0);
3624 (Big3 (X1, X2, X3) =
3625 Big3 (XX1, XX2, XX3) - Big3 (Single_Uns'(0), 1, 0));
3626 Lemma_Sub3_With_Carry3
(X1
, X2
, X3
, Y3
);
3628 Lemma_Sub3_No_Carry
(X1
, X2
, X3
, 0, 0, Y3
);
3634 (Big3
(X1
, X2
, X3
) = Big3
(XX1
, XX2
, XX3
) - Big3
(0, 0, Y3
));
3637 pragma Assert
(X1
>= 1);
3638 Lemma_Sub3_No_Carry
(X1
, X2
, X3
, 1, 0, 0);
3643 (Big3
(X1
, X2
, X3
) = Big3
(XX1
, XX2
, XX3
)
3644 - Big3
(0, 0, Y3
) - Big3
(Single_Uns
'(1), 0, 0));
3645 Lemma_Sub3_With_Carry2 (X1, X2, X3, Y2);
3647 Lemma_Sub3_No_Carry (X1, X2, X3, 0, Y2, 0);
3653 (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3) - Big3 (0, Y2, Y3));
3654 pragma Assert (X1 >= Y1);
3655 Lemma_Sub3_No_Carry (X1, Y2, X3, Y1, 0, 0);
3660 (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3)
3661 - Big3 (0, Y2, Y3) - Big3 (Y1, 0, 0));
3662 Lemma_Add3_No_Carry (0, Y2, Y3, Y1, 0, 0);
3664 (Big3 (X1, X2, X3) = Big3 (XX1, XX2, XX3) - Big3 (Y1, Y2, Y3));
3667 -------------------------------
3668 -- Subtract_With_Ovflo_Check --
3669 -------------------------------
3671 function Subtract_With_Ovflo_Check (X, Y : Double_Int) return Double_Int is
3672 R : constant Double_Int := To_Int (To_Uns (X) - To_Uns (Y));
3676 procedure Prove_Negative_X
3679 Pre => X < 0 and then (Y <= 0 or else R < 0),
3682 procedure Prove_Non_Negative_X
3685 Pre => X >= 0 and then (Y > 0 or else R >= 0),
3688 procedure Prove_Overflow_Case
3692 (if X >= 0 then Y <= 0 and then R < 0
3693 else Y > 0 and then R >= 0),
3694 Post => not In_Double_Int_Range (Big (X) - Big (Y));
3696 ----------------------
3697 -- Prove_Negative_X --
3698 ----------------------
3700 procedure Prove_Negative_X is
3702 if X = Double_Int'First then
3703 if Y = Double_Int'First or else Y > 0 then
3707 (To_Uns (X) - To_Uns (Y) =
3708 2 ** (Double_Size - 1) + Double_Uns (-Y));
3711 elsif Y >= 0 or else Y = Double_Int'First then
3716 (To_Uns (X) - To_Uns (Y) = -Double_Uns (-X) + Double_Uns (-Y));
3718 end Prove_Negative_X;
3720 --------------------------
3721 -- Prove_Non_Negative_X --
3722 --------------------------
3724 procedure Prove_Non_Negative_X is
3728 Ru : constant Double_Uns := To_Uns (X) - To_Uns (Y);
3730 pragma Assert (Ru = Double_Uns (X) - Double_Uns (Y));
3731 if Ru < 2 ** (Double_Size - 1) then -- R >= 0
3732 pragma Assert (To_Uns (Y) <= To_Uns (X));
3733 Lemma_Subtract_Double_Uns (X => Y, Y => X);
3734 pragma Assert (Ru = Double_Uns (X - Y));
3736 elsif Ru = 2 ** (Double_Size - 1) then
3737 pragma Assert (Double_Uns (Y) < 2 ** (Double_Size - 1));
3738 pragma Assert (False);
3742 (R = -Double_Int (-(Double_Uns (X) - Double_Uns (Y))));
3744 (R = -Double_Int (-Double_Uns (X) + Double_Uns (Y)));
3746 (R = -Double_Int (Double_Uns (Y) - Double_Uns (X)));
3750 elsif Y = Double_Int'First then
3752 (To_Uns (X) - To_Uns (Y) =
3753 Double_Uns (X) - 2 ** (Double_Size - 1));
3754 pragma Assert (False);
3758 (To_Uns (X) - To_Uns (Y) = Double_Uns (X) + Double_Uns (-Y));
3760 end Prove_Non_Negative_X;
3762 -------------------------
3763 -- Prove_Overflow_Case --
3764 -------------------------
3766 procedure Prove_Overflow_Case is
3768 if X >= 0 and then Y /= Double_Int'First then
3770 (To_Uns (X) - To_Uns (Y) = Double_Uns (X) + Double_Uns (-Y));
3772 elsif X < 0 and then X /= Double_Int'First then
3774 (To_Uns (X) - To_Uns (Y) = -Double_Uns (-X) - Double_Uns (Y));
3776 end Prove_Overflow_Case;
3778 -- Start of processing for Subtract_With_Ovflo_Check
3782 if Y > 0 or else R >= 0 then
3783 Prove_Non_Negative_X;
3788 if Y <= 0 or else R < 0 then
3794 Prove_Overflow_Case;
3796 end Subtract_With_Ovflo_Check;
3802 function To_Neg_Int (A : Double_Uns) return Double_Int is
3803 R : constant Double_Int :=
3804 (if A = 2 ** (Double_Size - 1) then Double_Int'First else -To_Int (A));
3805 -- Note that we can't just use the expression of the Else, because it
3806 -- overflows for A = 2 ** (Double_Size - 1).
3819 function To_Pos_Int (A : Double_Uns) return Double_Int is
3820 R : constant Double_Int := To_Int (A);
3829 end System.Arith_Double;