start page | rating of books | rating of authors | reviews | copyrights

Perl Cookbook

Perl CookbookSearch this book
Previous: 2.13. Taking Logarithms Chapter 2
Numbers
Next: 2.15. Using Complex 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


Previous: 2.13. Taking Logarithms Perl Cookbook Next: 2.15. Using Complex Numbers
2.13. Taking Logarithms Book Index 2.15. Using Complex Numbers