#ifndef MATRIX_H #define MATRIX_H #include #include /** \mainpage

CSCI 146 Project

These pages provide documentation for the various definitions related to adding support for matrices in C++. */ /** * A namespace for all classes defined in our CSCI 146 project. * * To use these classes from another problem, in addition to * using the syntax * \verbatim #include "matrix.h" \endverbatim * * one should also use the command * \verbatim using namespace csci146; \endverbatim * * or else you must explicitly designate all uses of classes such as * \verbatim csci146::matrix m; \endverbatim */ namespace csci146 { /** * Representation of a two-dimensional matrix. * * This represents a two-dimensional matrix of double precision * floating-point numbers. It may be that the span of one or both * of the dimensions is one, in which case this represents a row * vector or column vector. One or both of the dimensions might be * zero, in which case it represents an empty matrix. * * When linearized, the matrix is stored in column-major order. */ class matrix { private: /** number of rows */ int _nr; /** number of columns */ int _nc; /** underlying data storage */ std::vector _data; public: /** * Constructs an empty matrix. * * Technically, this matrix is 0x0 dimensional. */ matrix(); /** * Constructs a matrix with given number of rows and columns. * * By default, all matrix entries are zero, but they can be set * to any indicated scalar value. * * @param numberRows the initial number of rows * @param numberColumns the initial number of columns * @param value the initial value for all entries (0 by default) */ matrix(int numberRows, int numberColumns, double value=0); /** * Returns the current number of columns for the matrix. */ int numColumns() const; // number of columns /** * Converts between two-dimensional matrixes and one-dimensional diagonals. * * Specifically, if the given matrix is one-dimensional, then this constructs a new * square matrix that has the given entries along the diagonal, and zeros elsewhere. * * Alternatively, if the given matrix is two-dimensional, this returns a new matrix that * represents a row-vector describing the diagonal of the given matrix. * * * As an example, given a matrix m with contents: \verbatim 5 15 3 \endverbatim * a call to m.diag() would return the result \verbatim 5 0 0 0 15 0 0 0 3 \endverbatim * * Conversely, given a matrix m with contents \verbatim 5 15 3 8 20 2 25 3 0 0 23 9 0 0 50 0 \endverbatim * a call to m.diag() would return the result \verbatim 5 2 23 9 \endverbatim * * Note that if the original matrix is not square, the diagonal * has length that is the shorter of the number of rows or number * of columns. For example, givne a matrix m with contents \verbatim 5 15 3 8 20 2 25 3 \endverbatim * a call to m.diag() would return the result \verbatim 5 2 \endverbatim */ matrix diag() const; /** * Returns the current number of rows for the matrix. */ int numRows() const; // number of rows /** * Reshapes the matrix to the new number of rows and columns. * * @param r desired number of rows * @param c desired number of columns * * @throw invalid_argument if total number of elements does not remain the same */ void reshape(int r, int c); /** * Returns a row-vector whose entries designate the current dimensions of the matrix. * * As an example, if a matrix currently had contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * a call to size would return the result \verbatim 2 4 \endverbatim * as there are two rows and four columns. */ matrix size() const; // returns vector designating the size /** * Generates a matrix that is the transpose form of the current one. * * As a simple example, assume that matrix m has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the expression \verbatim m.transpose() \endverbatim * will result in a new matrix \verbatim 5 20 15 2 3 14 8 3 \endverbatim * * Note that the contents of the original matrix m remain unchanged. */ matrix transpose() const; // equivalent to M' in matlab /** * Tests if two matrices have identical dimension and content. * * @param other the second matrix in an expression (m == other) */ bool operator==(const matrix &other) const; /** * The converse of the equivalence test. * * @param other the second matrix in an expression (m != other) */ bool operator!=(const matrix &other) const; /** * Provides read-only access to a specific matrix element. * * As a simple example, assume that matrix m has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * This method is invoked when using the syntax \verbatim double v = m(1,2); \endverbatim *in which case the value 14 results (as that is row 1, column 2). * * @param r the indicated row (with 0 designating the top row) * @param c the indicated column (with 0 designating the leftmost column) * * @throw out_of_range if either index is invalid for the current dimensions */ double operator()(int r, int c) const; /** * Provides a live reference to a specific matrix element. * * The caller may use the reference to directly mutate the content of the cell. * As a simple example, assume that matrix m has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * This method is invoked when using the syntax \verbatim m(1,2) = 25; \endverbatim * in which case the matrix now has contents \verbatim 5 15 3 8 20 2 25 3 \endverbatim * * Note that if a row or column is indicated beyond the current * extent of the matrix, the matrix is automatically reized to make room * for the new entry, with other new cells getting value 0. For example * the syntax * This method is invoked when using the syntax \verbatim m(3,2) = 50; \endverbatim * causes the above matrix to be reconfigured as \verbatim 5 15 3 8 20 2 25 3 0 0 0 0 0 0 50 0 \endverbatim * * @param r the indicated row (with 0 designating the top row) * @param c the indicated column (with 0 designating the leftmost column) * * @throw out_of_range if either index is negative */ double& operator()(int r, int c); /** * Provides read-only access to a matrix element specified with a linear index. * * Matrices are linearized using the column-major convention. * As a simple example, assume that matrix m has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * This method is invoked when using the syntax \verbatim double v = m(5); \endverbatim *in which case the value 14 results (as that has index 5 in column-major order). * * @param k the zero-indexed location in column-major order * * @throw out_of_range if index is invalid */ double operator()(int k) const; /** * Provides a live reference to a matrix element specified with a linear index. * * Matrices are linearized using the column-major convention. * As a simple example, assume that matrix m has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * This method is invoked when using the syntax \verbatim m(5) = 25 \endverbatim * in which case the matrix now has contents \verbatim 5 15 3 8 20 2 25 3 \endverbatim * * Note: unlike the (row,column) form of this assignment, a matrix * cannot be resized using the linearized index unless it is * either a row vector or column vector. * * @param k the zero-indexed location in column-major order * * @throw out_of_range if index is negative * @throw out_of_range if index is beyond the extent of a two-dimensional matrix */ double& operator()(int k); /** * Generates a matrix that is the negated form of the current one. * * As a simple example, assume that matrix m has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the expression \verbatim -m \endverbatim * will result in a new matrix \verbatim -5 -15 -3 -8 -20 -2 -14 -3 \endverbatim * * Note that the contents of the original matrix m remain unchanged. */ matrix operator-() const; // negate all entries // addition /** * Generates a matrix that is the element-by-element sum of two matrices. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * and matrix B has contents: \verbatim 2 14 23 10 11 12 5 9 \endverbatim Then the syntax \verbatim C = A + B \endverbatim * will result in a new matrix C with contents \verbatim 7 29 26 18 31 14 19 12 \endverbatim * * Note that the contents of both A and B remain unchanged, * although one could be reassigned using a syntax such as \verbatim A = A + B; \endverbatim * See also operator+= below. * * @throw invalid_argument if matrix dimensions do not agree */ matrix operator+(const matrix& other) const; // produce sum of two matrices /** * Mutates a matrix by doing an element-by-element addition with another matrix. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * and matrix B has contents: \verbatim 2 14 23 10 11 12 5 9 \endverbatim Then the command \verbatim A += B \endverbatim * will cause the contents of A to be set to \verbatim 7 29 26 18 31 14 19 12 \endverbatim * while leaving the contents of B unchanged. * * @throw invalid_argument if matrix dimensions do not agree */ matrix& operator+=(const matrix& other); // add other matrix to this (mutate) /** * Generates a matrix by adding a scalar constant to each element of another matrix. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the syntax \verbatim B = A + 5; \endverbatim * will result in a new matrix B with contents \verbatim 10 20 8 13 25 7 19 8 \endverbatim * while leaving the contents of A unchanged. */ matrix operator+(double scalar) const; // add scalar to each element /** * Mutates a matrix by adding a scalar constant to each element. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the syntax \verbatim A += 5 \endverbatim * causes the contents of A to be set to \verbatim 10 20 8 13 25 7 19 8 \endverbatim */ matrix& operator+=(double scalar); // add scalar to each element (mutate) // subtraction /** * Generates a matrix that is the element-by-element difference of two matrices. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * and matrix B has contents: \verbatim 2 14 23 10 11 12 5 9 \endverbatim Then the syntax \verbatim C = A - B \endverbatim * will result in a new matrix C with contents \verbatim 3 1 -20 -2 9 -10 9 -6 \endverbatim * * Note that the contents of both A and B remain unchanged, * although one could be reassigned using a syntax such as \verbatim A = A - B; \endverbatim * See also operator-= below. * * @throw invalid_argument if matrix dimensions do not agree */ matrix operator-(const matrix& other) const; // produce difference of two matrices /** * Mutates a matrix by doing an element-by-element addition with another matrix. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * and matrix B has contents: \verbatim 2 14 23 10 11 12 5 9 \endverbatim Then the command \verbatim A -= B \endverbatim * will cause the contents of A to be set to \verbatim 3 1 -20 -2 9 -10 9 -6 \endverbatim * while leaving the contents of B unchanged. * * @throw invalid_argument if matrix dimensions do not agree */ matrix& operator-=(const matrix& other); // subtract other matrix from this (mutate) /** * Generates a matrix by subtracting a scalar constant from each element of another matrix. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the syntax \verbatim B = A - 5; \endverbatim * will result in a new matrix B with contents \verbatim 0 10 -2 3 15 -3 9 -2 \endverbatim * while leaving the contents of A unchanged. */ matrix operator-(double scalar) const; // subtract scalar from each element /** * Mutates a matrix by subtracting a scalar constant from each element. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the syntax \verbatim A -= 5 \endverbatim * causes the contents of A to be set to \verbatim 0 10 -2 3 15 -3 9 -2 \endverbatim */ matrix& operator-=(double scalar); // subract scalar to each element (mutate) // multiplicaiton /** * Generates a matrix that is the product of two matrices. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * and matrix B has contents: \verbatim 3 10 2 14 \endverbatim Then the syntax \verbatim C = A * B \endverbatim * will result in a new matrix C with contents \verbatim 283 150 \endverbatim * Note that the contents of both A and B remain unchanged. * * @throw invalid_argument if the inner matrix dimensions do not agree. * That is, when computing A*B, the number of columns in A must * match the number of rows in B. */ matrix operator*(const matrix& other) const; /** * Mutates a matrix by multiplying it with another * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim * and matrix B has contents: \verbatim 3 10 2 14 \endverbatim Then the syntax \verbatim A *= B \endverbatim * will cause the contents of A to be reset to \verbatim 283 150 \endverbatim * while leaving the contents of B unchanged. * * Note: the inner dimensions of the product must agree or else a * runtime error occurs. That is the number of columns in A must * match the number of rows in B when computing A*B. The * resulting product has the same number of rows as A and the same * number of columns as B. */ matrix& operator*=(const matrix& other); /** * Generates a matrix by multiplying each element of another matrix by a scalar constant. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the syntax \verbatim B = A * 2; \endverbatim * will result in a new matrix B with contents \verbatim 10 30 6 16 40 4 28 6 \endverbatim * while leaving the contents of A unchanged. */ matrix operator*(double scalar) const; // multiply each element by scalar /** * Mutates a matrix by multiplying each element by a scalar constant. * * As a simple example, assume that matrix A has contents: \verbatim 5 15 3 8 20 2 14 3 \endverbatim Then the syntax \verbatim A *= 2 \endverbatim * causes the contents of A to be set to \verbatim 10 30 6 16 40 4 28 6 \endverbatim */ matrix& operator*=(double scalar); }; // Support for commutative operations with scalar /** * Generates a matrix by adding a scalar constant to each element of another matrix. * * This allows a commutative syntax of (5 + A) to be equivalent to (A + 5). */ matrix operator+(double scalar, const matrix& m); /** * Generates a matrix by multiplying each element of another matrix by a scalar constant. * * This allows a commutative syntax of (5 * A) to be equivalent to (A * 5). */ matrix operator*(double scalar, const matrix& m); // Support for extracting to output stream /** * Outputs the contents of a matrix in tabular form. */ std::ostream& operator<<(std::ostream& out, const matrix& m); /** * Reconfigures the matrix to match data read from a stream. * * The input must have the same number of columns per line * and must be terminated with a blank line. */ std::istream& operator>>(std::istream& in, matrix& m); } // end of csci146 namespace #endif