The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

Matrix2

2*2 matrix manipulation

PhilipRBrenan@yahoo.com, 2004, Perl License

Synopsis

Example t/matrix2.t

 #_ Matrix _____________________________________________________________
 # Test 2*2 matrices    
 # philiprbrenan@yahoo.com, 2004, Perl License    
 #______________________________________________________________________
 
 use Math::Zap::Matrix2 identity=>i;
 use Math::Zap::Vector2;
 use Test::Simple tests=>8;
 
 my ($a, $b, $c, $v);
 
 $a = matrix2
  (8, 0,
   0, 8,
  );
 
 $b = matrix2
  (4, 2,
   2, 4,
  );
 
 $c = matrix2
  (2, 2,
   1, 2,
  );
 
 $v = vector2(1,2);
 
 ok($a/$a           == i());
 ok($b/$b           == i());
 ok($c/$c           == i());
 ok(2/$a*$a/2       == i());
 ok(($a+$b)/($a+$b) == i());
 ok(($a-$c)/($a-$c) == i());
 ok(-$a/-$a         == i());
 ok(1/$a*($a*$v)    == $v);
 

Description

2*2 matrix manipulation

 package Math::Zap::Matrix2;
 $VERSION=1.07;
 use Math::Zap::Vector2 check=>'vector2Check', is=>'vector2Is';
 use Carp;
 use constant debug => 0; # Debugging level
 
 

Constructors

new

Create a matrix

 sub new($$$$)
  {my
   ($a11, $a12,
    $a21, $a22,
   ) = @_;
 
   my $m = round(bless(
    {11=>$a11, 12=>$a12,
     21=>$a21, 22=>$a22,
    }));
   singular($m, 1);
   $m;
  }
 
 

matrix2

Create a matrix. Synonym for "new".

 sub matrix2($$$$)
  {new($_[0],$_[1],$_[2],$_[3]);
  }
 
 

identity

Identity matrix

 sub identity()
  {bless
    {11=>1, 21=>0,                              
     12=>0, 22=>1,                              
    }; 
  }
 
 

new2v

Create a matrix from two vectors

 sub new2v($$)
  {vector2Check(@_) if debug;
   my ($a, $b, $c) =  @_;
   my $m = round(bless(
    {11=>$a->{x}, 12=>$b->{x},
     21=>$a->{y}, 22=>$b->{y},
    }));
   singular($m, 1);
   $m;
  }
 
 

Methods

check

Check its a matrix

 sub check(@)
  {if (debug)
    {for my $m(@_)
      {confess "$m is not a matrix2" unless ref($m) eq __PACKAGE__;
      } 
    }
   return (@_)
  }
 
 

is

Test its a matrix

 sub is(@)
  {for my $m(@_)
    {return 0 unless ref($m) eq __PACKAGE__;
    }
   'matrix2';
  }
 
 

accuracy

Get/Set accuracy

 my $accuracy = 1e-10;
 
 sub accuracy
  {return $accuracy unless scalar(@_);
   $accuracy = shift();
  }
 
 

round

Round: round to nearest integer if within accuracy of that integer

 sub round($)
  {unless (debug)
    {return $_[0];
    }
   else
    {my ($a) = @_;
     for my $k(keys(%$a))
      {my $n = $a->{$k};
       my $N = int($n);
       $a->{$k} = $N if abs($n-$N) < $accuracy;
      }
     return $a;
    }
  }
 
 

singular

Singular matrix?

 sub singular($$)
  {my $m = shift;  # Matrix   
   my $a = 1e-2;   # Accuracy
   my $A = shift;  # Action 0: return indicator, 1: confess 
   my $n = abs
     ($m->{11} * $m->{22} -                                        
      $m->{12} * $m->{21})
     < $a;
   confess "Singular matrix2" if $n and $A;
   $n;      
  }
 
 

clone

Create a matrix from another matrix

 sub clone($)
  {my ($m) = check(@_); # Matrix
   round bless
    {11=>$m->{11}, 12=>$m->{12},
     21=>$m->{21}, 22=>$m->{22},
    }; 
  }
 
 

print

Print matrix

 sub print($)
  {my ($m) = check(@_); # Matrix 
   'matrix2('.$m->{11}.', '.$m->{12}. 
         ', '.$m->{21}.', '.$m->{22}.
   ')';
  } 
 
 

add

Add matrices

 sub add($$)
  {my ($a, $b) = check(@_); # Matrices
   my $m = round bless
    {11=>$a->{11}+$b->{11}, 12=>$a->{12}+$b->{12}, 
     21=>$a->{21}+$b->{21}, 22=>$a->{22}+$b->{22}, 
    }; 
   singular($m, 1);
   $m;
  }
 
 

negate

Negate matrix

 sub negate($)
  {my ($a) = check(@_); # Matrices
   my $m = round bless
    {11=>-$a->{11}, 12=>-$a->{12},
     21=>-$a->{21}, 22=>-$a->{22},
    }; 
   singular($m, 1);
   $m;
  }
 
 

subtract

Subtract matrices

 sub subtract($$)
  {my ($a, $b) = check(@_); # Matrices
   my $m = round bless
    {11=>$a->{11}-$b->{11}, 12=>$a->{12}-$b->{12},
     21=>$a->{21}-$b->{21}, 22=>$a->{22}-$b->{22},
    }; 
   singular($m, 1);
   $m;
  }
 
 

matrixVectorMultiply

Vector = Matrix * Vector

 sub matrixVectorMultiply($$)
  {       check(@_[0..0]) if debug; # Matrix
   vector2Check(@_[1..1]) if debug; # Vector 
   my ($a, $b) = @_;
   vector2
    ($a->{11}*$b->{x}+$a->{12}*$b->{y},
     $a->{21}*$b->{x}+$a->{22}*$b->{y},
    );
  }
 
 

matrixScalarMultiply

Matrix = Matrix * scalar

 sub matrixScalarMultiply($$)
  {my ($a) = check(@_[0..0]); # Matrix
   my ($b) = @_[1..1];        # Scalar
   confess "$b is not a scalar" if ref($b);   
   round bless
    {11=>$a->{11}*$b, 12=>$a->{12}*$b,
     21=>$a->{21}*$b, 22=>$a->{22}*$b,
    }; 
  }
 
 

matrixMatrixMultiply

Matrix = Matrix * Matrix

 sub matrixMatrixMultiply($$)
  {my ($a, $b) = check(@_); # Matrices
   round bless
    {11=>$a->{11}*$b->{11}+$a->{12}*$b->{21}, 12=>$a->{11}*$b->{12}+$a->{12}*$b->{22},
     21=>$a->{21}*$b->{11}+$a->{22}*$b->{21}, 22=>$a->{21}*$b->{12}+$a->{22}*$b->{22},
    }; 
  }
 
 

matrixScalarDivide

Matrix=Matrix / non zero scalar

 sub matrixScalarDivide($$)
  {my ($a) = check(@_[0..0]); # Matrices
   my ($b) = @_[1..1];        # Scalar
   confess "$b is not a scalar" if ref($b);   
   confess "$b is zero"         if $b == 0;   
   round bless
    {11=>$a->{11}/$b, 12=>$a->{12}/$b,
     21=>$a->{21}/$b, 22=>$a->{22}/$b,
    }; 
  }
 
 

det

Determinant of matrix.

 sub det($)
  {my ($a) = check(@_); # Matrices
 
 +$a->{11}*$a->{22}
 -$a->{12}*$a->{21}
  }
 
 

inverse

Inverse of matrix

 sub inverse($)
  {my ($a) = check(@_); # Matrices
 
   my $d = det($a);
   return undef if $d == 0;
 
   round bless
    {11=> $a->{22}/$d, 21=>-$a->{21}/$d,
     12=>-$a->{12}/$d, 22=> $a->{11}/$d,
    }; 
  }
 
 

rotate

Rotation matrix: rotate anti-clockwise by t radians

 sub rotate($)
  {my ($a) = @_;
    bless
    {11=>cos($t), 21=>-sin($t),                              
     12=>sin($t), 22=> cos($t),                              
    }; 
  }
 
 

equals

Equals to within accuracy

 sub equals($$)
  {my ($a, $b) = check(@_); # Matrices
   abs($a->{11}-$b->{11}) < $accuracy and
   abs($a->{12}-$b->{12}) < $accuracy and
 
   abs($a->{21}-$b->{21}) < $accuracy and
   abs($a->{22}-$b->{22}) < $accuracy;
  }
 
 

Operators

Operator overloads

 use overload
  '+'        => \&add3,      # Add two vectors
  '-'        => \&subtract3, # Subtract one vector from another
  '*'        => \&multiply3, # Times by a scalar, or vector dot product 
  '/'        => \&divide3,   # Divide by a scalar
  '!'        => \&det3,      # Determinant                       
  '=='       => \&equals3,   # Equals (to accuracy)
  '""'       => \&print3,    # Print
  'fallback' => FALSE;
 
 

add operator

Add operator.

 sub add3
  {my ($a, $b) = @_;
   $a->add($b);
  }
 
 

subtract operator

Subtract operator.

 sub subtract3
  {my ($a, $b, $c) = @_;
 
   return $a->subtract($b) if $b;
   negate($a);
  }
 
 

multiply operator

Multiply operator.

 sub multiply3
  {my ($a, $b) = @_;
   return $a->matrixScalarMultiply($b) unless ref($b);
   return $a->matrixVectorMultiply($b) if vector2Is($b);
   return $a->matrixMatrixMultiply($b) if is($b);
   confess "Cannot multiply $a by $b\n";
  }
 
 

divide operator

Divide operator.

 sub divide3
  {my ($a, $b, $c) = @_;
   if (!ref($b))
    {return $a->matrixScalarDivide($b)            unless $c;
     return $a->inverse->matrixScalarMultiply($b) if     $c;
    }
   else 
    {return $a->inverse->matrixVectorMultiply($b) if vector2Is($b);
     return $a->matrixMatrixMultiply($b->inverse) if is($b);
     confess "Cannot multiply $a by $b\n";
    }
  }
 
 

equals operator

Equals operator.

 sub equals3
  {my ($a, $b, $c) = @_;
   return $a->equals($b);
  }
 
 

determinant operator

Determinant of a matrix

 sub det3
  {my ($a, $b, $c) = @_;
   $a->det;
  }
 
 

Print a vector.

 sub print3
  {my ($a) = @_;
   return $a->print;
  }
 
 

Exports

Export "matrix2", "identity"

 use Math::Zap::Exports qw(
   matrix2  ($$$$)
   new2v    ($$)
   identity ()
  );
 
 #_ Matrix2 ____________________________________________________________
 # Package loaded successfully
 #______________________________________________________________________
 
 1;
 
 

Credits

Author

philiprbrenan@yahoo.com

philiprbrenan@yahoo.com, 2004

License

Perl License.