public Matrix SolveFor(Matrix mRight) { Debug.Assert(mRight.NumRows == m_nNumColumns); Debug.Assert(m_nNumColumns == m_nNumRows); Matrix mRet = new Matrix(m_nNumColumns, mRight.NumColumns); LUDecompositionResults resDecomp = LUDecompose(); int[] nP = resDecomp.PivotArray; Matrix mL = resDecomp.L; Matrix mU = resDecomp.U; double dSum = 0.0; for (int k = 0; k < mRight.NumColumns; k++) { Matrix D = new Matrix(m_nNumRows, 1); D[0, 0] = mRight[nP[0], k] / mL[0, 0]; for (int i = 1; i < m_nNumRows; i++) { dSum = 0.0; for (int j = 0; j < i; j++) { dSum += mL[i, j] * D[j, 0]; } D[i, 0] = (mRight[nP[i], k] - dSum) / mL[i, i]; } mRet[m_nNumRows - 1, k] = D[m_nNumRows - 1, 0]; for (int i = m_nNumRows - 2; i >= 0; i--) { dSum = 0.0; for (int j = i + 1; j < m_nNumRows; j++) { dSum += mU[i, j] * mRet[j, k]; } mRet[i, k] = D[i, 0] - dSum; } } return(mRet); }
private LUDecompositionResults LUDecompose() { Debug.Assert(m_nNumColumns == m_nNumRows); LUDecompositionResults resRet = new LUDecompositionResults(); int[] nP = new int[m_nNumRows]; //Pivot matrix. Matrix mU = new Matrix(m_nNumRows, m_nNumColumns); Matrix mL = new Matrix(m_nNumRows, m_nNumColumns); Matrix mUWorking = Clone(); Matrix mLWorking = new Matrix(m_nNumRows, m_nNumColumns); for (int i = 0; i < m_nNumRows; i++) { nP[i] = i; } for (int i = 0; i < m_nNumRows; i++) { double dMaxRowRatio = double.NegativeInfinity; int nMaxRow = -1; int nMaxPosition = -1; for (int j = i; j < m_nNumRows; j++) { double dRowSum = 0.0; for (int k = i; k < m_nNumColumns; k++) { dRowSum += Math.Abs(mUWorking[nP[j], k]); } if (Math.Abs(mUWorking[nP[j], i] / dRowSum) > dMaxRowRatio) { dMaxRowRatio = Math.Abs(mUWorking[nP[j], i] / dRowSum); nMaxRow = nP[j]; nMaxPosition = j; } } if (nMaxRow != nP[i]) { int nHold = nP[i]; nP[i] = nMaxRow; nP[nMaxPosition] = nHold; } double dRowFirstElementValue = mUWorking[nP[i], i]; for (int j = 0; j < m_nNumRows; j++) { if (j < i) { mUWorking[nP[i], j] = 0.0; } else if (j == i) { mLWorking[nP[i], j] = dRowFirstElementValue; mUWorking[nP[i], j] = 1.0; } else { mUWorking[nP[i], j] /= dRowFirstElementValue; mLWorking[nP[i], j] = 0.0; } } for (int k = i + 1; k < m_nNumRows; k++) { dRowFirstElementValue = mUWorking[nP[k], i]; for (int j = 0; j < m_nNumRows; j++) { if (j < i) { mUWorking[nP[k], j] = 0.0; } else if (j == i) { mLWorking[nP[k], j] = dRowFirstElementValue; mUWorking[nP[k], j] = 0.0; } else { mUWorking[nP[k], j] = mUWorking[nP[k], j] - dRowFirstElementValue * mUWorking[nP[i], j]; } } } } for (int i = 0; i < m_nNumRows; i++) { for (int j = 0; j < m_nNumRows; j++) { mU[i, j] = mUWorking[nP[i], j]; mL[i, j] = mLWorking[nP[i], j]; } } resRet.U = mU; resRet.L = mL; resRet.PivotArray = nP; return(resRet); }