Multiply two 2×2 matrices by hand using the standard triple loop. For each output cell C[i][j], the innermost loop accumulates the dot product of row i of A with column j of B. The replay shows C filling cell by cell across all 8 inner products.

By hand

With NumPy

mat_a @ mat_b applies matrix multiplication in one call. The snapshot shows both inputs and the result, each with their (2, 2) shape.

naive.py
A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
n = 2
C = [[0, 0], [0, 0]]
for i in range(n):
    for j in range(n):
        for k in range(n):
            C[i][j] += A[i][k] * B[k][j]
print('RESULT:', C)
library.py
import numpy as np

A = [[1, 2], [3, 4]]
B = [[5, 6], [7, 8]]
mat_a = np.array(A)
mat_b = np.array(B)
result = mat_a @ mat_b
print('A: shape:', mat_a.shape, 'dtype:', mat_a.dtype, 'values:', mat_a.tolist())
print('B: shape:', mat_b.shape, 'dtype:', mat_b.dtype, 'values:', mat_b.tolist())
print('result: shape:', result.shape, 'dtype:', result.dtype, 'values:', result.tolist())
print('RESULT:', result.tolist())
A: shape: (2, 2) dtype: int64 values: [[1, 2], [3, 4]]
B: shape: (2, 2) dtype: int64 values: [[5, 6], [7, 8]]
result: shape: (2, 2) dtype: int64 values: [[19, 22], [43, 50]]
RESULT: [[19, 22], [43, 50]]

Implementation notes

  • Each cell C[i][j] is the dot product of row i of A with column j of B — the same scalar computation as dot-product, repeated for every (i, j) pair. The triple loop makes this structure explicit.
  • For a general (m, n) @ (n, p) multiplication the triple loop would range over i in range(m), j in range(p), k in range(n). The 2×2 case is the minimal non-trivial example.
  • @ dispatches to np.matmul. For 2-D arrays np.dot(A, B) gives the same result, but @ is preferred for readability and consistency with the matvec-multiply lesson.
  • Shape, dtype, and values are shown explicitly here because ndarray.__repr__ output varies with NumPy version and print options.