public void SolveLinear(SimpleMatrix vec) { if (xDim != yDim || yDim != vec.yDim) { throw (new InvalidOperationException ("Matrix not quadratic or vector dimension mismatch")); } for (int y = 0; y < (yDim - 1); ++y) { int yMaxIndex = y; double yMaxValue = Math.Abs(values[y, y]); for (int py = y; py < yDim; ++py) { if (Math.Abs(values[py, y]) > yMaxValue) { yMaxValue = Math.Abs(values[py, y]); yMaxIndex = py; } } SwapRow(y, yMaxIndex); vec.SwapRow(y, yMaxIndex); for (int py = y + 1; py < yDim; ++py) { double elimMul = values[py, y] / values[y, y]; for (int x = 0; x < xDim; ++x) { values[py, x] -= elimMul * values[y, x]; } vec[py, 0] -= elimMul * vec[y, 0]; } } for (int y = yDim - 1; y >= 0; --y) { double solY = vec[y, 0]; for (int x = xDim - 1; x > y; --x) { solY -= values[y, x] * vec[x, 0]; } vec[y, 0] = solY / values[y, y]; } }
// The vector 'vec' is used both for input/output purposes. As input, it // contains the vector v, and after this method finishes it contains x, // the solution in the formula // this * x = v // This matrix might get row-swapped, too. public void SolveLinear(SimpleMatrix vec) { if (xDim != yDim || yDim != vec.yDim) { throw (new InvalidOperationException ("Matrix not quadratic or vector dimension mismatch")); } // Gaussian Elimination Algorithm, as described by // "Numerical Methods - A Software Approach", R.L. Johnston // Forward elimination with partial pivoting for (int y = 0; y < (yDim - 1); ++y) { // Searching for the largest pivot (to get "multipliers < 1.0 to // minimize round-off errors") int yMaxIndex = y; double yMaxValue = Math.Abs(values[y, y]); for (int py = y; py < yDim; ++py) { if (Math.Abs(values[py, y]) > yMaxValue) { yMaxValue = Math.Abs(values[py, y]); yMaxIndex = py; } } // if a larger row has been found, swap with the current one SwapRow(y, yMaxIndex); vec.SwapRow(y, yMaxIndex); // Now do the elimination left of the diagonal for (int py = y + 1; py < yDim; ++py) { // always <= 1.0 double elimMul = values[py, y] / values[y, y]; for (int x = 0; x < xDim; ++x) { values[py, x] -= elimMul * values[y, x]; } // FIXME: do we really need this? vec[py, 0] -= elimMul * vec[y, 0]; } } // Back substitution for (int y = yDim - 1; y >= 0; --y) { double solY = vec[y, 0]; for (int x = xDim - 1; x > y; --x) { solY -= values[y, x] * vec[x, 0]; } vec[y, 0] = solY / values[y, y]; } }