⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 matrix.cpp

📁 一个矩阵类的源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
    if (!m_dVals) return;
    for (i = 0; i<m_nRows; i++)
        delete[] m_dVals[i];
    delete[] m_dVals;
    m_dVals = NULL;
}

void TMatrix::GetMem ()
{
    int i;
    if (m_dVals) FreeMem ();
    if ((m_nRows>0) && (m_nCols>0)) {
        m_dVals = new double*[m_nRows];
        for (i = 0; i<m_nRows; i++) {
            m_dVals[i] = new double[m_nCols];
            memset(m_dVals[i],0,sizeof(double)*m_nCols);
        }
    }
    else {
        m_nRows = m_nCols = 0;
        m_dVals = NULL;
    }
}

void TMatrix::SetSize (int i, int j)
{
    if ((i == m_nRows) && (j == m_nCols)) return;
    FreeMem ();
    m_nRows = i;
    m_nCols = j;
    GetMem ();
}

void TMatrix::Reset ()
{
    SetSize (0, 0);
}

void TMatrix::Transpose ()
{
    int i, j;
    TMatrix tmp (*this);
    if (m_nCols != m_nRows) SetSize (m_nCols, m_nRows);
    for (i = 0; i<m_nRows; i++)
        for (j = 0; j<m_nCols; j++)
            m_dVals[i][j] = tmp.m_dVals[j][i];
}

void TMatrix::MakeIdentity ()
{
    int i, j;
    if (m_nRows != m_nCols)
        SetSize (m_nRows, m_nRows);
    for (i = 0; i<m_nRows; i++)
        for (j = 0; j<m_nCols; j++)
            m_dVals[i][j] = ((i == j) ? 1.0 : 0.0);
}

void TMatrix::MakeZero ()
{
    int i, j;
    for (i = 0; i<m_nRows; i++)
        for (j = 0; j<m_nCols; j++)
            m_dVals[i][j] = 0.0;
}

bool TMatrix::Multiply (TMatrix* R, TMatrix* Dest)
{
    if (m_nCols != R->m_nRows)
        return false;
    int i, j, k;
    double val;
    TMatrix tmp(m_nRows,R->m_nCols);

    for (i = 0; i<m_nRows; i++)
    {
        for (j = 0; j<R->m_nCols; j++)
        {
            val = 0.0;
            for (k = 0; k<m_nCols; k++)
                val += m_dVals[i][k]*R->m_dVals[k][j];
            tmp.m_dVals[i][j] = val;
        }
    }
    *Dest = tmp;
    return true;
//  this->Multiply (Some, WhereTo); WhereTo = this*Some
}

bool TMatrix::Multiply (TVector* R, TMatrix* Dest)
{
    int i, j;
    double val;
    TMatrix tmp;
//  1. Vector is VERTICAL, i.e. [N * 1]
    if (R->m_bVertical && (m_nCols == R->m_nRows))
    {
        tmp.SetSize(m_nRows,1);
        for (i = 0; i<m_nRows; i++)
        {
            val = 0.0;
            for (j = 0; j<R->m_nRows; j++)
                val += m_dVals[i][j]*R->m_dVals[j];
            tmp.m_dVals[i][0] = val;
        }
    }
//  2. Vector is HORIZONTAL, i.e. [1 * N]
    else if (!R->m_bVertical && (m_nCols == 1))
    {
        tmp.SetSize(m_nRows,R->m_nRows);
        for (i = 0; i<m_nRows; i++)
            for (j = 0; j<R->m_nRows; j++)
                tmp.m_dVals[i][j] = m_dVals[i][0]*R->m_dVals[j];
    }
    else
        return false;
    *Dest = tmp;
    return true;
}

bool TMatrix::Add (TMatrix* R, TMatrix* Dest)
{
    if ((m_nCols != R->m_nCols) || (m_nRows != R->m_nRows))
        return false;
    int i, j;
    TMatrix tmp(m_nRows,m_nCols);
/*  Dest->FreeMem ();
    Dest->m_nRows = m_nRows;
    Dest->m_nCols = R->m_nCols;
    Dest->GetMem ();*/

    for (i = 0; i<m_nRows; i++)
        for (j = 0; j<m_nCols; j++)
            tmp.m_dVals[i][j] = m_dVals[i][j] + R->m_dVals[i][j];
    *Dest = tmp;
    return true;
//  this->Multiply (Some, WhereTo); WhereTo = this*Some
}

bool TMatrix::Square ()
{
    if (m_nRows == m_nCols)
        return true;
    return false;
}

int TMatrix::Rows ()
{
    return m_nRows;
}

int TMatrix::Cols ()
{
    return m_nCols;
}

int TMatrix::AddLine (TVector& vctr)
{
    double** tmp;
    int i;
    if (m_dVals)
    {
        tmp = new double*[m_nRows+1];
        for (i = 0; i<m_nRows; i++)
            tmp[i] = m_dVals[i];
        tmp[i] = new double[m_nCols];
        delete[] m_dVals;
        m_dVals = tmp;
        m_nRows ++;
    }
    else
        SetSize (1, vctr.m_nRows);
    for (i = 0; i<m_nCols; i++)
        m_dVals[m_nRows-1][i] = vctr[i];
    return m_nRows-1;
}

void TMatrix::GrowBy (int rows, int cols)
{
    double** ppd;
    int i, j, c = m_nCols, r = m_nRows;

    ppd = m_dVals;
    m_dVals = NULL;
    SetSize (m_nRows + rows, m_nCols + cols);
    for (i = 0; i<min(r,m_nRows); i++)
        for (j = 0; j<min(c,m_nCols); j++)
            m_dVals[i][j] = ppd[i][j];
    for (i = 0; i<r; i++)
        delete[] ppd[i];
    delete[] ppd;
}

double& TMatrix::Val (int i, int j)
{
    if ((i < m_nRows) && (j < m_nCols) && (i >= 0) && (j >= 0))
        return m_dVals[i][j];
    return m_dVals[0][0];
}

double* TMatrix::operator[] (int idx)
{
    int i;
    if ((idx >= m_nRows) || (idx < 0))
        i = 0;
    else
        i = idx;
    return m_dVals[i];
}

double TMatrix::Determinant()
{
    if(!Square()) return 0.0;
    TMatrix tmp(*this);
    int* indx = new int[m_nRows];
    double d = 0.0,f,sum = 0.0;
    if(LU_decomp(tmp,indx,d)) {
        for(int i = 0; i < m_nRows; i ++) {
            if((f = fabs(tmp.m_dVals[i][i])) < TINY) {
                d = 0.0;
                break;
            }
            sum += log(f);
            if(f != tmp.m_dVals[i][i]) d *= -1.0;
        }
    }
    delete[] indx;
    if(d == 0.0) return 0.0;
    return d*exp(sum);
}

double TMatrix::AlgAdd (int row, int col)
{
    char* rows = new char[m_nRows];
    char* cols = new char[m_nCols];
    memset (rows, 1, m_nRows*sizeof(char));
    memset (cols, 1, m_nCols*sizeof(char));
    rows[row] = cols[col] = 0;
    double d = (((row+col)%2) ? -1.0 : 1.0)*Minor (rows, cols);
    delete[] rows;
    delete[] cols;
    return d;
}

double TMatrix::Minor (char* rowsused, char* colsused)
{
    int i, j;
    int cj = 0;
    double sum = 0.0;
    for (i = 0; i<m_nRows; i++)
        if (rowsused[i])
            break;
    if (i == m_nRows)
        return 1.0;
    for (j = 0; j<m_nCols; j++)
    {
        if (!colsused[j]) continue;
        if (m_dVals[i][j] != 0.0)
        {
            rowsused[i] = colsused[j] = 0;
            sum += ((cj%2) ? -1.0 : 1.0)*m_dVals[i][j]*Minor (rowsused, colsused);
            rowsused[i] = colsused[j] = 1;
        }
        cj ++;
    }
    return sum;
}

bool TMatrix::Invert()
{
    if(!Square()) return false;
    TMatrix tmp(*this);
    double* col = new double[m_nRows];
    int* indx = new int[m_nRows];
    int i, j;
    double d = 0.0;
    if(!LU_decomp(tmp,indx,d)) return false; // Decompose the matrix just once.
    for(j = 0; j < m_nCols; j++) { // Find inverse by columns. 
        for(i = 0; i < m_nRows; i++) col[i] = (i == j) ? 1.0 : 0.0;
        LU_backsub(tmp,indx,col);
        for(i = 0; i < m_nRows; i++) m_dVals[i][j] = col[i];
    }
    delete[] col;
    delete[] indx;
    return true;
}

bool TMatrix::LU_decomp(TMatrix& m,int* indx,double& d)
{
    int n = m.m_nRows;
    double* vv = new double[n]; //vv stores the implicit scaling of each row. 
    double big,dum,sum,temp;
    double** a = m.m_dVals;
    int imax = 0,i,j,k;
  
    d = 1.0; // No row interchanges yet. 
    for(i = 0; i < n; i++) { // Loop over rows to get the implicit scaling information.
        big = 0.0; 
        for(j = 0; j < n; j++)
            if((temp = fabs(a[i][j])) > big) big = temp; 
        if(big == 0.0) // No nonzero largest element. 
            return false;
        vv[i] = 1.0/big; // Save the scaling. 
    } 
    for (j = 0; j < n; j++) { // This is the loop over columns of Crout's method. 
        for(i = 0; i < j; i++) { // This is equation (2.3.12) except for i = j. 
            sum = a[i][j]; 
            for(k = 0; k < i; k++)
                sum -= a[i][k]*a[k][j];
            a[i][j] = sum;
        } 
        big = 0.0; // Initialize for the search for largest pivot element. 
        for(i = j; i < n; i++) { // This is i = j of equation (2.3.12) and 
                                 // i=j+1: ::N of equation (2.3.13). 
            sum = a[i][j]; 
            for(k = 0; k < j; k++) 
                sum -= a[i][k]*a[k][j];
            a[i][j] = sum;
            if((dum = vv[i]*fabs(sum)) >= big) { //Is the figure of merit 
                // for the pivot better than the best so far?
                big = dum; 
                imax = i; 
            } 
        } 
        if(j != imax) { // Do we need to interchange rows? 
            for (k = 0; k < n; k++) { // Yes, do so...
                dum = a[imax][k];
                a[imax][k] = a[j][k];
                a[j][k] = dum; 
            } 
            d = -d; // ...and change the parity of d.
            vv[imax] = vv[j]; // Also interchange the scale factor. 
        }
        indx[j] = imax; 

        // If the pivot element is zero the matrix is singular 
        // (at least to the precision of the algorithm). For some 
        // applications on singular matrices, it is desirable 
        // to substitute TINY for zero.
        if(fabs(a[j][j]) < TINY) a[j][j] = TINY;
        if(j != n) { // Now, finally, divide by the pivot element. 
            dum = 1.0 / a[j][j]; 
            for(i = j+1; i < n; i++) a[i][j] *= dum;
        } 
    }
    delete[] vv;
    return true;
}

void TMatrix::LU_backsub(TMatrix& m,int* indx,double* b)
{
    double** a = m.m_dVals;
    double sum = 0.0;
    int ii = -1,ip = 0,i,j,n = m.m_nRows;

    for(i = 0; i < n; i++) { 
        // When ii is set to a positive value, it will become the 
        // index of the first nonvanishing element of b. We now do 
        // the forward substitution, equation (2.3.6). The only 
        // new wrinkle is to unscramble the permutation as we go. 
        ip = indx[i]; 
        sum = b[ip]; 
        b[ip] = b[i]; 
        if(ii != -1) for(j = ii; j <= i-1; j++)
            sum -= a[i][j]*b[j];
        else if(sum) ii=i;
        // A nonzero element was encountered, so from now on we will 
        // have to do the sums in the loop above. 
        b[i] = sum; 
    } 
    for(i = n-1; i >= 0; i--) { 
      // Now we do the backsubstitution, equation (2.3.7). 
      sum = b[i]; 
      for(j = i+1; j < n; j++) sum -= a[i][j]*b[j];
      b[i] = sum/a[i][i]; // Store a component of the solution vector X. 
    } // All done!
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -