Recipe 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
|