// *********************** Package rjf.m ****************************
//
// Contains functions for constructing the Real Jordan Form of a
// matrix.
intrinsic Re(v::ModTupFldElt) -> ModTupFldElt
{Return the real part of a vector}
return VectorSpace(RealField(),
Degree(v))![Re(v[i]) : i in [1..Degree(v)]];
end intrinsic;
intrinsic Im(v::ModTupFldElt) -> ModTupFldElt
{Return the imaginary part of a vector}
return VectorSpace(RealField(),
Degree(v))![Im(v[i]) : i in [1..Degree(v)]];
end intrinsic;
intrinsic LambdaMatrix(lambda::.) -> AlgMatElt
{Given a real or complex number lambda return a matrix used
in the construction of the RealJordanBlock(lambda)}
return IsReal(lambda)
select MatrixAlgebra(RealField(), 1)![lambda]
else MatrixAlgebra(RealField(), 2)![a, b, -b, a]
where a := Re(lambda)
where b := Im(lambda);
end intrinsic;
intrinsic RealJordanBlock(lambda::., k::RngIntElt) -> AlgMatElt
{Return the RealJordanBlock of lambda of dimension k i.e.
J(lambda, k) if lambda is real and K(lambda, k) otherwise}
M := MatrixAlgebra(RealField(), k);
N := M!0;
for i in [1 .. k-1] do
N[i+1, i] := 1;
end for;
return TensorProduct(Ik, LambdaMatrix(lambda)) +
TensorProduct(N, I)
where Ik := M!1
where I := MatrixAlgebra(RealField(),
IsReal(lambda)
select 1
else 2
)!1;
end intrinsic;
intrinsic JoinJordanBlocks(blocks::List) -> ModMatFldElt
{Return the Jordan matrix with Jordan Blocks blocks}
J := blocks[1];
Remove(~blocks, 1);
for B in blocks do
J := VerticalJoin(HorizontalJoin(J, OmJnB),
HorizontalJoin(OmBnJ, B))
where OmJnB := RMatrixSpace(RealField(), mJ, nB)!0
where OmBnJ := RMatrixSpace(RealField(), mB, nJ)!0
where mJ := Nrows(J)
where nJ := Ncols(J)
where mB := Nrows(B)
where nB := Ncols(B);
end for;
return J;
end intrinsic;
intrinsic RealJordanForm(X::., p::RngIntElt)
-> ModMatFldElt, ModMatFldElt
{Given a sequence or matrix X return the Real Jordan Form J of X
and a matrix U such that J = U^-1 X U, where calculations in the
Real Field are done to precision p}
if p eq 0 then
R := RealField();
C := ComplexField();
else
R := RealField(p);
C := ComplexField(p);
end if;
if Type(X) eq SeqEnum then
isSquare, n := IsSquare(#X);
if not isSquare then
error "Argument 1 is not a square matrix";
else
delete isSquare;
end if;
else
n := Nrows(X);
end if;
// Magma considers matrices to act on the right ...
// hence we need to transpose X and consider the vectors
// we get as multiplying on the left.
M := MatrixAlgebra(R, n);
X := Transpose(M!X);
I := M!1;
eigenvalues := [e : e in Eigenvalues(X)
| IsReal(e[1]) or Im(e[1]) gt 0];
eigenvalues := Sort([e : e in eigenvalues | IsReal(e[1])],
func) cat
Sort([e : e in eigenvalues | not IsReal(e[1])],
func);
eigenbasis := [];
jordanblocks := [* *];
jordandescription := "";
AssertAttribute(FldPr, "OutputPrecision", 5);
for lambdai in eigenvalues do
V := VectorSpace(IsReal(lambdai[1])
select R
else C,
n);
XmlambdaI := X - lambdai[1] * I;
B := I;
geneigenspaces := [ sub ]; // 0-dimensional subspace of V,
// used as a sentinel
while lambdai[2] gt Dimension(geneigenspaces[#geneigenspaces]) do
B *:= XmlambdaI;
geneigenspaces cat:= [ NullSpace(B) ];
end while;
eigendepth := #geneigenspaces;
eigenchains := [ [u] : u in Basis(geneigenspaces[eigendepth])
| u notin geneigenspaces[eigendepth - 1] ];
while eigendepth gt 2 do
for i in [1..#eigenchains] do
Append(~eigenchains[i],
eigenchains[i, #eigenchains[i]] * XmlambdaI);
end for;
eigendepth -:= 1;
eigenchains cat:=
[ [u] : u in Basis(geneigenspaces[eigendepth])
| u notin geneigenspaces[eigendepth - 1] and
u notin sub ];
end while;
for chain in eigenchains do
Append(~jordanblocks, RealJordanBlock(lambdai[1], #chain));
jordandescription
cat:= IsReal(lambdai[1])
select Sprintf(" (+) J_%o(%o)",
#chain, lambdai[1])
else Sprintf(" (+) K_%o(%o, %o)",
#chain, Re(lambdai[1]),
Im(lambdai[1]));
end for;
eigenbasis
cat:= &cat (IsReal(lambdai[1])
select eigenchains
else [ &cat [ [ Re(chaini), Im(chaini)]
: chaini in chain]
: chain in eigenchains ]);
end for;
jordandescription := Substring(jordandescription, 6,
#jordandescription - 5);
return JoinJordanBlocks(jordanblocks), // Real Jordan Form J
Transpose(VerticalJoin(eigenbasis)),// Transformation Matrix U
// such that J = U^-1 X U
jordandescription; // J(lambda, k) (+) ...
end intrinsic;
intrinsic RealJordanForm(X::.) -> ModMatFldElt, ModMatFldElt
{Given a sequence or matrix X return the Real Jordan Form J of X
and a matrix U such that J = U^-1 X U}
return J, U, S where J, U, S := RealJordanForm(X, 0);
end intrinsic;
// *********************** End of rjf.m *****************************