/// <summary>
        /// Calculates the LU-decomposition of the given matrix.
        /// </summary>
        /// <param name="matrix">The matrix to decompose.</param>
        /// <exception cref="NonSquareMatrixException"> if matrix is not square</exception>
        public FieldLUDecomposition(FieldMatrix <T> matrix)
        {
            if (!matrix.isSquare())
            {
                throw new NonSquareMatrixException(matrix.getRowDimension(), matrix.getColumnDimension());
            }

            int m = matrix.getColumnDimension();

            field   = matrix.getField();
            lu      = matrix.getData();
            pivot   = new int[m];
            cachedL = null;
            cachedU = null;
            cachedP = null;

            // Initialize permutation array and parity
            for (int row = 0; row < m; row++)
            {
                pivot[row] = row;
            }
            even     = true;
            singular = false;

            // Loop over columns
            for (int col = 0; col < m; col++)
            {
                T sum = field.getZero();

                // upper
                for (int row = 0; row < col; row++)
                {
                    T[] luRow = lu[row];
                    sum = luRow[col];
                    for (int i = 0; i < row; i++)
                    {
                        sum = sum.subtract(luRow[i].multiply(lu[i][col]));
                    }
                    luRow[col] = sum;
                }

                // lower
                int nonZero = col; // permutation row
                for (int row = col; row < m; row++)
                {
                    T[] luRow = lu[row];
                    sum = luRow[col];
                    for (int i = 0; i < col; i++)
                    {
                        sum = sum.subtract(luRow[i].multiply(lu[i][col]));
                    }
                    luRow[col] = sum;

                    if (lu[nonZero][col].Equals(field.getZero()))
                    {
                        // try to select a better permutation choice
                        ++nonZero;
                    }
                }

                // Singularity check
                if (nonZero >= m)
                {
                    singular = true;
                    return;
                }

                // Pivot if necessary
                if (nonZero != col)
                {
                    T tmp = field.getZero();
                    for (int i = 0; i < m; i++)
                    {
                        tmp            = lu[nonZero][i];
                        lu[nonZero][i] = lu[col][i];
                        lu[col][i]     = tmp;
                    }
                    int temp = pivot[nonZero];
                    pivot[nonZero] = pivot[col];
                    pivot[col]     = temp;
                    even           = !even;
                }

                // Divide the lower elements by the "winning" diagonal elt.
                T luDiag = lu[col][col];
                for (int row = col + 1; row < m; row++)
                {
                    T[] luRow = lu[row];
                    luRow[col] = luRow[col].divide(luDiag);
                }
            }
        }