Mark Miller
Mark Miller

Reputation: 13123

multiply matrices in loop in C

I am attempting to multiply several matrices using a loop in C. I obtain the expected answer in R, but cannot obtain the expected answer in C. I suspect the problem is related to the += function which seems to double the value of the product after the first iteration of the loop.

I am not very familiar with C and have not been able to replace the += function with one that will return the expected answer.

Thank you for any advice.

First, here is the R code that returns the expected answer:

B0 = -0.40
B1 =  0.20

mycov1 = exp(B0 + -2 * B1) / (1 + exp(B0 + -2 * B1))
mycov2 = exp(B0 + -1 * B1) / (1 + exp(B0 + -1 * B1))
mycov3 = exp(B0 +  0 * B1) / (1 + exp(B0 +  0 * B1))
mycov4 = exp(B0 +  1 * B1) / (1 + exp(B0 +  1 * B1))

trans1 = matrix(c(1 - 0.25 - mycov1,     mycov1,   0.25 * 0.80,              0,
                                  0,   1 - 0.50,             0,    0.50 * 0.75,
                                  0,          0,             1,              0,
                                  0,          0,             0,              1), 
               nrow=4, ncol=4, byrow=TRUE)

trans2 = matrix(c(1 - 0.25 - mycov2,     mycov2,   0.25 * 0.80,              0,
                                  0,   1 - 0.50,             0,    0.50 * 0.75,
                                  0,          0,             1,              0,
                                  0,          0,             0,              1), 
               nrow=4, ncol=4, byrow=TRUE)

trans3 = matrix(c(1 - 0.25 - mycov3,     mycov3,   0.25 * 0.80,              0,
                                  0,   1 - 0.50,             0,    0.50 * 0.75,
                                  0,          0,             1,              0,
                                  0,          0,             0,              1), 
               nrow=4, ncol=4, byrow=TRUE)

trans4 = matrix(c(1 - 0.25 - mycov4,     mycov4,   0.25 * 0.80,              0,
                                  0,   1 - 0.50,             0,    0.50 * 0.75,
                                  0,          0,             1,              0,
                                  0,          0,             0,              1), 
               nrow=4, ncol=4, byrow=TRUE)

trans2b <- trans1  %*% trans2
trans3b <- trans2b %*% trans3
trans4b <- trans3b %*% trans4
trans4b

#
# This is the expected answer
#
#            [,1]      [,2]      [,3]      [,4]
# [1,] 0.01819965 0.1399834 0.3349504 0.3173467
# [2,] 0.00000000 0.0625000 0.0000000 0.7031250
# [3,] 0.00000000 0.0000000 1.0000000 0.0000000
# [4,] 0.00000000 0.0000000 0.0000000 1.0000000
#

Here is my C code. The C code is fairly long because I do not know C well enough to be efficient:

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

char quit;

int main(){

int i, j, k, ii, jj, kk ;

double B0, B1, mycov ;

double trans[4][4]     = {0} ;

double prevtrans[4][4] = {{1,0,0,0},
                          {0,1,0,0},
                          {0,0,1,0},
                          {0,0,0,1}};

B0 = -0.40 ;
B1 =  0.20 ;

for (i=1; i <= 4; i++) {

          mycov = exp(B0 + B1 * (-2+i-1)) / (1 + exp(B0 + B1 * (-2+i-1))) ;

          trans[0][0] =     1 - 0.25 - mycov ;
          trans[0][1] =                mycov ;
          trans[0][2] =          0.25 * 0.80 ;
          trans[0][3] =                    0 ;

          trans[1][0] =                    0 ;
          trans[1][1] =             1 - 0.50 ;
          trans[1][2] =                    0 ;
          trans[1][3] =          0.50 * 0.75 ;

          trans[2][0] =                    0 ;
          trans[2][1] =                    0 ;
          trans[2][2] =                    1 ;
          trans[2][3] =                    0 ;

          trans[3][0] =                    0 ;
          trans[3][1] =                    0 ;
          trans[3][2] =                    0 ;
          trans[3][3] =                    1 ;

          for (ii=0; ii<4; ii++){

               for(jj=0; jj<4; jj++){

                    for(kk=0; kk<4; kk++){

                         trans[ii][jj] += trans[ii][kk] * prevtrans[kk][jj] ;

                    }
               }
          }

          prevtrans[0][0] =     trans[0][0] ;
          prevtrans[0][1] =     trans[0][1] ;
          prevtrans[0][2] =     trans[0][2] ;
          prevtrans[0][3] =     trans[0][3] ;
          prevtrans[1][0] =     trans[1][0] ;
          prevtrans[1][1] =     trans[1][1] ;
          prevtrans[1][2] =     trans[1][2] ;
          prevtrans[1][3] =     trans[1][3] ;
          prevtrans[2][0] =     trans[2][0] ;
          prevtrans[2][1] =     trans[2][1] ;
          prevtrans[2][2] =     trans[2][2] ;
          prevtrans[2][3] =     trans[2][3] ;
          prevtrans[3][0] =     trans[3][0] ;
          prevtrans[3][1] =     trans[3][1] ;
          prevtrans[3][2] =     trans[3][2] ;
          prevtrans[3][3] =     trans[3][3] ;

}

  printf("To close this program type 'quit' and hit the return key\n");
  printf("               \n");
  scanf("%d", &quit);

  return 0;

}

Here is the final matrix returned by the above C code:

0.4821  3.5870  11.68  381.22
0       1       0      76.875
0       0       5      0
0       0       0      5

Upvotes: 0

Views: 100

Answers (1)

R Sahu
R Sahu

Reputation: 206717

This line

                     trans[ii][jj] += trans[ii][kk] * prevtrans[kk][jj] ;

is not right. You're modifying trans in place while you are still using it to compute the resultant matrix. You need another matrix to store the result of the multiplication temporarily. And then use:

      // Store the resultant matrix in temp.
      for (ii=0; ii<4; ii++){

           for(jj=0; jj<4; jj++){

                temp[ii][jj] = 0.0;

                for(kk=0; kk<4; kk++){

                     temp[ii][jj] += trans[ii][kk] * prevtrans[kk][jj] ;

                }
           }
      }

      // Transfer the data from temp to trans
      for (ii=0; ii<4; ii++){

           for(jj=0; jj<4; jj++){
                trans[ii][jj] = temp[ii][jj];
           }
      }

Upvotes: 1

Related Questions