#include #include #include using namespace std; class range { private: int _start; int _stop; int _stride; public: // supports construction such as range(3,6), which includes values {3, 4, 5} range(int start, int stop) : _start(start), _stop(stop), _stride(1) { } // supports construction such as range(3,2,8), which includes values {3, 5, 7} range(int start, int stride, int stop) : _start(start), _stop(stop), _stride(stride) { if (stride < 1) throw invalid_argument("stride must be positive."); } // Returns starting index int start() const { return _start; } // Returns stopping index int stop() const { return _stop; } // Returns stopping index int stride() const { return _stride; } // Returns the number of values included within the range int size() const { // partials strides should count as one. e.g. range(1,2,4).size() should be 2 return (_stop - _start + _stride - 1) / _stride; // trucates properly } }; class matrix { private: int _nr; /* number of rows */ int _nc; /* number of columns */ vector data; /* underlying data storage */ public: matrix() : _nr(0), _nc(0), data() {}; matrix(int numRows, int numColumns, double value=0) : _nr(numRows), _nc(numColumns), data(numRows*numColumns, value) {} int numRows() const { return _nr; } int numColumns() const { return _nc; } matrix size() const { matrix result(1,2); result(0,0) = numRows(); result(0,1) = numColumns(); return result; } void reshape(int r, int c) { if (r * c != _nr * _nc) throw invalid_argument("To reshape, the number of elements must not change."); _nr = r; _nc = c; } bool operator==(const matrix &other) const { return (_nr == other._nr && _nc == other._nc && data == other.data); } bool operator!=(const matrix &other) const { return !(*this == other); } // provides read-only access to a matrix entry double operator()(int r, int c) const { if (r < 0 || r >= _nr || c < 0 || c >= _nc) throw out_of_range("Invalid indices for matrix"); return data[r + c * _nr]; // column-major } // provides write access to a matrix entry (albeit, without expansion) double& operator()(int r, int c) { if (r < 0 || r >= _nr || c < 0 || c >= _nc) throw out_of_range("Invalid indices for matrix"); return data[r + c * _nr]; // column-major } // provides read-only access to a matrix entry based upon ranges matrix operator()(range rows, range cols) const { // needs implementation... matrix result; return result; } //----------------------------------------------- // addition //----------------------------------------------- matrix operator+(const matrix& other) const { // produce sum of two matrices if (_nr != other._nr && _nc != other._nc) throw invalid_argument("Matrix dimensions must agree."); matrix result = matrix(*this); for (int r=0; r < _nr; r++) for (int c=0; c < _nc; c++) result(r,c) += other(r,c); return result; } matrix operator+(double scalar) const { // add scalar to all elements matrix result = matrix(*this); for (int r=0; r < _nr; r++) for (int c=0; c < _nc; c++) result(r,c) += scalar; return result; } //----------------------------------------------- // multiplication //----------------------------------------------- matrix operator*(double scalar) const { // multiply each element by scalar matrix result = matrix(*this); for (int r=0; r < _nr; r++) for (int c=0; c < _nc; c++) result(r,c) *= scalar; return result; } matrix operator*(const matrix& other) const { // matrix multiplicaiton if (_nc != other._nr) throw invalid_argument("Inner matrix dimensions must agree."); // *** rest of implementation missing *** } }; //------------------------------------------------------ // define additional support for reading/writing matrices // (implementations are given in matrixio.cpp) //------------------------------------------------------ ostream& operator<<(ostream& out, const matrix& m); istream& operator>>(istream& in, matrix& m);