Files
Skeleton/src/Algebra/Matrices/MatrixProperty/MatrixProperty.cs
2024-06-21 21:48:07 +08:00

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