# -*- Perl -*- use strict; use warnings; package Matrix; use Scalar::Util qw/refaddr/; use Data::Dumper; use base 'Exporter'; our @EXPORT='matrix'; use overload '*' => sub { $_[0]->mult($_[1]) }, '*=' => sub { $_[0]->multby($_[1]) }, '**' => sub { $_[0]->pow($_[1]) }; sub matrix { Matrix->new(@_) } sub mkaoa { [[ @_[0,1] ], [ @_[2,3] ]] } { my %entry; sub entry : lvalue { my $id=refaddr shift; @_==0 ? $entry{$id} : @_==1 ? $entry{$id}[ $_[0] ] : $entry{$id}[ $_[0] ][ $_[1] ]; } sub DESTROY { delete $entry{refaddr shift} } } sub new { my $class = shift; my $self; $self = sub : lvalue { $self->entry(@_) }; bless($self => $class)->init(@_); } sub init { my $obj=shift; $obj->() = mkaoa @_; $obj; } sub _mult { my ($s,$o)=@_; $s->(0,0)*$o->(0,0) + $s->(0,1)*$o->(1,0), $s->(0,0)*$o->(0,1) + $s->(0,1)*$o->(1,1), $s->(1,0)*$o->(0,0) + $s->(1,1)*$o->(1,0), $s->(1,0)*$o->(0,1) + $s->(1,1)*$o->(1,1); } sub mult { my ($s,$o)=@_; matrix $s->_mult($o) } sub multby { my ($s,$o)=@_; $s->() = mkaoa $s->_mult($o); $s; } sub pow { my ($self, $pow)=@_; my $out=matrix 1,0,0,1; $out->multby($self) for 1..$pow; $out; } 1; __END__