public static double Det(this SymmetricMatrix3 @this) { var mx = @this.YY * @this.ZZ - @this.YZ * @this.YZ; var my = @this.XY * @this.ZZ - @this.YZ * @this.ZX; var mz = @this.XY * @this.YZ - @this.YY * @this.ZX; return(@this.XX * mx - @this.XY * my + @this.ZX * mz); }
// finds least-squares solution to a system of orthogonality equations (i.e. result is fitted to be orthogonal to vectors) public static void FitOrthogonal(IEnumerable <Vector3> vectors, out Vector3 result, out double residual) { var mat = SymmetricMatrix3.TensorSquare(vectors.First()); foreach (var vector in vectors.Skip(1)) { mat += SymmetricMatrix3.TensorSquare(vector); } mat.ComputeLowestEigendata(out residual, out result); }
public static double LowestEigenvalue(this SymmetricMatrix3 @this) { var b = @this.Trace(); var c = [email protected] * @this.ZZ + @this.YZ * @this.YZ - @this.XX * @this.ZZ + @this.ZX * @this.ZX - @this.XX * @this.YY + @this.XY * @this.XY; var d = @this.Det(); return(CubicEquation.Solve(-1, b, c, d).Min()); }
public void Eigenvectors_and_eigenvalues_of_satisfy_defining_equations( [Values(1, 0.577, 0.577, 0.577, 0.577, 0.577, 0.577)] double xx, [Values(1, 2.718, 2.718, 0.577, 0.577, 0.577, 0.577)] double yy, [Values(1, 3.141, 3.141, 3.141, 0.577, 3.141, 0.577)] double zz, [Values(0, 0, 1.618, 1e-40, 1e-40, 1e-60, 1e-60)] double xy, [Values(0, 0, 2.665, 2e-40, 2e-40, 2e-60, 2e-60)] double yz, [Values(0, 0, 4.669, 3e-40, 3e-40, 3e-60, 3e-60)] double zx) { var mat = new SymmetricMatrix3(xx, yy, zz, xy, yz, zx); var loVal = mat.LowestEigenvalue(); var loVec = mat.LowestEigenvector(); Expect((mat - SymmetricMatrix3.Scalar(loVal)).Det(), Is.EqualTo(0).Within(_tolerance)); Expect(Vector3.Distance(mat * loVec, loVal * loVec), Is.LessThan(_tolerance)); }
private static Vector3 Eigenvector(this SymmetricMatrix3 @this, double eigenvalue) { var rowX = new Vector3(@this.XX - eigenvalue, @this.XY, @this.ZX); var rowY = new Vector3(@this.XY, @this.YY - eigenvalue, @this.YZ); var rowZ = new Vector3(@this.ZX, @this.YZ, @this.ZZ - eigenvalue); var normX2 = rowX.Norm2; var normY2 = rowY.Norm2; var normZ2 = rowZ.Norm2; Vector3 row1, row2, row3; if (normX2 > normY2) { if (normX2 > normZ2) { row1 = rowX / Math.Sqrt(normX2); row2 = rowY; row3 = rowZ; } else { row1 = rowZ / Math.Sqrt(normZ2); row2 = rowX; row3 = rowY; } } else { if (normY2 > normZ2) { row1 = rowY / Math.Sqrt(normY2); row2 = rowX; row3 = rowZ; } else { row1 = rowZ / Math.Sqrt(normZ2); row2 = rowY; row3 = rowX; } } var cross2 = row1.Cross(row2); var cross3 = row1.Cross(row3); var norm22 = cross2.Norm2; var norm32 = cross3.Norm2; if (norm22 > norm32) { if (norm22 > BasicMath.Epsilon) { return(cross2 / Math.Sqrt(norm22)); } else { return(Vector3Utils.VectorOrthogonalTo(row1).Normalized); } } else { if (norm32 > BasicMath.Epsilon) { return(cross3 / Math.Sqrt(norm32)); } else { return(Vector3Utils.VectorOrthogonalTo(row1).Normalized); } } }
public static double Trace(this SymmetricMatrix3 @this) { return(@this.XX + @this.YY + @this.ZZ); }
public static Vector3 RowZ(this SymmetricMatrix3 @this) { return(new Vector3(@this.ZX, @this.YZ, @this.ZZ)); }
public static Vector3 RowY(this SymmetricMatrix3 @this) { return(new Vector3(@this.XY, @this.YY, @this.YZ)); }
public static Vector3 RowX(this SymmetricMatrix3 @this) { return(new Vector3(@this.XX, @this.XY, @this.ZX)); }
public static void ComputeLowestEigendata(this SymmetricMatrix3 @this, out double eigenvalue, out Vector3 eigenvector) { eigenvalue = @this.LowestEigenvalue(); eigenvector = @this.Eigenvector(eigenvalue); }
public static Vector3 LowestEigenvector(this SymmetricMatrix3 @this) { return(@this.Eigenvector(@this.LowestEigenvalue())); }