Can you create and destroy pthreads inside operator overloading function - c++

I am trying to overload the * operator to use for matrix multiplication. It must be multithreaded using pthreads. I have never done multithreading before, and I am really struggling. If possible I would like to create and destroy the pthreads within the function(so the only place pthreads appear is within the function).
Here is my Matrix Class:
class Matrix
{
private:
int numRows_;
int numColumns_;
std::vector<double> data_;
public:
Matrix();
Matrix(Matrix const& matrix_objext);
Matrix(int numRows, int numColumns);
Matrix(int numRows, int numColumns, std::vector<double> data);
Matrix(std::string importFilePath);
~Matrix();
int get_numRows();
int get_numColumns();
std::vector<double> get_data();
void set_numRows(int);
void set_numColumns(int);
void set_data(std::vector<double>);
Matrix operator*(Matrix x);
Matrix operator*(int x);
Matrix operator+(Matrix x);
Matrix operator-(Matrix x);
Matrix operator^(int exp);
Matrix operator-();
Matrix operator=(Matrix x);
bool operator==(Matrix x);
Matrix MultiplySlow(Matrix x);
Matrix Transpose();
void ExportToFile(std::string);
std::string to_string();
};
This is the function I am struggling with:
Matrix Matrix::operator*(Matrix x){
pthread_t thread;
int rc;
rc = pthread_create(&thread, NULL, MultiplySlow, x)
}
The MultiplySlow function is not intended to be used only for this overloaded operator, so if it needs to be changed I would have to make a new multiplication function.
Here is the MultiplySlow function just in case:
Matrix Matrix::MultiplySlow(Matrix x){
Matrix mat;
mat.numColumns_=numColumns_;
mat.numRows_=numRows_;
mat.data_.resize(numRows_*numColumns_);
if(numColumns_ != x.numRows_){
std::cout << "The number of columns of the 1st matrix must equal the number of rows of the 2nd matrix." << std::endl;
}
for(int i=0; i<numRows_;i++){
for(int j=0; j<x.numColumns_;j++){
double sum =0.0;
for(int k=0; k<x.numRows_; k++){
sum = sum + data_[i * numColumns_ + k] * x.data_[k * x.numColumns_ +j];
}
mat.data_[i * mat.numColumns_ + j] = sum;
}
}
return mat;
}
Please help!!

There are a few problems here:
pthread_create() returns 0 or 1 depending on success or failure (not a matrix).
The function that is spawn by the thread is supposed to return void * and receive a void * (not a matrix)
Spawning another thread to do the actual multiplication hinders efficiency. It doesn’t help it. So, why are you doing this?
My suggestions are
Look into C++ threads
look into C++ async calls
Think about how to divide the matrix multiplication into independent components, so multi-threading could help efficiency.

Related

Addition of Matrix in C++ using OOP

the following code is not giving the correct output. Matrix data is displaying perfectly, but after the addition of two objects M1 and M2, it did not display the correct output. If I use setData to input data in the matrix, data is stored perfectly, but the addition is not performing correctly. kindly suggest to me how can I correct this logical error?
#include <iostream>
#include <string.h>
using namespace std;
class Matrix{
private:
void Allocate();
int noOfRows;
int noOfColumns;
int **data;
public:
Matrix(int noOfRows, int noOfColumns);
void setData();
void displayData();
~Matrix();
Matrix (const Matrix &ref);
Matrix operator + (const Matrix &m);
void operator = (const Matrix &M );
Matrix& operator = (int x);
};
Matrix::Matrix(int inr=0, int inc=0){
noOfRows=inr; noOfColumns=inc;
Allocate();
}
Matrix::Matrix (const Matrix &ref){
Allocate();
for(int r=0;r<ref.noOfRows;r++)
for(int c=0;c<ref.noOfColumns;c++)
data[r][c]=ref.data[r][c];
}
void Matrix :: operator = (const Matrix &M ) {
Allocate();
noOfRows = M.noOfRows;
noOfColumns = M.noOfColumns;
data=M.data;
}
Matrix& Matrix :: operator = (int x){
Allocate();
for(int r=0;r<noOfRows;r++)
for(int c=0;c<noOfColumns;c++)
data[r][c]=x;
return *this;
}
void Matrix::Allocate(){
data=new int*[noOfRows];
for(int i=0;i<noOfRows;i++)
data[i]=new int[noOfColumns]();
}
void Matrix::setData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++){
cout<<"Enter ...";cin>>data[r][c];
}
cout<<endl;
}
}
Matrix Matrix::operator + (const Matrix &m){
Matrix ms(m.noOfRows,m.noOfColumns);
for (int i=0; i<m.noOfRows; i++)
for (int j=0; j<m.noOfColumns; j++)
ms.data[i][j] = data[i][j]+m.data[i][j];
return ms;
}
void Matrix::displayData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++)
cout<<data[r][c]<<"\t";
cout<<endl;
}
}
Matrix::~Matrix(){
for (int i = 0; i < noOfRows; ++i)
delete[] data[i];
delete [] data;
}
int main(){
Matrix M3(2,2);M3=0;
Matrix M1(2,2);M1=1;
Matrix M2(2,2);M2=2;
//M1.setData();M2.setData();M3.setData();
cout<<"\n Matrix A = "<<endl;
M1.displayData();
cout<<"\n Matrix B = "<<endl;
M2.displayData();
cout<<"\n Matrix C = "<<endl;
M3 = M1;
M3.displayData();
cout<<"\n Sum of Matrix = "<<endl;
M3 = M1 + M2;
M3.displayData();
return 0;
}
Output is here for detail
Copy constructor and assignment operator were both broken. Let's take a quick stroll to see what went wrong
Matrix::Matrix (const Matrix &ref){
// noOfRows and noOfColumns have not been initialized. Their values are unknown so
// the rest of this function is a crapshoot. Could do anything.
Allocate();
for(int r=0;r<ref.noOfRows;r++)
for(int c=0;c<ref.noOfColumns;c++)
data[r][c]=ref.data[r][c];
}
// An assignment operator is expected to return Matrix &
void Matrix :: operator = (const Matrix &M ) {
// noOfRows and noOfColumns have not been updated. Could be wrong, resulting in
// allocate allocating the wrong amount of storage. Moot point since this
// allocation is never used. See below.
Allocate();
noOfRows = M.noOfRows;
noOfColumns = M.noOfColumns;
data=M.data; // both instances share M's data. This will fail sooner or later
// If the program lives long enough, both instances will go out
// of scope and double delete the allocation.
// Also leaks allocation pointed at by `data`.
}
I was in a hurry so I didn't put much thought into fixing the assignment operator and just used the Copy and Swap Idiom. It's very possible that there is a more efficient solution, but copy and swap is usually fast enough and almost impossible to get wrong. Makes a great starting point and benchmarking will tell you if it's a problem.
Matrix::Matrix(const Matrix &ref):
noOfRows(ref.noOfRows),
noOfColumns(ref.noOfColumns) // initialize row and columns
{
Allocate(); // now safe to use
for (int r = 0; r < ref.noOfRows; r++)
for (int c = 0; c < ref.noOfColumns; c++)
data[r][c] = ref.data[r][c];
}
Matrix& Matrix::operator =(Matrix M) // correct return type, and does the heavy
// lifting with the copy constructor
{
std::swap(noOfRows, M.noOfRows);
std::swap(noOfColumns, M.noOfColumns);
std::swap(data, M.data);
return *this;
}

Addition of Matrix in C++ Object Oriented Programming

The following code gives me the wrong output. actually, it is not doing sum, it actually copies the 2nd object to the M3 object instead of calculating the sum. I think I have some logical errors in + operator overloading. Does anybody have any idea or any other suggestion? it displays the output actually which is called in the copy constructor function cout<data[r][c]<<"\t";. but it did not display output when I use M3.displayData().
#include <iostream>
#include <string.h>
using namespace std;
class Matrix{
private:
int noOfRows;
int noOfColumns;
int **data;
public:
Matrix(int noOfRows, int noOfColumns);
void displayData();
~Matrix();
Matrix (const Matrix &ref);
Matrix operator + (Matrix m);
Matrix& operator=(Matrix m) {
std::swap(m.noOfRows, noOfRows);
std::swap(m.noOfColumns, noOfColumns);
std::swap(m.data, data);
return *this; }
};
Matrix::Matrix(int inr=0, int inc=0){
noOfRows=inr; noOfColumns=inc;
data=new int*[noOfColumns];
for(int i=0;i<noOfRows;i++)
data[i]=new int[noOfColumns];
int d;
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++){
cout<<"Enter ...";cin>>d;
data[r][c]=d;
}
cout<<endl;
}
}
Matrix::Matrix (const Matrix &ref){
this->data=new int*[ref.noOfColumns];
for(int i=0;i<ref.noOfRows;i++)
this->data[i]=new int[ref.noOfRows];
for(int r=0;r<ref.noOfRows;r++){
for(int c=0;c<ref.noOfColumns;c++){
this->data[r][c]=ref.data[r][c];
cout<<this->data[r][c]<<"\t";
}
cout<<endl;
}
}
Matrix Matrix::operator + (Matrix m){
Matrix ms(m.noOfRows,m.noOfColumns);
ms=0;
for (int i=0; i<m.noOfRows; i++)
for (int j=0; j<m.noOfColumns; j++){
ms.data[i][j] = data[i][j]+m.data[i][j];
return ms;
}
}
void Matrix::displayData(){
for(int r=0;r<noOfRows;r++){
for(int c=0;c<noOfColumns;c++)
cout<<data[r][c]<<"\t";
cout<<endl;
}
}
Matrix::~Matrix(){
delete[] data;
}
int main(){
Matrix M1(2,2),M2(2,2);
cout<<"\n Matrix A="<<endl;
M1.displayData();
cout<<"\n Matrix B="<<endl;
M2.displayData();
cout<<"\n Sum of Matrix="<<endl;
Matrix M3=M1+M2;
M3.displayData();
return 0;
}
I'm not a matrix specialist, but I understood that matrix summation required both matrixes to be of the same size, and each elements to be summed up.
So you need to fully redefine operator+ (to avoid introducing exceptions here, I'd taken a permissive mathematical view, taking the max size of both matrixes and considering elements out of bounds to be 0):
Matrix Matrix::operator + (Matrix m){
Matrix ms(max(noOfRows,m.noOfRows), max(noOfColumns+m.noOfColumns));
for (int i=0; i<ms.noOfRows; i++)
for (int j=0; j<ms.noOfColumns; j++)
ms.data[i][j] = (i<noOfRows&&j<noOfColumns ? data[i][j]:0.0)
+ (i<m.noOfRows&&j<m.noOfColumns ? m.data[i][j]:0.0);
return ms;
}
By the way, it'll be safer to use the signature Matrix operator + (const Matrix& m) const, to avoid that a typo could accidentally change the value of the matrix, and avoid an unnecessary copy of the matrix argument.
Then, you must make Sum() a free standing function instead of a member function, if you want to call it like you do in main().
The problem is that you have declared Sum as a friend function of class Matrix while defined it as a member function.
To solve the mentioned error just remove the Matrix:: qualification while defining it as shown below:
//----v-------------------------->removed `Matrix::` from here
Matrix Sum(Matrix m1,Matrix m2){
Matrix m;
m=m1+m2;
return m;
}
Also, the program may have other logical errors. You can refer to the rule of three for more information about them or ask a separate question if that doesn't help.

Error: Type 'Classname' does not provide a call operator

Working on a program involving matrices and hit with an error involving Multiply and Transpose methods. I'm not sure how to proceed
//Header file
class Matrix
{
public:
Matrix(); // constructor
void initIdentity(int n); // initialize as an identity matrix of size nxn
void initFromFile(string fileName); // read the matrix from a file
bool isSquare(); // test whether matrix is square
int numRows(); // return number of rows
int numCols(); // return number of columns
double getVal(int row, int col); // return matrix value at given row/col location (0-indexed based)
void setVal(int row, int col, double val); // set the matrix value at given row/col location (0-index based)
Matrix Multiply(Matrix B); // post-multiply by B and return resulting matrix
Matrix Multiply(double A); // multiply by a scalar and return resulting matrix
Matrix Transpose(); // return transpose of matrix
vector<double> Diagonal(); // return a vector containing diagonal elements of the matrix
void Print(); // print the matrix to stdout
void Print(string name); // print the matrix to stdout with a name prefix
Matrix(int row, int col, double val); // initializing a matrix
private:
vector< vector<double> > matrix_;
vector< vector<int> > identMatrix_;
vector<double> innerVec_;
int numRows_;
int numCols_;
};
//Main file
Matrix Matrix::Multiply(double A){
Matrix ans(numRows_, numCols_, 0.0);
for (int i=0; i< numRows_; i++){
for (int j=0; j< numCols_; j++){
ans(i, j) = matrix_[i][j] * A;
}
}
return ans;
}
Matrix Matrix::Transpose(){
Matrix ans(numRows_, numCols_, 0.0);
for (int i=0; i<numRows_; i++){
for (int j=0; j<numCols_; j++){
ans(i, j) = matrix_[j][i];
}
}
return ans;
}
Error:
Main.cpp:110:7: error: type 'Matrix' does not provide a call operator
ans(i, j) = matrix_[i][j] * A;
^~~
Main.cpp:120:5: error: type 'Matrix' does not provide a call operator
ans(i, j) = matrix_[j][i];
^~~
As noted in comments, you have:
ans(i, j) = matrix_[i][j] * A;
Which is trying to call operator() on ans. But you haven't defined this operator for this type of object.
You'd either need to define that operator so this code works, or just use the existing setVal:
ans.setVal(i, j, matrix_[i][j] * A);

Matrix - return and pass as parameter c++

I'm trying to use clear functions to do a matrix multiplication with random generated values. Therefore I'm hoping to use a function(mat_def) to generate the matrices and another function(mat_mul) to multiply them when the matrices are sent as parameters.
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
double mat_def(int n) //how to return the matrix
{
double a[n][n];
double f;
for(int i=0; i<n; i++)
{
for(int j=0; j<n; j++)
{
f= rand();
cout<<f ;
a[i][j]=f;
}
}
return 0;
}
double mat_mul( int n, double a[n][n], double b[n][n]) //how to send matrix as parameter
{
return 0;
}
int main()
{
/* initialize random seed: */
srand (time(NULL));
mat_def(10);
}
Here's a nice, standard C++ Matrix template for you.
Matrix.h
#include <vector>
class Matrix
{
class InnerM
{
private:
int ydim;
double* values;
public:
InnerM(int y) : ydim(y)
{
values = new double[y];
}
double& operator[](int y)
{
return values[y];
}
};
private:
int xdim;
int ydim;
std::vector<InnerM> inner;
public:
Matrix(int x, int y) : xdim(x), ydim(y), inner(xdim, InnerM(ydim))
{
}
InnerM& operator[](int x)
{
return inner[x];
}
};
All the memory leaks are there for you but you get the idea. From here you can handle the multiplication by overiding ::operator*() in the Matrix class.
I assume your problem is to define 2-D array and then pass it to mat_mul function to multiply the matrices. And the rest will be quite simple.
Defining the 2-D array(considering memory needs are known at run time):
int rows,cols;
cin >> rows;
cin >> cols;
int **arr = new int*[rows]; // rows X cols 2D-array
for(int i = 0; i < rows; ++i) {
arr[i] = new int[cols];
}
You can define another 2-D array exactly the same way with required rows and column.
now, Passing the 2-D array to function:
void mat_mul(int **arr1, int **arr2, int m, int n, int p, int q){
//define a 2-D array to store the result
//do the multiplication operation
//you could store the result in one of the two arrays
//so that you don't have to return it
//or else the return type should be modified to return the 2-D array
}
example:
void display(int **arr, int row, int col){
for (int i=0; i<row; i++){
for(int j=0;j<col; j++){
cout << arr[i][j] << '\t';
}
cout << endl;
}
}
Delete the memory if not required anymore with the following syntax:
for(int i=0; i<rows; i++){
delete[] array[i];
}
delete[] array;
hope this will be sufficient to get your work done!
there is already an answer on how to return a 2-D array on SO. Check the link below.
https://stackoverflow.com/a/8618617/8038009
Returning the raw allocation is a sucker bet. You need to manage all of the memory allocated yourself and pass it around with the matrix size parameters.
Why suffer? Use a matrix class
template<class Type>
class Matrix{
int rows;
int cols;
std::vector<type> data;
public:
Matrix(int row, int col):rows(row), cols(col), data(rows*cols)
{
// does nothing. All of the heavy lifting was in the initializer
}
// std::vector eliminates the need for destructor, assignment operators, and copy
//and move constructors.
//add a convenience method for easy access to the vector
type & operator()(size_t row, size_t col)
{
return data[row*cols+col];
}
type operator()(size_t row, size_t col) const
{
return data[row*cols+col];
}
};
Usage would be
Matrix<double> mat_mul(const Matrix<double> &a, const Matrix<double> &b)
{
Matrix<double> result;
// do multiplication
return result;
}
int main()
{
/* initialize random seed: */
srand (time(NULL));
Matrix<double> matA(10, 10);
matA(0,0) = 3.14; // sample assignment
matA(9,9) = 2.78;
double x = matA(0,0) * matA(9,9)
Matrix<double> matB(10, 10);
Matrix<double> matC = mat_mul(matA, matB) ;
}
More functionality, such as construction from an initializer list, can be added to the class to make your life easier. You can also specify an operator * overload for Matrix and use that in place of mat_mul if you chose. Read Operator overloading for more on that option.

How to allocate a matrix in C++?

For a vector in C++, I have
class Vec
{
public:
int len;
double * vdata;
Vec();
Vec(Vec const & v)
{
cout<<"Vec copy constructor\n";
len = v.len;
vdata=new double[len];
for (int i=0;i<len;i++) vdata[i]=v.vdata[i];
};
I would greatly appreciate it if you could help me how to write an analogous code for a matrix. I am thinking something like this:
class Mat
{
public:
int nrows;
int ncols;
double * mdata;
Mat();
Mat(Mat const & m)
{
cout<<"Mat copy constructor\n";
nrows = m.nrows;
ncols = m.ncols;
But I don't know how to code the memory allocation for a matrix using the idea that first we put all the elements into a 1D array (row1 row2 ... rown) then we chop the array into rows and then chop each row into columns. Particularly, could you help me translate this idea into C++ language that is analogous to the following:
vdata=new double[len];
for (int i=0;i<len;i++) vdata[i]=v.vdata[i];
};
I am thinking of something like this:
double *data=new double[nrows*ncols];
for (int i=0;i<nrows;i++)
{
for (int j=0;j<ncols,j++){data(i,j)=m.mdata[i][j]};
};
But I am not sure about this part:
data(i,j)=m.mdata[i][j]
Also, I am supposed to use a pure virtual element indexing method: the (i,j) element of a Mat object m will be retrieved by m(i,j). I have to provide both const and non-const versions of this indexing operator.<-- May you show me how I could do this?
Thanks a lot.
Use as a single-dimensional array. You will notice that in practice, it's generally much simpler to use a 1d-array for such things.
class Matrix
{
public:
Matrix(unsigned int rows, unsigned int cols)
: _rows(rows)
, _cols(cols)
, _size(_rows*_cols)
, _components(new double[_size])
{
for(unsigned int i = 0; i < _size; ++i)
{
_components[i] = 0;
}
}
~Matrix()
{
delete[] _components;
}
double& operator()(unsigned int row, unsigned int col)
{
unsigned int index = row * _cols + col;
return _components[index];
}
private:
unsigned int _rows;
unsigned int _cols;
unsigned int _size;
double* _components;
};
However, if you want to actually use matrices and vectors, and not just implement them for learning, I would really advise you to use the Eigen library. It's free and open source and has great and easy-to-use vector and matrix classes.
While Eigen is great to use, if you want to look at source code of an existing implementation, it can be quite confusing for new programmers - it's very general and contains a lot of optimizations. A less complicated implementation of basic matrix and vector classes can be found in vmmlib.
Also you can use one standard vector to implement matrix but vector size will be nrows * ncols:
#include <vector>
class Mat {
public:
Mat(int rows, int cols):
nrows(rows),
ncols(cols),
elems(rows*cols,0)
{}
Mat(const Mat &m):
nrows(m.nrows),
ncols(m.ncols),
elems(m.elems.begin(), m.elems.end())
{}
double celem(int i,int j) const {
return elems[ncols*i + nrows*j];
}
double *pelem(int i,int j) {
return &elems[ncols*i + nrows*j];
}
private:
int nrows;
int ncols;
vector<double> elems;
};