I got a homework which looks something like this. I am working on it and hold beginner knowledge of the same.
I have to create a header file that contains this code and then use the header file to get the desired results.
I am working with C++ template, and operator overloading.
#include <iostream>
#include <memory>
#include "matrix.h"
#include "symetric_matrix.h"
using namespace std;
int main()
{
const Matrix<int, 3, 2> m1; // Creates 3*2 matrix, with all the default elements set to 0;
cout << m1 << endl;
Matrix<int, 3, 3> m2(4); // Creates 3*3 matrix, with the default elements equals to 4;
cout << m2 << endl;
const Matrix<int, 3, 3> m3 = m2; // C-py constructor may take O(MN) and not O(1).
cout << m3 << endl;
// min() returns the minimal value in the matrix.
if (min(m1) < min(m3))
cout << "Min value of m3(" << min(m3) << ") is bigger than min value of m1(" << min(m1) << ")" << endl;
if (m1.avg() < m3.avg()) // Compares the average of the elements
cout << "Average value of m3(" << m3.avg() << ") is bigger than average value of m1(" << m1.avg() << ")" << endl;
m2(0, 0) = 13;
cout << m2[0][0] << " " << m2[1][0] << endl; // Should print "13 4"
try
{
cout << m2 + m3 << endl;
cout << m3 * m1 << endl; // You can choose the format of matrix printing;
cout << m1 * m2; // This should throw an exception
}
catch (const Matrix<int, 3, 2>::IllegalOperation &e)
{
cout << e.what() << endl;
}
Matrix<int, 3, 3> m4;
m4 = m3;
cout << m4 << endl;
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
m4(i, j) = i + j;
cout << m4 << endl;
cout << "m4[1][1] = " << m4[1][1] << endl;
cout << "m4[1][1] = " << m4(1, 1) << endl; // m4(1,1) same result as m4[1][1]
Matrix<int, 3, 3> m5(3);
m5 = 2 * m4;
cout << m5 << endl;
Matrix<int, 3, 3> m6(m4);
cout << m6 << endl;
m5 += m4;
cout << m5 << endl;
if (m6 != m5)
cout << "m6 != m5" << endl;
Matrix<Matrix<int, 3, 2>, 4, 4> composite(m1); // Creates matrix, where each element is m1;
cout << composite;
unique_ptr<Matrix<int, 3, 3>> symetric_matrix(new SymetricMatrix<int, 3>(5)); // SymetricMatrix matrix 3*3 with default element equals to 5;
(*symetric_matrix)(1, 2) = 8;
cout << (*symetric_matrix)(1, 2) << " " << (*symetric_matrix)(2, 1) << endl; // Should print "8 8"
cout << (*symetric_matrix)[1][2] << " " << (*symetric_matrix)[2][1] << endl; // Should print "8 8"
(*symetric_matrix)[1][0] = 18;
cout << (*symetric_matrix)[1][0] << " " << (*symetric_matrix)[0][1] << endl; // Should print "18 18"
return 0;
}
My Updated solution for now.
template <class T, int M, int N>
class Matrix
{
private:
T mat[M][N];
int rows = M;
int cols = N;
public:
// constructor
Matrix(int v = 0)
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
mat[i][j] = v;
}
}
Matrix<T, M, N> operator+(Matrix<T, M, N> &other);
Matrix<T, M, M> operator*(T scalar);
T &operator()(int i, int j)
{
return mat[i][j];
};
T *operator[](int index)
{
return mat[index];
};
// << overloading
friend std::ostream &operator<<(std::ostream &os, const Matrix<T, M, N> &L)
{
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
os << L.mat[i][j] << " ";
os << "\n";
}
return os;
};
friend T min(Matrix obj)
{
T result = obj.mat[0][0];
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
if (result < obj.mat[i][j])
result = obj.mat[i][j];
}
return result;
};
long double avg() const
{
long double result = 0;
for (int i = 0; i < M; i++)
{
for (int j = 0; j < N; j++)
if (result < mat[i][j])
result = result + mat[i][j];
}
return result / (M * N);
}
};
template <class T, int M, int N>
Matrix<T, M, N> Matrix<T, M, N>::operator+(Matrix &other)
{
if ((this->rows == other.rows) && (this->cols == other.cols()))
{
Matrix<T, M, N> resultantMatrix;
for (auto i = 0; i < this->rows; i++)
{
for (auto j = 0; j < this->cols; j++)
{
auto &valueFirst = this->data[i][j];
auto &valueSecond = other(i, j);
if ((additionOverflow(valueFirst, valueSecond)) || (additionUnderflow(valueFirst, valueSecond)))
throw std::out_of_range("Resultant value of matrix is out of range");
else
resultantMatrix(i, j) = valueFirst + valueSecond;
}
}
return resultantMatrix;
}
else
throw std::runtime_error("Matrices cannot be added, sizes do not match");
}
I am confused about m2(0,0) = 13 & cout << m2+m3, how does this work and how is this possible?
I just need help with the whole program while I try and learn!
Any help is appreciated.
Related
My code is like this so far :
void matrix::print(int colWidth) const
{
cout << getRows() << " x " << getCols() << endl;
cout << "-";
for (unsigned int d = 0; d < getCols(); d++) {
cout << "--------";
}
cout << endl;
for (unsigned x = 0; x < getRows(); x++) {
cout << "|";
for (unsigned y = 0; y < getCols(); y++) {
cout << setw(colWidth) << at(x, y) << " |";
}
cout << endl;
}
cout << "-";
for (unsigned int d = 0; d < getCols(); d++) {
cout << "--------";
}
cout << endl;
}
But the output depends on the colWidth which will be the space between each number printed. So how can I adjust my dashes to be printed like the following no matter the colWidth it should align.
One output should look like this:
Second output is like this:
If the column width is a parameter, you're almost done with your code. Just turn the cout<<"--------" into:
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-');
That code prints a string of dashes, which width is: number of matrix columns, times column width plus 2, plus 1:
Plus 2 because you are appending a " |" to each column.
Plus 1 because you are adding a '|' at the beginning of each row.
You may want to check for empty matrices at the beginning of your print method.
[Demo]
#include <initializer_list>
#include <iomanip> // setw
#include <iostream> // cout
#include <vector>
class matrix
{
public:
matrix(std::initializer_list<std::vector<int>> l) : v{l} {}
size_t getRows() const { return v.size(); }
size_t getCols() const { if (v.size()) { return v[0].size(); } return 0; }
int at(size_t x, size_t y) const { return v.at(x).at(y); }
void print(int colWidth) const
{
std::cout << "Matrix: " << getRows() << " x " << getCols() << "\n";
// +2 due to " |", +1 due to initial '|'
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-') << "\n";
for (unsigned x = 0; x < getRows(); x++) {
std::cout << "|";
for (unsigned y = 0; y < getCols(); y++) {
std::cout << std::setw(colWidth) << at(x, y) << " |";
}
std::cout << "\n";
}
std::cout << std::string(getCols()*(colWidth + 2) + 1, '-') << "\n";
}
private:
std::vector<std::vector<int>> v{};
};
int main()
{
matrix m{{1, 2}, {-8'000, 100'000}, {400, 500}};
m.print(10);
}
// Outputs
//
// Matrix: 3 x 2
// -------------------------
// | 1 | 2 |
// | -8000 | 100000 |
// | 400 | 500 |
// -------------------------
I'm having an issue with a ranged based for loop causing my values to go negative, and I've resolved the issue with a regular for loop but want to understand why it messed up in the first place. You can see from the sample output below that the initial values exist correctly, but then when attempting to subtract from them, they get reset to a default initialized value of 0 I guess?
Broken code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE IS IN THE LOOP BELOW
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i] = multRank[i] - 1;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Maximum Score from Performing Multiplication Operations\n";
test1();
}
Broken code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
-1-2-1
multRank after: -2 -1 0
Repaired code:
#include <iostream>
#include <vector>
#define IS_TRUE(x) { if (!(x)) std::cout << __FUNCTION__ << " failed on line " << __LINE__ << std::endl; }
int maximumScore(std::vector<int>& nums, std::vector<int>& multipliers) {
std::vector<int> multRank;
multRank.resize(multipliers.size());
std::cout << "multRank: ";
//ISSUE WAS IN THE LOOP BELOW
for (auto i = 0; i < multipliers.size(); ++i) {
multRank[i] = multipliers.size();
std::cout << " " << multRank[i];
}
std::cout << std::endl;
for (auto i = 0; i < multipliers.size(); ++i) {
for (auto j = 0; j < multipliers.size(); ++j) {
int abs1 = std::abs(multipliers[i]);
int abs2 = std::abs(multipliers[j]);
if (abs1 > abs2) {
multRank[i]--;
std::cout << multRank[i];
}
}
}
std::cout << std::endl << "multRank after: ";
for (int n : multRank) {
std::cout << " " << n;
}
std::cout << std::endl << std::endl;
return 0;
}
void test1()
{
std::vector<int> nums = { 1, 2, 3 };
std::vector<int> multipliers = { 3, 2, 1 };
int test = maximumScore(nums, multipliers);
IS_TRUE(test == 14);
}
int main()
{
std::cout << "Calculate Rank\n";
test1();
}
Repaired code output:
Maximum Score from Performing Multiplication Operations
multRank: 3 3 3
212
multRank after: 1 2 3
The first range based for loop is not using references:
for (int n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
In this loop, n is a copy of the data in multRank. If you want to be able to modify the data in multRank, you want n to be a reference:
for (int& n : multRank) {
n = multipliers.size();
std::cout << " " << n;
}
I am trying to write a template-based function frequency that will return the count of the occurrences of an item in an array of items.
So far I have
#include <iostream>
using namespace std;
template <class T>
T frequency(T array[], T arraySize, T item) {
int count = 0;
for (int i = 0; i < arraySize; i++) {
if (array[i] == item) {
count++;
}
}
return count;
}
int main() {
// Testing template with int
int intArray[10] = { 1, 2, 3, 3, 14, 3, 2, 7, 99, 2 };
cout << "{ ";
for (int i = 0; i < 10; i++) {
cout << intArray[i] << " ";
}
cout << "}" << endl;
cout << "Frequency of 3: " << frequency(intArray, 10, 3) << endl;
cout << "Frequency of 2: " << frequency(intArray, 10, 2) << endl;
cout << "Frequency of 99: " << frequency(intArray, 10, 99) << endl;
// Testing template with double
double doubleArray[10] = { 1.5, 2.2, 99.4, 132.11, 1.5, 2.22, 1.515, 66.2, 51.8, 34.0 };
cout << "{ ";
for (int j = 0; j < 10; j++) {
cout << doubleArray[j] << " ";
}
cout << "}" << endl;
cout << "Frequency of 1.5: " << frequency(doubleArray, 10, 1.5) << endl;
cout << "Frequency of 2.2: " << frequency(doubleArray, 10, 2.2) << endl;
cout << "Frequency of 100.1: " << frequency(doubleArray, 10, 100.1) << endl;
return 0;
}
however, I get an error of "no matching function for call to 'frequency(double [10], int, double)'" towards when I try to print out the frequency of the doubles. I am unsure what I am doing wrong.
Thank you for any help!
frequency takes parameters of element of array and arraySize with the same type, i.e. T. But you pass arguments of that with different types, i.e. double vs int. Then the type deduction fails because T can't be deduced (determined).
According to your implemantaion, the type arraySize seems fixed, you can just declare it as std::size_t or int. And same for the return type. Their types won't change then shouldn't be declared with template parameters.
template <class T>
int frequency(T array[], std::size_t arraySize, T item) {
int count = 0;
for (std::size_t i = 0; i < arraySize; i++) {
if (array[i] == item) {
count++;
}
}
return count;
}
You should not use your template parameter with arraySize. Because you compare it with i, int i = 0; i < arraySize;. And the return type should not be T too because a double is not accurate don't use it like counter. Plus you do return count and you write int count = 0;
template <class T>
int frequency(T const array[], int arraySize, T const &item);
Be aware that the standard library has a template function to this purpose. In a production code, you should use std::count_if().
int count = std::count_if(intArray.begin(), intArray.end(), [](int i){ return i == 42; });
You can crate frequency as, so that it can be used with other containers.
#include <iostream>
#include <vector>
using namespace std;
template <class outputIterator,class T>
int frequency(outputIterator b,outputIterator e ,const T& v) {
int count = 0;
while(b != e)
{
if(*b == v)
{
count++;
}
b++;
}
return count;
}
int main ()
{
std::vector<int> first={1,1,2,3,4,5,5};
std::cout<<frequency(first.begin(),first.end(),1)<<std::endl;
int arr[]={1,2,3,5,5,5};
std::cout<<frequency(std::begin(arr),std::end(arr),5)<<std::endl;
return 0;
}
I have a simple main code that gives me segmentation fault when calling a function. In the following code, I have two functions, the first one works correctly but the program doesn't enter the second one and gives me segmentation fault error. Is there any reason for that? I have made sure about the following:
The variables o and c are not out of bound.
cn is initialized correctly.
I have a read-only access to cm and argv. Plus it does not even enter the function evaluate
Here is the code:
void print_cm(vector<vector<int> > *cm, char* gtf);
void evaluate(vector<vector<int> > *cm, char* gtf);
int main(int argc, char** argv)
{
int o = 2; // It is initialized
int c = 4; // It is initialized
vector<vector<int> > cm; // It is initialized
if (argc>4)
print_cm(&cm, argv[o]);
if (argc>4)
{
cout << argv[c] << endl; // Works
// The following also works
for (int i=0; i<cm.size(); i++)
for (int j=0; j<cm[i].size(); j++)
cout << cm[i][j] << " ";
// The following causes segmentation fault;
evaluate(&cm, argv[c]);
}
return 0;
}
void evaluate(vector<vector<int> > *cm, char* gtf)
{
// Read-only access to cm and gtf
}
void print_cm(vector<vector<int> > *cm, char* gtf)
{
// Read-only access to cm and gtf
}
Here is the complete code:
#include "includes/Utility.h"
#include "includes/Graph.h"
void print_cm(vector<vector<int> > *cores, char* output);
void evaluate(vector<vector<int> > const *cm, char* gtf);
int main(int argc, char** argv)
{
int g = -1, c = -1, o = -1;
for (int i=1; i<argc-1; i++)
if (argv[i][0]=='-')
{
if (argv[i][1]=='g')
g = i + 1;
else if (argv[i][1]=='c')
c = i + 1;
else if (argv[i][1]=='k')
ki = i + 1;
else if (argv[i][1]=='s')
si = i + 1;
else if (argv[i][1]=='o')
o = i + 1;
}
Graph G;
if (c>0) G.read_input(argv[g], argv[c]);
else G.read_input(argv[g]);
if (ki > 0)
{
int k = atoi(argv[ki]);
cout << k << endl;
}
if (si > 0)
{
int s = atoi(argv[si]);
cout << s << endl;
}
// Find communities
vector<vector<int> > cores;
G.partitioning(&cores);
if (o>0)
print_cm(&cores, argv[o]);
if (c>0)
{
cout << "here" << endl;
for (size_t i=0; i<cores.size(); i++)
for (size_t j=0; j<cores[i].size(); j++)
if (cores.at(i).at(j)<0) cout << "here";
cout << "here" << endl;
evaluate(&cores, argv[c]);
}
}
return 0;
}
void print_cm(vector<vector<int> > *cores, char* output)
{
ofstream out;
out.open(output);
for(size_t i=0; i<(*cores).size(); i++)
{
for(size_t j=0; j<(*cores)[i].size(); j++)
out << (*cores)[i][j] << " ";
out << endl;
}
out.close();
return ;
}
void evaluate(vector<vector<int> > const *cm, char* gtf)
{
// we evaluate precision, recall, F1 and F2
vector<vector<int> > gt;
ifstream in;
char str[100000000];
in.open(gtf);
while(in.getline(str, 100000000))
{
stringstream s;
s << str;
int a;
gt.resize(gt.size()+1);
while (s >> a) gt[gt.size()-1].push_back(a);
}
in.close();
cout << "==================== Evaluation Results ====================" << endl;
int imax = 0;
for(size_t i=0; i<(*cm).size(); i++)
imax = max(imax, *max_element((*cm)[i].begin(), (*cm)[i].end()));
for(size_t i=0; i<gt.size(); i++)
imax = max(imax, *max_element(gt[i].begin(), gt[i].end()));
vector<bool> flag(imax, false);
vector<double> recall((*cm).size(), 0), precision((*cm).size(), 0), f1((*cm).size(), 0), f2((*cm).size(), 0);
int overlap;
double size = 0;
for(size_t i=0; i<(*cm).size(); i++)
{
// evaluate
size += (double) (*cm)[i].size();
for(size_t j=0; j<(*cm)[i].size(); j++)
flag[(*cm)[i][j]] = true;
double p, r, ff1, ff2;
for(size_t j=0; j<gt.size(); j++)
{
overlap = 0;
for(size_t k=0; k<gt[j].size(); k++)
if (flag[gt[j][k]]) overlap++;
p = (double) overlap / (double) (*cm)[i].size();
if (p > precision[i])
precision[i] = p;
r = (double) overlap / (double) gt[j].size();
if (r > recall[i])
recall[i] = r;
ff1 = (double) 2*(p*r)/(p+r);
if (ff1 > f1[i])
f1[i] = ff1;
ff2 = (double) 5*(p*r)/(4*p + r);
if (ff2 > f2[i])
f2[i] = ff2;
}
for(size_t j=0; j<(*cm)[i].size(); j++)
flag[(*cm)[i][j]] = false;
}
double Recall = 0, Precision = 0, F1 = 0, F2 = 0;
for(size_t i=0; i<(*cm).size(); i++)
{
Recall += recall[i];
Precision += precision[i];
F1 += f1[i];
F2 += f2[i];
}
cout << "+--------------+--------------+--------------+--------------+" << endl;
cout << "| " << setiosflags( ios::left ) << setw(10) << "Precision";
cout << " | " << setiosflags( ios::left ) << setw(10) << "Recall";
cout << " | " << setiosflags( ios::left ) << setw(10) << "F1-measure";
cout << " | " << setiosflags( ios::left ) << setw(10) << "F2-measure";
cout << " |" << endl;
cout << "| " << setiosflags( ios::left ) << setw(10) << Precision/(*cm).size() ;
cout << " | " << setiosflags( ios::left ) << setw(10) << Recall/(*cm).size();
cout << " | " << setiosflags( ios::left ) << setw(10) << F1/(*cm).size();
cout << " | " << setiosflags( ios::left ) << setw(10) << F2/(*cm).size();
cout << " |" << endl;
cout << "+--------------+--------------+--------------+--------------+" << endl;
cout << "Number of communities: " << (*cm).size() << endl;
cout << "Average community size: " << size/(*cm).size() << endl;
return ;
}
char str[100000000];
This is in your evaluate function. This are 100 million bytes, or about 95 MB that you're allocating on the stack.
Typical stack sizes are far less than that, around 1 MB.
So apart from possible other problems this is most likely causing a stack overflow.
When entering the function, the stack frame gets extended to be large enough to hold the local variables. As soon as the stack is used then (to write a default value) you're accessing invalid (non stack, thankfully protected) memory.
I have a matrix multiplication code that I am supposed to process in parallel. I have a code here that I believe should work but does not. It either causes segmentation faults or gives me all gibberish values. Can any one help? Thanks in advance.
//*******************STRUCTS AND GLOBAL VARIABLES*****************************//
struct Matrix
{
int d[SIZE][SIZE];
};
Matrix* matrix_addr[SIZE]; // array to store the address of the matrices
int n;
int m;
pthread_mutex_t my_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t my_cond = PTHREAD_COND_INITIALIZER;
//****************************THREAD******************************************//
void* calcTerm(void* arg)
{
pthread_mutex_lock(&my_mutex);
int sum = 0;
Matrix* m0 = (Matrix*) arg;
Matrix* m1 = (Matrix*) ((int*)arg + 1);
Matrix* m2 = (Matrix*) ((int*)arg + 2);
cout << endl << "Print\n" << endl;
print (m0);
for (int i = 0; i < SIZE; ++i)
{
cout << "\ni = " << i << "\tn = " << m1->d[n][i] << "\tm = " << m2->d[i][m] << endl;
sum = sum + (m1->d[n][i] * m2->d[i][m]);
}
cout << endl << endl << sum << endl;
m0->d[n][m] = sum;
pthread_mutex_unlock(&my_mutex);
cout << endl << "Going out of thread\n" ;
pthread_exit(NULL);
}
//********************************MAIN****************************************//
int main()
{
Matrix m0, m1, m2; //Matrices are 3x3;
// m0 <= m1 * m2
pthread_t id[9]; // 3x3 matrix multiplication requires 9 threads.
matrix_addr[0] = &m0; // the pointers to the matrices are stored here.
matrix_addr[1] = &m1;
matrix_addr[2] = &m2;
n = m = 0; // initialize the global variable
srand(time(NULL)); // seed rand()
for (int i = 0; i < SIZE; i++)
{
for (int j = 0; j < SIZE; j++)
{
m0.d[i][j] = 0; // m0 is being cleared for the output
m1.d[i][j] = rand()%10; // m1 and m2 are generated with rand()
m2.d[i][j] = rand()%10;
}
}
//display the input matrices
cout << "MATRIX 1:\n\n";
print (&m1);
cout << "\nMATRIX 2:\n\n";
print (&m2);
cout << "\nMATRIX 3:\n\n";
print (&m0);
for (int i = 0; i < SIZE*SIZE; i++) // run all the threads for calculating each output
{
m = i % SIZE;
n = i / SIZE;
cout << endl << "Going in to thread " << i << " with n = " << n << " and m = " << m;
pthread_create(&id[i], NULL, calcTerm, (void*) matrix_addr);
cout << endl << "Out of thread " << i ;
//pthread_join(id[i], NULL);
}
//pthread_cond_wait(&my_cond, &my_mutex);
cout << endl << endl;
print_result (&m0, &m1, &m2);
return 0;
}
It seems like the calcTerm thread does not take the correct pointers or something. It calculates gibberish values, but the final output at the end of main prints the same matrices I started off with.
Thanks again.