示例#1
0
        /// <summary>
        /// Inverts a matrix A to B so that A * B = I
        /// Borrowed from here: https://www.geeksforgeeks.org/adjoint-inverse-matrix/
        ///
        /// O(N^5)
        /// </summary>
        public void InvertMatrix()
        {
            #if ALLOW_EXCEPTIONS
            if (!IsSquareMatrix)
            {
                throw new InvalidShapeException("this should be a square matrix");
            }
            #endif

            var diagLength = Shape.shape[0];

            var det = DeterminantGaussianSafeDivision();
            #if ALLOW_EXCEPTIONS
            if (ConstantsAndFunctions <T> .IsZero(det))
            {
                throw new InvalidDeterminantException("Cannot invert a singular matrix");
            }
            #endif

            var adj = Adjoint();
            for (int x = 0; x < diagLength; x++)
            {
                for (int y = 0; y < diagLength; y++)
                {
                    this.SetValueNoCheck(
                        ConstantsAndFunctions <T> .Divide(
                            adj.GetValueNoCheck(x, y),
                            det
                            ),
                        x, y
                        );
                }
            }
        }
示例#2
0
        /// <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());
        }