I'm currently trying to write a C++ program with pthreads.h for multi-threaded matrix multiplication.
I'm trying to create the threads as follows
int numthreads = (matrix[0].size() * rsize2);//Calculates # of threads needed
pthread_t *threads;
threads = (pthread_t*)malloc(numthreads * sizeof(pthread_t));//Allocates memory for threads
int rc;
for (int mult = 0; mult < numthreads; mult++)//rsize2
{
struct mult_args args;
args.row = mult;
args.col = mult;
cout << "Creating thread # " << mult;
cout << endl;
rc = pthread_create(&threads[mult], 0, multiply(&args), 0);
}
This then creates threads that execute my multiply function which is coded as follows
void *multiply(int x, int y)
{
int oldprod = 0, prod = 0, sum = 0;
cout << "multiply";
for(int i = 0; i < rsize2; i++)//For each row in #ofrows in matrix 2
{
prod = matrix[x][i] * matrix2[i][y];//calculates the product
sum = oldprod + prod; //Running sum starting at 0 + first product
oldprod = prod; //Updates old product
}
My error lies in my multiply function. I'm trying to find a compatible way to pass in an x and y coordinate for each thread so it knows specifically which summation to calculate but i'm not sure how to do this in a way that is acceptable for the pthreads_create() function.
Update:
I know that I have to use a struct to accomplish this
struct mult_args {
int row;
int col;
};
but I can't get the multiply function to accept the struct
You will have to modify your multiply function so that it takes a single void* parameter. To do this, you will need to make a struct to store x and y and pass a pointer to it in pthread_create.
struct multiply_params
{
int x;
int y;
multiply_params(int x_arg, int y_arg) noexcept :
x(x_arg), y(y_arg)
{}
};
// ...
for (int mult = 0; mult < numthreads; mult++)
{
cout << "Creating thread # " << mult;
cout << endl;
multiply_params* params = new multiply_params(1, 0);
rc = pthread_create(&threads[mult], 0, multiply, (void*) params);
}
Then in your multiply function, rewrite it like this, taking a single void* parameter which will be the pointer of multiply_params which we passed into pthread_create. You have to cast this argument from void* so we can access its fields.
void* multiply(void* arg)
{
multiply_params* params = (multiply_params*) arg;
int x = params->x;
int y = params->y;
delete params; // avoid memory leak
// ...
}
Related
I have a set of Arguments defined as struct for a set of operations (mean, minmax etc.)
struct Arguments {
double *data;
int num_data;
Arguments(double *data, int num_data) : data(data), num_data(num_data) {}
};
struct MeanOperationArguments: Arguments {
MeanOperationArguments(double *data, int num_data) : Arguments(data, num_data) {}
};
struct MinmaxOperationArguments: Arguments {
bool is_min_op;
MinmaxOperationArguments(double *data, int num_data, bool is_min_op) : is_min_op(is_min_op), Arguments(data, num_data) {}
};
I need to define an Operation class as follows:
class Operation {
public:
virtual void execute() = 0;
}
class MeanOperation: public Operation {}
// an operation that can be told to display either the minimum or the maximum.
class MinmaxOperation: public Operation {}
Also, I have an operation factory with returns the specifc operation object instance based on the type of operation:
class OperationFactory {
public:
Operation *get(OP_TYPE t, Arguments *args) {
switch(t) {
case MEAN:
return new MeanOperation(args);
case MINMAX:
return args->is_min_op ? // ERROR: Because struct downcasts to `Arguments`
new MinOperation(args):
new MaxOperation(args);
}
}
};
I need to be able to run my operation based on the type of argument struct like this:
int main() {
double data[] = { 1, 2, 3, 4 };
int num_data = 4;
OperationFactory operations;
Arguments *mean_args = new MeanOperationArguments(data, num_data);
Operation *mean_op = operations.get(MEAN, mean_args);
mean_op->execute();
Arguments *min_args = new MinmaxOperationArguments(data, num_data, true);
Operation *min_op = operations.get(MINMAX, min_args);
min_op->execute();
return 0;
}
How can I initialize my operation with require arguments based on the use case?
If you put a single virtual method in the base class, preferably the destructor, you could use dynamic_cast to convert the pointer to an instance of the derived class. If the conversion fails you have your answer, if it succeeds you can call any of the derived class methods on it.
There are multiple things I have to address. First, avoid structure parent / child relationships. It adds unnecessary dependencies. Look at structures like custom data structures. Data is data at the end of the day. It only has meaning when you interpret it. Going off that logic, your argument structure could be simplified as an array with an unsigned integer that tells how long is that array (similar to a vector, so maybe you could look into using a vector instead of a struct). Going off this logic, the best approach you can take is having multiple functions with different names that take in the same arguments but return different result based on whatever it is that you want it to do. Here is what I am talking about:
#include <iostream>
struct DataSet {
public:
double* data;
int size;
DataSet(double* data, unsigned int size) {
this->data = new double[size];
this->size = size;
for (unsigned int i = 0; i < size; i++)
this->data[i] = data[i];
}
};
double mean(const DataSet& dataSet) {
double mean = 0;
for (unsigned int i = 0; i < dataSet.size; i++)
mean += dataSet.data[i];
mean = mean / dataSet.size;
return mean;
}
double min(const DataSet& dataSet) {
double min = dataSet.data[0];
for (unsigned int i = 1; i < dataSet.size; i++)
if (dataSet.data[i] < min)
min = dataSet.data[i];
return min;
}
double max(const DataSet& dataSet) {
double min = dataSet.data[0];
for (unsigned int i = 1; i < dataSet.size; i++)
if (dataSet.data[i] > min)
min = dataSet.data[i];
return min;
}
int main() {
double data[5] = { 1, 2, 3, 4, 5 };
unsigned int size = 5;
DataSet dataSet = DataSet(data, size);
double result = 0;
result = mean(dataSet);
std::cout << "Mean: " << result << std::endl;
result = min(dataSet);
std::cout << "Min: " << result << std::endl;
result = max(dataSet);
std::cout << "Max: " << result << std::endl;
}
I included everything in one .cpp file for convenience. If you are trying to implement a system, I would suggest making an enum class, store an enum value that represents what operation the user wants to perform, make a switch statement that points to these functions.
Note, be careful with passing pointers around because you might end up with memory leaks. If you notice in the code implementation, I am doing a deep copy, therefore passing memory ownership to the structure to DataSet.
Edit for better system design fit
#include <iostream>
class DataSet {
public:
double* data;
int size;
DataSet() {
data = nullptr;
size = 0;
}
DataSet(double* data, unsigned int size) {
this->data = new double[size];
this->size = size;
for (unsigned int i = 0; i < size; i++)
this->data[i] = data[i];
}
~DataSet() {
if (data != nullptr)
delete(data);
}
};
class Operation {
protected:
DataSet dataSet;
public:
Operation(double* data, unsigned int size) : dataSet(data, size) {
}
virtual double execute() = 0;
};
class Mean : public Operation {
public:
Mean(double* data, unsigned int size) : Operation(data, size) {
}
~Mean() {
}
double execute() {
double mean = 0;
for (unsigned int i = 0; i < dataSet.size; i++)
mean += dataSet.data[i];
mean = mean / dataSet.size;
return mean;
}
};
class MinMax : public Operation {
public:
bool useMin;
MinMax(double* data, unsigned int size) : useMin(true), Operation(data, size) {
}
~MinMax() {
}
double execute() {
if (useMin) {
double min = dataSet.data[0];
for (unsigned int i = 1; i < dataSet.size; i++)
if (dataSet.data[i] < min)
min = dataSet.data[i];
return min;
}
else {
double min = dataSet.data[0];
for (unsigned int i = 1; i < dataSet.size; i++)
if (dataSet.data[i] > min)
min = dataSet.data[i];
return min;
}
}
};
int main() {
double data[5] = { 1, 2, 3, 4, 5 };
unsigned int size = 5;
DataSet dataSet = DataSet(data, size);
double result = 0;
Mean mean = Mean(data, size);
std::cout << "Mean: " << mean.execute() << std::endl;
MinMax minMax = MinMax(data, size);
std::cout << "MinMax: " << minMax.execute() << std::endl;
minMax.useMin = false;
std::cout << "MinMax: " << minMax.execute() << std::endl;
}
For better fit your system, I worked out a better solution. I still got rid of your struct hierarchy but kept the hierarchy in your classes. MinMax will return min or max depending on the useMin boolean value. You said you are printing it in the comments, so you would just have to change it to void and instead of returning the value, just print it. I hope this points you into a better direction.
Something like:
case MINMAX:
return dynamic_cast<MinmaxOperationArguments*>(args)->is_min_op ?
new MinOperation(args):
new MaxOperation(args);
}
Note, that result of cast should be checked before use or it may crash in case of incorrect argument.
RTTI has to be enabled.
I'm trying to do a sum of 2 matrices using pthreads in c++. I'm stuck at trying to pass the result of the sum calculated inside a thread to my main function.
The 2 values to be added are inside a struct:
struct sum{
int value1;
int value2;
int result;
}typedef struct_sum;
And the struct containing the values is passed as an argument to pthread_create() so that the operation is excuted inside a thread.
Here's my routine:
void * routine(void * sum) {
std::cout<<((struct_sum *)sum)->value1 + ((struct_sum *)sum)->value2<<std::endl;
std::cout<<((struct_sum *)sum)->value1<<std::endl;
std::cout<<((struct_sum *)sum)->value2<<std::endl;
int i = (((struct_sum *) sum)->value1 + ((struct_sum *) sum)->value2);
// memcpy(&(((struct_sum *)sum)->result), reinterpret_cast<const void *>(i), sizeof(i));
((struct_sum *)sum)->result = i;
std::cout<<&(((struct_sum *)sum)->result)<<std::endl;
pthread_exit(nullptr);
}
In the first 3 cout I check if my values are coming correctly to the thread.
In the last cout (before exiting the thread) I check the memory address of the result element of the struct (so I can see that it has the same address inside the main function).
Here's the main function:
int main(int argc, char * argv[]) {
int mat_1[ROW_SIZE][COLUMN_SIZE] = {{1, 2},
{6, 7}};
int mat_2[ROW_SIZE][COLUMN_SIZE] = {{3, 15},
{9, 14}};
int mat_result[ROW_SIZE][COLUMN_SIZE];
int mat_size = sizeof(mat_1) / sizeof(int);
int row_size = sizeof(mat_1) / sizeof(mat_1[0]);
int column_size = sizeof(mat_1[0]) / sizeof(int);
pthread_t threads[mat_size];
int thread_number = 0;
int thread_handler;
for (int row = 0; row < row_size; row++) {
for (int column = 0; column < column_size; column++) {
struct_sum *result;
result = static_cast<struct_sum *>(malloc(sizeof(struct_sum)));
result->value1 = mat_1[row][column];
result->value2 = mat_2[row][column];
result->result = 0;
thread_handler = pthread_create(&threads[thread_number], nullptr, routine, result);
if(thread_handler) return(-1);
std::cout << &(result->result)<<std::endl;
thread_number++;
mat_result[row][column] = result->result;
// free(result);
}
}
pthread_exit(nullptr);
}
I'm having two problems:
Even though the result has the same address in the main and in the thread, when I copy the value of i to ((struct_sum *)sum)->result, in the main function, result->result is still 0.
When I uncomment the memcpy() line the thread simply don't run, so I don't know how I'm doing it wrong.
I was expecting that in my main function the statement std::cout << (result->result) <<std::endl would return me the result of the operation, but the current value is 0.
So, how do I perform the memcpy() correctly in the thread?
You have to JOIN your threads. It means, wait them to finish.
The way you were doing is basically starting the thread and not giving it a guaranteed time do to anything. Besides that, some important change to the API, check the comments below:
void * routine(void * sum) {
int i = (((struct_sum *) sum)->value1 + ((struct_sum *) sum)->value2);
((struct_sum *)sum)->result = i;
// notice you don't need memcpy(), in fact...
// but you could use it here if you want... it won't fail.
// you have to use this function so it return your result to the main thread.
pthread_exit(sum);
}
int main(int argc, char * argv[]) {
int mat_1[ROW_SIZE][COLUMN_SIZE] = {{1, 2},
{6, 7}};
int mat_2[ROW_SIZE][COLUMN_SIZE] = {{3, 15},
{9, 14}};
int mat_result[ROW_SIZE][COLUMN_SIZE];
int mat_size = sizeof(mat_1) / sizeof(int);
int row_size = sizeof(mat_1) / sizeof(mat_1[0]);
int column_size = sizeof(mat_1[0]) / sizeof(int);
pthread_t threads[mat_size];
int thread_number = 0;
int thread_handler;
for (int row = 0; row < row_size; row++) {
for (int column = 0; column < column_size; column++) {
struct_sum *result;
result = static_cast<struct_sum *>(malloc(sizeof(struct_sum)));
result->value1 = mat_1[row][column];
result->value2 = mat_2[row][column];
result->result = 0;
thread_handler = pthread_create(&threads[thread_number], nullptr, routine, result);
if(thread_handler) return(-1);
// std::cout << &(result->result)<<std::endl;
thread_number++;
// forget this line below
// mat_result[row][column] = result->result;
}
}
// here you wait for the threads to JOIN
// here it means they actually "finished" their job
for (int i = 0; i < mat_size; i++)
{
struct_sum *result;
// here you wait for the threads to finish their job
// add something to your struct to "identify" the thread, so
// you can figure out where in the final matrix you put the result
pthread_join(threads[i], (void**)&result);
std::cout << result->result << "\n";
// this will print the correct sums: 4, 17, 15 and 21
// notice: it will be printed in ANY order, once you
// don't know which thread will finish first
// but result->result has the... result you need!
// you have to figure out how to fit this result in your matrix.
// but this is out of scope of the question
// and you can do yourself. have fun! :-)
// here you can free the result, you already got the value!
free(result);
}
// you don't need this line below... this goes to routine()
// pthread_exit(nullptr);
return 0;
}
I am trying to create a void pointer to a class object and have it be initialized inside a function. Unfortunately, the array member of the class cannot escape the function i.e. it cannot be accessed after initialization.
In the code below, the first call to print positions (inside the initialize function) works properly, however, the second call to print positions from outside the initialization function fails. I have a feeling that the array object created in the initialization function is destroyed and not passed along but I am not sure and also don't know how to fix it.
Any help would be greatly appreciated.
#include <iostream>
#include <iomanip>
#include <string>
class Atoms
{
double * positions;
int nAtoms;
public:
// Standard constructor prividing a pre-existant array
Atoms(int nAtoms, double * positionsArray)
{
this->nAtoms = nAtoms;
this->positions = positionsArray;
}
// Print positions to screen
void print_positions()
{
std::cout<< "nAtoms: " << this->nAtoms << std::endl;
int nDim = 3;
for (int i = 0; i < nAtoms; i++)
{
for (int j = 0; j < nDim; j++)
{
std::cout << std::setw(6) << this->positions[i * nDim + j] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
};
void initialize_Atoms_void_pointer(void ** voidAtomsPointer)
{
//Create a new instance of Atoms by a pointer
int numAtoms = 5;
int numDim = 3;
int elemN = numAtoms * numDim;
double data_array[elemN];
for (int i = 0; i < numAtoms; i++)
for (int j = 0; j < numDim; j++)
{
data_array[i * numDim + j] = i * numDim + j + 10;
}
Atoms *atoms = new Atoms(numAtoms, data_array);
// Set the vPointer that the void pointer points to a pointer to Atoms object
*voidAtomsPointer = static_cast<void *>(atoms);
//Test call
std::cout << std::endl << "Initializing atoms" << std::endl;
static_cast<Atoms *>(*voidAtomsPointer)->print_positions();
}
void print_Atoms_pointer_positions(void * voidAtomsPointer)
{
//Cast the pointer as an atoms pointer
Atoms *atomsPointer = static_cast<Atoms *>(voidAtomsPointer);
atomsPointer->print_positions();
}
int main()
{
//Use the initializer function for getting a pointer
void *testVoidAtomsPointer;
initialize_Atoms_void_pointer(&testVoidAtomsPointer);
print_Atoms_pointer_positions(testVoidAtomsPointer);
}
The problem is that in
Atoms *atoms = new Atoms(numAtoms, data_array);
data_array is a local array, which is destroyed when initialize_Atoms_void_pointer quits.
Instead of copying the raw pointer, make a new allocation in Atoms's constructor and copy the content:
Atoms(int nAtoms, double * positionsArray)
{
this->nAtoms = nAtoms;
this->positions = new double[nAtoms];
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}
~Atoms()
{
delete[] this->positions;
}
A safer implementation would include the use of a std::unique_ptr, which will automatically de-allocate the memory for you when Atoms is destroyed:
#include <memory>
class Atoms {
std::unique_ptr<double[]> positions;
// ...
public:
Atoms(int nAtoms, double * positionsArray) :
positions(new double[nAtoms]) {
this->nAtoms = nAtoms;
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}
// ...
};
You'd need also to check if nAtoms is 0 or negative, if the input array is null, etc., but I think it falls out of the scope of the question.
If you need to access the raw pointer, you can use the positions.get() method (do not try to delete it or your application will crash due to a double delete).
Update
Of course, another more straightforward solution is simply to use a std::vector<double> instead ;)
#include <vector>
class Atoms {
std::vector<double> positions;
// int nAtoms; -- no longer necessary
public:
Atoms(int nAtoms, double * positionsArray) :
positions(nAtoms) {
for (int ii = 0; ii < nAtoms; ++ii)
this->positions[ii] = positionsArray[ii];
}
// ...
};
If you need to access the raw pointer, you can use the positions.data() method (do not try to delete it or your application will crash due to a double delete). The number of atoms can be checked using positions.size().
As mentioned in a comment, if the only purpose of the Atoms class is to store doubles but not to add any other operation, then just forget about it and directly use the std::vector<double>.
I have an overloaded = operator which is correctly passing some of the values in the particle class, but not other values. I have troubleshooted online, and could not find anything which directly pertained to this problem. My peer who is fairly competent in C++ could not assist, and recommended I post here. Any assistance would be greatly appreciated.
All the values for width, height, wrap, particlen and array were passing perfectly. However, the values for xpos, ypos, xvel, and yvel were passing with incorrect values. For xpos and ypos, every 11th element was passing correctly, but all the other elements were equal to zero; I expect none of these values to be zero. In main, in the operation immediately proceeding gen1 = gen0;, all the dereferenced values for gen0 were correct. I estimate that they were somehow not passed correctly? I will happily post more code/info if required. Again, any insights would be deeply appreciated. Thank you.
Relevant code:
class particle{
private:
int* xpos;
int* ypos;
int* xvel;
int* yvel;
int* array;
int width;
int height;
int wrap;
int particlen;
public:
void operator=(const particle&);
}
Relevant parts of overloaded = operator:
void particle::operator=(const particle ¤t){
int a,b,i,j;
width = current.width;
height = current.height;
wrap = current.wrap;
particlen = current.particlen;
array = new int[width*height];
xpos = new int[particlen];
ypos = new int[particlen];
xvel = new int[particlen];
yvel = new int[particlen];
for(a=0; a<height; a++){
for(b=0; b< width; b++){
this->array[a*width + b] = current.array[a*width + b];
}
}
for(i = 0; i < particlen; i++){
this->xpos[i] = current.xpos[i];
this->ypos[i] = current.ypos[i];
this->xvel[i] = current.xvel[i];
this->yvel[i] = current.yvel[i];
}
Relevant parts of main:
int main(){
particle gen0,gen1;
gen1 = gen0;
}
With Sehe's suggestion, I edited my code. However, I am now getting memory allocation problems with the most simple of commands. The << operator, the first operation called in my main does not allow my array variable to be set equal to an integer in a read in file. I definitely know that the file is readable, as the first output line prints. However, I then get a segmentation fault 11 at array[i*width + j] = k;. GDB prints the output: program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000000
0x000000010001c4f4 in particle::operator<< (this=0x7fff5fbfcb08, file=0x7fff5fbffa90 "100100") at Before typedef 1 vector.cpp:686
686 array[i*width + j] = k;
I have looked up the correct terminology for the vector library online, and thought my syntax was correct. Any ideas?
Update (9:00 EST 2nd Aug)
I am still having trouble with a NULL pointer. When using gdb to debug, I receive the message:
KERN_INVALID_ADDRESS at address: 0x0000000000000000 0x000000010001d807 in particle::operator<< (this=0x7fff5fbfcb08, file=0x7fff5fbffa90 "5040") at Before typedef 1 vector.cpp:688
688 array[(i*width + j)] = k;
I have little experience with NULL pointers; any suggestions as to why this is happening, and how to fix it? Here is the relevant code (the total code is about 900 lines)
class particle{
private:
std::vector<int> xpos;
std::vector<int> ypos;
std::vector<int> xvel;
std::vector<int> yvel;
std::vector<int> array;
int width;
int height;
int wrap;
int particlen; // number of particles read in
public:
void operator<<(particle);
void Collision(int, int, particle);
void operator>>(char*);
void operator<<(char*);
};
void particle::operator<<(char* file) // Reads initial input file
{
ifstream in_file;
in_file.open( file); // open the file
int i,j,k;
}
in_file >> width >> height >> wrap >> particlen;
for(i=0; i<height; i++){
for(j=0; j< width; j++){
in_file >> k;
array[i*width + j] = k; // This is line 688 which GDB references
}
}
}
void particle::operator<<(particle current){
int i,k,j,l;
for(k = 0; k < height*width; k++)
{
array[k] = 0;
}
k = 0;
for(i=0; i < particlen; i++)
{
cout << "Current x pos is" << current.xpos[i] << endl;
}
for(i=0; i < particlen; i++)
{
if(array[ (current.ypos[i]-1)*width + (current.xpos[i] - 1) ] == 0 )
{
//cout << "Current X position[" << i << "] is" << current.xpos[i] << endl;
xpos[i] = current.xpos[i] + (current.xvel[i])*timeinc;
if(xpos[i] > width) xpos[i] = xpos[i] - width;
ypos[i] = current.ypos[i] + (current.yvel[i])*timeinc;
if(ypos[i] > width) ypos[i] = ypos[i] - height;
//cout << "Next X position[" << i << "] is" << xpos[i] << endl;
}
if(array[ (current.ypos[i]-1)*width + (current.xpos[i] - 1) ] > 1 && current.JC[i] != 1)
{
for(l=i+1; l < particlen; l++)
{
if(current.xpos[l] == current.xpos[i] && current.ypos[l] == current.ypos[i] && current.JC[l] != 1)
{
Collision(i,l,current);
}
}
}
}
for(i=0; i < particlen; i++)
{
array[ (xpos[i]-1)*width + (ypos[i]-1) ] = 1;
}
Display();}
int main()
{
char filename[256];
particle gen0, gen1;
gen0 << filename;
gen1 = gen0;
gen0 << gen1; // Calculates the next state of gen0, based on the values in gen1.
}
I know this is long, but I thought that this is the minimal information that I could provide. I thought that perhaps the problem is with the gen0 << gen1 operator, so I included the method.
Like I hinted in the comment, 99% says you're violating Rule Of Three
What is The Rule of Three?
Notably, you have the assignment operator, but there's no copy constructor in sight.. This could mean that if copied, the array pointers will end up "illegally" shared. I also assume you have a destructor somewhere that deletes those arrays (in one instance), thus invalidating the arrays that were copied into another instance.
Fix it by avoiding manual memory management in the first place:
#include <vector>
class particle{
std::vector<int> xpos;
std::vector<int> ypos;
std::vector<int> xvel;
std::vector<int> yvel;
std::vector<int> array;
int width;
int height;
int wrap;
int particlen; // or use `xpos.size()` e.g.
};
int main()
{
particle gen0,gen1;
gen1 = gen0;
}
PS. You might want to consider using v.at(i) instead of v[i] whenever you want bounds-checking. This can be considerable help in debugging issues.
I have a program that looks like the following:
double[4][4] startMatrix;
double[4][4] inverseMatrix;
initialize(startMatrix) //this puts the information I want in startMatrix
I now want to calculate the inverse of startMatrix and put it into inverseMatrix. I have a library function for this purpose whose prototype is the following:
void MatrixInversion(double** A, int order, double** B)
that takes the inverse of A and puts it in B. The problem is that I need to know how to convert the double[4][4] into a double** to give to the function. I've tried just doing it the "obvious way":
MatrixInversion((double**)startMatrix, 4, (double**)inverseMatrix))
but that doesn't seem to work. Is that actually the right way to do it?
No, there's no right way to do specifically that. A double[4][4] array is not convertible to a double ** pointer. These are two alternative, incompatible ways to implement a 2D array. Something needs to be changed: either the function's interface, or the structure of the array passed as an argument.
The simplest way to do the latter, i.e. to make your existing double[4][4] array compatible with the function, is to create temporary "index" arrays of type double *[4] pointing to the beginnings of each row in each matrix
double *startRows[4] = { startMatrix[0], startMatrix[1], startMatrix[2] , startMatrix[3] };
double *inverseRows[4] = { /* same thing here */ };
and pass these "index" arrays instead
MatrixInversion(startRows, 4, inverseRows);
Once the function finished working, you can forget about the startRows and inverseRows arrays, since the result will be placed into your original inverseMatrix array correctly.
For given reason that two-dimensional array (one contiguous block of memory) and an array of pointers (not contiguous) are very different things, you can't pass a two-dimensional array to a function working with pointer-to-pointer.
One thing you could do: templates. Make the size of the second dimension a template parameter.
#include <iostream>
template <unsigned N>
void print(double a[][N], unsigned order)
{
for (unsigned y = 0; y < order; ++y) {
for (unsigned x = 0; x < N; ++x) {
std::cout << a[y][x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(arr, 3);
}
Another, a bit clumsier way might be to make the function accept a pointer to a single-dimensional array, and both width and height given as arguments, and calculate the indexes into a two-dimensional representation yourself.
#include <iostream>
void print(double *a, unsigned height, unsigned width)
{
for (unsigned y = 0; y < height; ++y) {
for (unsigned x = 0; x < width; ++x) {
std::cout << a[y * width + x] << ' ';
}
std::cout << '\n';
}
}
int main()
{
double arr[3][3] = {{1, 2.3, 4}, {2.5, 5, -1.0}, {0, 1.1, 0}};
print(&arr[0][0], 3, 3);
}
Naturally, a matrix is something that deserves a class of its own (but the above might still be relevant, if you need to write helper functions).
Since you are using C++, the proper way to do something like this would be with a custom class and some templates. The following example is rather rough, but it gets the basic point across.
#include <iostream>
using namespace std;
template <int matrix_size>
class SquareMatrix
{
public:
int size(void) { return matrix_size; }
double array[matrix_size][matrix_size];
void copyInverse(const SquareMatrix<matrix_size> & src);
void print(void);
};
template <int matrix_size>
void SquareMatrix<matrix_size>::copyInverse(const SquareMatrix<matrix_size> & src)
{
int inv_x;
int inv_y;
for (int x = 0; x < matrix_size; x++)
{
inv_x = matrix_size - 1 - x;
for (int y = 0; y < matrix_size; y++)
{
inv_y = matrix_size - 1 - y;
array[x][y] = src.array[inv_x][inv_y];
}
}
}
template <int matrix_size>
void SquareMatrix<matrix_size>::print(void)
{
for (int y = 0; y < 4; y++)
{
for (int x = 0; x < 4; x++)
{
cout << array[x][y] << " ";
}
cout << endl;
}
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix);
int main(int argc, char * argList[])
{
SquareMatrix<4> startMatrix;
SquareMatrix<4> inverseMatrix;
Initialize(startMatrix);
inverseMatrix.copyInverse(startMatrix);
cout << "Start:" << endl;
startMatrix.print();
cout << "Inverse:" << endl;
inverseMatrix.print();
return 0;
}
template <int matrix_size>
void Initialize(SquareMatrix<matrix_size> & matrix)
{
for (int x = 0; x < matrix_size; x++)
{
for (int y = 0; y < matrix_size; y++)
{
matrix.array[x][y] = (x+1)*10+(y+1);
}
}
}
Two dimensional array is not a pointer to pointer or something similar. The correct type for you startMatrix is double (*)[4]. For your function, the signature should be like:
MatrixInversion( double (*A)[4], int order, double (*B)[4] );
There is a solution using the pointer to point by bobobobo
William Sherif (bobobobo) used the C version and I just want to show C++ version of bobobobo's answer.
int numRows = 16 ;
int numCols = 5 ;
int **a ;
a = new int*[ numRows* sizeof(int*) ];
for( int row = 0 ; row < numRows ; row++ )
{
a[row] = new int[ numCols*sizeof(int) ];
}
The rest of code is the same with bobobobo's.
You can definitely do something like the code below, if you want.
template <typename T, int n>
class MatrixP
{
public:
MatrixP operator()(T array[][n])
{
for (auto i = 0; i < n; ++i) {
v_[i] = &array[i][0];
}
return *this;
}
operator T**()
{
return v_;
}
private:
T* v_[n] = {};
};
void foo(int** pp, int m, int n)
{
for (auto i = 0; i < m; ++i) {
for (auto j = 0; j < n; ++j) {
std::cout << pp[i][j] << std::endl;
}
}
}
int main(int argc, char** argv)
{
int array[2][2] = { { 1, 2 }, { 3, 4 } };
auto pa = MatrixP<int, 2>()(array);
foo(pa, 2, 2);
}
The problem is that a two-dimensional array is not the same as an array of pointers. A two-dimensional array stores the elements one row after another — so, when you pass such an array around, only a pointer to the start is given. The receiving function can work out how to find any element of the array, but only if it knows the length of each row.
So, your receiving function should be declared as void MatrixInversion(double A[4][], int order, double B[4][]).
by nice coding if c++:
struct matrix {
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
so the interface would be
void MatrixInversion(matrix &A, int order, matrix &B);
and use it
MatrixInversion(startMatrix, 4, inverseMatrix);
The benefit
the interface is very simple and clear.
once need to modify "m" of matrix internally, you don't need to update the interface.
Or this way
struct matrix {
void Inversion(matrix &inv, int order) {...}
protected:
double m[4][4];
};
matrix startMatrix;
matrix inverseMatrix;
...
An ugly way in c
void MatrixInversion(void *A, int order, void *B);
MatrixInversion((void*)startMatrix, 4, (void*)inverseMatrix);
EDIT: reference code for MatrixInversion which will not crash:
void MatrixInversion(void *A, int order, void *B)
{
double _a[4][4];
double _b[4][4];
memcpy(_a, A, sizeof _a);
memcpy(_b, B, sizeof _b);
// processing data here
// copy back after done
memcpy(B, _b, sizeof _b);
}