I am trying to write a function to transpose matrices.
paramters of that function:
the matrix to transpose
the output matrix which is empty.
The problem is I am able to transpose some matrices but some other fail like the one i am giving in my example. WHy? how could I solve it?
code:
int main (void)
{
//this works well
/* double array[3][2] = {{1,2},{3,4},{5,6}};
height = 3;
width = 2;
*/
//this input doesn't work
double array[2][3] = {{1,2,3},{4,5,6}};
height = 2;
width = 3;
int heightOutput = width; //2
int widthOutput = height; //3
double **output;
output = malloc(widthOutput * sizeof(double *)); //rows from 1
for (i = 0; i < widthOutput; i++)
{
output[i] = malloc(heightOutput * sizeof(double)); //columns
}
transposeMatrix(&array[0][0], height,width, &output[0][0], heightOutput, widthOutput);
printf("\n");
printf("\noutput matrix\n");
for(i=0;i<heightOutput;i++)
{
for(j=0;j<widthOutput;j++)
{
printf("%f\t",output[i][j]);
}
printf("\n");
}
}
void transposeMatrix(double* array2, int height, int width, double * output, int height2, int width2)
{
double workaround[3][3] ={0};
double result;
int i,j;
printf("input matrix:\n");
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
printf("%f\t",(*((array2+i*width)+j)));
}
printf("\n");
}
printf("\n");
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
result = (*((array2+i*width)+j));
workaround[i][j] = result;
}
}
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
*((output+j*3)+i) = workaround[i][j];
printf("%f\t",(*((output+j*3)+i)));
}
printf("\n");
}
}
The main problem is that you confused with sizes of matrices.
When you fill workaround
matrix your loop should be like this, since size of original matrix is (height
x width
).
for(i=0;i<width;i++)
{
for(j=0;j<height;j++)
{
result = (*((array2+i*width)+j));
workaround[i][j] = result;
}
}
When transposing matrix
for(i=0;i<height2;i++)
{
for(j=0;j<width2;j++)
{
*((output+i*width2)+j) = workaround[j][i];
printf("%f\t",(*((output+i*width2)+j)));
}
}
In memory allocation you also got wrong sizes, it should be
output = malloc(heightOutput * sizeof(double *)); //rows from 1
for (i = 0; i < heightOutput; i++)
{
output[i] = malloc(widthOutput * sizeof(double)); //columns
}
With this changes your program will run without errors, but output is still wil be wrong
input matrix:
1.000000 2.000000 3.000000
4.000000 5.000000 6.000000
1.000000 2.000000 3.000000
4.000000 5.000000 6.000000
output matrix
1.000000 4.000000
5.000000 0.000000
0.000000 0.000000
The last problem is with argument passing. You dynamically allocate memory, pointers to rows first
output = malloc(heightOutput * sizeof(double *)); //rows from 1
With this you got array of pointers
* -> NULL
* -> NULL
* -> NULL
and with loop you assign values to them
for (i = 0; i < heightOutput; i++)
{
output[i] = malloc(widthOutput * sizeof(double)); //columns
}
* -> [e00, e01]
* -> [e10, e11]
* -> [e20, e21]
But there is no guarantee that they will be allocated one after another, still you operate with output
like with linear allocated data. To correctly work with this you need to pass double pointer.
void transposeMatrix(double* array2, int height, int width, double ** output, int height2, int width2)
{
...
for(i=0;i<width2;i++)
{
for(j=0;j<height2;j++)
{
output[j][i] = workaround[i][j];
printf("%f\t",output[j][i]);
}
printf("\n");
}
}
If you want to allocate memory linear do it like follows
output = malloc(heightOutput * widthOutput * sizeof(double));
But to me all of it looks kind of complicated, simply it would looks like
void transposeMatrix(double* src, double* dst, int n, int m)
{
int i, j;
for(i = 0; i < n; ++i)
for(j = 0; j < m; ++j)
dst[j * n + i] = src[i * m + j];
}
int main(void)
{
double array[2][3] = {{1,2,3},{4,5,6}};
int height = 2;
int width = 3;
int i, j;
double *output = malloc(height * width * sizeof(double));
printf("input matrix\n");
for(i=0;i<height;i++)
{
for(j=0;j<width;j++)
{
printf("%f\t",array[i][j]);
}
printf("\n");
}
transposeMatrix(&array[0][0], output, height,width);
printf("output matrix\n");
for(i=0;i<width;i++)
{
for(j=0;j<height;j++)
{
printf("%f\t",output[i*height + j]);
}
printf("\n");
}
}
Edit: To answer to your comment: Let' say we have matrix 4 * 5
| a00 a01 a02 a03 a04 |
| a10 a11 a12 a13 a14 |
| a20 a21 a22 a23 a24 |
| a30 a31 a32 a33 a34 |
In memory allocated with
// n = 4, m = 5
double* A = malloc(n * m * sizeof(double));
it will look like
| a00 a01 a02 a03 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24 a30 a31 a32 a33 a34 |
So to get element let's say (2, 3) we need to skip 2 * 5 elements (it's two rows each of 5 elements) and 3 elements from the beginning of the third row, so - 13 elements to skip in array. And to generalize for matrix m * n to get (i, j) element we need to skip (i * m) + j elements in array.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With