Thread: program to multiply any two 3 x 3 matrices.alternate logic.

  1. #1
    F#ck me Freddy!!
    Join Date
    Sep 2013
    Location
    jaipur
    Posts
    79

    program to multiply any two 3 x 3 matrices.alternate logic.

    I have created a program and it works fine.Just wondering if there is a more efficient logic for this program,

    My code :

    Code:
     #include<stdio.h>
    
    
    void mult(int [][3]); 
    int main( void)
    { 
      int i,j,Matrix[3][3] ={            /*Initializing array*/				
                             2,4,3,
    					     6,8,2,
    					     9,12,6
    					    };	
     mult(Matrix);										
     printf ( "Matrix after addition : \n");
      
     for(i=0;i<3;i++)
     {
       for(j=0;j<3;j++)
        {
         printf("%d,",Matrix[i][j]);
    	}
    	printf("\n");
     }
    }
    
    
    void mult(int a[3][3])
     {
     int b[3][3] ;
     int i,j;
      for(i=0;i<3;i++)
     {
       for(j=0;j<3;j++)
        {
         b[i][j]=a[i][j];
    	}
     }
    	for(i=0;i<3;i++)
    	 {
    	  for(j=0;j<3;j++)
    	   {
    	    a[i][j]= b[i][0]*b[0][j] + b[i][1]*b[1][j] + b[i][2]*b[2][j];
    	   }
    	 }
     }

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I guess you are not searching for a parallel algorithm, because there are many of them out there.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    F#ck me Freddy!!
    Join Date
    Sep 2013
    Location
    jaipur
    Posts
    79
    Quote Originally Posted by std10093 View Post
    I guess you are not searching for a parallel algorithm, because there are many of them out there.
    Just the more efficient one than this

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Any parallel algorithm would be more efficient than this, if of course the dimensions would worth it.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  5. #5
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    The current code multiplies a 3 x 3 matrix by itself as opposed to multiplying one matrix by another. You could unfold the double loop and use constants for the indices, which would be 9 lines of code.

  6. #6
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    At a minimum you could copy the array using memcpy and unroll the multiplication loops.

    BTW, this isn't a matrix multiply routine but a matrix squaring routine.

    EDIT: I've been scooped!
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  7. #7
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Doesn't the compiler unroll the loop?
    Last edited by std10093; 09-29-2013 at 04:28 PM.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  8. #8
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by std10093 View Post
    Doesn't the compiler unrolls the loop?
    With optimizations is certainly might. But this is such a simple case that the code is really no more complicated if you do it yourself. And coder might notice things in the resulting code that he can take advantage of, such as doing it in a different order than the looping version, maybe taking advantage of multiplications that repeat.

    EDIT: However, after running a couple of tests it seems that it's best to let the compiler unroll the loops.
    Last edited by oogabooga; 09-29-2013 at 05:11 PM.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  9. #9
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by oogabooga View Post
    EDIT: However, after running a couple of tests it seems that it's best to let the compiler unroll the loops.
    Have the compiler produce assembly code for both version and see what the difference is. Did you use constant values for the matrix indices in the unfolded loop?

  10. #10
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    It's difficult to compare them. Here's the code I used:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    
    //#define UNROLLED
    
    void print(int m[][3])
    {
        int r, c;
        for (r = 0; r < 3; r++) {
            for (c = 0; c < 3; c++)
                printf("%12d ", m[r][c]);
            putchar('\n');
        }
    }
    
    #ifdef UNROLLED
    
    void square(int m[][3])
    {
        int x[3][3];
    
        x[0][0] = m[0][0]*m[0][0] + m[0][1]*m[1][0] + m[0][2]*m[2][0];
        x[0][1] = m[0][0]*m[0][1] + m[0][1]*m[1][1] + m[0][2]*m[2][1];
        x[0][2] = m[0][0]*m[0][2] + m[0][1]*m[1][2] + m[0][2]*m[2][2];
    
        x[1][0] = m[1][0]*m[0][0] + m[1][1]*m[1][0] + m[1][2]*m[2][0];
        x[1][1] = m[1][0]*m[0][1] + m[1][1]*m[1][1] + m[1][2]*m[2][1];
        x[1][2] = m[1][0]*m[0][2] + m[1][1]*m[1][2] + m[1][2]*m[2][2];
    
        x[2][0] = m[2][0]*m[0][0] + m[2][1]*m[1][0] + m[2][2]*m[2][0];
        x[2][1] = m[2][0]*m[0][1] + m[2][1]*m[1][1] + m[2][2]*m[2][1];
        x[2][2] = m[2][0]*m[0][2] + m[2][1]*m[1][2] + m[2][2]*m[2][2];
    
        memcpy(m, x, 9 * sizeof(int));
    }
    
    #else
    
    void square(int m[][3])
    {
        int r, c;
        int x[3][3];
        for (r = 0; r < 3; r++)
            for (c = 0; c < 3; c++)
                x[r][c] = m[r][0]*m[0][c] + m[r][1]*m[1][c] + m[r][2]*m[2][c];
        memcpy(m, x, 9 * sizeof(int));
    }
    #endif
    
    int main(void)
    {
        int mdata[3][3] = {
            1, 2, 3,
            3, 1, 2,
            1, 3, 2
        };
        int m[3][3];
        int i;
        clock_t start = clock();
    
        for (i = 0; i < 100000000; i++) {  // one hundred million reps
            memcpy(m, mdata, 9 * sizeof(int));
            square(m);
        }
    
    
        printf("%u\n", clock() - start);
    
        print(m); // necessary so optimization doesn't simply remove everything!
    
        return 0;
    }
    Last edited by oogabooga; 09-29-2013 at 06:01 PM. Reason: edited code so result isn't always 0
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  11. #11
    Registered User
    Join Date
    Apr 2013
    Posts
    1,658
    Quote Originally Posted by oogabooga View Post
    It's difficult to compare them. Here's the code I used ...
    Using your code

    Visual C / C++ 4.0 - loop = 2.891 seconds, unrolled = 2.282 seconds
    Visual Studio 2005 - loop = 2.906 seconds, unrolled = 2.187 seconds

    In windows, the ticker rate is 64hz or 0.015625 seconds, so the difference between the compilers time is probably less than what the results show.

  12. #12
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    Quote Originally Posted by rcgldr View Post
    Using your code

    Visual C / C++ 4.0 - loop = 2.891 seconds, unrolled = 2.282 seconds
    Visual Studio 2005 - loop = 2.906 seconds, unrolled = 2.187 seconds

    In windows, the ticker rate is 64hz or 0.015625 seconds, so the difference between the compilers time is probably less than what the results show.
    Using Visual Studio Express 2010 I get essentially the same results as you, but with gcc I get the opposite result and a better time overall.

    VS Express 2010 release: loop = 4.406 secs, unrolled = 3.750 secs
    gcc -march=i686 -O3 : loop = 1.703 secs, unrolled = 2.031 secs

    This is the code I used:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <time.h>
    
    void print(int m[][3])
    {
        int r, c;
        for (r = 0; r < 3; r++) {
            for (c = 0; c < 3; c++)
                printf("%12d ", m[r][c]);
            putchar('\n');
        }
    }
    
    void square_unrolled(int m[][3])
    {
        int x[3][3];
    
        x[0][0] = m[0][0]*m[0][0] + m[0][1]*m[1][0] + m[0][2]*m[2][0];
        x[0][1] = m[0][0]*m[0][1] + m[0][1]*m[1][1] + m[0][2]*m[2][1];
        x[0][2] = m[0][0]*m[0][2] + m[0][1]*m[1][2] + m[0][2]*m[2][2];
    
        x[1][0] = m[1][0]*m[0][0] + m[1][1]*m[1][0] + m[1][2]*m[2][0];
        x[1][1] = m[1][0]*m[0][1] + m[1][1]*m[1][1] + m[1][2]*m[2][1];
        x[1][2] = m[1][0]*m[0][2] + m[1][1]*m[1][2] + m[1][2]*m[2][2];
    
        x[2][0] = m[2][0]*m[0][0] + m[2][1]*m[1][0] + m[2][2]*m[2][0];
        x[2][1] = m[2][0]*m[0][1] + m[2][1]*m[1][1] + m[2][2]*m[2][1];
        x[2][2] = m[2][0]*m[0][2] + m[2][1]*m[1][2] + m[2][2]*m[2][2];
    
        memcpy(m, x, 9 * sizeof(int));
    }
    
    void square_loop(int m[][3])
    {
        int r, c;
        int x[3][3];
        for (r = 0; r < 3; r++)
            for (c = 0; c < 3; c++)
                x[r][c] = m[r][0]*m[0][c] + m[r][1]*m[1][c] + m[r][2]*m[2][c];
        memcpy(m, x, 9 * sizeof(int));
    }
    
    int main(void)
    {
        int m[3][3] = {
            { 1, 2, 3 },
            { 3, 1, 2 },
            { 1, 3, 2 }
        };
        int i;
        long t1, t2;
        clock_t start;
    
        start = clock();
        for (i = 0; i < 100000000; i++)  // one hundred million reps
            square_loop(m);
        t1 = clock() - start;
        print(m); // necessary so optimization doesn't simply remove everything!
    
        start = clock();
        for (i = 0; i < 100000000; i++)  // one hundred million reps
            square_unrolled(m);
        t2 = clock() - start;
        print(m);
    
        printf("loop = %.3f secs, unrolled = %.3f secs\n",
            t1 / (double)CLOCKS_PER_SEC,
            t2 / (double)CLOCKS_PER_SEC);
    
        return 0;
    }
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  13. #13
    F#ck me Freddy!!
    Join Date
    Sep 2013
    Location
    jaipur
    Posts
    79
    I am new to the use of memcpy() and trying to understand it . you used :
    Code:
    memcpy(m, x, 9 * sizeof(int));
    where m = destination
    x = source
    9 = size to be copied
    Now why you used * sizeof(int).what is this for?

    also why you used i<=100000000 for
    Code:
     start = clock();
        for (i = 0; i < 100000000; i++) 

  14. #14
    F#ck me Freddy!!
    Join Date
    Sep 2013
    Location
    jaipur
    Posts
    79
    I used your memcpy advice

    new code :

    Code:
     #include<stdio.h>
    #include<string.h>
    void square(int [][3]); 
    int main( void)
    { 
      int i,j,Matrix[3][3] ={            /*Initializing array*/				
                             2,4,3,
    					     6,8,2,
    					     9,12,6
    					    };	
     square(Matrix);										
     printf ( "Matrix after square : \n");
      
     for(i=0;i<3;i++)
     {
       for(j=0;j<3;j++)
        {
         printf("%d,",Matrix[i][j]);
    	}
    	printf("\n");
     }
    }
    
    
    void square(int a[3][3])
     {
     int b[3][3] ;
     int i,j;
      memcpy(b,a,9 * sizeof(int));
    	for(i=0;i<3;i++)
    	 {
    	  for(j=0;j<3;j++)
    	   {
    	    a[i][j]= b[i][0]*b[0][j] + b[i][1]*b[1][j] + b[i][2]*b[2][j];
    	   }
    	 }
     }
    However i have to add * sizeof(int) in memcpy(b,a,9 * sizeof(int)); without it the code wont work,why is it that.What is the significance of * sizeof(int) in memcpy

  15. #15
    F#ck me Freddy!!
    Join Date
    Sep 2013
    Location
    jaipur
    Posts
    79
    Sorry for confusing this square matrix to multiplication one.My multiplication matrix works fine.its code :
    Code:
     #include<stdio.h>
    
    
    void mult(int [][3],int[][3],int[][3]); 
    int main( void)
    { 
     int i,j,m1[3][3],m2[3][3],m3[3][3] ;
     printf("Enter value of matrix m1 :");
     scanf("%d,%d,%d,%d,%d,%d,%d,%d,%d",&m1[0][0],&m1[0][1],&m1[0][2],&m1[1][0],&m1[1][1],&m1[1][2],&m1[2][0],&m1[2][1],&m1[2][2]); 
     printf("Enter value of matrix m2 :");
     scanf("%d,%d,%d,%d,%d,%d,%d,%d,%d",&m2[0][0],&m2[0][1],&m2[0][2],&m2[1][0],&m2[1][1],&m2[1][2],&m2[2][0],&m2[2][1],&m2[2][2]); 
     mult(m1,m2,m3);										
     printf ( "Multipied Matrix : \n");
      
     for(i=0;i<3;i++)
     {
       for(j=0;j<3;j++)
        {
         printf("%d,",m3[i][j]);
    	}
    	printf("\n");
     }
    }
    
    
    void mult(int a[3][3],int b[3][3],int c[3][3])
     {
     int i,j;
    	for(i=0;i<3;i++)
    	 {
    	  for(j=0;j<3;j++)
    	   {
    	    c[i][j]= a[i][0]*b[0][j] + a[i][1]*b[1][j] + a[i][2]*b[2][j];
    	   }
    	 }
     }
    let me know if i can improve it in any way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. c-program on multiplication of matrices using functions
    By dishagarg in forum C Programming
    Replies: 4
    Last Post: 02-28-2013, 11:14 AM
  2. how many ways exists in order to multiply n matrices?
    By Amin sma in forum C++ Programming
    Replies: 7
    Last Post: 03-30-2012, 02:32 AM
  3. 2 Matrices multiply problem
    By ydan87 in forum C Programming
    Replies: 1
    Last Post: 01-22-2012, 12:48 AM
  4. program won't multiply right
    By Will_rookwood in forum C++ Programming
    Replies: 5
    Last Post: 04-11-2006, 07:28 PM
  5. how to multiply 2 matrices
    By newguy in forum C Programming
    Replies: 1
    Last Post: 10-29-2001, 03:48 AM