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 Languagemodules 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);```

The documentation with the CPAN module PDL

 Chapter 1. Strings
 Chapter 3. Dates and Times
 Chapter 4. Arrays
 Chapter 5. Hashes
 Chapter 6. Pattern Matching
 Chapter 7. File Access
 Chapter 8. File Contents
 Chapter 9. Directories
 Chapter 10. Subroutines
 Chapter 11. References and Records
 Chapter 12. Packages, Libraries, and Modules
 Chapter 13. Classes, Objects, and Ties
 Chapter 14. Database Access
 Chapter 15. Interactivity
 Chapter 16. Process Management and Communication
 Chapter 17. Sockets
 Chapter 18. Internet Services
 Chapter 19. CGI Programming
 Chapter 20. Web Automation
 Chapter 21. mod_perl
 Chapter 22. XML