Multiply Two Matrices in C++

This article will explain several methods of how to multiply two matrices in C++.

Use Serial Implementation to Multiply Two Matrices in C++

Matrix multiplication is one of the most commonly used operations across a wide range of engineering solutions. Thus, there are various algorithms to improve the performance on different hardware platforms. These algorithms often utilize concurrent programming as well as matrix tiling to accelerate matrix multiplication. In this case, though, we implement a straightforward algorithm that executes serially without any explicit optimizations.

At first, we need to implement some utility functions to help allocate and initialize matrices to operate with. Note that we are implementing the code so that the programmer can modify ROW and COL constant integers to specify the matrix dimensions. allocateMatrix function allocates the array of arrays and initializes elements with zero values. Next, initilizeMatrix function is called that generates random numbers in range - [0, 100) and stores them as matrix elements. Notice that there’s also a function that prints the matrix elements to the cout stream to verify the calculation results.

The multiplyMatrix function implements a simple triple-nested for loop to multiply two matrices and store the results in the preallocated third matrix. The result matrix dimensions are taken from the first matrix rows and the second matrix columns. Mind that, the loop order is quite important for the multiplication performance. E.g., if we move the innermost for statement in the middle, there’s an almost guaranteed performance boost expected. The performance improvement is caused by the cache memories that are located in almost every contemporary CPU. Cache memory is faster than the main memory, and it stores contiguous memory blocks when the data is retrieved. Thus, the next data retrieval can be served from caches themselves.

#include <iostream>
#include <iomanip>
#include <vector>

using std::cout; using std::endl;
using std::setw; using std::vector;

constexpr int ROW = 2;
constexpr int COL = 3;

void initilizeMatrix(int **m, int row, int col)
{
    for(auto i = 0; i < row; ++i) {
        for(auto j = 0; j < col; ++j) {
            m[i][j] = rand() % 100;
        }
    }
}

void printMatrix(int **m, int row, int col)
{
    for(auto i = 0; i < row; ++i) {
        for(auto j = 0; j < col; ++j) {
            cout << setw(5) << m[i][j] << "; ";
        }
        cout << endl;
    }
}

int **allocateMatrix(int row, int col)
{
    int **matrix = new int*[row];
    for(int i = 0; i < row; ++i) {
        matrix[i] = new int[col]{0};
    }
    return matrix;
}

int deallocateMatrix(int **matrix, int row)
{
    for(int i = 0; i < row; ++i) {
        delete matrix[i];
    }
    delete [] matrix;
    return 0;
}

int **multiplyMatrix(int **m1, int row1, int col1, int **m2, int row2, int col2)
{
    if (col1 != row2)
        return nullptr;

    auto ret = allocateMatrix(row1, col2);

    int i,j,k;

    for(i = 0; i < row1; i++) {
        for(j = 0; j < col2; j++) {
            for(k = 0; k < col1; k++) {
                ret[i][j] += m1[i][k] * m2[k][j];
            }
        }
    }

    return ret;
}

int main(){
    int **matrix1 = allocateMatrix(ROW, COL);
    int **matrix2 = allocateMatrix(COL, ROW);

    initilizeMatrix(matrix1, ROW, COL);
    initilizeMatrix(matrix2, COL, ROW);

    printMatrix(matrix1, ROW, COL);
    cout << endl;
    printMatrix(matrix2, COL, ROW);

    auto result = multiplyMatrix(matrix1, ROW, COL, matrix2, COL, ROW);

    cout << endl;
    printMatrix(result, ROW, ROW);

    deallocateMatrix(matrix1, ROW);
    deallocateMatrix(matrix2, COL);
    deallocateMatrix(result, ROW);

    return EXIT_SUCCESS;
}

Output:

83;    86;    77;
15;    93;    35;

86;    92;
49;    21;
62;    27;

16126; 11521;
8017;  4278;

Finally, it’s important to free all the memory resources used by the matrices before the program exits. deallocateMatrix function is implemented so that it takes a matrix pointer and rows in it to delete each element in the object. Notice that the result matrix allocated in the multiplyMatrix function scope should also be deallocated explicitly.

Contribute
DelftStack is a collective effort contributed by software geeks like you. If you like the article and would like to contribute to DelftStack by writing paid articles, you can check the write for us page.

Related Article - C++ Math

  • Generate Fibonacci Numbers in C++