package RadioMobile::Utils::Matrix;
our $VERSION = '0.10';
use strict;
use warnings;
use Data::Dumper;
use Array::AsObject;
use Class::Container;
use Params::Validate qw(:types);
use base qw(Class::Container);
__PACKAGE__->valid_params (
rowsSize => {type=>SCALAR, optional => 1},
colsSize => {type=>SCALAR, optional => 1},
);
use Class::MethodMaker [scalar => [qw/data cols rows/]];
sub new {
my $package = shift;
my $s = $package->SUPER::new(@_);
$s->_init(@_);
return $s;
}
sub _init {
my $s = shift;
$s->{rows} = new Array::AsObject();
#my $singleCell = new Array::AsObject();
#$s->rows->set(0,$singleCell);
my %p = @_;
$s->rowsCount($p{rowsSize}) if ($p{rowsSize});
$s->colsCount($p{colsSize}) if ($p{colsSize});
}
sub at {
my $s = shift;
my $row = shift;
my $col = shift;
if (@_) {
my $v = shift;
$s->rowsCount($row+1) if ($row+1 > $s->rowsCount);
$s->colsCount($col+1) if ($col+1 > $s->colsCount);
$s->rows->at($row)->set($col,$v)
}
return undef unless ($s->rows->at($row));
return $s->rows->at($row)->at($col);
}
sub size {
my $s = shift;
if (@_) {
my $newRowsCount = shift;
my $newColsCount = shift;
$s->rowsCount($newRowsCount);
$s->colsCount($newColsCount);
}
return ($s->rowsCount,$s->colsCount);
}
sub length {
my $s = shift;
my @s = $s->size;
return $s[0] * $s[1];
}
sub rowsCount {
my $s = shift;
if (@_) {
my $newSize = shift;
my $diff = $newSize - $s->rows->length;
if ($diff > 0) {
$s->rows->push($s->_newRow) foreach (1..$diff);
} elsif ($diff <0) {
$s->rows->pop foreach (1..$diff);
}
}
return $s->rows->length;
}
sub colsCount {
my $s = shift;
if (@_) {
my $newSize = shift;
my $diff = $newSize - $s->rows->at(0)->length;
if ($diff > 0) {
my @push;
push @push, undef foreach (1..$diff);
foreach (0..$s->rowsCount-1) {
$s->rows->at($_)->push(@push);
}
} elsif ($diff <0) {
foreach (0..$s->rowsCount-1) {
$s->rows->at($_)->pop foreach (1..$diff);
}
}
}
return $s->rows->length == 0 ? 0 : $s->rows->at(0)->length;
}
sub setRow {
my $s = shift;
my $i = shift;
my @d = @_;
$s->colsCount(scalar(@d)) if (scalar(@d) > $s->colsCount);
$s->rows->at($i)->set($_,$d[$_]) foreach(0..scalar(@d)-1);
}
sub addRow {
my $s = shift;
my @d = @_;
$s->rowsCount($s->rowsCount+1);
$s->setRow(-1,@d);
}
sub setCol {
my $s = shift;
my $i = shift;
my @d = @_;
$s->rowsCount(scalar(@d)) if (scalar(@d) > $s->rowsCount);
$s->rows->at($_)->set($i,$d[$_]) foreach(0..scalar(@d)-1);
}
sub addCol {
my $s = shift;
my @d = @_;
$s->colsCount($s->colsCount+1);
$s->setCol(-1,@d);
}
sub _newRow {
my $s = shift;
my $r = new Array::AsObject;
$r->fill(undef,0,$s->colsCount);
return $r;
}
sub getRow {
my $s = shift;
my $i = shift;
return $s->rows->at($i)->list;
}
sub getCol {
my $s = shift;
my $i = shift;
my @ret;
push @ret, $s->rows->at($_)->at($i) foreach(0..$s->rowsCount-1);
return @ret;
}
sub dump {
my $s = shift;
my $ret = '';
foreach (0..$s->rowsCount-1) {
my @row = $s->rows->at($_)->list;
@row = map(defined $_ ? $_ : '',@row);
$ret .= '| ' . join(' | ',@row) . " |\n";
}
return $ret;
}
1;
__END__