You want to multiply a pair of two-dimensional arrays. Mathematicians and engineers often need this.
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); }
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);