示例#1
0
    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];
        }
    }
示例#2
0
    // 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];
        }
    }