Recipe 2.14. Multiplying Matrices
Author: Tom Christiansen & Nathan Torkington
Date: 1999-07-02T01:30:19Z

#

| Chapter 2 Numbers |

## 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 .. ($_[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);
    }

### 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);

### See Also

The documentation with the CPAN module PDL

2.13. Taking Logarithms |  | 2.15. Using Complex Numbers