Multiplying Matrices (Perl Cookbook, 2nd Edition)

## 2.13. Multiplying Matrices

### 2.13.1. Problem

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

### 2.13.2. 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 x $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 .. ($_[0] - 1) }

>     sub veclen {
>         my $ary_ref = $_[0];
>         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 = $_[0];
>         my $rows = veclen($matrix);
>         my $cols = veclen($matrix->[0]);
>         return ($rows, $cols);
>     }

### 2.13.3. Discussion

If you have the PDL library installed, you can use 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 shown earlier

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

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

>     $z = mmult($x, $y);

### 2.13.4. See Also

The documentation with the CPAN module PDL

Copyright © 2003 O'Reilly & Associates. All rights reserved.