internal T DeterminantLaplace(int diagLength) { if (diagLength == 1) { return(ConstantsAndFunctions <T> .Forward(this.GetValueNoCheck(0, 0))); } var det = ConstantsAndFunctions <T> .CreateZero(); var sign = ConstantsAndFunctions <T> .CreateOne(); var temp = SquareMatrixFactory <T> .GetMatrix(diagLength); for (int i = 0; i < diagLength; i++) { GetCofactor(this, temp, 0, i, diagLength); det = ConstantsAndFunctions <T> .Add(det, ConstantsAndFunctions <T> .Multiply( sign, ConstantsAndFunctions <T> .Multiply( this.GetValueNoCheck(0, i), temp.DeterminantLaplace(diagLength - 1) )) ); sign = ConstantsAndFunctions <T> .Negate(sign); } return(det); }
// TODO: how to avoid code duplication? /// <summary> /// Performs simple Gaussian elimination method on a tensor /// /// O(N^3) /// </summary> public T DeterminantGaussianSimple() { #if ALLOW_EXCEPTIONS if (!IsMatrix) { throw new InvalidShapeException("this should be matrix"); } if (Shape[0] != Shape[1]) { throw new InvalidShapeException("this should be square matrix"); } #endif if (Shape[0] == 1) { return(ConstantsAndFunctions <T> .Forward(this.GetValueNoCheck(0, 0))); } var n = Shape[0]; var elemMatrix = this.Forward(); for (int k = 1; k < n; k++) { for (int j = k; j < n; j++) { var m = ConstantsAndFunctions <T> .Divide( ConstantsAndFunctions <T> .Forward(elemMatrix.GetValueNoCheck(j, k - 1)), ConstantsAndFunctions <T> .Forward(elemMatrix.GetValueNoCheck(k - 1, k - 1)) ); for (int i = 0; i < n; i++) { var curr = ConstantsAndFunctions <T> .Forward(elemMatrix.GetValueNoCheck(j, i)); elemMatrix.SetValueNoCheck(ConstantsAndFunctions <T> .Subtract( curr, ConstantsAndFunctions <T> .Multiply( m, elemMatrix.GetValueNoCheck(k - 1, i) ) ), j, i); } } } var det = ConstantsAndFunctions <T> .CreateOne(); for (int i = 0; i < n; i++) { det = ConstantsAndFunctions <T> .Multiply(det, elemMatrix.GetValueNoCheck(i, i)); } return(det); }
/// <summary> /// Returns adjugate matrix /// /// O(N^5) /// </summary> public GenTensor <T> Adjoint() { #if ALLOW_EXCEPTIONS if (!IsSquareMatrix) { throw new InvalidShapeException("Matrix should be square"); } #endif var diagLength = Shape.shape[0]; var res = GenTensor <T> .CreateSquareMatrix(diagLength); var temp = SquareMatrixFactory <T> .GetMatrix(diagLength); if (diagLength == 1) { res.SetValueNoCheck(ConstantsAndFunctions <T> .CreateOne(), 0, 0); return(res); } var toNegate = false; for (int x = 0; x < diagLength; x++) { for (int y = 0; y < diagLength; y++) { GetCofactor(this, temp, x, y, diagLength); toNegate = (x + y) % 2 == 1; var det = temp.DeterminantGaussianSafeDivision(diagLength - 1); if (toNegate) { res.SetValueNoCheck(ConstantsAndFunctions <T> .Negate(det), y, x); } else { res.SetValueNoCheck(det, y, x); } } } return(res); }
/// <summary> /// Finds Determinant with possible overflow /// because it uses fractions for avoiding division /// /// O(N^3) /// </summary> internal T DeterminantGaussianSafeDivision(int diagLength) { InitIfNotInitted(); #if ALLOW_EXCEPTIONS if (!IsMatrix) { throw new InvalidShapeException("this should be matrix"); } if (Shape[0] != Shape[1]) { throw new InvalidShapeException("this should be square matrix"); } #endif if (Shape[0] == 1) { return(ConstantsAndFunctions <T> .Forward(this.GetValueNoCheck(0, 0))); } var n = diagLength; var elemMatrix = InnerGaussianEliminationSafeDivision(n); var det = ConstantsAndFunctions <SafeDivisionWrapper <T> > .CreateOne(); for (int i = 0; i < n; i++) { det = ConstantsAndFunctions <SafeDivisionWrapper <T> > .Multiply(det, elemMatrix.GetValueNoCheck(i, i)); } if (ConstantsAndFunctions <T> .IsZero(det.den)) { return(ConstantsAndFunctions <T> .CreateZero()); } return(det.Count()); }
public SafeDivisionWrapper(W val) { num = val; den = ConstantsAndFunctions <W> .CreateOne(); }
private static void InitIfNotInitted() { if (isFracInitted) { return; } isFracInitted = true; ConstantsAndFunctions <SafeDivisionWrapper <T> > .Add = (a, b) => new SafeDivisionWrapper <T>( ConstantsAndFunctions <T> .Add( ConstantsAndFunctions <T> .Multiply(a.num, b.den), ConstantsAndFunctions <T> .Multiply(a.den, b.num) ), ConstantsAndFunctions <T> .Multiply(a.den, b.den) ); ConstantsAndFunctions <SafeDivisionWrapper <T> > .Subtract = (a, b) => new SafeDivisionWrapper <T>( ConstantsAndFunctions <T> .Subtract( ConstantsAndFunctions <T> .Multiply(a.num, b.den), ConstantsAndFunctions <T> .Multiply(a.den, b.num) ), ConstantsAndFunctions <T> .Multiply(a.den, b.den) ); ConstantsAndFunctions <SafeDivisionWrapper <T> > .Multiply = (a, b) => new SafeDivisionWrapper <T>( ConstantsAndFunctions <T> .Multiply(a.num, b.num), ConstantsAndFunctions <T> .Multiply(a.den, b.den) ); ConstantsAndFunctions <SafeDivisionWrapper <T> > .Divide = (a, b) => new SafeDivisionWrapper <T>( ConstantsAndFunctions <T> .Multiply(a.num, b.den), ConstantsAndFunctions <T> .Multiply(a.den, b.num) ); ConstantsAndFunctions <SafeDivisionWrapper <T> > .CreateOne = () => new SafeDivisionWrapper <T>(ConstantsAndFunctions <T> .CreateOne()); }