(Continued from here )

I am trying to use column major order to a 2d matrix which I am using as 1d.

``````int N=3,R=2;
for (int i=0;i<N;i++){
for (int j=0;j<R;j++){
//printf("\nX[%d]=%d\t",i+j*N,res[i+j*N]); //column major
// printf("\nX[%d]=%d\t",i*R+j,res[i*R+j]); //row major
}
printf("\n");
}
``````

but the column major doesn not work as it should.

Can you tell me why these 2 things don't work?

1) I have 2 matrices ,I multiply them and I can printf as row major or column major (everything is fine until now).
Now,if I store the result matrix (which I received from multiplication) :

`````` ...
//store as column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i+j*rows]=res[i*cols+j];
}
}
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
printf("\nB[%d]=%d\t",i+j*rows,res[i+j*rows]);
//printf("\nB[%d]=%d\t",i*cols+j,res[i*cols+j]);
}
}

then neither printf shows the right results.
``````

2) Can you tell me why this doesn't show the right results for column major but only for row major?

``````int main(int argc, const char* argv[]) {
int rows=3;
int cols=2;
int *A=(int*)malloc(rows*rows*sizeof(int));
int *B=(int*)malloc(rows*cols*sizeof(int));
int *result=(int*)malloc(rows*cols*sizeof(int));
A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;
A[4]=5;
A[5]=6;
A[6]=7;
A[7]=8;
A[8]=9;
B[0]=5;
B[1]=6;
B[2]=7;
B[3]=8;
B[4]=4;
B[5]=5;
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
result[i*cols+j]=0;
for (int k=0;k<rows;k++){
result[i*cols+j]+=A[i*rows+k]*B[k*cols+j];
}
}
}
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
printf("\nB[%d]=%d\t",i+j*rows,result[i+j*rows]); //column major
//printf("\nB[%d]=%d\t",i*cols+j,result[i*cols+j]); //row major
}
printf("\n");
}
return 0;
}
``````

Yes, which every thing you are going to make major has to be the outside loop, the equation doesn't need changing.

Think about how a 3 by 2 matrix is layed out in memory if O is the offset to the first cell the each cell has the memory location

O+0, O+1
O+2, O+3
O+4, O+5

The array operator [] takes care of the offset O you need to generate the addition so for row major you need to generate the sequence 0, 1, 2, 3, 4, 5 for column major you need to generate the sequence 0, 2, 4, 1, 3, 5.

Taking your first code sample using a row major equation i*2+j and column major equation j*3+i iterating i in the range 0-2 and for every value of i j in the range 0-1 those 2 equations give in order

``````i j i*2+j j*3+i
0 0   0     0
0 1   1     3
1 0   2     1
1 1   3     4
2 0   4     2
2 1   5     5
``````

You can see you row major equation gives the wrong sequence. If you reverse the loops, so that J is the outer loop you get

``````j i i*2+j j*3+i
0 0   0     0
0 1   2     1
0 2   4     2
1 0   1     3
1 1   3     4
1 2   5     5
``````

Which gives you the 2 sequences you want all be it that the equations are actually used the other way round.

Ok,thanks for the info.It is starting to make sense now.
So,if I use the approach below ,is it ok?

``````#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, const char* argv[]) {
int rows=3;
int cols=2;

int *A=(int*)malloc(rows*rows*sizeof(int));
int *B=(int*)malloc(rows*cols*sizeof(int));
int *res=(int*)malloc(rows*cols*sizeof(int));

A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;
A[4]=5;
A[5]=6;
A[6]=7;
A[7]=8;
A[8]=9;

B[0]=5;
B[1]=6;
B[2]=2;
B[3]=3;
B[4]=1;
B[5]=2;

//multiplication
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i*cols+j]=0;
for (int k=0;k<rows;k++){
res[i*cols+j]+=A[i*rows+k]*B[k*cols+j];

}

}
}

//row major layout
printf("\nRow major\n");
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){

printf("\nX[%d]=%d\t",i*cols+j,res[i*cols+j]); //row major
}
printf("\n");
}

//column major layout
printf("\n\nColumn major\n");
for (int j=0;j<cols;j++){
for (int i=0;i<rows;i++){

printf("\nX[%d]=%d\t",i*cols+j,res[i*cols+j]); //column major

}
printf("\n");
}

return 0;

}
``````

Note ,that in column major the results are shown as:

X[0]=12 , X[2]=36 .. X[4]=..

We must leave the index like this or change it like X[0],X[1]...?
Or it depends on the way we want to see it?

And this (which is the same as above ) doesn't work because first I am storing as column major and then trying to show it?

I am refering to this piece after the storing:

`````` //this doesn't work
//show the column major
for (int j=0;j<cols;j++){

for (int i=0;i<rows;i++){
printf("\nB[%d]=%d\t",i*cols+j,result[i*cols+j]);

}

}

#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, const char* argv[]) {
int rows=2;
int cols=2;

int *A=(int*)malloc(rows*rows*sizeof(int));
int *B=(int*)malloc(rows*cols*sizeof(int));
int *res=(int*)malloc(rows*cols*sizeof(int));
int *result=(int*)malloc(rows*cols*sizeof(int));

A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;

B[0]=5;
B[1]=6;
B[2]=2;
B[3]=3;

//multiplication
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i*cols+j]=0;
for (int k=0;k<rows;k++){
res[i*cols+j]+=A[i*rows+k]*B[k*cols+j];

}

}
}

//store as column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
result[i+j*rows]=res[i*cols+j];

}
}

//this doen't work
//show the column major
for (int j=0;j<cols;j++){

for (int i=0;i<rows;i++){
printf("\nB[%d]=%d\t",i*cols+j,result[i*cols+j]);

}

}

// OR
//show the column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
printf("\nB[%d]=%d\t",i*cols+j,result[i*cols+j]);
}

}

//OR

for (int i=0;i<rows*cols;i++){
printf("\n\nB[%d]=%d\t",i,result[i]);
}

return 0;

}
``````

Hmm..Also this (the last loop only ) doesn't show the column major order.

``````#include <stdio.h>
#include <stdlib.h>
#include <math.h>

int main(int argc, const char* argv[]) {
int rows=2;
int cols=2;

int *A=(int*)malloc(rows*rows*sizeof(int));
int *B=(int*)malloc(rows*cols*sizeof(int));
int *res=(int*)malloc(rows*cols*sizeof(int));

A[0]=1;
A[1]=2;
A[2]=3;
A[3]=4;

B[0]=5;
B[1]=6;
B[2]=2;
B[3]=3;

//multiplication as column major
for (int i=0;i<rows;i++){
for (int j=0;j<cols;j++){
res[i+j*rows]=0;
for (int k=0;k<rows;k++){
res[i+j*rows]+=A[j*rows+k]*B[i+k*rows];

}

}
}

for (int i=0;i<rows;i++){

for (int j=0;j<cols;j++){
printf("\nB[%d]=%d\t",i*cols+j,res[i+j*rows]);

}

}

//OR

for (int i=0;i<rows*cols;i++){
printf("\n\nB[%d]=%d\t",i,res[i]);

}

return 0;

}
``````

oops ... see below

This example may be helpful ...

``````/* matrixMult.c */

/* each matrix here is stored as one long vector with row*col length */

#include <stdio.h>
#include <stdlib.h> /* re. malloc ... */
#include <ctype.h> /* re. tolower ... */

void myAssert( int condition, const char text[] )
{
if( !condition )
{
fprintf(stderr, "%s\n", text );
fputs( "Press 'Enter' to exit program ... ", stderr );
getchar();
exit(1);
}
}

int* getNewIntArrayMemory( int size )
{
int* ary = malloc( size * sizeof( int ) );
myAssert( (ary != NULL), "\nERROR ... malloc failed in"
" 'getNewIntArrayMemory' \n" );
return ary;
}
int* takeInArrayMatrix( int r, int c )
{
int i, j;
int* m = getNewIntArrayMemory( r * c );

printf( "Enter the %d elements of this matrix\n", r * c );
for(  i = 0 ; i < r ; i++ )
for( j = 0 ; j < c ; j++ )
{
printf( "a[%d] = ", i*c + j );
scanf("%d", &m[i*c + j]);
}
return m;
}
void print( const int* m, int rows, int cols )
{
int i, j;
for ( i = 0 ; i < rows ; ++i )
{
for( j = 0 ; j < cols ; ++j ) printf( "%3d ", m[i*cols + j] );
putchar( '\n' );
}
}

int takeInChar( const char* msg )
{
fputs( msg, stdout ); fflush( stdout );
while( getchar() != '\n' ) ; /* 'flush' stdin buffer */
}
int more() /* defaults to 'true'/'yes'/'1' unless 'n' or 'N' entered */
{
if( tolower( takeInChar( "More (y/n) ? " )) == 'n' ) return 0;
/* else ... */
return 1;
}

int main()
{
int m, n, p, q, i, j;
int* Mat1;

do
{
m = 3, n = 4; /* row, col default values ... */
printf( "Enter the number of rows and columns of Mat1 matrix: " );
scanf( "%d%d", &m, &n );
while( getchar() != '\n' )  ; /* 'flush' stdin ...   */

Mat1 = takeInArrayMatrix( m, n );

p = 4, q = 2;  /* row, col default values */
printf( "Enter the number of rows and columns of Mat2 matrix: " );
scanf( "%d%d", &p, &q );
while( getchar() != '\n' )  ; /* 'flush' stdin ...   */

if ( n != p )
printf( "Size mis-match error ... rows must match %d here.\n", n );
else
{
int k, sum = 0;

int* Mat2 = takeInArrayMatrix( p, q );

/* get product Mat1 * Mat2  with dimensions m x q */

int* Prod = getNewIntArrayMemory( m*q );

for( i = 0 ; i < m ; i++ )
for( j = 0 ; j < q ; j++ )
{
for( k = 0 ; k < p ; k++ )
sum += Mat1[i*n + k] * Mat2[k*q + j];

Prod[i*q + j]  =  sum;
sum = 0;
}

printf( "Product = \n" );
print( Mat1, m, n );
printf( "x\n" );

print( Mat2, p, q );
printf( "=\n" );

print( Prod, m, q );

free( Prod ); free( Mat2 ); free( Mat1 );

while( getchar() != '\n' )  ; /* 'flush' stdin ...   */
}
}
while( more() );

return 0;
}
``````

Thanks but I can't see how your example is related to my problem :)

I had thought, (maybe wrongly, it seems now), that you had wanted to multiply Matrix A ... by a Matrix B ... where both were input as one long vector ... and the product Matrix was also returned as one long vector.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.