Beefy Boxes and Bandwidth Generously Provided by pair Networks
good chemistry is complicated,
and a little bit messy -LW

RE: Matrix Multiplier

by BlaisePascal (Monk)
on Sep 10, 2000 at 08:49 UTC ( #31784=note: print w/replies, xml ) Need Help??

in reply to Matrix Multiplier

Y'know, until now, I never noticed that "d/l code" anchor right below the "comment on this" anchor. The things you learn every day...

Suggestions subroutine by subroutine...

getmatrix: Pre-defining $input to 1 to prime the while, then checking for valid input at the bottom after you have read it is a little hard to understand. You could accomplish the same thing by making the read from <STDIN> as part of the while, with <while ($input = <STDIN>). That would allow you to eliminate the $input &&... at the end as well.

Going one step further, every use of $input at that point is in locations that default to $_, so you can eliminate it all together. I'd recommend, for clarity sake, also renaming @input to @matrix, since that's what it is.

sub getmatrix { my $what = shift; my @matrix; while (<STDIN>) { chop; if (/^0-9 ]/) die "Not a legal matrix row!\n"; } push @matrix, split / /; } return @matrix; }
checkmatrix: This is short enough that there really isn't much to suggest for improvement. The one thing I would suggest, though is moving the $rowlength assignment out of the loop. First, for clarity, second for efficiency. That and get rid of @row, it's unnecessary.

And I just noticed... ne is for string comparison, not numeric. Since you are dealing with numbers, use !=.

sub checkmatrix { my $rowlength = @$_[0]; for (@_) { $rowlength == @$_ or die "Number of columns was not consistant!\n" +; } }
As a matter of style, I'd have this return some boolean value rather than simply up and dying. It allows the caller to decide what to do with a broken matrix.

printmatrix: If that's how you want to format matrices, good enough for me. Not much to criticize here. (This included for completeness).

getdimen: This is really not clear what you are doing. Obviously, you wanted to get the number of rows and columns, but it seems a round-about way to get them. Especially the for loop with an unguarded last, meaning the loop will execute only once. Not clear at all. I'll do a total rewrite:

sub getdimen { my $rows = @_; # get number of rows my $cols = @$_[0]; # get number of elems in first row return ($rows,$columns); }
getproduct: This is the heart of your routine. The major thing I'll mention here is that you can do something like $product[$i][$j] += $a[$i][$k]*$b[$k][$j]; directly, and perl will DWIM correctly. You don't even need to pre-initialize @product. Using that would make your matrix multiply much simpler to understand. This also eliminates most of your "temp" variables.

The other thing I'd do is make product responsible for validating it's arguments and extracting the info it needs directly, rather than expect it to be called in.

sub getproduct { my ($aref, $bref) = @_; my @a = @$aref; my @b = @$bref; my @product; checkmatrix(@a); checkmatrix(@b); my ($arow, $acol) = getdimen(@a); my ($brow, $bcol) = getdimen(@b); $acol == $brow or die "The matrices can't be multiplied!\n"; for $i (0..$arow) { for $j (0..$bcol) { for $k (0..$acol) { $product[$i][$j] += $a[$i][$k] * $b[$k][$j]; } } } return @product; }
Now, if I got the multiplication wrong, it's easy to see what my mistake was (I haven't done linear algebra in a while, I might have the rows/columns mixed up, for instance).

Perl is very good at having the features that DWIM when you need them to. Trying to go overboard with pushes, temp arrays, etc are not necessarily the way to go. As a general rule, I'd say that if you have to force it to do what you want, there might be an easier way...

Hope this helps...

Replies are listed 'Best First'.
RE (tilly) 2: Matrix Multiplier
by tilly (Archbishop) on Sep 10, 2000 at 16:38 UTC
    You have the multiplication right. But one major comment. Checking that the matrixes look right is fairly time intensive. You really don't want that effort to be spent on every multiply. Likewise the dimensions. So this is a place where OO fits well. I won't provide that solution so zdog can have the experience of writing it.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://31784]
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others avoiding work at the Monastery: (1)
As of 2023-06-04 03:54 GMT
Find Nodes?
    Voting Booth?
    How often do you go to conferences?

    Results (17 votes). Check out past polls.