]> git.imager.perl.org - imager.git/commitdiff
expand the matrix multiply overload to allow mult by array ref or number
authorTony Cook <tony@develop-help.com>
Mon, 24 Jan 2011 11:32:09 +0000 (22:32 +1100)
committerTony Cook <tony@develop-help.com>
Mon, 24 Jan 2011 11:32:09 +0000 (22:32 +1100)
Changes
lib/Imager/Matrix2d.pm
t/t16matrix.t

diff --git a/Changes b/Changes
index 29363106b3c5279c82071da73e36f9d718947f73..be599eaa29067b4a1b4eae6c57134952d1aaaed9 100644 (file)
--- a/Changes
+++ b/Changes
@@ -14,7 +14,8 @@ Bug fixes:
    https://rt.cpan.org/Ticket/Display.html?id=56513
 
  - add the matrix() method to Imager::Matrix2d to allow creation of a
-   matrix with specified co-efficients.
+   matrix with specified co-efficients.  You can now multiple an
+   Imager::Matrix2d object by a 9 element array ref or a number.
    https://rt.cpan.org/Ticket/Display.html?id=29938
 
 Imager 0.80 - 17 Jan 2011
index 49984c5cfe677c3ba74f2834b21e358fafe34a84..d44e3b0aed26c44899279f1ceda813889a812505 100644 (file)
@@ -1,6 +1,8 @@
 package Imager::Matrix2d;
 use strict;
 use vars qw($VERSION);
+use Scalar::Util qw(reftype looks_like_number);
+use Carp qw(croak);
 
 $VERSION = "1.009";
 
@@ -264,28 +266,41 @@ Currently both the left and right-hand sides of the operator must be
 an Imager::Matrix2d.
 
 =cut
+
 sub _mult {
   my ($left, $right, $order) = @_;
 
-  if (ref($right) && UNIVERSAL::isa($right, __PACKAGE__)) {
-    if ($order) {
-      ($left, $right) = ($right, $left);
-    }
-    my @result;
-    for my $i (0..2) {
-      for my $j (0..2) {
-        my $accum = 0;
-        for my $k (0..2) {
-          $accum += $left->[3*$i + $k] * $right->[3*$k + $j];
-        }
-        $result[3*$i+$j] = $accum;
+  if (ref($right)) {
+    if (reftype($right) eq "ARRAY") {
+      @$right == 9
+       or croak "9 elements required in array ref";
+      if ($order) {
+       ($left, $right) = ($right, $left);
       }
+      my @result;
+      for my $i (0..2) {
+       for my $j (0..2) {
+         my $accum = 0;
+         for my $k (0..2) {
+           $accum += $left->[3*$i + $k] * $right->[3*$k + $j];
+         }
+         $result[3*$i+$j] = $accum;
+       }
+      }
+      return bless \@result, __PACKAGE__;
+    }
+    else {
+      croak "multiply by array ref or number";
     }
+  }
+  elsif (defined $right && looks_like_number($right)) {
+    my @result = map $_ * $right, @$left;
+
     return bless \@result, __PACKAGE__;
   }
   else {
-    # presumably N * matrix or matrix * N
-    return undef; # for now
+    # something we don't handle
+    croak "multiply by array ref or number";
   }
 }
 
index e6c23e2508da2a18ee3d858277de22c1de57a2dc..460460291339d72c4867b5f8115b78182e9afe33 100644 (file)
@@ -1,6 +1,6 @@
 #!perl -w
 use strict;
-use Test::More tests => 13;
+use Test::More tests => 23;
 use Imager;
 
 BEGIN { use_ok('Imager::Matrix2d', ':handy') }
@@ -54,6 +54,61 @@ ok($trans_called, "translate called on rotate with just y");
 ok(!Imager::Matrix2d->matrix(), "bad custom matrix");
 is(Imager->errstr, "9 co-efficients required", "check error");
 
+{
+  my @half = ( 0.5, 0, 0,
+              0, 0.5, 0,
+              0, 0, 1 );
+  my @quart = ( 0, 0.25, 0,
+               1, 0, 0,
+               0, 0, 1 );
+  my $half_matrix = Imager::Matrix2d->matrix(@half);
+  my $quart_matrix = Imager::Matrix2d->matrix(@quart);
+  my $result = $half_matrix * $quart_matrix;
+  is_deeply($half_matrix * \@quart, $result, "mult by unblessed matrix");
+  is_deeply(\@half * $quart_matrix, $result, "mult with unblessed matrix");
+
+  my $half_three = Imager::Matrix2d->matrix(1.5, 0, 0, 0, 1.5, 0, 0, 0, 3);
+  is_deeply($half_matrix * 3, $half_three, "mult by three");
+  is_deeply(3 * $half_matrix, $half_three, "mult with three");
+
+  {
+    # check error handling - bad ref type
+    my $died = 
+      !eval {
+      my $foo = $half_matrix * +{};
+      1;
+    };
+    ok($died, "mult by hash ref died");
+    like($@, qr/multiply by array ref or number/, "check message");
+  }
+
+  {
+    # check error handling - bad array
+    $@ = '';
+    my $died = 
+      !eval {
+      my $foo = $half_matrix * [ 1 .. 8 ];
+      1;
+    };
+    ok($died, "mult by short array ref died");
+    like($@, qr/9 elements required in array ref/, "check message");
+  }
+
+  {
+    # check error handling - bad value
+    $@ = '';
+    my $died = 
+      !eval {
+      my $foo = $half_matrix * "abc";
+      1;
+    };
+    ok($died, "mult by bad scalar died");
+    like($@, qr/multiply by array ref or number/, "check message");
+  }
+  
+}
+
+
 sub almost_equal {
   my ($m1, $m2) = @_;