add solution for hw 5

This commit is contained in:
JamesFlare1212
2025-03-12 10:00:49 -04:00
parent c20ce7c2c3
commit 903e76ef1f
6 changed files with 772 additions and 326 deletions

View File

@@ -1,15 +1,12 @@
#include "Matrix.h"
#include <iostream>
#include <iomanip>
//helper function to allocate memory for a matrix of size r x c and fill it with "fill"
void Matrix::allocateMemory(unsigned int r, unsigned int c, double fill) {
if(r == 0 || c == 0) {
rows = 0;
cols = 0;
data = nullptr;
return;
}
//-------------------------
// Private Helper Functions
//-------------------------
// Allocates memory for an r x c matrix and fills every element with 'fill'
void Matrix::allocate(unsigned int r, unsigned int c, double fill) {
rows = r;
cols = c;
data = new double*[rows];
@@ -21,149 +18,180 @@ void Matrix::allocateMemory(unsigned int r, unsigned int c, double fill) {
}
}
//helper function to deallocate memory
void Matrix::deallocateMemory() {
if(data != nullptr) {
// Deallocates the memory used by the matrix
void Matrix::deallocate() {
if (data) {
for (unsigned int i = 0; i < rows; i++) {
delete [] data[i];
}
delete [] data;
data = nullptr;
}
data = nullptr;
rows = 0;
cols = 0;
}
//default constructor: creates an empty 0 x 0 matrix
Matrix::Matrix() : rows(0), cols(0), data(nullptr) { }
//-------------------------
// Constructors & Destructor
//-------------------------
//parameterized constructor
// Default constructor: creates an empty matrix (0 x 0)
Matrix::Matrix() : rows(0), cols(0), data(nullptr) {}
// Parameterized constructor: creates an r x c matrix filled with 'fill'
// If either dimension is 0, an empty matrix is created.
Matrix::Matrix(unsigned int r, unsigned int c, double fill) : rows(0), cols(0), data(nullptr) {
allocateMemory(r, c, fill);
if (r == 0 || c == 0) {
// Create an empty matrix.
rows = 0;
cols = 0;
data = nullptr;
} else {
allocate(r, c, fill);
}
}
//copy constructor
Matrix::Matrix(const Matrix& other) : rows(0), cols(0), data(nullptr) {
allocateMemory(other.rows, other.cols, 0.0);
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
data[i][j] = other.data[i][j];
// Copy constructor
Matrix::Matrix(const Matrix &other) : rows(0), cols(0), data(nullptr) {
if (other.rows == 0 || other.cols == 0) {
rows = 0;
cols = 0;
data = nullptr;
} else {
allocate(other.rows, other.cols, 0.0);
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
data[i][j] = other.data[i][j];
}
}
}
}
//destructor
// Destructor
Matrix::~Matrix() {
deallocateMemory();
deallocate();
}
//assignment operator
Matrix& Matrix::operator=(const Matrix& other) {
// Assignment operator
Matrix& Matrix::operator=(const Matrix &other) {
if (this == &other)
return *this;
deallocateMemory();
allocateMemory(other.rows, other.cols, 0.0);
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
data[i][j] = other.data[i][j];
deallocate();
if (other.rows == 0 || other.cols == 0) {
rows = 0;
cols = 0;
data = nullptr;
} else {
allocate(other.rows, other.cols, 0.0);
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
data[i][j] = other.data[i][j];
}
}
}
return *this;
}
//returns the number of rows
//-------------------------
// Dimension Accessors & Clear
//-------------------------
unsigned int Matrix::num_rows() const {
return rows;
}
//returns the number of columns
unsigned int Matrix::num_cols() const {
return cols;
}
//clears the matrix by deallocating its memory
void Matrix::clear() {
deallocateMemory();
deallocate();
}
//-------------------------
// Safe Accessors & Modifiers
//-------------------------
// get(): If (row,col) is within bounds, set value and return true; otherwise, return false.
bool Matrix::get(unsigned int row, unsigned int col, double &value) const {
if(row >= rows || col >= cols) {
if (row >= rows || col >= cols)
return false;
}
value = data[row][col];
return true;
}
//modifier
// set(): If (row,col) is valid, assign value and return true; else return false.
bool Matrix::set(unsigned int row, unsigned int col, double value) {
if(row >= rows || col >= cols) {
if (row >= rows || col >= cols)
return false;
}
data[row][col] = value;
return true;
}
//equality operator
bool Matrix::operator==(const Matrix& other) const {
//two matrices are equal if dimensions match
//and every element is equal within a small epsilon
if(rows != other.rows || cols != other.cols)
return false;
//-------------------------
// Simple Matrix Operations
//-------------------------
// Multiplies every element in the matrix by the given coefficient.
void Matrix::multiply_by_coefficient(double coefficient) {
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
if (fabs(data[i][j] - other.data[i][j]) > 1e-10)
return false;
}
}
return true;
}
bool Matrix::operator!=(const Matrix& other) const {
return !(*this == other);
}
//multiplies every element by the given coefficient
void Matrix::multiply_by_coefficient(double coeff) {
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
data[i][j] *= coeff;
data[i][j] *= coefficient;
}
}
}
//swaps two rows of the matrix (by swapping the row pointers)
// Swaps the entire contents of row1 and row2 if both indices are valid.
bool Matrix::swap_row(unsigned int row1, unsigned int row2) {
if(row1 >= rows || row2 >= rows) {
if (row1 >= rows || row2 >= rows)
return false;
}
double* temp = data[row1];
data[row1] = data[row2];
data[row2] = temp;
return true;
}
//transposes the matrix in place
// Transposes the matrix in place.
// For non-square matrices, a new 2D array is allocated, the contents are transposed,
// and the old memory is deallocated.
void Matrix::transpose() {
if(rows == 0 || cols == 0)
if (rows == 0 || cols == 0)
return;
unsigned int newRows = cols;
unsigned int newCols = rows;
double** newData = new double*[newRows];
for (unsigned int i = 0; i < newRows; i++) {
newData[i] = new double[newCols];
for (unsigned int j = 0; j < newCols; j++) {
newData[i][j] = data[j][i];
// Allocate new array with swapped dimensions.
double** newData = new double*[cols];
for (unsigned int i = 0; i < cols; i++) {
newData[i] = new double[rows];
}
// Transpose: newData[j][i] becomes data[i][j]
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
newData[j][i] = data[i][j];
}
}
deallocateMemory();
rows = newRows;
cols = newCols;
// Free old data.
for (unsigned int i = 0; i < rows; i++) {
delete [] data[i];
}
delete [] data;
// Swap dimensions.
unsigned int temp = rows;
rows = cols;
cols = temp;
data = newData;
}
//adds another matrix to this one element-wise
bool Matrix::add(const Matrix& other) {
if(rows != other.rows || cols != other.cols)
//-------------------------
// Binary Matrix Operations
//-------------------------
// Adds the corresponding elements of other to this matrix.
// Returns true if dimensions match, else returns false.
bool Matrix::add(const Matrix &other) {
if (rows != other.rows || cols != other.cols)
return false;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
@@ -173,9 +201,10 @@ bool Matrix::add(const Matrix& other) {
return true;
}
//subtracts another matrix from this one element-wise
bool Matrix::subtract(const Matrix& other) {
if(rows != other.rows || cols != other.cols)
// Subtracts the corresponding elements of other from this matrix.
// Returns true if dimensions match, else returns false.
bool Matrix::subtract(const Matrix &other) {
if (rows != other.rows || cols != other.cols)
return false;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
@@ -185,11 +214,15 @@ bool Matrix::subtract(const Matrix& other) {
return true;
}
//returns a dynamically allocated copy of the specified row
//caller must delete[] the returned array
//-------------------------
// Advanced Accessors
//-------------------------
// Returns a new dynamically allocated array containing the requested row.
// Returns nullptr if the row index is out of bounds.
double* Matrix::get_row(unsigned int row) const {
if(row >= rows)
return NULL;
if (row >= rows)
return nullptr;
double* rowArray = new double[cols];
for (unsigned int j = 0; j < cols; j++) {
rowArray[j] = data[row][j];
@@ -197,11 +230,11 @@ double* Matrix::get_row(unsigned int row) const {
return rowArray;
}
//returns a dynamically allocated copy of the specified column
//caller must delete[] the returned array
// Returns a new dynamically allocated array containing the requested column.
// Returns nullptr if the column index is out of bounds.
double* Matrix::get_col(unsigned int col) const {
if(col >= cols)
return NULL;
if (col >= cols)
return nullptr;
double* colArray = new double[rows];
for (unsigned int i = 0; i < rows; i++) {
colArray[i] = data[i][col];
@@ -209,84 +242,102 @@ double* Matrix::get_col(unsigned int col) const {
return colArray;
}
//divides the matrix into four quadrants and returns a pointer to an array of four matrices
//each quadrant size = ceil(rows/2) x ceil(cols/2)
//-------------------------
// Quarter Operation
//-------------------------
// Splits the matrix into four quadrants (UL, UR, LL, LR) and returns them in a new array.
// All four quadrants will have the same dimensions.
// If the matrix has fewer than 2 rows or 2 columns, returns four empty matrices.
Matrix* Matrix::quarter() const {
if (rows == 0 || cols == 0) {
return nullptr;
Matrix* quadrants = new Matrix[4];
if (rows < 2 || cols < 2) {
// Return four empty matrices.
return quadrants;
}
// Determine quadrant size so that all four quadrants are identical.
// For overlapping, use ceil for both dimensions.
unsigned int q_rows = (rows % 2 == 0) ? (rows / 2) : (rows / 2 + 1);
unsigned int q_cols = (cols % 2 == 0) ? (cols / 2) : (cols / 2 + 1);
// For an overlapping quarter, the top quadrants start at row 0,
// the bottom quadrants start at floor(rows/2), similarly for columns.
unsigned int start_row_bottom = rows / 2;
unsigned int start_col_right = cols / 2;
// Determine quadrant dimensions.
// Using (dim + 1) / 2 ensures that if the dimension is odd the shared middle row/col is included.
unsigned int quad_rows = (rows + 1) / 2;
unsigned int quad_cols = (cols + 1) / 2;
Matrix* quadrants = new Matrix[4]{
Matrix(q_rows, q_cols, 0.0), // Upper Left
Matrix(q_rows, q_cols, 0.0), // Upper Right
Matrix(q_rows, q_cols, 0.0), // Lower Left
Matrix(q_rows, q_cols, 0.0) // Lower Right
};
quadrants[0] = Matrix(quad_rows, quad_cols, 0.0); // Upper Left (UL)
quadrants[1] = Matrix(quad_rows, quad_cols, 0.0); // Upper Right (UR)
quadrants[2] = Matrix(quad_rows, quad_cols, 0.0); // Lower Left (LL)
quadrants[3] = Matrix(quad_rows, quad_cols, 0.0); // Lower Right (LR)
// Fill Upper Left quadrant from original (starting at (0,0)).
for (unsigned int i = 0; i < q_rows; i++) {
for (unsigned int j = 0; j < q_cols; j++) {
double value;
if (i < rows && j < cols && get(i, j, value))
quadrants[0].set(i, j, value);
// Fill UL quadrant: rows 0 .. quad_rows-1, cols 0 .. quad_cols-1.
for (unsigned int i = 0; i < quad_rows; i++) {
for (unsigned int j = 0; j < quad_cols; j++) {
quadrants[0].set(i, j, data[i][j]);
}
}
// Fill Upper Right quadrant from original (starting at (0, start_col_right)).
for (unsigned int i = 0; i < q_rows; i++) {
for (unsigned int j = 0; j < q_cols; j++) {
double value;
if (i < rows && (j + start_col_right) < cols && get(i, j + start_col_right, value))
quadrants[1].set(i, j, value);
// Fill UR quadrant: rows 0 .. quad_rows-1, cols (cols - quad_cols) .. (cols - 1).
for (unsigned int i = 0; i < quad_rows; i++) {
for (unsigned int j = 0; j < quad_cols; j++) {
quadrants[1].set(i, j, data[i][(cols - quad_cols) + j]);
}
}
// Fill Lower Left quadrant from original (starting at (start_row_bottom, 0)).
for (unsigned int i = 0; i < q_rows; i++) {
for (unsigned int j = 0; j < q_cols; j++) {
double value;
if ((i + start_row_bottom) < rows && j < cols && get(i + start_row_bottom, j, value))
quadrants[2].set(i, j, value);
// Fill LL quadrant: rows (rows - quad_rows) .. (rows - 1), cols 0 .. quad_cols-1.
for (unsigned int i = 0; i < quad_rows; i++) {
for (unsigned int j = 0; j < quad_cols; j++) {
quadrants[2].set(i, j, data[(rows - quad_rows) + i][j]);
}
}
// Fill Lower Right quadrant from original (starting at (start_row_bottom, start_col_right)).
for (unsigned int i = 0; i < q_rows; i++) {
for (unsigned int j = 0; j < q_cols; j++) {
double value;
if ((i + start_row_bottom) < rows && (j + start_col_right) < cols &&
get(i + start_row_bottom, j + start_col_right, value))
quadrants[3].set(i, j, value);
// Fill LR quadrant: rows (rows - quad_rows) .. (rows - 1), cols (cols - quad_cols) .. (cols - 1).
for (unsigned int i = 0; i < quad_rows; i++) {
for (unsigned int j = 0; j < quad_cols; j++) {
quadrants[3].set(i, j, data[(rows - quad_rows) + i][(cols - quad_cols) + j]);
}
}
return quadrants;
}
//-------------------------
// Equality Operators
//-------------------------
//overloaded output operator to print the matrix
// 4 x 4 matrix:
// [ 14 14 14 14
// 14 14 14 14
// 14 9 14 14
// 14 14 14 13 ]
std::ostream& operator<<(std::ostream& out, const Matrix& m) {
out << m.rows << " x " << m.cols << " matrix:" << std::endl;
out << "[ ";
for (unsigned int i = 0; i < m.rows; i++) {
for (unsigned int j = 0; j < m.cols; j++) {
out << m.data[i][j];
if(j < m.cols - 1)
out << " ";
bool Matrix::operator==(const Matrix &other) const {
if (rows != other.rows || cols != other.cols)
return false;
for (unsigned int i = 0; i < rows; i++) {
for (unsigned int j = 0; j < cols; j++) {
if (data[i][j] != other.data[i][j])
return false;
}
if(i < m.rows - 1)
out << std::endl << " ";
}
out << " ]";
return true;
}
bool Matrix::operator!=(const Matrix &other) const {
return !(*this == other);
}
//-------------------------
// Overloaded Output Operator
//-------------------------
std::ostream& operator<<(std::ostream &out, const Matrix &m) {
out << m.rows << " x " << m.cols << " matrix:" << std::endl;
out << "[";
if (m.rows > 0 && m.cols > 0) {
for (unsigned int i = 0; i < m.rows; i++) {
out << " ";
for (unsigned int j = 0; j < m.cols; j++) {
out << m.data[i][j];
if (j < m.cols - 1)
out << " ";
}
if (i < m.rows - 1)
out << std::endl;
}
out << " ]";
} else {
out << " ]";
}
return out;
}

View File

@@ -2,75 +2,63 @@
#define MATRIX_H
#include <iostream>
#include <cmath>
class Matrix {
public:
// Constructors & Destructor
Matrix(); // Default constructor (creates an empty 0 x 0 matrix)
Matrix(unsigned int rows, unsigned int cols, double fill);
Matrix(const Matrix &other);
~Matrix();
Matrix& operator=(const Matrix &other);
// Accessors for dimensions
unsigned int num_rows() const;
unsigned int num_cols() const;
// Clears the matrix (deallocates any memory and sets size to 0 x 0)
void clear();
// Safe accessor and modifier methods
bool get(unsigned int row, unsigned int col, double &value) const;
bool set(unsigned int row, unsigned int col, double value);
// Simple matrix operations
void multiply_by_coefficient(double coefficient);
bool swap_row(unsigned int row1, unsigned int row2);
void transpose();
// Binary matrix operations (modifies this matrix)
bool add(const Matrix &other);
bool subtract(const Matrix &other);
// Advanced accessors: returns a dynamic array with the requested row or column.
// The caller is responsible for deleting the returned array.
double* get_row(unsigned int row) const;
double* get_col(unsigned int col) const;
// Quarter the matrix into four equally sized quadrants.
// The four matrices are returned in a dynamically allocated array in the order:
// UL, UR, LL, LR.
// If the matrix is too small (i.e. less than 2 rows or 2 cols), returns four empty matrices.
Matrix* quarter() const;
// Equality operators
bool operator==(const Matrix &other) const;
bool operator!=(const Matrix &other) const;
// Friend overloaded output operator for printing the matrix.
friend std::ostream& operator<<(std::ostream &out, const Matrix &m);
private:
unsigned int rows;
unsigned int cols;
double** data;
//allocate memory and fill with a given value
void allocateMemory(unsigned int r, unsigned int c, double fill);
//deallocate memory
void deallocateMemory();
public:
////Constructors
Matrix();
Matrix(unsigned int r, unsigned int c, double fill);
//copy constructor
Matrix(const Matrix& other);
////Destructor
~Matrix();
////Accessors
Matrix& operator=(const Matrix& other);
unsigned int num_rows() const;
unsigned int num_cols() const;
//deallocates memory and resets rows/cols to 0)
void clear();
//if (row, col) is within bounds, stores the element in `value` and returns true;
//otherwise, returns false
bool get(unsigned int row, unsigned int col, double &value) const;
////Modifier
//if (row, col) is within bounds, sets the element to `value` and returns true;
//otherwise, returns false.
bool set(unsigned int row, unsigned int col, double value);
//multiplies every element in the matrix by the provided coefficient
void multiply_by_coefficient(double coeff);
//swaps two rows of the matrix. Returns true if both indices are valid,
//false otherwise
bool swap_row(unsigned int row1, unsigned int row2);
//transposes the matrix in place (switches rows and columns).
void transpose();
//adds another matrix to this one element-wise (if dimensions match) and returns true;
//otherwise, returns false.
bool add(const Matrix& other);
//subtracts another matrix from this one element-wise (if dimensions match)
//and returns true; otherwise, returns false.
bool subtract(const Matrix& other);
//returns a new dynamically allocated array (of size num_cols)
//containing the elements in the specified row.
double* get_row(unsigned int row) const;
//returns a new dynamically allocated array (of size num_rows)
//containing the elements in the specified column.
double* get_col(unsigned int col) const;
//divides the matrix into four quadrants and returns a pointer to an array of
//4 Matrix objects: Upper Left, Upper Right, Lower Left, Lower Right.
//each quadrant is of size ceil(rows/2) x ceil(cols/2)
//and the quadrants overlap when the dimensions are odd.
Matrix* quarter() const;
////Operators
//equality operator: two matrices are equal if they have the same dimensions and
//every corresponding element differs by no more than a small epsilon.
bool operator==(const Matrix& other) const;
//inequality operator
bool operator!=(const Matrix& other) const;
//overloaded output operator for printing the matrix
friend std::ostream& operator<<(std::ostream& out, const Matrix& m);
// Helper functions to allocate and deallocate the 2D array.
void allocate(unsigned int r, unsigned int c, double fill);
void deallocate();
};
#endif

View File

@@ -198,124 +198,96 @@ void SimpleTest(){ //well behaved getrow/read after
//Write your own test cases here
void StudentTest() {
//Test transpose
Matrix m(2, 3, 0);
m.set(0, 0, 1);
m.set(0, 1, 2);
m.set(0, 2, 3);
m.set(1, 0, 4);
m.set(1, 1, 5);
m.set(1, 2, 6);
m.transpose();
assert(m.num_rows() == 3);
assert(m.num_cols() == 2);
double val;
m.get(0, 0, val);
assert(double_compare(val, 1.0));
m.get(0, 1, val);
assert(double_compare(val, 4.0));
m.get(1, 0, val);
assert(double_compare(val, 2.0));
m.get(2, 1, val);
assert(double_compare(val, 6.0));
// Test 1: Transpose a non-square matrix.
Matrix m(2, 3, 1.0);
m.set(0, 0, 1.0); m.set(0, 1, 2.0); m.set(0, 2, 3.0);
m.set(1, 0, 4.0); m.set(1, 1, 5.0); m.set(1, 2, 6.0);
m.transpose(); // Now m should be 3 x 2.
assert(m.num_rows() == 3 && m.num_cols() == 2);
m.get(0, 0, val); assert(val == 1.0);
m.get(0, 1, val); assert(val == 4.0);
m.get(1, 0, val); assert(val == 2.0);
m.get(1, 1, val); assert(val == 5.0);
m.get(2, 0, val); assert(val == 3.0);
m.get(2, 1, val); assert(val == 6.0);
//Test quarter with odd dimensions
Matrix q(5, 5, 1);
Matrix* quarters = q.quarter();
assert(quarters != nullptr);
//each quadrant should be 3x3 (ceiling: (5+1)/2 == 3)
assert(quarters[0].num_rows() == 3);
assert(quarters[0].num_cols() == 3);
assert(quarters[1].num_rows() == 3);
assert(quarters[1].num_cols() == 3);
assert(quarters[2].num_rows() == 3);
assert(quarters[2].num_cols() == 3);
assert(quarters[3].num_rows() == 3);
assert(quarters[3].num_cols() == 3);
//verify that the quadrants hold the expected values.
for (int i = 0; i < 3; i++) {
for (int j = 0; j < 3; j++) {
quarters[0].get(i, j, val);
assert(double_compare(val, 1.0));
quarters[1].get(i, j, val);
assert(double_compare(val, 1.0));
quarters[2].get(i, j, val);
assert(double_compare(val, 1.0));
quarters[3].get(i, j, val);
assert(double_compare(val, 1.0));
// Test 2: Multiply matrix by a coefficient.
Matrix m2(2, 2, 2.0);
m2.multiply_by_coefficient(3.0);
m2.get(0, 0, val); assert(val == 6.0);
m2.get(1, 1, val); assert(val == 6.0);
// Test 3: get_col() functionality.
Matrix m3(3, 3, 0.0);
int counter = 1;
for (unsigned int i = 0; i < 3; i++) {
for (unsigned int j = 0; j < 3; j++) {
m3.set(i, j, counter++);
}
}
delete[] quarters;
double* col1 = m3.get_col(1);
// Expecting column 1 to be: 2, 5, 8.
assert(col1[0] == 2);
assert(col1[1] == 5);
assert(col1[2] == 8);
delete [] col1;
//Test add and subtract
Matrix a(2, 2, 2);
Matrix b(2, 2, 3);
assert(a.add(b)); // Now a is all 5's.
double v;
a.get(0, 0, v);
assert(double_compare(v, 5.0));
assert(a.subtract(b)); // Now a is back to all 2's.
a.get(0, 0, v);
assert(double_compare(v, 2.0));
// Test 4: swap_row().
Matrix m4(2, 3, 0.0);
m4.set(0, 0, 1); m4.set(0, 1, 2); m4.set(0, 2, 3);
m4.set(1, 0, 4); m4.set(1, 1, 5); m4.set(1, 2, 6);
m4.swap_row(0, 1);
m4.get(0, 0, val); assert(val == 4);
m4.get(1, 0, val); assert(val == 1);
//Test multiply by coefficient
a.multiply_by_coefficient(2.5); //Now a is all 5's (2*2.5).
a.get(0, 0, v);
assert(double_compare(v, 5.0));
// Test 5: subtract().
Matrix m5(2, 2, 10.0);
Matrix m6(2, 2, 3.0);
bool success = m5.subtract(m6);
assert(success);
m5.get(0, 0, val); assert(val == 7.0);
//Test get_row
double* row = a.get_row(0);
assert(row != nullptr);
assert(double_compare(row[0], 5.0));
assert(double_compare(row[1], 5.0));
delete[] row;
// Test 6: quarter() on an even-dimensioned matrix.
Matrix m7(4, 4, 0.0);
counter = 1;
for (unsigned int i = 0; i < 4; i++) {
for (unsigned int j = 0; j < 4; j++) {
m7.set(i, j, counter++);
}
}
Matrix* quads = m7.quarter();
// For a 4 x 4 matrix, quadrant size should be (4+1)/2 = 2 (integer division)
assert(quads[0].num_rows() == 2 && quads[0].num_cols() == 2);
// Upper Left quadrant should be:
// [ 1 2 ]
// [ 5 6 ]
quads[0].get(0, 0, val); assert(val == 1);
quads[0].get(0, 1, val); assert(val == 2);
quads[0].get(1, 0, val); assert(val == 5);
quads[0].get(1, 1, val); assert(val == 6);
delete [] quads;
// Test get_col
double* col = a.get_col(1);
assert(col != nullptr);
assert(double_compare(col[0], 5.0));
assert(double_compare(col[1], 5.0));
delete[] col;
// Test 7: clear() method.
Matrix m8(3, 3, 9.0);
m8.clear();
assert(m8.num_rows() == 0 && m8.num_cols() == 0);
//Test clear
a.clear();
assert(a.num_rows() == 0 && a.num_cols() == 0);
// Test 8: Self-assignment.
Matrix m9(2, 2, 7.0);
m9 = m9;
m9.get(0, 0, val); assert(val == 7.0);
//Test swap_row
Matrix s(3, 2, 0);
s.set(0, 0, 1); s.set(0, 1, 2);
s.set(1, 0, 3); s.set(1, 1, 4);
s.set(2, 0, 5); s.set(2, 1, 6);
//swap row 0 and row 2
assert(s.swap_row(0, 2));
s.get(0, 0, val);
assert(double_compare(val, 5.0));
s.get(0, 1, val);
assert(double_compare(val, 6.0));
s.get(2, 0, val);
assert(double_compare(val, 1.0));
s.get(2, 1, val);
assert(double_compare(val, 2.0));
//invalid swap should return false.
assert(!s.swap_row(0, 3));
// Test 9: Binary add() with mismatched dimensions.
Matrix m10(2, 3, 1.0);
Matrix m11(3, 2, 1.0);
bool res = m10.add(m11);
assert(res == false);
//Test copy constructor and assignment operator.
Matrix orig(2, 3, 7);
Matrix copy(orig); // Using copy constructor.
Matrix assign;
assign = orig; // Using assignment operator.
//change orig to ensure copy and assign remain unchanged.
orig.set(0, 0, 10);
orig.get(0, 0, val);
assert(double_compare(val, 10.0));
copy.get(0, 0, val);
assert(double_compare(val, 7.0));
assign.get(0, 0, val);
assert(double_compare(val, 7.0));
//Test out-of-bound get and set
assert(!orig.get(5, 5, val));
assert(!orig.set(5, 5, 3.0));
// Test 10: Binary subtract() with mismatched dimensions.
res = m10.subtract(m11);
assert(res == false);
}