[Ada] Fix proof of runtime unit System.Arith_64
After changes in provers and Why3, changes are needed to recover automatic proof of System.Arith_64. This is the first part of it. gcc/ada/ * libgnat/s-aridou.adb (Lemma_Mult_Div, Lemma_Powers): New lemmas. (Prove_Sign_Quotient): New local lemma. (Prove_Signs): Expand definition of Big_R and Big_Q in the postcondition. Add intermediate assertions. (Double_Divide): Call new lemma. (Lemma_Div_Eq): Provide body for proving lemma. (Lemma_Powers_Of_2, Lemma_Shift_Without_Drop, Prove_Dividend_Scaling, Prove_Multiplication, Prove_Z_Low): Call lemmas, add intermediate assertions.
This commit is contained in:
parent
d03a7f8c24
commit
4709037646
@ -438,6 +438,12 @@ is
|
||||
Ghost,
|
||||
Post => X * (Y + Z) = X * Y + X * Z;
|
||||
|
||||
procedure Lemma_Mult_Div (A, B : Big_Integer)
|
||||
with
|
||||
Ghost,
|
||||
Pre => B /= 0,
|
||||
Post => A * B / B = A;
|
||||
|
||||
procedure Lemma_Mult_Non_Negative (X, Y : Big_Integer)
|
||||
with
|
||||
Ghost,
|
||||
@ -469,6 +475,12 @@ is
|
||||
Post => not In_Double_Int_Range (Big_2xxDouble)
|
||||
and then not In_Double_Int_Range (-Big_2xxDouble);
|
||||
|
||||
procedure Lemma_Powers (A : Big_Natural; B, C : Natural)
|
||||
with
|
||||
Ghost,
|
||||
Pre => B <= Natural'Last - C,
|
||||
Post => A**B * A**C = A**(B + C);
|
||||
|
||||
procedure Lemma_Powers_Of_2 (M, N : Natural)
|
||||
with
|
||||
Ghost,
|
||||
@ -606,7 +618,6 @@ is
|
||||
is null;
|
||||
procedure Lemma_Div_Ge (X, Y, Z : Big_Integer) is null;
|
||||
procedure Lemma_Div_Lt (X, Y, Z : Big_Natural) is null;
|
||||
procedure Lemma_Div_Eq (A, B, S, R : Big_Integer) is null;
|
||||
procedure Lemma_Double_Big_2xxSingle is null;
|
||||
procedure Lemma_Double_Shift (X : Double_Uns; S, S1 : Double_Uns) is null;
|
||||
procedure Lemma_Double_Shift (X : Single_Uns; S, S1 : Natural) is null;
|
||||
@ -629,6 +640,7 @@ is
|
||||
procedure Lemma_Mult_Non_Positive (X, Y : Big_Integer) is null;
|
||||
procedure Lemma_Neg_Rem (X, Y : Big_Integer) is null;
|
||||
procedure Lemma_Not_In_Range_Big2xx64 is null;
|
||||
procedure Lemma_Powers (A : Big_Natural; B, C : Natural) is null;
|
||||
procedure Lemma_Rem_Commutation (X, Y : Double_Uns) is null;
|
||||
procedure Lemma_Rem_Is_Ident (X, Y : Big_Integer) is null;
|
||||
procedure Lemma_Rem_Sign (X, Y : Big_Integer) is null;
|
||||
@ -864,6 +876,23 @@ is
|
||||
Post => abs Big_Q = Big (Qu);
|
||||
-- Proves correctness of the rounding of the unsigned quotient
|
||||
|
||||
procedure Prove_Sign_Quotient
|
||||
with
|
||||
Ghost,
|
||||
Pre => Mult /= 0
|
||||
and then Quot = Big (X) / (Big (Y) * Big (Z))
|
||||
and then Big_R = Big (X) rem (Big (Y) * Big (Z))
|
||||
and then Big_Q =
|
||||
(if Round then
|
||||
Round_Quotient (Big (X), Big (Y) * Big (Z), Quot, Big_R)
|
||||
else Quot),
|
||||
Post =>
|
||||
(if X >= 0 then
|
||||
(if Den_Pos then Big_Q >= 0 else Big_Q <= 0)
|
||||
else
|
||||
(if Den_Pos then Big_Q <= 0 else Big_Q >= 0));
|
||||
-- Proves the correct sign of the signed quotient Big_Q
|
||||
|
||||
procedure Prove_Signs
|
||||
with
|
||||
Ghost,
|
||||
@ -880,7 +909,13 @@ is
|
||||
and then
|
||||
Q = (if (X >= 0) = Den_Pos then To_Int (Qu) else To_Int (-Qu))
|
||||
and then not (X = Double_Int'First and then Big (Y) * Big (Z) = -1),
|
||||
Post => Big (R) = Big_R and then Big (Q) = Big_Q;
|
||||
Post => Big (R) = Big (X) rem (Big (Y) * Big (Z))
|
||||
and then
|
||||
(if Round then
|
||||
Big (Q) = Round_Quotient (Big (X), Big (Y) * Big (Z),
|
||||
Big (X) / (Big (Y) * Big (Z)),
|
||||
Big (R))
|
||||
else Big (Q) = Big (X) / (Big (Y) * Big (Z)));
|
||||
-- Proves final signs match the intended result after the unsigned
|
||||
-- division is done.
|
||||
|
||||
@ -891,6 +926,7 @@ is
|
||||
procedure Prove_Overflow_Case is null;
|
||||
procedure Prove_Quotient_Zero is null;
|
||||
procedure Prove_Round_To_One is null;
|
||||
procedure Prove_Sign_Quotient is null;
|
||||
|
||||
-------------------------
|
||||
-- Prove_Rounding_Case --
|
||||
@ -1056,6 +1092,8 @@ is
|
||||
pragma Assert (Big (Double_Uns (Hi (T2))) >= 1);
|
||||
pragma Assert (Big (Double_Uns (Lo (T2))) >= 0);
|
||||
pragma Assert (Big (Double_Uns (Lo (T1))) >= 0);
|
||||
pragma Assert (Big_2xxSingle * Big (Double_Uns (Lo (T2)))
|
||||
+ Big (Double_Uns (Lo (T1))) >= 0);
|
||||
pragma Assert (Mult >= Big_2xxDouble * Big (Double_Uns (Hi (T2))));
|
||||
pragma Assert (Mult >= Big_2xxDouble);
|
||||
if Hi (T2) > 1 then
|
||||
@ -1064,6 +1102,10 @@ is
|
||||
Mult > Big_2xxDouble);
|
||||
elsif Lo (T2) > 0 then
|
||||
pragma Assert (Big (Double_Uns (Lo (T2))) > 0);
|
||||
pragma Assert (Big_2xxSingle > 0);
|
||||
pragma Assert (Big_2xxSingle * Big (Double_Uns (Lo (T2))) > 0);
|
||||
pragma Assert (Big_2xxSingle * Big (Double_Uns (Lo (T2)))
|
||||
+ Big (Double_Uns (Lo (T1))) > 0);
|
||||
pragma Assert (if X = Double_Int'First and then Round then
|
||||
Mult > Big_2xxDouble);
|
||||
elsif Lo (T1) > 0 then
|
||||
@ -1138,6 +1180,7 @@ is
|
||||
end if;
|
||||
|
||||
pragma Assert (abs Big_Q = Big (Qu));
|
||||
Prove_Sign_Quotient;
|
||||
|
||||
-- Set final signs (RM 4.5.5(27-30))
|
||||
|
||||
@ -1225,6 +1268,18 @@ is
|
||||
pragma Assert ((Hi or Lo) = Hi + Lo);
|
||||
end Lemma_Concat_Definition;
|
||||
|
||||
------------------
|
||||
-- Lemma_Div_Eq --
|
||||
------------------
|
||||
|
||||
procedure Lemma_Div_Eq (A, B, S, R : Big_Integer) is
|
||||
begin
|
||||
pragma Assert ((A - B) * S = R);
|
||||
pragma Assert ((A - B) * S / S = R / S);
|
||||
Lemma_Mult_Div (A - B, S);
|
||||
pragma Assert (A - B = R / S);
|
||||
end Lemma_Div_Eq;
|
||||
|
||||
------------------------
|
||||
-- Lemma_Double_Shift --
|
||||
------------------------
|
||||
@ -1317,6 +1372,19 @@ is
|
||||
+ Big (Double_Uns'(Xlo * Ylo)));
|
||||
end Lemma_Mult_Decomposition;
|
||||
|
||||
--------------------
|
||||
-- Lemma_Mult_Div --
|
||||
--------------------
|
||||
|
||||
procedure Lemma_Mult_Div (A, B : Big_Integer) is
|
||||
begin
|
||||
if B > 0 then
|
||||
pragma Assert (A * B / B = A);
|
||||
else
|
||||
pragma Assert (A * (-B) / (-B) = A);
|
||||
end if;
|
||||
end Lemma_Mult_Div;
|
||||
|
||||
-------------------
|
||||
-- Lemma_Neg_Div --
|
||||
-------------------
|
||||
@ -1341,6 +1409,7 @@ is
|
||||
Lemma_Powers_Of_2_Commutation (M);
|
||||
Lemma_Powers_Of_2_Commutation (N);
|
||||
Lemma_Powers_Of_2_Commutation (M + N);
|
||||
Lemma_Powers (Big (Double_Uns'(2)), M, N);
|
||||
|
||||
if M + N < Double_Size then
|
||||
pragma Assert (Big (Double_Uns'(2))**M * Big (Double_Uns'(2))**N
|
||||
@ -1516,6 +1585,8 @@ is
|
||||
pragma Assert (X < 2**(Double_Size - Shift));
|
||||
pragma Assert (Big (X) < Big_2xx (Double_Size - Shift));
|
||||
pragma Assert (Y = 2**Shift * X);
|
||||
Lemma_Lt_Mult (Big (X), Big_2xx (Double_Size - Shift), Big_2xx (Shift),
|
||||
Big_2xx (Shift) * Big_2xx (Double_Size - Shift));
|
||||
pragma Assert (Big_2xx (Shift) * Big (X)
|
||||
< Big_2xx (Shift) * Big_2xx (Double_Size - Shift));
|
||||
Lemma_Powers_Of_2 (Shift, Double_Size - Shift);
|
||||
@ -2063,8 +2134,8 @@ is
|
||||
|
||||
begin
|
||||
Lemma_Shift_Left (D (1) & D (2), Scale);
|
||||
pragma Assert (By (Big_2xxSingle * Big_2xx (Scale) <= Big_2xxDouble,
|
||||
Big_2xx (Scale) <= Big_2xxSingle));
|
||||
Lemma_Ge_Mult (Big_2xxSingle, Big_2xx (Scale), Big_2xxSingle,
|
||||
Big_2xxSingle * Big_2xx (Scale));
|
||||
Lemma_Lt_Mult (Big (Double_Uns (D (3))), Big_2xxSingle,
|
||||
Big_2xx (Scale), Big_2xxDouble);
|
||||
Lemma_Shift_Left (Double_Uns (D (3)), Scale);
|
||||
@ -2225,10 +2296,23 @@ is
|
||||
pragma Assert
|
||||
(Big (Double_Uns (Hi (T3))) + Big (Double_Uns (Hi (T2))) =
|
||||
Big (Double_Uns (S1)));
|
||||
Lemma_Mult_Distribution (Big_2xxSingle * Big_2xxSingle,
|
||||
Big (Double_Uns (Hi (T3))),
|
||||
Big (Double_Uns (Hi (T2))));
|
||||
pragma Assert
|
||||
(Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T2)))
|
||||
+ Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (Hi (T3)))
|
||||
= Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (S1)));
|
||||
pragma Assert (Big (Double_Uns (Q)) * Big (Zu) =
|
||||
Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (S1))
|
||||
+ Big_2xxSingle * Big (Double_Uns (S2))
|
||||
+ Big (Double_Uns (S3)));
|
||||
pragma Assert
|
||||
(By (Big (Double_Uns (Q)) * Big (Zu) = Big3 (S1, S2, S3),
|
||||
Big3 (S1, S2, S3) =
|
||||
Big_2xxSingle * Big_2xxSingle * Big (Double_Uns (S1))
|
||||
+ Big_2xxSingle * Big (Double_Uns (S2))
|
||||
+ Big (Double_Uns (S3))));
|
||||
end Prove_Multiplication;
|
||||
|
||||
-----------------------------
|
||||
@ -2357,6 +2441,7 @@ is
|
||||
Lemma_Div_Definition (T1, Zlo, T1 / Zlo, T1 rem Zlo);
|
||||
pragma Assert (Double_Uns (Lo (T1 rem Zlo)) = T1 rem Zlo);
|
||||
Lemma_Hi_Lo (T2, Lo (T1 rem Zlo), D (4));
|
||||
pragma Assert (T1 rem Zlo < Double_Uns (Zlo));
|
||||
pragma Assert (T1 rem Zlo + Double_Uns'(1) <= Double_Uns (Zlo));
|
||||
Lemma_Ge_Commutation (Double_Uns (Zlo), T1 rem Zlo + Double_Uns'(1));
|
||||
Lemma_Add_Commutation (T1 rem Zlo, 1);
|
||||
@ -2365,6 +2450,9 @@ is
|
||||
pragma Assert
|
||||
(Mult = Big (Double_Uns (Zlo)) *
|
||||
(Big_2xxSingle * Big (T1 / Zlo) + Big (T2 / Zlo)) + Big (Ru));
|
||||
pragma Assert (Big_2xxSingle * Big (Double_Uns (D (2)))
|
||||
+ Big (Double_Uns (D (3)))
|
||||
< Big_2xxSingle * (Big (Double_Uns (D (2))) + 1));
|
||||
Lemma_Div_Lt (Big (T1), Big_2xxSingle, Big (Double_Uns (Zlo)));
|
||||
Lemma_Div_Commutation (T1, Double_Uns (Zlo));
|
||||
Lemma_Lo_Is_Ident (T1 / Zlo);
|
||||
|
Loading…
Reference in New Issue
Block a user