C++: 矩阵操作

在原作的基础上添加对矩阵扩充的支持:

void insert(unsigned row, unsigned col, TYPE const& value);

matrix.h   :

/*****************************************************************************/
/* Name: matrix.h                                                            */
/* Uses: Class for matrix math functions.                                    */
/* Date: 4/19/2011                                                           */
/* Author: Andrew Que <http://www.DrQue.net/>                                */
/* Revisions:                                                                */
/*   0.1 - 2011/04/19 - QUE - Creation.                                      */
/*   0.5 - 2011/04/24 - QUE - Most functions are complete.                   */
/*   0.8 - 2011/05/01 - QUE -                                                */
/*     = Bug fixes.                                                          */
/*     + Dot product.                                                        */
/*   1.0 - 2011/11/26 - QUE - Release.                                       */
/*                                                                           */
/* Notes:                                                                    */
/*   This unit implements some very basic matrix functions, which include:   */
/*    + Addition/subtraction                                                 */
/*    + Transpose                                                            */
/*    + Row echelon reduction                                                */
/*    + Determinant                                                          */
/*    + Dot product                                                          */
/*    + Matrix product                                                       */
/*    + Scalar product                                                       */
/*    + Inversion                                                            */
/*    + LU factorization/decomposition                                       */
/*     There isn't much for optimization in this unit as it was designed as  */
/*   more of a learning experience.                                          */
/*                                                                           */
/* License:                                                                  */
/*   This program is free software: you can redistribute it and/or modify    */
/*   it under the terms of the GNU General Public License as published by    */
/*   the Free Software Foundation, either version 3 of the License, or       */
/*   (at your option) any later version.                                     */
/*                                                                           */
/*   This program is distributed in the hope that it will be useful,         */
/*   but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*   GNU General Public License for more details.                            */
/*                                                                           */
/*   You should have received a copy of the GNU General Public License       */
/*   along with this program.  If not, see <http://www.gnu.org/licenses/>.   */
/*                                                                           */
/*                     (C) Copyright 2011 by Andrew Que                      */
/*                           http://www.DrQue.net/                           */
/*****************************************************************************/
#ifndef _MATRIX_H_
#define _MATRIX_H_

#include <iostream>
#include <cassert>
#include <climits>
#include <vector>

// Class forward for identity matrix.
template< class TYPE > class IdentityMatrix;

//=============================================================================
// Matrix template class
//   Contains a set of matrix manipulation functions.  The template is designed
// so that the values of the matrix can be of any type that allows basic
// arithmetic.
//=============================================================================
template< class TYPE = int >
  class Matrix
  {
    protected:
      // Matrix data.
      unsigned rows;
      unsigned columns;

      // Storage for matrix data.
      std::vector< std::vector< TYPE > > matrix;

      // Order sub-index for rows.
      //   Use: matrix[ order[ row ] ][ column ].
      unsigned * order;

      //-------------------------------------------------------------
      // Return the number of leading zeros in the given row.
      //-------------------------------------------------------------
      unsigned getLeadingZeros
      (
        // Row to count
        unsigned row
      ) const
      {
        TYPE const ZERO = static_cast< TYPE >( 0 );
        unsigned column = 0;
        while ( ZERO == matrix[ row ][ column ] )
          ++column;

        return column;
      }

      //-------------------------------------------------------------
      // Reorder the matrix so the rows with the most zeros are at
      // the end, and those with the least at the beginning.
      //
      // NOTE: The matrix data itself is not manipulated, just the
      // 'order' sub-indexes.
      //-------------------------------------------------------------
      void reorder()
      {
        unsigned * zeros = new unsigned[ rows ];

        for ( unsigned row = 0; row < rows; ++row )
        {
          order[ row ] = row;
          zeros[ row ] = getLeadingZeros( row );
        }

        for ( unsigned row = 0; row < (rows-1); ++row )
        {
          unsigned swapRow = row;
          for ( unsigned subRow = row + 1; subRow < rows; ++subRow )
          {
            if ( zeros[ order[ subRow ] ] < zeros[ order[ swapRow ] ] )
              swapRow = subRow;
          }

          unsigned hold    = order[ row ];
          order[ row ]     = order[ swapRow ];
          order[ swapRow ] = hold;
        }

        delete zeros;
      }

      //-------------------------------------------------------------
      // Divide a row by given value.  An elementary row operation.
      //-------------------------------------------------------------
      void divideRow
      (
        // Row to divide.
        unsigned row,

        // Divisor.
        TYPE const & divisor
      )
      {
        for ( unsigned column = 0; column < columns; ++column )
          matrix[ row ][ column ] /= divisor;
      }

      //-------------------------------------------------------------
      // Modify a row by adding a scaled row. An elementary row
      // operation.
      //-------------------------------------------------------------
      void rowOperation
      (
        unsigned row,
        unsigned addRow,
        TYPE const & scale
      )
      {
        for ( unsigned column = 0; column < columns; ++column )
          matrix[ row ][ column ] += matrix[ addRow ][ column ] * scale;
      }

      //-------------------------------------------------------------
      // Allocate memory for matrix data.
      //-------------------------------------------------------------
      void allocate
      (
        unsigned rowNumber,
        unsigned columnNumber
      )
      {
        // Allocate order integers.
        order = new unsigned[ rowNumber ];

        // Setup matrix sizes.
        matrix.resize( rowNumber );
        for ( unsigned row = 0; row < rowNumber; ++row )
          matrix[ row ].resize( columnNumber );
      }

      //-------------------------------------------------------------
      // Free memory used for matrix data.
      //-------------------------------------------------------------
      void deallocate
      (
        unsigned rowNumber,
        unsigned columnNumber
      )
      {
        // Free memory used for storing order (if there is any).
        if ( 0 != rowNumber )
          delete[] order;
      }

    public:
      // Used for matrix concatenation.
      typedef enum
      {
        TO_RIGHT,
        TO_BOTTOM
      } Position;

      //-------------------------------------------------------------
      // Return the number of rows in this matrix.
      //-------------------------------------------------------------
      unsigned getRows() const
      {
        return rows;
      }

      //-------------------------------------------------------------
      // Return the number of columns in this matrix.
      //-------------------------------------------------------------
      unsigned getColumns() const
      {
        return columns;
      }

      //-------------------------------------------------------------
      // Get an element of the matrix.
      //-------------------------------------------------------------
      TYPE get
      (
        unsigned row,   // Which row.
        unsigned column // Which column.
      ) const
      {
        assert( row < rows );
        assert( column < columns );

        return matrix[ row ][ column ];
      }

      //-------------------------------------------------------------
      // Proform LU decomposition.
      // This will create matrices L and U such that A=LxU
      //-------------------------------------------------------------
      void LU_Decomposition
      (
        Matrix & upper,
        Matrix & lower
      ) const
      {
        assert( rows == columns );

        TYPE const ZERO = static_cast< TYPE >( 0 );

        upper = *this;
        lower = *this;

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            lower.matrix[ row ][ column ] = ZERO;

        for ( unsigned row = 0; row < rows; ++row )
        {
          TYPE value = upper.matrix[ row ][ row ];
          if ( ZERO != value )
          {
            upper.divideRow( row, value );
            lower.matrix[ row ][ row ] = value;
          }

          for ( unsigned subRow = row + 1; subRow < rows; ++subRow )
          {
            TYPE value = upper.matrix[ subRow ][ row ];
            upper.rowOperation( subRow, row, -value );
            lower.matrix[ subRow ][ row ] = value;
          }
        }
      }

      //-------------------------------------------------------------
      // Set an element in the matrix.
      //-------------------------------------------------------------
      void put
      (
        unsigned row,
        unsigned column,
        TYPE const & value
      )
      {
        assert( row < rows );
        assert( column < columns );

        matrix[ row ][ column ] = value;
      }

      //-------------------------------------------------------------
	  // Set an element in the matrix can extern the size of matrix
	  //-------------------------------------------------------------
	  void insert(unsigned row, unsigned col, TYPE const& value)
	  {
		  TYPE const ZERO = static_cast< TYPE >(0);

		  if (rows <= row)
		  {
			  int extend_row = row + 1 - rows;
			  if (rows == 0)
			  {
				  for (int n_row = 0; n_row < row + 1; n_row++)
				  {
					  std::vector< TYPE > temp;
					  for (int n_col = 0; n_col < columns; n_col++)
					  {
						  temp.push_back(ZERO);
					  }
					  matrix.push_back(temp);
				  }
			  }
			  else
			  {
				  for (int n_row = rows - 1; n_row < row + 1; n_row++)
				  {
					  std::vector< TYPE > temp;
					  for (int n_col = 0; n_col < columns; n_col++)
					  {
						  temp.push_back(ZERO);
					  }
					  matrix.push_back(temp);
				  }
			  }
		  }

		  if (columns <= col)
		  {
			  int extend_col = col + 1 - columns;
			  if (columns == 0)
			  {
				  for (int n_col = 0; n_col < col + 1; n_col++)
				  {
					  matrix.at(row).push_back(ZERO);
				  }
			  }
			  else
			  {
				  for (int n_col = columns - 1; n_col < col + 1; n_col++)
				  {
					  matrix.at(row).push_back(ZERO);
				  }
			  }
		  }

		  if (rows <= row)
		  {
			  rows = row + 1;
		  }

		  if (columns <= col)
		  {
			  columns = col + 1;
		  }

		  this->put(row, col, value);
	  }

      //-------------------------------------------------------------
      // Return part of the matrix.
      // NOTE: The end points are the last elements copied.  They can
      // be equal to the first element when wanting just a single row
      // or column.  However, the span of the total matrix is
      // ( 0, rows - 1, 0, columns - 1 ).
      //-------------------------------------------------------------
      Matrix getSubMatrix
      (
        unsigned startRow,
        unsigned endRow,
        unsigned startColumn,
        unsigned endColumn,
        unsigned const * newOrder = NULL
      )
      {
        Matrix subMatrix( endRow - startRow + 1, endColumn - startColumn + 1 );

        for ( unsigned row = startRow; row <= endRow; ++row )
        {
          unsigned subRow;
          if ( NULL == newOrder )
            subRow = row;
          else
            subRow = newOrder[ row ];

          for ( unsigned column = startColumn; column <= endColumn; ++column )
            subMatrix.matrix[ row - startRow ][ column - startColumn ] =
              matrix[ subRow ][ column ];
        }

        return subMatrix;
      }

      //-------------------------------------------------------------
      // Return a single column from the matrix.
      //-------------------------------------------------------------
      Matrix getColumn
      (
        unsigned column
      )
      {
        return getSubMatrix( 0, rows - 1, column, column );
      }

      //-------------------------------------------------------------
      // Return a single row from the matrix.
      //-------------------------------------------------------------
      Matrix getRow
      (
        unsigned row
      )
      {
        return getSubMatrix( row, row, 0, columns - 1 );
      }

      //-------------------------------------------------------------
      // Place matrix in reduced row echelon form.
      //-------------------------------------------------------------
      void reducedRowEcholon()
      {
        TYPE const ZERO = static_cast< TYPE >( 0 );

        // For each row...
        for ( unsigned rowIndex = 0; rowIndex < rows; ++rowIndex )
        {
          // Reorder the rows.
          reorder();

          unsigned row = order[ rowIndex ];

          // Divide row down so first term is 1.
          unsigned column = getLeadingZeros( row );
          TYPE divisor = matrix[ row ][ column ];
          if ( ZERO != divisor )
          {
            divideRow( row, divisor );

            // Subtract this row from all subsequent rows.
            for ( unsigned subRowIndex = ( rowIndex + 1 ); subRowIndex < rows; ++subRowIndex )
            {
              unsigned subRow = order[ subRowIndex ];
              if ( ZERO != matrix[ subRow ][ column ] )
                rowOperation
                (
                  subRow,
                  row,
                  -matrix[ subRow ][ column ]
                );
            }
          }

        }

        // Back substitute all lower rows.
        for ( unsigned rowIndex = ( rows - 1 ); rowIndex > 0; --rowIndex )
        {
          unsigned row = order[ rowIndex ];
          unsigned column = getLeadingZeros( row );
          for ( unsigned subRowIndex = 0; subRowIndex < rowIndex; ++subRowIndex )
          {
            unsigned subRow = order[ subRowIndex ];
            rowOperation
            (
              subRow,
              row,
              -matrix[ subRow ][ column ]
            );
          }
        }

      } // reducedRowEcholon

      //-------------------------------------------------------------
      // Return the determinant of the matrix.
      // Recursive function.
      //-------------------------------------------------------------
      TYPE determinant() const
      {
        TYPE result = static_cast< TYPE >( 0 );

        // Must have a square matrix to even bother.
        assert( rows == columns );

        if ( rows > 2 )
        {
          int sign = 1;
          for ( unsigned column = 0; column < columns; ++column )
          {
            TYPE subDeterminant;

            Matrix subMatrix = Matrix( *this, 0, column );

            subDeterminant  = subMatrix.determinant();
            subDeterminant *= matrix[ 0 ][ column ];

            if ( sign > 0 )
              result += subDeterminant;
            else
              result -= subDeterminant;

            sign = -sign;
          }
        }
        else
        {
          result = ( matrix[ 0 ][ 0 ] * matrix[ 1 ][ 1 ] )
                 - ( matrix[ 0 ][ 1 ] * matrix[ 1 ][ 0 ] );
        }

        return result;

      } // determinant

      //-------------------------------------------------------------
      // Calculate a dot product between this and an other matrix.
      //-------------------------------------------------------------
      TYPE dotProduct
      (
        Matrix const & otherMatrix
      ) const
      {
        // Dimentions of each matrix must be the same.
        assert( rows == otherMatrix.rows );
        assert( columns == otherMatrix.columns );

        TYPE result = static_cast< TYPE >( 0 );
        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
          {
            result +=
              matrix[ row ][ column ]
              * otherMatrix.matrix[ row ][ column ];
          }

        return result;

      } // dotProduct

      //-------------------------------------------------------------
      // Return the transpose of the matrix.
      //-------------------------------------------------------------
      Matrix const getTranspose() const
      {
        Matrix result( columns, rows );

        // Transpose the matrix by filling the result's rows will
        // these columns, and vica versa.
        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            result.matrix[ column ][ row ] = matrix[ row ][ column ];

        return result;

      } // transpose

      //-------------------------------------------------------------
      // Transpose the matrix.
      //-------------------------------------------------------------
      void transpose()
      {
        *this = getTranspose();
      }

      //-------------------------------------------------------------
      // Return inverse matrix.
      //-------------------------------------------------------------
      Matrix const getInverse() const
      {
        // Concatenate the identity matrix onto this matrix.
        Matrix inverseMatrix
          (
            *this,
            IdentityMatrix< TYPE >( rows, columns ),
            TO_RIGHT
          );

        // Row reduce this matrix.  This will result in the identity
        // matrix on the left, and the inverse matrix on the right.
        inverseMatrix.reducedRowEcholon();

        // Copy the inverse matrix data back to this matrix.
        Matrix result
        (
          inverseMatrix.getSubMatrix
          (
            0,
            rows - 1,
            columns,
            columns + columns - 1,
            inverseMatrix.order
          )
        );

        return result;

      } // invert


      //-------------------------------------------------------------
      // Invert this matrix.
      //-------------------------------------------------------------
      void invert()
      {
        *this = getInverse();

      } // invert

      //=======================================================================
      // Operators.
      //=======================================================================

      //-------------------------------------------------------------
      // Index in matrix.
      //-------------------------------------------------------------
      std::vector< TYPE >& operator [](const int index)
      {
        return this->matrix.at(index);
      }

      //-------------------------------------------------------------
      // Add by an other matrix.
      //-------------------------------------------------------------
      Matrix const operator +
      (
        Matrix const & otherMatrix
      ) const
      {
        assert( otherMatrix.rows == rows );
        assert( otherMatrix.columns == columns );

        Matrix result( rows, columns );

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            result.matrix[ row ][ column ] =
              matrix[ row ][ column ]
              + otherMatrix.matrix[ row ][ column ];

        return result;
      }

      //-------------------------------------------------------------
      // Add self by an other matrix.
      //-------------------------------------------------------------
      Matrix const & operator +=
      (
        Matrix const & otherMatrix
      )
      {
        *this = *this + otherMatrix;
        return *this;
      }

      //-------------------------------------------------------------
      // Subtract by an other matrix.
      //-------------------------------------------------------------
      Matrix const operator -
      (
        Matrix const & otherMatrix
      ) const
      {
        assert( otherMatrix.rows == rows );
        assert( otherMatrix.columns == columns );

        Matrix result( rows, columns );

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            result.matrix[ row ][ column ] =
              matrix[ row ][ column ]
              - otherMatrix.matrix[ row ][ column ];

        return result;
      }

      //-------------------------------------------------------------
      // negative matrix.
      //-------------------------------------------------------------
      Matrix const & operator - ()
      {
        for (int p_row = 0; p_row < rows; p_row++)
        {
          for (int p_col = 0; p_col < columns; p_col++)
          {
            matrix[p_row][p_col] = -matrix[p_row][p_col];
          }
        }

        return *this;
      }

      //-------------------------------------------------------------
      // Subtract self by an other matrix.
      //-------------------------------------------------------------
      Matrix const & operator -=
      (
        Matrix const & otherMatrix
      )
      {
        *this = *this - otherMatrix;
        return *this;
      }

      //-------------------------------------------------------------
      // Matrix multiplication.
      //-------------------------------------------------------------
      Matrix const operator *
      (
        Matrix const & otherMatrix
      ) const
      {
        TYPE const ZERO = static_cast< TYPE >( 0 );

        assert( otherMatrix.rows == columns );

        Matrix result( rows, otherMatrix.columns );

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < otherMatrix.columns; ++column )
          {
            result.matrix[ row ][ column ] = ZERO;

            for ( unsigned index = 0; index < columns; ++index )
              result.matrix[ row ][ column ] +=
                matrix[ row ][ index ]
                * otherMatrix.matrix[ index ][ column ];
          }

        return result;
      }

      //-------------------------------------------------------------
      // Multiply self by matrix.
      //-------------------------------------------------------------
    Matrix const& operator /
    (
            const double& quotiety
    )const
    {
        TYPE const ZERO = static_cast< TYPE >( 0 );

//        assert( otherMatrix.rows == columns );
        assert(quotiety != 0);

        Matrix result( rows, columns );

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
          {
            result.matrix[ row ][ column ] = ZERO;
            result.matrix[ row ][ column ] = matrix[ row ][ column ] / quotiety;
          }

        return result;
    }

      //-------------------------------------------------------------
      // Multiply self by matrix.
      //-------------------------------------------------------------
      Matrix const & operator *=
      (
        Matrix const & otherMatrix
      )
      {
        *this = *this * otherMatrix;
        return *this;
      }

      //-------------------------------------------------------------
      // Multiply by scalar constant.
      //-------------------------------------------------------------
      Matrix const operator *
      (
        TYPE const & scalar
      ) const
      {
        Matrix result( rows, columns );

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            result.matrix[ row ][ column ] = matrix[ row ][ column ] * scalar;

        return result;
      }

      //-------------------------------------------------------------
      // Multiply self by scalar constant.
      //-------------------------------------------------------------
      Matrix const & operator *=
      (
        TYPE const & scalar
      )
      {
        *this = *this * scalar;
        return *this;
      }

      //-------------------------------------------------------------
      // Copy matrix.
      //-------------------------------------------------------------
      Matrix & operator =
      (
        Matrix const & otherMatrix
      )
      {
        if ( this == &otherMatrix )
          return *this;

        // Release memory currently in use.
        deallocate( rows, columns );

        rows    = otherMatrix.rows;
        columns = otherMatrix.columns;
        allocate( rows, columns );

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            matrix[ row ][ column ] =
            otherMatrix.matrix[ row ][ column ];

        return *this;
      }

      //-------------------------------------------------------------
      // Copy matrix data from array.
      // Although matrix data is two dimensional, this copy function
      // assumes the previous row is immediately followed by the next
      // row's data.
      //
      // Example for 3x2 matrix:
      //     int const data[ 3 * 2 ] =
      //     {
      //       1, 2, 3,
      //       4, 5, 6
      //     };
      //    Matrix< int > matrix( 3, 2 );
      //    matrix = data;
      //-------------------------------------------------------------
      Matrix & operator =
      (
        TYPE const * data
      )
      {
        unsigned index = 0;

        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            matrix[ row ][ column ] = data[ index++ ];

        return *this;
      }

      //-----------------------------------------------------------------------
      // Return true if this matrix is the same of parameter.
      //-----------------------------------------------------------------------
      bool operator ==
      (
        Matrix const & value
      ) const
      {
        bool isEqual = true;
        for ( unsigned row = 0; row < rows; ++row )
          for ( unsigned column = 0; column < columns; ++column )
            if ( matrix[ row ][ column ] != value.matrix[ row ][ column ] )
              isEqual = false;

        return isEqual;
      }

      //-----------------------------------------------------------------------
      // Return true if this matrix is NOT the same of parameter.
      //-----------------------------------------------------------------------
      bool operator !=
      (
        Matrix const & value
      ) const
      {
        return !( *this == value );
      }

      //-------------------------------------------------------------
      // Constructor for empty matrix.
      // Only useful if matrix is being assigned (i.e. copied) from
      // somewhere else sometime after construction.
      //-------------------------------------------------------------
      Matrix()
      :
        rows( 0 ),
        columns( 0 )
      {
        allocate( 0, 0 );
      }

      //-------------------------------------------------------------
      // Constructor using rows and columns.
      //-------------------------------------------------------------
      Matrix
      (
        unsigned rowsParameter,
        unsigned columnsParameter
      )
      :
        rows( rowsParameter ),
        columns( columnsParameter )
      {
        TYPE const ZERO = static_cast< TYPE >( 0 );

        // Allocate memory for new matrix.
        allocate( rows, columns );

        // Fill matrix with zero.
        for ( unsigned row = 0; row < rows; ++row )
        {
          order[ row ] = row;

          for ( unsigned column = 0; column < columns; ++column )
            matrix[ row ][ column ] = ZERO;
        }
      }

      //-------------------------------------------------------------
      // This constructor will allow the creation of a matrix based off
      // an other matrix.  It can copy the matrix entirely, or omitted a
      // row/column.
      //-------------------------------------------------------------
      Matrix
      (
        Matrix const & copyMatrix,
        unsigned omittedRow    = INT_MAX,
        unsigned omittedColumn = INT_MAX
      )
      {
        // Start with the number of rows/columns from matrix to be copied.
        rows    = copyMatrix.getRows();
        columns = copyMatrix.getColumns();

        // If a row is omitted, then there is one less row.
        if ( INT_MAX != omittedRow  )
          rows--;

        // If a column is omitted, then there is one less column.
        if ( INT_MAX != omittedColumn )
          columns--;

        // Allocate memory for new matrix.
        allocate( rows, columns );

        unsigned rowIndex = 0;
        for ( unsigned row = 0; row < rows; ++row )
        {
          // If this row is to be skipped...
          if ( rowIndex == omittedRow )
            rowIndex++;

          // Set default order.
          order[ row ] = row;

          unsigned columnIndex = 0;
          for ( unsigned column = 0; column < columns; ++column )
          {
            // If this column is to be skipped...
            if ( columnIndex == omittedColumn )
              columnIndex++;

            matrix[ row ][ column ] = copyMatrix.matrix[ rowIndex ][ columnIndex ];

            columnIndex++;
          }

          ++rowIndex;
        }

      }

      //-------------------------------------------------------------
      // Constructor to concatenate two matrices.  Concatenation
      // can be done to the right, or to the bottom.
      //   A = [B | C]
      //-------------------------------------------------------------
      Matrix
      (
        Matrix const & copyMatrixA,
        Matrix const & copyMatrixB,
        Position position = TO_RIGHT
      )
      {
        unsigned rowOffset    = 0;
        unsigned columnOffset = 0;

        if ( TO_RIGHT == position )
          columnOffset = copyMatrixA.columns;
        else
          rowOffset = copyMatrixA.rows;

        rows    = copyMatrixA.rows    + rowOffset;
        columns = copyMatrixA.columns + columnOffset;

        // Allocate memory for new matrix.
        allocate( rows, columns );

        for ( unsigned row = 0; row < copyMatrixA.rows; ++row )
          for ( unsigned column = 0; column < copyMatrixA.columns; ++column )
            matrix[ row ][ column ] = copyMatrixA.matrix[ row ][ column ];

        for ( unsigned row = 0; row < copyMatrixB.rows; ++row )
          for ( unsigned column = 0; column < copyMatrixB.columns; ++column )
            matrix[ row + rowOffset ][ column + columnOffset ] =
              copyMatrixB.matrix[ row ][ column ];
      }

      //-------------------------------------------------------------
      // Destructor.
      //-------------------------------------------------------------
      ~Matrix()
      {
        // Release memory.
        deallocate( rows, columns );
      }

  };

//=============================================================================
// Class for identity matrix.
//=============================================================================
template< class TYPE >
  class IdentityMatrix : public Matrix< TYPE >
  {
    public:
      IdentityMatrix
      (
        unsigned rowsParameter,
        unsigned columnsParameter
      )
      :
        Matrix< TYPE >( rowsParameter, columnsParameter )
      {
        TYPE const ZERO = static_cast< TYPE >( 0 );
        TYPE const ONE  = static_cast< TYPE >( 1 );

        for ( unsigned row = 0; row < Matrix< TYPE >::rows; ++row )
        {
          for ( unsigned column = 0; column < Matrix< TYPE >::columns; ++column )
            if ( row == column )
              Matrix< TYPE >::matrix[ row ][ column ] = ONE;
            else
              Matrix< TYPE >::matrix[ row ][ column ] = ZERO;
        }
      }
  };

//-----------------------------------------------------------------------------
// Stream operator used to convert matrix class to a string.
//-----------------------------------------------------------------------------
template< class TYPE >
  std::ostream & operator<<
  (
    // Stream data to place string.
    std::ostream & stream,

    // A matrix.
    Matrix< TYPE > const & matrix
  )
  {
    for ( unsigned row = 0; row < matrix.getRows(); ++row )
    {
      for ( unsigned column = 0; column < matrix.getColumns(); ++column )
        stream << "\t" << matrix.get( row , column );

      stream << std::endl;
    }

    return stream;
  }

#endif // _MATRIX_H_

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值