ProgMe

Strassen multiplication

Oct 16th, 2023
1,107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.73 KB | None | 0 0
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <assert.h>
  4.  
  5. int* summation(const int* A, const int* B, int n) {
  6.     int* C = malloc(n * n * sizeof(*C));
  7.     for (int i = 0; i < n; i++) {
  8.         for (int j = 0; j < n; j++) {
  9.             C[i * n + j] = A[i * n + j] + B[i * n + j];
  10.         }
  11.     }
  12.     return C;
  13. }
  14.  
  15. int* subtraction(const int* A, const int* B, int n) {
  16.     int* C = malloc(n * n * sizeof(*C));
  17.     for (int i = 0; i < n; i++) {
  18.         for (int j = 0; j < n; j++) {
  19.             C[i * n + j] = A[i * n + j] - B[i * n + j];
  20.         }
  21.     }
  22.     return C;
  23. }
  24.  
  25. int* multiply(const int* A, const int* B, int n) {
  26.     int* C = malloc(n * n * sizeof(*C));
  27.     for (int i = 0; i < n; i++) {
  28.         for (int j = 0; j < n; j++) {
  29.             C[i * n + j] = 0;
  30.             for (int k = 0; k < n; k++) {
  31.                 C[i * n + j] += A[i * n + k] * B[k * n + j];
  32.             }
  33.         }
  34.     }
  35.     return C;
  36. }
  37.  
  38. void splitMatrix(const int* A, int* A11, int* A12, int* A21, int* A22, int n) {
  39.     for (int i = 0; i < n; i++) {
  40.         for (int j = 0; j < n; j++) {
  41.             A11[i * n + j] = A[i * n + j];
  42.             A12[i * n + j] = A[i * n + j + n];
  43.             A21[i * n + j] = A[(i + n) * n + j];
  44.             A22[i * n + j] = A[(i + n) * n + j + n];
  45.         }
  46.     }
  47. }
  48.  
  49. int* mergeMatrix(const int* A11, const int* A12, const int* A21, const int* A22, int n) {
  50.     int* A = malloc((n << 1) * (n << 1) * sizeof(*A));
  51.     for (int i = 0; i < n; i++) {
  52.         for (int j = 0; j < n; j++) {
  53.             A[i * n + j] = A11[i * n + j];
  54.             A[i * n + j + n] = A12[i * n + j];
  55.             A[(i + n) * n + j] = A21[i * n + j];
  56.             A[(i + n) * n + j + n] = A22[i * n + j];
  57.         }
  58.     }
  59.     return A;
  60. }
  61.  
  62. int* strassenMultiply(int* A, int* B, int n) {
  63.     if (n <= 64) {
  64.         return multiply(A, B, n);
  65.     }
  66.  
  67.     n >>= 1;
  68.  
  69.     int* A11 = malloc(n * n * sizeof(*A11));
  70.     int* A12 = malloc(n * n * sizeof(*A12));
  71.     int* A21 = malloc(n * n * sizeof(*A21));
  72.     int* A22 = malloc(n * n * sizeof(*A22));
  73.  
  74.     int* B11 = malloc(n * n * sizeof(*B11));
  75.     int* B12 = malloc(n * n * sizeof(*B12));
  76.     int* B21 = malloc(n * n * sizeof(*B21));
  77.     int* B22 = malloc(n * n * sizeof(*B22));
  78.  
  79.     splitMatrix(A, A11, A12, A21, A22, n);
  80.     splitMatrix(B, B11, B12, B21, B22, n);
  81.  
  82.     int* P1 = strassenMultiply(summation(A11, A22, n), summation(B11, B22, n), n);
  83.     int* P2 = strassenMultiply(summation(A21, A22, n), B11, n);
  84.     int* P3 = strassenMultiply(A11, subtraction(B12, B22, n), n);
  85.     int* P4 = strassenMultiply(A22, subtraction(B21, B11, n), n);
  86.     int* P5 = strassenMultiply(summation(A11, A12, n), B22, n);
  87.     int* P6 = strassenMultiply(subtraction(A21, A11, n), summation(B11, B12, n), n);
  88.     int* P7 = strassenMultiply(subtraction(A12, A22, n), summation(B21, B22, n), n);
  89.  
  90.     int* C11 = summation(summation(P1, P4, n), subtraction(P7, P5, n), n);
  91.     int* C12 = summation(P3, P5, n);
  92.     int* C21 = summation(P2, P4, n);
  93.     int* C22 = summation(subtraction(P1, P2, n), summation(P3, P6, n), n);
  94.  
  95.     return mergeMatrix(C11, C12, C21, C22, n);
  96. }
  97.  
  98. int main() {
  99.     int n;
  100.     scanf("%i", &n);
  101.  
  102.     assert(__builtin_popcount(n) == 1);
  103.  
  104.     int* A = malloc(n * n * sizeof(*A));
  105.     for (int i = 0; i < n; ++i) {
  106.         for (int j = 0; j < n; ++j) {
  107.             scanf("%i", &A[i * n + j]);
  108.         }
  109.     }
  110.  
  111.     int* B = malloc(n * n * sizeof(*B));
  112.     for (int i = 0; i < n; ++i) {
  113.         for (int j = 0; j < n; ++j) {
  114.             scanf("%i", &B[i * n + j]);
  115.         }
  116.     }
  117.  
  118.     int* C = strassenMultiply(A, B, n);
  119.  
  120.     for (int i = 0; i < n; i++) {
  121.         for (int j = 0; j < n; j++) {
  122.             printf("%i ", C[i * n + j]);
  123.         }
  124.         putchar('\n');
  125.     }
  126. }
Advertisement
Add Comment
Please, Sign In to add comment