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());
}