예제 #1
0
bool LinearSystem<Real>::Inverse (const GMatrix<Real>& A,
    GMatrix<Real>& invA)
{
    // Computations are performed in-place.
    assertion(A.GetNumRows() == A.GetNumColumns(), "Matrix must be square\n");

    int size = invA.GetNumRows();
    invA = A;

    int* colIndex = new1<int>(size);
    int* rowIndex = new1<int>(size);
    bool* pivoted = new1<bool>(size);
    memset(pivoted, 0, size*sizeof(bool));

    int i1, i2, row = 0, col = 0;
    Real save;

    // Elimination by full pivoting.
    for (int i0 = 0; i0 < size; ++i0)
    {
        // Search matrix (excluding pivoted rows) for maximum absolute entry.
        Real maxValue = (Real)0;
        for (i1 = 0; i1 < size; ++i1)
        {
            if (!pivoted[i1])
            {
                for (i2 = 0; i2 < size; ++i2)
                {
                    if (!pivoted[i2])
                    {
                        Real absValue = Math<Real>::FAbs(invA[i1][i2]);
                        if (absValue > maxValue)
                        {
                            maxValue = absValue;
                            row = i1;
                            col = i2;
                        }
                    }
                }
            }
        }

        if (maxValue == (Real)0)
        {
            // The matrix is not invertible.
            delete1(colIndex);
            delete1(rowIndex);
            delete1(pivoted);
            return false;
        }

        pivoted[col] = true;

        // Swap rows so that A[col][col] contains the pivot entry.
        if (row != col)
        {
            invA.SwapRows(row,col);
        }

        // Keep track of the permutations of the rows.
        rowIndex[i0] = row;
        colIndex[i0] = col;

        // Scale the row so that the pivot entry is 1.
        Real inv = ((Real)1)/invA[col][col];
        invA[col][col] = (Real)1;
        for (i2 = 0; i2 < size; i2++)
        {
            invA[col][i2] *= inv;
        }

        // Zero out the pivot column locations in the other rows.
        for (i1 = 0; i1 < size; ++i1)
        {
            if (i1 != col)
            {
                save = invA[i1][col];
                invA[i1][col] = (Real)0;
                for (i2 = 0; i2 < size; ++i2)
                {
                    invA[i1][i2] -= invA[col][i2]*save;
                }
            }
        }
    }

    // Reorder rows so that A[][] stores the inverse of the original matrix.
    for (i1 = size-1; i1 >= 0; --i1)
    {
        if (rowIndex[i1] != colIndex[i1])
        {
            for (i2 = 0; i2 < size; ++i2)
            {
                save = invA[i2][rowIndex[i1]];
                invA[i2][rowIndex[i1]] = invA[i2][colIndex[i1]];
                invA[i2][colIndex[i1]] = save;
            }
        }
    }

    delete1(colIndex);
    delete1(rowIndex);
    delete1(pivoted);
    return true;
}
예제 #2
0
bool LinearSystem<Real>::Inverse (const GMatrix<Real>& rkA,
    GMatrix<Real>& rkInvA)
{
    // computations are performed in-place
    assert(rkA.GetRows() == rkA.GetColumns());
    int iSize = rkInvA.GetRows();
    rkInvA = rkA;

    int* aiColIndex = WM4_NEW int[iSize];
    int* aiRowIndex = WM4_NEW int[iSize];
    bool* abPivoted = WM4_NEW bool[iSize];
    memset(abPivoted,0,iSize*sizeof(bool));

    int i1, i2, iRow = 0, iCol = 0;
    Real fSave;

    // elimination by full pivoting
    for (int i0 = 0; i0 < iSize; i0++)
    {
        // search matrix (excluding pivoted rows) for maximum absolute entry
        Real fMax = 0.0f;
        for (i1 = 0; i1 < iSize; i1++)
        {
            if (!abPivoted[i1])
            {
                for (i2 = 0; i2 < iSize; i2++)
                {
                    if (!abPivoted[i2])
                    {
                        Real fAbs = Math<Real>::FAbs(rkInvA[i1][i2]);
                        if (fAbs > fMax)
                        {
                            fMax = fAbs;
                            iRow = i1;
                            iCol = i2;
                        }
                    }
                }
            }
        }

        if (fMax == (Real)0.0)
        {
            // matrix is not invertible
            WM4_DELETE[] aiColIndex;
            WM4_DELETE[] aiRowIndex;
            WM4_DELETE[] abPivoted;
            return false;
        }

        abPivoted[iCol] = true;

        // swap rows so that A[iCol][iCol] contains the pivot entry
        if (iRow != iCol)
        {
            rkInvA.SwapRows(iRow,iCol);
        }

        // keep track of the permutations of the rows
        aiRowIndex[i0] = iRow;
        aiColIndex[i0] = iCol;

        // scale the row so that the pivot entry is 1
        Real fInv = ((Real)1.0)/rkInvA[iCol][iCol];
        rkInvA[iCol][iCol] = (Real)1.0;
        for (i2 = 0; i2 < iSize; i2++)
        {
            rkInvA[iCol][i2] *= fInv;
        }

        // zero out the pivot column locations in the other rows
        for (i1 = 0; i1 < iSize; i1++)
        {
            if (i1 != iCol)
            {
                fSave = rkInvA[i1][iCol];
                rkInvA[i1][iCol] = (Real)0.0;
                for (i2 = 0; i2 < iSize; i2++)
                {
                    rkInvA[i1][i2] -= rkInvA[iCol][i2]*fSave;
                }
            }
        }
    }
예제 #3
0
bool LinearSystem<Real>::Solve (const GMatrix<Real>& rkA, const Real* afB,
    Real* afX)
{
    // computations are performed in-place
    int iSize = rkA.GetColumns();
    GMatrix<Real> kInvA = rkA;
    memcpy(afX,afB,iSize*sizeof(Real));

    int* aiColIndex = new int[iSize];
    assert( aiColIndex );

    int* aiRowIndex = new int[iSize];
    assert( aiRowIndex );

    bool* abPivoted = new bool[iSize];
    assert( abPivoted );
    memset(abPivoted,0,iSize*sizeof(bool));

    int i1, i2, iRow = 0, iCol = 0;
    Real fSave;

    // elimination by full pivoting
    for (int i0 = 0; i0 < iSize; i0++)
    {
        // search matrix (excluding pivoted rows) for maximum absolute entry
        Real fMax = 0.0f;
        for (i1 = 0; i1 < iSize; i1++)
        {
            if ( !abPivoted[i1] )
            {
                for (i2 = 0; i2 < iSize; i2++)
                {
                    if ( !abPivoted[i2] )
                    {
                        Real fAbs = Math<Real>::FAbs(kInvA[i1][i2]);
                        if ( fAbs > fMax )
                        {
                            fMax = fAbs;
                            iRow = i1;
                            iCol = i2;
                        }
                    }
                }
            }
        }

        if ( fMax == (Real)0.0 )
        {
            // matrix is not invertible
            delete[] aiColIndex;
            delete[] aiRowIndex;
            delete[] abPivoted;
            return false;
        }

        abPivoted[iCol] = true;

        // swap rows so that A[iCol][iCol] contains the pivot entry
        if ( iRow != iCol )
        {
            kInvA.SwapRows(iRow,iCol);

            fSave = afX[iRow];
            afX[iRow] = afX[iCol];
            afX[iCol] = fSave;
        }

        // keep track of the permutations of the rows
        aiRowIndex[i0] = iRow;
        aiColIndex[i0] = iCol;

        // scale the row so that the pivot entry is 1
        Real fInv = ((Real)1.0)/kInvA[iCol][iCol];
        kInvA[iCol][iCol] = (Real)1.0;
        for (i2 = 0; i2 < iSize; i2++)
            kInvA[iCol][i2] *= fInv;
        afX[iCol] *= fInv;

        // zero out the pivot column locations in the other rows
        for (i1 = 0; i1 < iSize; i1++)
        {
            if ( i1 != iCol )
            {
                fSave = kInvA[i1][iCol];
                kInvA[i1][iCol] = (Real)0.0;
                for (i2 = 0; i2 < iSize; i2++)
                    kInvA[i1][i2] -= kInvA[iCol][i2]*fSave;
                afX[i1] -= afX[iCol]*fSave;
            }
        }
    }

    // reorder rows so that A[][] stores the inverse of the original matrix
    for (i1 = iSize-1; i1 >= 0; i1--)
    {
        if ( aiRowIndex[i1] != aiColIndex[i1] )
        {
            for (i2 = 0; i2 < iSize; i2++)
            {
                fSave = kInvA[i2][aiRowIndex[i1]];
                kInvA[i2][aiRowIndex[i1]] = kInvA[i2][aiColIndex[i1]];
                kInvA[i2][aiColIndex[i1]] = fSave;
            }
        }
    }

    delete[] aiColIndex;
    delete[] aiRowIndex;
    delete[] abPivoted;
    return true;
}