Search code examples
cmatrix-multiplicationtranspose

C, matrix transposed multiplication using dynamic memory allocation


I'm trying to transpose and multiply some matrices, basically I get 2 matrices, matrixA and matrixB the action to be performed is trace(transpose(matrixA)*matrixB).

I managed to get this working for nxn matrices but I can't get it to work with mxn where (n>m or m>n).

I've looked online for solutions but I can't implement theirs solution into mine.

I removed almost all the code to simplify reading, if you prefer the entire code I linked it here.

If you do want to run the entire code, to recreate the problem use the following commands:

zeroes matrixA 2 3
zeroes matrixB 2 3
set matrixA
1 2 3 4 5 6
set matrixB
6 5 4 3 2 1
frob matrixA matrixB

The above commands should return Sum 56 but instead I get Sum 18

int* matrixATransposed = (int*) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixARowLenght; i++)
{
    for (int j = 0; j < matrixAColLenght; j++)
    {
        *(matrixATransposed + i * matrixAColLenght + j) = *(matrixA + j * matrixAColLenght + i);
    }
}
// Multiply
int* mulRes = (int*)malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
for (int i = 0; i < matrixAColLenght; i++) {
    for (int j = 0; j < matrixBColLenght; j++) {
        *(mulRes + i * matrixARowLenght + j) = 0;
        for (int k = 0; k < matrixARowLenght; k++)
            *(mulRes + i * matrixAColLenght + j) += *(matrixATransposed + i * matrixAColLenght + k) * *(matrixB + k * matrixBColLenght + j);
    }
}
// Sum the trace
int trace = 0;
for (int i = 0; i < matrixARowLenght; i++) {
    for (int j = 0; j < matrixAColLenght; j++) {
        if (i == j) {
            trace += *(mulRes + i * matrixAColLenght + j);
        }
    }
}
printf_s("Sum: %d\n", trace);

Solution

  • Your array indices for calculating the transpose, multiplication, and the trace seem to be incorrect. I've corrected them in the following program:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char **argv) {
        int matrixARowLenght = 2;
        int matrixAColLenght = 3;
        int matrixA[] = {1,2,3,4,5,6};
    
        int matrixBRowLenght = 2;
        int matrixBColLenght = 3; 
        int matrixB[] = {6,5,4,3,2,1};
    
        // Transpose
        int* matrixATransposed = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
        for (int i = 0; i < matrixAColLenght; i++) {
            for (int j = 0; j < matrixARowLenght; j++) {
                *(matrixATransposed + i * matrixARowLenght + j) = *(matrixA + j * matrixAColLenght + i);
            }
        }
    
        // Multiply
        int *mulRes = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
        for (int i = 0; i < matrixAColLenght; ++i) {
            for (int j = 0; j < matrixAColLenght; ++j) {
                *(mulRes + (i * matrixAColLenght) + j) = 0;
                for (int k = 0; k < matrixARowLenght; ++k) {
                    *(mulRes + (i * matrixAColLenght) + j) += *(matrixATransposed + (i * matrixARowLenght) + k) * *(matrixB + (k * matrixAColLenght) + j);
                } 
            }
        }
        free(matrixATransposed);
    
        // Sum the trace
        int trace = 0;
        for (int i = 0; i < matrixAColLenght; i++) {
            for (int j = 0; j < matrixAColLenght; j++) {
                if (i == j) {
                    trace += *(mulRes + i * matrixAColLenght + j);
                }
            }
        }
        printf("Sum: %d\n", trace);
        free(mulRes);
    
        return 0;
    }
    

    The above program will output your expected value:

    Sum: 56
    


    ** UPDATE **
    As pointed by MFisherKDX, the above code will not work if the result matrix is not a square matrix. The following code fixes this issue:

    #include <stdlib.h>
    #include <stdio.h>
    
    int main(int argc, char **argv) {
        int matrixARowLenght = 2;
        int matrixAColLenght = 3;
        int matrixA[] = {1,2,3,4,5,6};
    
        int matrixBRowLenght = 2;
        int matrixBColLenght = 4; 
        int matrixB[] = {8,7,6,5,4,3,2,1};
    
        // Transpose
        int* matrixATransposed = (int *) malloc(matrixARowLenght * matrixAColLenght * sizeof(int));
        for (int i = 0; i < matrixAColLenght; i++) {
            for (int j = 0; j < matrixARowLenght; j++) {
                *(matrixATransposed + i * matrixARowLenght + j) = *(matrixA + j * matrixAColLenght + i);
            }
        }
    
        // Multiply
        int *mulRes = (int *) malloc(matrixAColLenght * matrixBColLenght * sizeof(int));
        for (int i = 0; i < matrixAColLenght; ++i) {
            for (int j = 0; j < matrixBColLenght; ++j) {
                *(mulRes + (i * matrixBColLenght) + j) = 0;
                for (int k = 0; k < matrixARowLenght; ++k) {
                    *(mulRes + (i * matrixBColLenght) + j) += *(matrixATransposed + (i * matrixARowLenght) + k) * *(matrixB + (k * matrixBColLenght) + j);
                } 
            }
        }
        free(matrixATransposed);
    
        // Sum the trace
        int trace = 0;
        for (int i = 0; i < matrixAColLenght; i++) {
            for (int j = 0; j < matrixBColLenght; j++) {
                if (i == j) {
                    trace += *(mulRes + i * matrixBColLenght + j);
                }
            }
        }
        printf("Sum: %d\n", trace);
        free(mulRes);
    
        return 0;
    }
    

    This code will output the following as expected:

    Sum: 83