using Skeleton.Algebra.ScalarFieldStructure; using Skeleton.Algebra.Vectors; namespace Skeleton.Algebra.Matrices.MatrixProperty; /// /// test properties of matrix /// /// /// /// public class MatrixProperty where TVector : Vector, new() where TMatrix : Matrix, new() where TScalar : notnull { private TMatrix Mat { get; } private static readonly FieldStructure Structure = FieldStructure.Dispatch(); internal MatrixProperty(TMatrix m) => Mat = m; /// /// M[i, j] = 0 if i!= j /// public bool IsDiagonal => Mat.OffDiagonals .All(x => Structure.IsEqualApprox(x, StaticAccess.AdditionUnit)); /// /// exist of inv(M) /// /// public bool IsInvertible => !Structure.IsEqualApprox(Mat.Det(), StaticAccess.AdditionUnit); /// /// M M* = M* M /// public bool IsNormal => (Mat * Mat.Hermitian()).IsEqualApprox(Mat.Hermitian() * Mat); /// /// M = M* /// public bool IsHermitian => Mat.IsEqualApprox(Mat.Hermitian()); /// /// M[i, j] = 0 for all j < i /// public bool IsUpperTriangle { get { for (int i = 2; i <= Mat.Dim; i++) for (int j = 1; j < i; j++) if (!Structure.IsEqualApprox(Mat[i, j], StaticAccess.AdditionUnit)) return false; return true; } } /// /// M[i, j] = 0 for all j > i /// public bool IsLowerTriangle { get { for (int i = 1; i <= Mat.Dim; i++) for (int j = i + 1; j <= Mat.Dim; j++) if (!Structure.IsEqualApprox(Mat[i, j], StaticAccess.AdditionUnit)) return false; return true; } } /// /// U*U = UU* = I /// public bool IsUnitary => (Mat * Mat.Hermitian()).IsEqualApprox(Mat.VarOne); /// /// U + U* = 0 /// public bool IsSkewHermitian => (Mat + Mat.Hermitian()).IsEqualApprox(Mat.VarZero); /// /// tr(M) = 0 /// public bool IsTraceless => Structure.IsEqualApprox(Mat.Trace(), StaticAccess.AdditionUnit); /// /// M M^T = I /// public bool IsOrthogonal => (Mat * Mat.Transpose()).IsEqualApprox(Mat.VarOne); /// /// M = M^T /// public bool IsSymmetric => Mat.IsEqualApprox(Mat.Transpose()); /// /// M = -M^T /// public bool IsSkewSymmetric => Mat.IsEqualApprox(-Mat.Transpose()); }