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