Multiplying a small matrix inside a bigger matrix in C

I have a 4*4 matrix and I want to divide it into 4 blocks of 2*2 matrices so that I can multiply them by a different 2*2 matrix. How do I do that in C?

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

B = [2 3; 4 5]

I know the matrix form is from MATLAB but it's just easier to write it that way here.

Just in case you weren't clear, I wanted to multiply B, into the 4 different blocks of A, namely [1 2; 2 3], [3 4; 4 5], [3 4; 4 5] and [5 6 ;6 7]...

Here's what I've done so far that has resulted in crappy answers:

for (i = 1; i<= 4; i++)
{
  for (j = 1; j<=4; j++)
  {
    C[i][j] = A[i][j]*B[i-2][j-2];   
  }
}

I assume that you wanted to do this, had you been writing a MATLAB script.

A11 = [11, 12; 21, 22];
A12 = [13, 14; 23, 24];
A21 = [31, 32; 41, 42];
A22 = [33, 34; 43, 44];

A = [A11, A12; A21, A22]
B = [11, 12; 21, 22]
C = [A11 * B, A12 * B; A21 * B, A22 * B]

If I run the script through GNU Octave – which I recommend as a largely compatible free software replacement for MATLAB – it produces the following output:

A =

   11   12   13   14
   21   22   23   24
   31   32   33   34
   41   42   43   44

B =

   11   12
   21   22

C =

    373    396    437    464
    693    736    757    804
   1013   1076   1077   1144
   1333   1416   1397   1484

So let's see how it can be done in C.

#include <stdio.h>

int
main()
{
  int i, j;
  int A[4][4] = {
    {11, 12, 13, 14},
    {21, 22, 23, 24},
    {31, 32, 33, 34},
    {41, 42, 43, 44},
  };
  int B[2][2] = {
    {11, 12},
    {21, 22},
  };
  int C[4][4] = {
    { 0,  0,  0,  0},
    { 0,  0,  0,  0},
    { 0,  0,  0,  0},
    { 0,  0,  0,  0},
  };
  for (i = 0; i < 4; i += 2)
    {
      for (j = 0; j < 4; j += 2)
        {
          /* For each 2 x 2 block with upper-left corner at (i, j). */
          C[i + 0][j + 0] = A[i + 0][j + 0] * B[0][0] + A[i + 0][j + 1] * B[1][0];
          C[i + 0][j + 1] = A[i + 0][j + 0] * B[0][1] + A[i + 0][j + 1] * B[1][1];
          C[i + 1][j + 0] = A[i + 1][j + 0] * B[0][0] + A[i + 1][j + 1] * B[1][0];
          C[i + 1][j + 1] = A[i + 1][j + 0] * B[0][1] + A[i + 1][j + 1] * B[1][1];
        }
    }
  for (i = 0; i < 4; ++i)
    printf("%8d%8d%8d%8dn", C[i][0], C[i][1], C[i][2], C[i][3]);
  return 0;
}

Assuming you know the essentials of linear algebra, I don't think that the program will need much more explanation. I leave it as an exercise to you to figure out the pattern in the innermost loop and re-write it as two more nested loops. If your matrices are really just 2 × 2 then hard-coding the indices like this is probably the most readable way to write your program. As the matrices get bigger, you'd really want a loop.

The output of the C program is

     373     396     437     464
     693     736     757     804
    1013    1076    1077    1144
    1333    1416    1397    1484

which happens to be confirmed by the GNU Octave script.

For tiny matrices like this, performance is almost certainly a non-issue. If you are dealing with bigger matrices, you should be using a dedicated library such as (C)BLAS for your linear algebra computations. The BLAS interface has a somewhat steep learning curve and is not very convenient to use. If you have a chance to program in C++, there are much more expressive libraries such as Eigen that achieve comparable performance.

链接地址: http://www.djcxy.com/p/85988.html

上一篇: 矩阵乘法的OpenMP性能问题

下一篇: 在C中将较大的矩阵乘以一个小矩阵