(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; 

 }

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 )
{
    int reply;
    fputs( msg, stdout ); fflush( stdout );
    reply = getchar();
    if( reply != '\n' )
        while( getchar() != '\n' ) ; /* 'flush' stdin buffer */
    return reply;
}
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;
}

Edited 2 Years Ago by David W: fixed spelling in code

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.

This article has been dead for over six months. Start a new discussion instead.