/*
* File: main.cpp
* Author: Maelstrom
*
* Created on February 18, 2011, 2:25 PM
*/
#include <cstdlib>
#include <iostream>
#include <sstream>
#include <vector>
/*
* This program asks the user to enter a matrix, and then offers the user a number of operations the user can do to the matrix they
* entered. The program starts off by having the user input the dimensions of the matrix. Then, it asks for each element of the matrix. Current
* operations the user can can select are addition, subtraction, and multiplication. E.R.O will be added in the future.
*/
void add(std::vector < std::vector <double> >, int, int); //will add two matrices, one of which is a parameter.
void e_r_o(std::vector < std::vector <double> >, int, int);
void multi(std::vector < std::vector <double> >, int, int); //will multiple two matrices, one of which is a parameter.
void print(std::vector < std::vector <double> >, int, int); //prints out the matrix.
int main() {
std::cout << "Welcome to the Matrix manipulation program! This program can do a number of different mathmatical operations to matrices"
" including Gaussian elimination. ";
std::cout << "Please enter the dimensions and the elements of the matrix. Once completed"
", you will be given a number of mathmatical operations that can be applied to the matrix. "
"Note: if you wish to find the solutions to a linear system, make sure to include what the equations are equal to." << '\n';
int column, row; //for dimensions of the mxn matrix.
std::string input; //used to store all input.
while (true) { //infinite loop, will on be exited out of when user enters appropriate info.
std::cout << "Enter the number of rows for the matrix: "; //asks for # of rows.
std::getline(std::cin, input); //takes input as a string
std::stringstream convert(input); //enters string into the stringstream.
if (convert >> row) { //checks if the input can be converted into a double. If it can, it enters the number into row.
if (row != 0) { //can't go having a matrix with 0 rows
break; //exits out of loop.
}
}
std::cout << "Error, please enter an appropriate number of rows." << '\n';
}
while (true) { //does the same as above, but for the number of columns.
std::cout << "Enter the number of columns for the matrix: ";
std::getline(std::cin, input);
std::stringstream convert(input);
if (convert >> column) {
if (column != 0) {
break;
}
}
std::cout << "Error, please enter an appropriate number of columns." << '\n';
}
std::vector <std::vector <double> > matrix; //creates a multidimensional vector. Used instead of an array for ease of parameterizing.
matrix.resize(row);
for (int i = 0; i < row; ++i) {
matrix[i].resize(column);
} //makes the vector the desired size by using .resize
std::cout << "Please enter each element for the row." << '\n';
int r = 0;
while (r < row) { //asks user for the elements in each row of the matrix. Will repeat while r < row.
int c = 0;
std::cout << "Row " << r + 1 << ": ";
std::getline(std::cin, input);
std::stringstream convert(input);
while (true) { //loops indefinately, until each element has a double.
if (convert >> matrix[r][c]) { //checks to see if input can be converted into a double
++c; //moves to next column
}
else {
break;
}
if (c == column) { //once the last column has a double, will break out of while loop.
++r; //moves to next row
break;
}
}
}
while (true) { //asks user to select which operation they would like to do to the matrix.
std::cout << "Select which operation you would like to use on the matrix. " << '\n';
std::cout << "0) Print matrix" << '\n';
std::cout << "1) Matrix addition and subtraction" << '\n';
std::cout << "2) Matrix multiplication" << '\n';
std::cout << "3) Gaussian elimination" << '\n';
std::cout << "Selection? ";
std::getline(std::cin, input);
std::stringstream convert(input);
int selection;
if (convert >> selection) {
if (selection == 0) { //allows user to print their matrix in all its glory!
print(matrix, row, column);
break;
}
else if (selection == 1) {
add(matrix, row, column); //calls the add function, which will add to user inputed matrices.
break; //breaks out of infite while loop.
}
else if (selection ==2 ) {
multi(matrix, row, column);
break;
}
else if (selection == 3) {
e_r_o(matrix, row, column);
break;
}
}
std::cout << "Please enter an appropriate selection." << '\n';
}
std::cout << "Would you like to rerun the program?" << std::endl; //gives user the option to rerun program by using recursion.
std::cout << "Y/N? ";
std::getline(std::cin, input);
if (input == "y" || input == "Y") {
return main();
}
return 0;
}
/*
* Allows for the addition and subtraction, based on user choice, of two matrices. The first one is taken from the main, along with
* the row and column length of the first matrix. Using a multidimensional vector, a second matrix is made with the same dimensions
* as the first matrix. User is then asked to input each element. Finally, the matrices are either added or subtracted, and then
* the result is printed out, using the print function.
*/
void add(std::vector < std::vector <double> > nom, int row, int column) {
std::cout << "Please enter the elements for the row. Note: in order to add or subtract matrices, the dimensions of both must be the same."
" The dimensions of the first matrix you entered will be used for this one." << '\n';
//using same method to acquire details of second matrix.
std::string input;
std::vector <std::vector <double> > nom2;
nom2.resize(row);
for (int i = 0; i < row; ++i) {
nom2[i].resize(column);
}
int r = 0;
while (r < row) {
int c = 0;
std::cout << "Row " << r+1 << ": ";
std::getline(std::cin, input);
std::stringstream convert(input);
while (true) {
if (convert >> nom2[r][c]) {
++c;
}
else {
break;
}
if (c == column) {
++r;
break;
}
}
}
std::cout << "Addition or subtraction? "; //user can chose to add or subtract.
std::getline(std::cin, input);
if (input == "Add" || input == "add" || input == "Addition" || input == "addition") {
for (int i = 0; i < row; ++i) {
for (int j = 0; j < column; ++j) {
nom [i][j] += nom2 [i][j]; //adds each corresponding element of the two matrices together. Goes row by row.
}
}
print(nom, row, column);
}
else if (input == "Subtract" || input == "subtract" || input == "Subtraction" || input == "subtraction") {
for (int i = 0; i < row; ++i) {
for (int j = 0; j < column; ++j) {
nom [i][j] -= nom2 [i][j]; //same as above, just with subtraction.
}
}
print(nom, row, column);
}
else {
std::cout << "Please choose to add or subtract." << '\n';
}
}
/*
* Uses Gaussian-Jordan elimination to put the matrix into the reduced row-echelon form. It then prints out the matrix.
*/
void e_r_o(std::vector < std::vector <double> > nom, int row, int column) {
//puts the matrix into row-echelon form.
int a = 0, b = 0, c = 1;
while (a < row - 1) {
if (nom [a][b] != 0) {
int y = 0;
std::vector <double> holder;
holder.resize(row - 1);
for (int i = c; i < row; ++i) {
holder [y] = (nom [i][b]) / (nom [a][b]);
++y;
}
int z = 0;
for (int i = c; i < row; ++i) {
for (int j = b; j < column; ++j) {
nom [i][j] -= holder [z] * nom [a][j];
}
++z;
}
}
++a;
++b;
++c;
}
//makes leading element for each row a leading one.
for (int i = 0; i < row; ++i) {
double k = nom [i][i];
for (int j = 0; j < column; ++j) {
nom [i][j] /= k;
}
}
//makes the row-echelon formed matrix into a reduced row-echelon form.
int d = row - 1, e = column - 2, f = row - 2;
while (d > 0) {
if (nom [d][e] != 0) {
int y = 0;
std::vector <double> holder;
holder.resize(row - 1);
for (int i = f; i > -1; --i) {
holder [y] = (nom [i][e]) / (nom [d][e]);
++y;
}
int z = 0;
for (int i = f; i > -1; --i) {
for (int j = (column - 1); j > -1; --j) {
nom [i][j] -= holder [z] * nom [d][j];
}
++z;
}
}
--d;
--e;
--f;
}
print (nom, row, column);
}
/*
* Multiplies two matrices together, and then prints out the product. Gets the first matrix from the parameter, and the second
* is created by the user.
*/
void multi(std::vector < std::vector <double> > nom, int row1, int column1) {
std::cout << "Please enter the dimensions of the second matrix. Note: The number of columns of the first matrix must "
"equal the number of rows of the second matrix." << '\n';
std::string input;
int row2, column2;
while (true) { //asks for number of rows. Checks to make sure it equals the number of columns in the first matrix.
std::cout << "Number of rows (must be same as number of columns of first matrix!): ";
std::getline(std::cin, input);
std::stringstream convert (input);
if (convert >> row2) {
if (row2 == column1) {
break;
}
}
std::cout << "Please enter an appropriate value." << '\n';
}
while (true) { //asks for number of columns.
std::cout << "Number of columns: ";
std::getline(std::cin, input);
std::stringstream convert (input);
if (convert >> column2) {
if (column2 != 0) {
break;
}
}
std::cout << "Please enter an appropriate value." << '\n';
}
std::vector < std::vector <double> > nom2; //creates the second matrix based off the entered dimensions.
nom2.resize(row2);
for (int i = 0; i < row2; ++i) {
nom2[i].resize(column2);
}
std::cout << "Please enter the elements for each row." << '\n';
int r = 0;
while (r < row2) { //User enters each element for each row. Has checks in place to make sure user enters doubles.
int c = 0;
std::cout << "Row " << r+1 << ": ";
std::getline(std::cin, input);
std::stringstream convert(input);
while (true) {
if (convert >> nom2[r][c]) {
++c;
}
else {
break;
}
if (c == column2) {
++r;
break;
}
}
}
std::vector < std::vector <double> > nom3; //creates a third matrix to hold of the values of other two matrices multiplied.
nom3.resize(row1); //has row1 rows, and column 2 columns.
for (int i = 0; i < row1; ++i) {
nom3[i].resize(column2);
}
/*
* Algorithm for multiplying the two matrices. Multiples the corresponding element of the ith row of the 1st matrix and jth column
* of the 2nd matrix. Adds them together, and places the final number into the a(i,j) element of the product matrix.
*/
int z = 0;
while (z < row1) { //Z is used to track the row number for the 3rd and 1st matrix. Stops once it equals row1.
for (int a = 0; a < column2; ++a) { //Used to track the column of the 3rd and 2nd matrix. Stops once it equals column2.
for (int b = 0; b < row2; ++b) { //Used to track the column for the 1st matrix, and the row for the 2nd matrix.
nom3[z][a] += nom[z][b] * nom2[b][a]; //Multiplies the elements together, then adds the product to the corresponding element in nom3.
}
}
++z;
}
print(nom3, row1, column2);
}
/*
* Prints each element of the matrix.
*/
void print(std::vector < std::vector <double> > nom, int row, int column) {
for (int i = 0; i < row; ++i) {
for (int j = 0; j < column; ++j) {
std::cout << nom[i][j] << " ";
}
std::cout << std::endl;
}
}