initial import from Debian
version: 14.3.0-5 commit: bee30ab0fff2fd6af94c62376c8aa4221bb831e0
This commit is contained in:
290
debian/patches/ada-numerics-arrays-eigenv-revert-a210011.diff
vendored
Normal file
290
debian/patches/ada-numerics-arrays-eigenv-revert-a210011.diff
vendored
Normal file
@@ -0,0 +1,290 @@
|
||||
Revert upstream commit a210011c5c7f7be5e7a9aea294947bdc555202ce
|
||||
(Ada: Fix thinko in Eigensystem for complex Hermitian matrices)
|
||||
|
||||
This fix would change the libgnat-14-HASH virtual package and require
|
||||
a rebuild of all Ada libraries.
|
||||
|
||||
Bug-Debian: http://bugs.debian.org/1104593
|
||||
|
||||
--- a/src/gcc/ada/libgnat/a-ngcoar.adb
|
||||
+++ b/src/gcc/ada/libgnat/a-ngcoar.adb
|
||||
@@ -1058,21 +1058,19 @@ package body Ada.Numerics.Generic_Comple
|
||||
is
|
||||
N : constant Natural := Length (A);
|
||||
|
||||
- -- For a Hermitian matrix A, we convert the eigenvalue problem to a
|
||||
- -- real symmetric one: if A = X + i * Y, then the (N, N) complex
|
||||
+ -- For a Hermitian matrix C, we convert the eigenvalue problem to a
|
||||
+ -- real symmetric one: if C = A + i * B, then the (N, N) complex
|
||||
-- eigenvalue problem:
|
||||
- --
|
||||
- -- (X + i * Y) * (u + i * v) = Lambda * (u + i * v)
|
||||
+ -- (A + i * B) * (u + i * v) = Lambda * (u + i * v)
|
||||
--
|
||||
-- is equivalent to the (2 * N, 2 * N) real eigenvalue problem:
|
||||
+ -- [ A, B ] [ u ] = Lambda * [ u ]
|
||||
+ -- [ -B, A ] [ v ] [ v ]
|
||||
--
|
||||
- -- [ X, -Y ] [ u ] = Lambda * [ u ]
|
||||
- -- [ Y, X ] [ v ] [ v ]
|
||||
- --
|
||||
- -- Note that the (2 * N, 2 * N) matrix M above is symmetric, because
|
||||
- -- Transpose (X) = X and Transpose (Y) = -Y as A is Hermitian.
|
||||
+ -- Note that the (2 * N, 2 * N) matrix above is symmetric, as
|
||||
+ -- Transpose (A) = A and Transpose (B) = -B if C is Hermitian.
|
||||
|
||||
- -- We solve this eigensystem using the real-valued algorithm. The final
|
||||
+ -- We solve this eigensystem using the real-valued algorithms. The final
|
||||
-- result will have every eigenvalue twice, so in the sorted output we
|
||||
-- just pick every second value, with associated eigenvector u + i * v.
|
||||
|
||||
@@ -1087,8 +1085,10 @@ package body Ada.Numerics.Generic_Comple
|
||||
C : constant Complex :=
|
||||
(A (A'First (1) + (J - 1), A'First (2) + (K - 1)));
|
||||
begin
|
||||
- M (J, K) := Re (C); M (J, K + N) := -Im (C);
|
||||
- M (J + N, K) := Im (C); M (J + N, K + N) := Re (C);
|
||||
+ M (J, K) := Re (C);
|
||||
+ M (J + N, K + N) := Re (C);
|
||||
+ M (J + N, K) := Im (C);
|
||||
+ M (J, K + N) := -Im (C);
|
||||
end;
|
||||
end loop;
|
||||
end loop;
|
||||
@@ -1103,9 +1103,10 @@ package body Ada.Numerics.Generic_Comple
|
||||
|
||||
for K in 1 .. N loop
|
||||
declare
|
||||
- Row : constant Integer := Vectors'First (1) + (K - 1);
|
||||
+ Row : constant Integer := Vectors'First (2) + (K - 1);
|
||||
begin
|
||||
- Vectors (Row, Col) := (Vecs (K, 2 * J), Vecs (K + N, 2 * J));
|
||||
+ Vectors (Row, Col)
|
||||
+ := (Vecs (J * 2, Col), Vecs (J * 2, Col + N));
|
||||
end;
|
||||
end loop;
|
||||
end;
|
||||
@@ -1117,14 +1118,13 @@ package body Ada.Numerics.Generic_Comple
|
||||
-----------------
|
||||
|
||||
function Eigenvalues (A : Complex_Matrix) return Real_Vector is
|
||||
- N : constant Natural := Length (A);
|
||||
-
|
||||
-- See Eigensystem for a description of the algorithm
|
||||
|
||||
+ N : constant Natural := Length (A);
|
||||
+ R : Real_Vector (A'Range (1));
|
||||
+
|
||||
M : Real_Matrix (1 .. 2 * N, 1 .. 2 * N);
|
||||
- R : Real_Vector (A'Range (1));
|
||||
Vals : Real_Vector (1 .. 2 * N);
|
||||
-
|
||||
begin
|
||||
for J in 1 .. N loop
|
||||
for K in 1 .. N loop
|
||||
@@ -1132,8 +1132,10 @@ package body Ada.Numerics.Generic_Comple
|
||||
C : constant Complex :=
|
||||
(A (A'First (1) + (J - 1), A'First (2) + (K - 1)));
|
||||
begin
|
||||
- M (J, K) := Re (C); M (J, K + N) := -Im (C);
|
||||
- M (J + N, K) := Im (C); M (J + N, K + N) := Re (C);
|
||||
+ M (J, K) := Re (C);
|
||||
+ M (J + N, K + N) := Re (C);
|
||||
+ M (J + N, K) := Im (C);
|
||||
+ M (J, K + N) := -Im (C);
|
||||
end;
|
||||
end loop;
|
||||
end loop;
|
||||
--- a/src/gcc/ada/libgnat/a-ngrear.adb
|
||||
+++ b/src/gcc/ada/libgnat/a-ngrear.adb
|
||||
@@ -85,7 +85,7 @@ package body Ada.Numerics.Generic_Real_A
|
||||
|
||||
function Is_Symmetric (A : Real_Matrix) return Boolean is
|
||||
(Transpose (A) = A);
|
||||
- -- Return True iff A is symmetric, see RM G.3.1 (90)
|
||||
+ -- Return True iff A is symmetric, see RM G.3.1 (90).
|
||||
|
||||
function Is_Tiny (Value, Compared_To : Real) return Boolean is
|
||||
(abs Compared_To + 100.0 * abs (Value) = abs Compared_To);
|
||||
@@ -104,7 +104,7 @@ package body Ada.Numerics.Generic_Real_A
|
||||
-- not a square matrix, and otherwise returns its length.
|
||||
|
||||
procedure Rotate (X, Y : in out Real; Sin, Tau : Real);
|
||||
- -- Perform a Givens rotation of angle Theta given by sin and sin/(1 + cos)
|
||||
+ -- Perform a Givens rotation
|
||||
|
||||
procedure Sort_Eigensystem
|
||||
(Values : in out Real_Vector;
|
||||
@@ -525,13 +525,13 @@ package body Ada.Numerics.Generic_Real_A
|
||||
Vectors : out Real_Matrix;
|
||||
Compute_Vectors : Boolean)
|
||||
is
|
||||
- -- This subprogram uses Carl Gustav Jacob Jacobi's cyclic iterative
|
||||
- -- method for computing eigenvalues and eigenvectors and is based on
|
||||
+ -- This subprogram uses Carl Gustav Jacob Jacobi's iterative method
|
||||
+ -- for computing eigenvalues and eigenvectors and is based on
|
||||
-- Rutishauser's implementation.
|
||||
|
||||
-- The given real symmetric matrix is transformed iteratively to
|
||||
-- diagonal form through a sequence of appropriately chosen elementary
|
||||
- -- orthogonal transformations, called Jacobi rotations.
|
||||
+ -- orthogonal transformations, called Jacobi rotations here.
|
||||
|
||||
-- The Jacobi method produces a systematic decrease of the sum of the
|
||||
-- squares of off-diagonal elements. Convergence to zero is quadratic,
|
||||
@@ -542,44 +542,41 @@ package body Ada.Numerics.Generic_Real_A
|
||||
-- best choice here, even though for large matrices other methods will
|
||||
-- be significantly more efficient in both time and space.
|
||||
|
||||
- -- While the eigensystem computation is absolutely foolproof for all
|
||||
+ -- While the eigensystem computations are absolutely foolproof for all
|
||||
-- real symmetric matrices, in presence of invalid values, or similar
|
||||
- -- exceptional situations, it may not be. In such cases, the results
|
||||
- -- cannot be trusted and Constraint_Error is raised.
|
||||
+ -- exceptional situations it might not. In such cases the results cannot
|
||||
+ -- be trusted and Constraint_Error is raised.
|
||||
|
||||
-- Note: this implementation needs temporary storage for 2 * N + N**2
|
||||
-- values of type Real.
|
||||
|
||||
- Max_Iterations : constant := 50;
|
||||
- N : constant Natural := Length (A);
|
||||
+ Max_Iterations : constant := 50;
|
||||
+ N : constant Natural := Length (A);
|
||||
|
||||
subtype Square_Matrix is Real_Matrix (1 .. N, 1 .. N);
|
||||
|
||||
- -- In order to annihilate the M (Row, Col) element, the rotation angle
|
||||
- -- Theta is chosen as follows:
|
||||
+ -- In order to annihilate the M (Row, Col) element, the
|
||||
+ -- rotation parameters Cos and Sin are computed as
|
||||
+ -- follows:
|
||||
|
||||
- -- Cot (2.0 * Theta) = (Diag (Col) - Diag (Row)) / (2.0 * M (Row, Col))
|
||||
+ -- Theta = Cot (2.0 * Phi)
|
||||
+ -- = (Diag (Col) - Diag (Row)) / (2.0 * M (Row, Col))
|
||||
|
||||
- -- If C = Cot (2.0 * Theta), then Tan (Theta) is computed as the smaller
|
||||
- -- root (in modulus) of:
|
||||
+ -- Then Tan (Phi) as the smaller root (in modulus) of
|
||||
|
||||
- -- X**2 + 2 * C * X - 1 = 0
|
||||
+ -- T**2 + 2 * T * Theta = 1 (or 0.5 / Theta, if Theta is large)
|
||||
|
||||
- -- or else as 0.5 / C, if C is large.
|
||||
-
|
||||
- function Compute_Tan (C : Real) return Real is
|
||||
- (Real'Copy_Sign (1.0 / (abs C + Sqrt (1.0 + C**2)), C));
|
||||
+ function Compute_Tan (Theta : Real) return Real is
|
||||
+ (Real'Copy_Sign (1.0 / (abs Theta + Sqrt (1.0 + Theta**2)), Theta));
|
||||
|
||||
function Compute_Tan (P, H : Real) return Real is
|
||||
- (if Is_Tiny (P, Compared_To => H)
|
||||
- then P / H
|
||||
- else Compute_Tan (C => H / (2.0 * P)));
|
||||
+ (if Is_Tiny (P, Compared_To => H) then P / H
|
||||
+ else Compute_Tan (Theta => H / (2.0 * P)));
|
||||
pragma Annotate
|
||||
(CodePeer, False_Positive, "divide by zero", "H, P /= 0");
|
||||
|
||||
function Sum_Strict_Upper (M : Square_Matrix) return Real;
|
||||
- -- Return the sum of the absolute value of all the elements in the
|
||||
- -- strict upper triangle of M.
|
||||
+ -- Return the sum of all elements in the strict upper triangle of M
|
||||
|
||||
----------------------
|
||||
-- Sum_Strict_Upper --
|
||||
@@ -598,13 +595,11 @@ package body Ada.Numerics.Generic_Real_A
|
||||
return Sum;
|
||||
end Sum_Strict_Upper;
|
||||
|
||||
- -- Local variables
|
||||
-
|
||||
M : Square_Matrix := A; -- Work space for solving eigensystem
|
||||
+ Threshold : Real;
|
||||
+ Sum : Real;
|
||||
Diag : Real_Vector (1 .. N);
|
||||
Diag_Adj : Real_Vector (1 .. N);
|
||||
- Sum : Real;
|
||||
- Threshold : Real;
|
||||
|
||||
-- The vector Diag_Adj indicates the amount of change in each value,
|
||||
-- while Diag tracks the value itself and Values holds the values as
|
||||
@@ -626,24 +621,22 @@ package body Ada.Numerics.Generic_Real_A
|
||||
raise Constraint_Error with "matrix not symmetric";
|
||||
end if;
|
||||
|
||||
- Values := Diagonal (M);
|
||||
-
|
||||
-- Note: Only the locally declared matrix M and vectors (Diag, Diag_Adj)
|
||||
-- have lower bound equal to 1. The Vectors matrix may have
|
||||
-- different bounds, so take care indexing elements. Assignment
|
||||
-- as a whole is fine as sliding is automatic in that case.
|
||||
|
||||
- Vectors := (if Compute_Vectors
|
||||
- then Unit_Matrix (N)
|
||||
- else [1 .. 0 => [1 .. 0 => 0.0]]);
|
||||
+ Vectors := (if not Compute_Vectors then [1 .. 0 => [1 .. 0 => 0.0]]
|
||||
+ else Unit_Matrix (Vectors'Length (1), Vectors'Length (2)));
|
||||
+ Values := Diagonal (M);
|
||||
|
||||
Sweep : for Iteration in 1 .. Max_Iterations loop
|
||||
|
||||
- -- During the first three iterations, perform the rotation only for
|
||||
- -- elements that are not much smaller than the average off-diagonal
|
||||
- -- element. After this, rotate for any non-zero elements. After the
|
||||
- -- fifth iteration, additionally zero out off-diagonal elements that
|
||||
- -- are very small compared to elements on the diagonal with the same
|
||||
+ -- The first three iterations, perform rotation for any non-zero
|
||||
+ -- element. After this, rotate only for those that are not much
|
||||
+ -- smaller than the average off-diagnal element. After the fifth
|
||||
+ -- iteration, additionally zero out off-diagonal elements that are
|
||||
+ -- very small compared to elements on the diagonal with the same
|
||||
-- column or row index.
|
||||
|
||||
Sum := Sum_Strict_Upper (M);
|
||||
@@ -652,8 +645,8 @@ package body Ada.Numerics.Generic_Real_A
|
||||
|
||||
Threshold := (if Iteration < 4 then 0.2 * Sum / Real (N**2) else 0.0);
|
||||
|
||||
- -- Iterate over all off-diagonal elements, rotating any that have an
|
||||
- -- absolute value that exceeds the threshold.
|
||||
+ -- Iterate over all off-diagonal elements, rotating any that have
|
||||
+ -- an absolute value that exceeds the threshold.
|
||||
|
||||
Diag := Values;
|
||||
Diag_Adj := [others => 0.0]; -- Accumulates adjustments to Diag
|
||||
@@ -661,11 +654,11 @@ package body Ada.Numerics.Generic_Real_A
|
||||
for Row in 1 .. N - 1 loop
|
||||
for Col in Row + 1 .. N loop
|
||||
|
||||
- -- If, before the rotation, M (Row, Col) is tiny compared to
|
||||
+ -- If, before the rotation M (Row, Col) is tiny compared to
|
||||
-- Diag (Row) and Diag (Col), rotation is skipped. This is
|
||||
-- meaningful, as it produces no larger error than would be
|
||||
-- produced anyhow if the rotation had been performed.
|
||||
- -- Suppress this optimization in the first four iterations, so
|
||||
+ -- Suppress this optimization in the first four sweeps, so
|
||||
-- that this procedure can be used for computing eigenvectors
|
||||
-- of perturbed diagonal matrices.
|
||||
|
||||
@@ -677,8 +670,8 @@ package body Ada.Numerics.Generic_Real_A
|
||||
|
||||
elsif abs M (Row, Col) > Threshold then
|
||||
Perform_Rotation : declare
|
||||
- Tan : constant Real :=
|
||||
- Compute_Tan (M (Row, Col), Diag (Col) - Diag (Row));
|
||||
+ Tan : constant Real := Compute_Tan (M (Row, Col),
|
||||
+ Diag (Col) - Diag (Row));
|
||||
Cos : constant Real := 1.0 / Sqrt (1.0 + Tan**2);
|
||||
Sin : constant Real := Tan * Cos;
|
||||
Tau : constant Real := Sin / (1.0 + Cos);
|
||||
@@ -717,7 +710,7 @@ package body Ada.Numerics.Generic_Real_A
|
||||
Values := Values + Diag_Adj;
|
||||
end loop Sweep;
|
||||
|
||||
- -- All normal matrices with valid values should converge perfectly
|
||||
+ -- All normal matrices with valid values should converge perfectly.
|
||||
|
||||
if Sum /= 0.0 then
|
||||
raise Constraint_Error with "eigensystem solution does not converge";
|
Reference in New Issue
Block a user