I have declared a matrix this way:
double **MB;
MB = new double *[650000];
for (int count = 0; count < 650000; count++)
MB[count] = new double [2];
Now I want to call my matrix in a function that should modify it.
bool notindic (..., double MB [][2], ...) {}
and in the main:
notindic(..., MB, ...)
Now it gives me this error: *[Error] cannot convert 'double**' to 'double ()[2]' for argument '3' to 'bool notindic(std::string, std::string, double ()[2], int, int)'
How can I fix it?
Thank you.
Just pass array pointer as parameter
#include <iostream>
const int NX = 65;
const int NY = 2;
bool notindic(double** MB) {
for(int i = 0; i < NX; ++i) {
for(int j = 0; j < NY; ++j) {
MB[i][j] = i + j;
}
}
}
int main() {
double **MB = new double *[650000];
for (int count = 0; count < 650000; count++) {
MB[count] = new double [2];
}
notindic(MB);
for(int i = 0; i < NX; ++i) {
for(int j = 0; j < NY; ++j) {
std::cout << MB[i][j] << " ";
}
std::cout << std::endl;
}
}
Forget about all that pointer nonsense. It's error-prone, exception-unsafe, hard to write, hard to read, hard to maintain and may perform poorly. Represent your matrix as std::vector<double> and calculate the offsets accordingly.
bool notindic (std::vector<double> const& matrix, int m) {
// ...
auto const element = matrix[y * m + x];
// ...
}
auto const m = 650000;
auto const n = 2;
std::vector<double> my_matrix(m * n);
auto const result = notindic(my_matrix, m);
While you're at it, wrap it in a class like this:
template <class T>
class Matrix final
{
public:
Matrix(int m, int n) :
data(m * n),
m(m)
{
}
T& operator()(int x, int y)
{
return data[y * m + x];
}
T const& operator()(int x, int y) const
{
return data[y * m + x];
}
private:
std::vector<T> data;
int m;
};
bool notindic (Matrix<double> const& matrix) {
// ...
auto const element = matrix(x, y);
// ...
}
auto const m = 650000;
auto const n = 2;
Matrix<double> my_matrix(m, n);
auto const result = notindic(my_matrix);
Add additional member functions if you need them.
Related
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 9 months ago.
Improve this question
This is the code for my matrix class
The goal here was to Complete the member functions 'void Matrix::add(const Matrix &), void Matrix::mul(double),
void Matrix::mul(const Matrix &), void Matrix::tr(void), and void Matrix::eye(int)'
of the Matrix class in the header file file matrix class
but as soon as I completed that my code started giving me errors and will not run. I am not sure what the problem is.
#ifndef MATRIX_H_
#define MATRIX_H_
#include <iostream>
#include <iomanip>
#include <sstream>
using namespace std;
#define ROW_MAX 10
#define COL_MAX 10
// In the following, the matrix object is referred to as A,
// upper case letters denote matrices,
// and lover case letters denote scalars.
class Matrix
{
public:
Matrix(int m_, int n_, double v_) : m(m_), n(n_) { fill(v_); }; // constructor for an m_ x n_ matrix A initialized to v_
Matrix(int m_, int n_) : Matrix(m_, n_, 0.0) {} // constructor for an m_ x n_ matrix A initialized to 0.0
Matrix(int m_) : Matrix(m_, m_) {} // constructor for an m_ x m_ matrix A initialized to 0.0
Matrix() : Matrix(0) {} // constructor for a 0 x 0 matrix A (empty matrix)
Matrix(const Matrix &A_) { set(A_); } // copy constructor
void from_str(const string &str_); // reads in m, n, and the matrix elements from the string str_ in the format of "m n A[0][0] A[0][1]...A[m-1][n-1]"
string to_str(void); // returns the string representation of A in the format of "m n A[0][0] A[0][1]...A[m-1][n-1]"
int getRows(void) const; // returns the number of rows
int getCols(void) const; // returns the number of columns
double get(int i_, int j_) const; // returns A[i_][j_]
void set(int i_, int j_, double v_); // sets A[i_][j_] to v_ (A[i_][j_] = v_)
void set(const Matrix &A_); // sets A to A_ (A = A_)
void add(const Matrix &A_); // adds A_ to A (A := A + A_)
void mul(double v_); // multiplies A by the scalar v_ (A := v_ A)
void mul(const Matrix &A_); // multiplies A by A_ (A := A A_)
void tr(void); // sets A to its transpose (A := A^T)
void eye(int m_); // sets A to the m_ x m_ identity matrix (A := I)
private:
int m; // the number of rows
int n; // the number of cols
void setRows(int m_); // sets the number of rows to m_
void setCols(int n_); // sets the number of columns to n_
double data[ROW_MAX][COL_MAX]; // holds the matrix data as 2D array
void fill(double v_); // fills the matrix with v_
};
void Matrix::fill(double v_)
{
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
set(i, j, v_);
}
}
}
void Matrix::from_str(const string &str_)
{
istringstream stream(str_);
int m_ = 0, n_ = 0;
stream >> m_;
stream >> n_;
setRows(m_);
setCols(n_);
int i = 0, j = 0;
double v_;
while (stream >> v_)
{
set(i, j, v_);
j += 1;
if (j == getCols())
{
i = i + 1;
j = 0;
}
if (i == getRows())
{
break;
}
}
}
string Matrix::to_str(void)
{
ostringstream _stream("");
_stream << getRows() << " " << getCols();
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
_stream << " " << fixed << defaultfloat << get(i, j);
}
}
return _stream.str();
}
int Matrix::getRows(void) const
{
return m;
}
int Matrix::getCols(void) const
{
return n;
}
void Matrix::setRows(int m_)
{
m = m_;
}
void Matrix::setCols(int n_)
{
n = n_;
}
double Matrix::get(int i_, int j_) const
{
return data[i_][j_];
}
void Matrix::set(int i_, int j_, double v_)
{
data[i_][j_] = v_;
}
void Matrix::set(const Matrix &A_)
{
setRows(A_.getRows());
setCols(A_.getCols());
for (int i = 0; i < getRows(); i++)
{
for (int j = 0; j < getCols(); j++)
{
set(i, j, A_.get(i, j));
}
}
}
void Matrix::add(const Matrix &A_)
{
int r = getRows();
int c = getCols();
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
A_[i][j] = A_[i][j] + A_[i][j];
}
}
}
void Matrix::mul(double v_)
{
int r = getRows();
int c = getCols();
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
A[i][j] = v_ * A[i][j];
}
}
}
void Matrix::mul(const Matrix &A_)
{
int r = getRows();
int c = getCols();
int result[r][c];
for (int i = 0; i < r; i++)
{
for (int j = 0; j < c; j++)
{
result[i][j] = 0;
for (int k = 0; k < r; k++)
{
result[i][j] += A[i][k] * A_[k][j];
}
}
}
}
void Matrix::tr(void)
{
int r = getRows();
int c = getCols();
int result[r][c];
for (int i = 0; i < N; i++)
{
for (intj = 0; j < N; j++)
{
result[i][j] = A[j][i];
}
}
}
void Matrix::eye(int m_)
{
int r = getRows();
int c = getCols();
for (int row = 0; row < m_; row++)
{
for (int col = 0; col < m_; col++)
{
if (row == col)
A[row][col] = 1;
else
A[row][col] = 0;
}
}
}
#endif
There's quite a few problems in your code. For example, in 'add', you have the following:
A_[i][j] = A_[i][j] + A_[i][j];
However, A_ is const, so you can't be modifying its data. Further, the Matrix class does not have an operator[], so you can't use A_[i] in the first place. You likely want the following:
data[i][j] = A_.data[i][j] + A_.data[i][j];
In your mul(double v_) function, you have the following line:
A[i][j] = v_ * A[i][j];
Again, there is no operator[] for your matrix, so it's not valid. Further, this function does not even have an A defined. You want to deal with the data directly.
data[i][j] = v_ * data[i][j];
In the mul(const Matrix &A_) you again have similar issues with using [], and again you have an A instead of A_. There's other issues in this function, such as not using the result after you've done the calculations.
In the tr function, you have intj instead of int j, and you're using a variable N which is not defined.
The function eye references the variable A which, again, never defined. You want data.
Using an IDE, or even an online compiler like godbolt, points out exactly where every one of these errors are. You can see here a fixed version of the code, though this doesn't fix any logic errors, just the syntax ones.
Does accessing the same array's different elements create a data race?
I have a "Matrix" wrapper class for an array with matrix interface, and i wrote a parallel multiplication by a scalar function for it.
I use CTPL library for thread pools.
I know that writing from a thread into an array cell passed by reference is not a data race (please correct me if i'm wrong) so i decided to pass a cell from the array to the function so i can write multiplication result into the cell itself, not by passing the reference to an array and the index, so i can avoid a data race.
I ran the function 10k times and the results did not differ even once, but a sanitizer i use ("-fsanitize=thread -fPIE -pie -g" in Cmake flags) still alerts me of a data race on the line where i create the thread pool.
Is the sanitizer mistaken or am i really experiencing a data race somewhere?
Here are the pieces of code, relevant to the prolem:
Wrapper:
class Matrix {
protected:
int width;
int height;
double* matrix;
public:
Matrix(int m, int n);
Matrix(int m, int n, const std::vector<double>& values);
int get_width() {
return width;
}
int get_height() {
return height;
}
double get_element(int row_num, int col_num);
void set_element(int row_num, int col_num, double el);
double* get_cell_ref(int row_num, int col_num);
};
Method implementations:
Matrix::Matrix(int m, int n) {
assert(m > 0 && n > 0);
matrix = new double[m * n]{0};
width = n;
height = m;
}
Matrix::Matrix(int m, int n, const std::vector<double>& values) {
assert(m > 0 && n > 0 && values.size() == m * n);
matrix = new double[m * n];
width = n;
height = m;
for (int i = 0; i < m * n; ++i) {
matrix[i] = values[i];
}
}
double Matrix::get_element(int row_num, int col_num) {
assert(check_valid(row_num, col_num, get_width(), get_height()));
return matrix[col_num + get_width() * row_num];
}
void Matrix::set_element(int row_num, int col_num, double el) {
assert(check_valid(row_num, col_num, get_width(), get_height()));
matrix[col_num + row_num * get_width()] = el;
}
double* Matrix::get_cell_ref(int row_num, int col_num) {
int idx = col_num + get_width() * row_num;
return &matrix[idx];
}
The function that supposedly has a data race:
Matrix* scalar_multiply_parallel(Matrix* a, double mul, int threadN) {
auto* b = new Matrix(a->get_height(), a->get_width());
ctpl::thread_pool thr_pool(threadN);
std::vector<std::future<void>> futures(a->get_height() * a->get_width());
for (int i =0; i < a->get_height(); i++) {
for (int j =0; j < a->get_width(); j++) {
int idx = j + a->get_width() * i;
auto util = [&a, &b, i, j, mul](int) {
//b->set_element(i, j, a->get_element(i, j) * mul);
double *cell;
cell = b->get_cell_ref(i, j);
*cell = a->get_element(i, j) * mul;
};
futures[idx] = thr_pool.push(util);
}
}
for (auto& f: futures) {
f.get();
}
return b;
}
I'm actually trying to sort a vector of Descriptor basing on a vector included in the Descriptor
float xi, yi; // Descriptor location
vector<double> fv; // The feature vector
(here the vector named fv)
What I want to do is to search in the vector of Descriptor (I will name it Vec_Desc for more clarity from now) the dimension that have the most variance
to do so, I use :
double Tree::_get_mean(vector<Descriptor>& vec, int indice)
{
double sum = 0;
int size = vec.size();
for (int i = 0; i < size; i++) {
sum += vec[i].fv[indice];
}
sum /= size;
return sum;
}
double Tree::_get_variance(vector<Descriptor>& vec, int indice)
{
int size = vec.size();
double var = 0;
double mean = _get_mean(vec, indice);
for (int i = 0; i < size; i++) {
var += ((vec[i].fv[indice] - mean) * (vec[i].fv[indice] - mean)) / size;
}
return var;
}
int Tree::choose_dimension(vector<Descriptor>& vec)
{
double var = _get_variance(vec, 0);
int indice = 0;
for (int i = 1; i < vec[0].fv.size(); i++) {
if (var > _get_variance(vec, i)) {
var = _get_variance(vec, i);
indice = i;
}
}
}
Then I want to sort the vec_desc based on the dim I found.
Tried to do like this :
class _compare {
int step;
public:
_compare(int s) : step(s) {}
bool operator()(const vector<double>& p1, const vector<double>& p2) {
return p1[step] < p2[step];
}
};
void Tree::_sort_vector(vector<Descriptor>& vec, int i)
{
std::sort(vec.begin(), vec.end(), _compare(i));
}
void Tree::sort_vector(vector<Descriptor>& vec)
{
_sort_vector(vec, choose_dimension(vec));
}
But with this, I will sort vec_desc using his own values, and not the values contained in the fv's...
How can I do this?
Your comparator is incorrect - since you are sorting vector<Descriptor> it has to compare two instances of Descriptor not vector<double>:
class _compare {
int step;
public:
_compare(int s) : step(s) {}
bool operator()(const Descriptor& d1, const Descriptor& d2) const {
return d1.fv[step] < d2.fv[step];
}
};
I have a function:
void computeC(array3D fp, double& C) {
C = 0.0;
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
C += fp[x][y][i];
}
}
}
}
here the variable fp and C are defined as:
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
The function is a called as:
computeC(fp, C);
When I execute the main code, following error appears:
vect.cpp:9:22: error: invalid initialization of reference of type 'double&'
from expression of type 'array2D {aka std::vector<std::vector<double> >}'
and
vect.hpp:130:6: error: in passing argument 2 of 'void computeRho(array3D, double&)'
How can I solve this?
The compiler message is quite clear. The type of the second parameter that you try to pass to the function does match with the type the parameter is declared to have. The type of the parameter is double& but you try pass an array2D. array2D is not a double, so you may not pass it to the function.
To solve this, define C to be a double.
But array2D is a vector of vector of doubles. how can I again define C as double?
You can do this by removing the definition array2D C(M, array1D(N, 0)); and replacing it with double C = 0.0;
Any other idea of function definition with vectors as input and output arguments?
Yes, that's another possible approach. Instead of defining a function that takes a double& as a parameter, you could instead implement a function that does take an array2D& parameter. You could then pass C to such function.
(Edit: Answer updated after comments from OP)
Is this what you are looking for:
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
void computeC(array3D& fp, array2D& C) {
double tmp = 0.0;
// Calculate sum of element in 3D array
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
tmp += fp[x][y][i];
}
}
}
// Update the 2D array
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
C[x][y] = tmp;
}
}
}
int main()
{
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
computeC(fp, C);
return 0;
}
or
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
void computeC(array3D& fp, array2D& C) {
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
for (int i = 0; i < 5; ++i) {
C[x][y] += fp[x][y][i];
}
}
}
}
int main()
{
array2D C(M, array1D(N, 0));
array3D fp(M, array2D(N, array1D(5, 0.0)));
computeC(fp, C);
return 0;
}
I think that the answer of StillLearning is the best fit to your question.
Maybe you can get rid of global variables and divide that function into two more basic functionality, like sumOfElements and setElements:
#include <iostream>
#include <vector>
typedef std::vector<double> array1D;
typedef std::vector<array1D> array2D;
typedef std::vector<array2D> array3D;
template< typename T>
double sumOfElements (T & a) {
double sum = 0.0;
for ( auto i : a) sum += sumOfElements(i);
return sum;
}
template<>
double sumOfElements<array1D> (array1D & a) {
double sum = 0.0;
for ( auto i : a) sum += i;
return sum;
}
template< typename T >
void setElements ( double val, T & a) {
for ( auto & i : a) setElements(val,i);
}
template<>
void setElements<array1D> ( double val, array1D & a) {
for ( auto & i : a) i = val;
}
int main() {
double d;
array2D b(4,array1D(5,0.1));
array3D c(3,array2D(4,array1D(5,2.0)));
d = sumOfElements(c);
std::cout << "Sum of elements: " << d << std::endl;
setElements(d,b);
std::cout << "Now all the elements of the array2D are: " << b[2][3] << std::endl;;
return 0;
}
Finally, I get the results and the functions is working perfect as desired. Thanks for the help. Working function is:
void computeC(array3D& fp, array2D& C) {
for (int x = 0; x < M; ++x) {
for (int y = 0; y < N; ++y) {
C[x][y] = 0.0
for (int i = 0; i < 5; ++i) {
C[x][y] += fp[x][y][i];
}
}
}
}
I'm writing a genetic algorithm for which I'm creating a "crossover" operator as a class object that is passed the two parent "chromosomes" Because the input and therefore the output chromosomes are variable lengths, my idea was two divide the input chromosomes and place in a sort of storage class variable, then resize the input chromosomes, and then finally refill the input chromosomes. I'm getting a bad_alloc error, however. If someone could spot my error I'd very much appreciate the help.
Thanks! My class code is below. Note that "plan_vector" is a 2d vector of int types.
#include <iostream>
#include <vector>
#include <eo>
class wetland_vector : public std::vector<int> {
public:
wetland_vector() : std::vector<int>(1, 0) {
}
};
std::istream& operator>>(std::istream& is, wetland_vector& q) {
for (unsigned int i = 0, n = 1; i < q.size(); ++i) {
is >> q[i];
}
return is;
}
std::ostream& operator<<(std::ostream& os, const wetland_vector& q) {
os << q[0];
for (unsigned int i = 1, n = 1; i < q.size(); ++i) {
os << " " << q[i];
}
os << " ";
return os;
}
class wetland_vector_Init : public eoInit<wetland_vector> {
public:
void operator()(wetland_vector& q) {
for (unsigned int i = 0, n = q.size(); i < n; ++i) {
q[i] = rng.random(10);
}
}
};
class plan_vector : public eoVector<double, wetland_vector> {
};
int read_plan_vector(plan_vector _plan_vector) {
for (unsigned i = 0; i < _plan_vector.size(); i++) {
//Call function that reads Quad[1]
//Call function that reads Quad[2]
//etc
return 0;
}
return 0;
};
class eoMutate : public eoMonOp<plan_vector> {
int subbasin_id_min;
int subbasin_id_max;
int wetland_id_min;
int wetland_id_max;
bool operator() (plan_vector& _plan_vector) {
//decide which Quad to mutate
int mutate_quad_ID = rng.random(_plan_vector.size());
//decide which Gene in Quad to mutate
int mutate_gene_ID = rng.random(_plan_vector[mutate_quad_ID].size());
//mutation procedure if first slot in the Quad is selected for mutation
if (mutate_quad_ID = 0) {
_plan_vector[mutate_quad_ID][mutate_gene_ID] = rng.random(subbasin_id_max);
}
//mutation procedure if second slot in the Quad is selected for mutation
if (mutate_quad_ID = 1) {
_plan_vector[mutate_quad_ID][mutate_gene_ID] = rng.random(subbasin_id_max);
}
//note: you'll need to add more for additional wetland characteristics
return true;
};
public:
void set_bounds(int, int, int, int);
};
void eoMutate::set_bounds(int a, int b, int c, int d) {
subbasin_id_min = a;
subbasin_id_max = b;
wetland_id_min = c;
wetland_id_max = d;
}
double evaluate(const plan_vector& _plan_vector) {
int count = 0;
for (int i = 0; i < _plan_vector.size(); i++) {
for (int j = 0; j < _plan_vector[i].size(); j++) {
count += _plan_vector[i][j];
}
}
return (count);
}
class eoQuadCross : public eoQuadOp<plan_vector> {
public:
std::string className() const {
return "eoQuadCross";
}
plan_vector a1;
plan_vector a2;
plan_vector b1;
plan_vector b2;
bool operator() (plan_vector& a, plan_vector& b) {
int cross_position_a = rng.random(a.size() - 1);
int cross_position_b = rng.random(b.size() - 1);
for (int i = 0; i < cross_position_a; i++) {
a1.push_back(a[i]);
}
for (int i = cross_position_a; i < a.size(); i++) {
a2.push_back(a[i]);
}
for (int i = 0; i < cross_position_b; i++) {
b1.push_back(b[i]);
}
for (int i = cross_position_b; i < b.size(); i++) {
b2.push_back(b[i]);
}
int size_a = b2.size() + a1.size();
int size_b = a2.size() + b1.size();
a.resize(size_a);
b.resize(size_b);
for (int i = 0; i < b2.size(); i++) {
a.push_back(b2[i]);
}
for (int i = 0; i < a1.size(); i++) {
a.push_back(a1[i]);
}
for (int i = 0; i < a2.size(); i++) {
b.push_back(a2[i]);
}
for (int i = 0; i < b1.size(); i++) {
b.push_back(b1[i]);
};
//Return bool
return true;
}
};
int main() {
unsigned int vec_size_min = 1;
unsigned int vec_size_max = 10;
unsigned int pop_size = 100;
//BEGIN COPY PARAMETRES
const unsigned int MAX_GEN = 100;
const unsigned int MIN_GEN = 5;
const unsigned int STEADY_GEN = 50;
const float P_CROSS = 0.8;
const float P_MUT = 0.5;
const double EPSILON = 0.01;
double SIGMA = 0.3;
const double uniformMutRate = 0.5;
const double detMutRate = 0.5;
const double normalMutRate = 0.5;
//END COPY PARAMETERS
rng.reseed(1);
//Create population
wetland_vector_Init atom_init;
eoInitVariableLength<plan_vector> vec_init(vec_size_min, vec_size_max, atom_init);
eoPop<plan_vector> pop(pop_size, vec_init);
//Create variation operators
eoMutate mutate;
mutate.set_bounds(1, 453, 1, 4);
eoQuadCross crossover;
eoDetTournamentSelect<plan_vector> select(3);
eoSGATransform<plan_vector> transform(crossover, .5, mutate, .2);
//Create fitness function
eoEvalFuncPtr<plan_vector> eval(evaluate);
//Evaluate initial population and cout
apply<plan_vector > (eval, pop);
std::cout << pop << std::endl;
//Set GA for execution and execute
eoGenContinue<plan_vector> GenCount(5);
eoSGA<plan_vector> gga(select, crossover, .5, mutate, .1, eval, GenCount);
gga(pop);
//cout final population and end
std::cout << pop << std::endl;
std::cout << "The End" << std::endl;
}
a1.~vector();
a2.~vector();
b1.~vector();
b2.~vector();
You shall not destruct the vectors manually, otherwise the next time you try to access them (upon next call to the operator ()) you get undefined behavior.
Why do you call vector destructor manually?? You should let C++ call that for you. If you want to clear the vector use clear member function