#  Chapter 2Numbers ## 2.14. Multiplying Matrices

### Problem

You want to multiply a pair of two-dimensional arrays. Mathematicians and engineers often need this.

### Solution

Use the PDL modules, available from CPAN. PDL is the Perl Data Language  - modules that give fast access to compact matrix and mathematical functions:

```use PDL;
# \$a and \$b are both pdl objects
\$c = \$a * \$b;```

Alternatively, apply the matrix multiplication algorithm to your two-dimensional array:

```sub mmult {
my (\$m1,\$m2) = @_;
my (\$m1rows,\$m1cols) = matdim(\$m1);
my (\$m2rows,\$m2cols) = matdim(\$m2);

unless (\$m1cols == \$m2rows) {  # raise exception
die "IndexError: matrices don't match: \$m1cols != \$m2rows";
}

my \$result = [];
my (\$i, \$j, \$k);

for \$i (range(\$m1rows)) {
for \$j (range(\$m2cols)) {
for \$k (range(\$m1cols)) {
\$result->[\$i][\$j] += \$m1->[\$i][\$k] * \$m2->[\$k][\$j];
}
}
}
return \$result;
}

sub range { 0 .. (\$_ - 1) }

sub veclen {
my \$ary_ref = \$_;
my \$type = ref \$ary_ref;
if (\$type ne "ARRAY") { die "\$type is bad array ref for \$ary_ref" }
return scalar(@\$ary_ref);
}

sub matdim {
my \$matrix = \$_;
my \$rows = veclen(\$matrix);
my \$cols = veclen(\$matrix->);
return (\$rows, \$cols);
}```

### Discussion

If you have the PDL library installed, you can make use of its lightning-fast manipulation of numbers. This requires far less memory and CPU than Perl's array manipulation. When using PDL objects, many numeric operators (such as `+` and `*`) are overloaded and work on an element-by-element basis (e.g., `*` is the so-called scalar multiplication operator). To get true matrix multiplication, use the overloaded `x` operator.

```use PDL;

\$a = pdl [
[ 3, 2, 3 ],
[ 5, 9, 8 ],
];

\$b = pdl [
[ 4, 7 ],
[ 9, 3 ],
[ 8, 1 ],
];

\$c = \$a x \$b;  # x overload```

If you don't have the PDL library, or don't feel like pulling it in for a small problem, you can always do the work yourself the good old-fashioned way.

```# mmult() and other subroutines as above

\$x = [
[ 3, 2, 3 ],
[ 5, 9, 8 ],
];

\$y = [
[ 4, 7 ],
[ 9, 3 ],
[ 8, 1 ],
];

\$z = mmult(\$x, \$y);```  