package ToyArrayFold; use Carp; # A _toy_ helper class to fold an array into what seems to be an # array of arrays (of arrays, etc), based on a list of the sizes # of each dimension. # Eg, # @array = (1..6); # $folded = ToyArrayFold->new_array(\@array, [ 2, 3 ]); # dump $folded->[0]; # [ 1 , 2 , 3 ] # dump $folded->[1]; # [ 4 , 5 , 6 ] # dump $folded->[1][0]; # 4 # dump $folded->[1][1]; # 5 # $folded->[1][1] = 50; # dump $folded->[1][1]; # 50 # # [I also have a real version of this class... somewhere...] sub new_array { my $class = shift; my @a; tie @a, $class, @_; return \@a; } sub TIEARRAY { my($class,$array,$shape,$coors_opt) = @_; bless { ARRAY => $array, SHAPE => $shape, COORS => ($coors_opt || []) }, $class; } sub FETCH { my($self,$index) = @_; my $shape = $self->{SHAPE}; my @coors = @{$self->{COORS}}; $index += $shape->[@coors] if $index < 0; croak "invalid index" if($index < 0 || $index >= $shape->[@coors]); push(@coors,$index); if(@coors < @$shape) { my @a; tie @a, ref($self), $self->{ARRAY}, $shape, \@coors; return \@a; } return $self->{ARRAY}->[ $self->_calculate_index(@coors) ]; } sub STORE { my($self,$index,$value) = @_; my $shape = $self->{SHAPE}; my @coors = @{$self->{COORS}}; $index += $shape->[@coors] if $index < 0; croak "invalid index" if($index < 0 || $index >= $shape->[@coors]); push(@coors,$index); if(@coors < @$shape) { die "Multipoint STORE not implemented by this toy."; } $self->{ARRAY}->[ $self->_calculate_index(@coors) ] = $value; } sub FETCHSIZE { my($self)= @_; my $shape = $self->{SHAPE}; my @coors = @{$self->{COORS}}; return $shape->[scalar(@coors)]; } sub _calculate_index { my($self,@coors)= @_; my $shape = $self->{SHAPE}; my @offsets; my $step = 1; for(my $i=$#$shape; $i>=0; $i--) { $offsets[$i] = $step; $step *= $shape->[$i]; } my $index = 0; for(my $i = 0; $i < @coors; $i++) { $index += $offsets[$i] * $coors[$i]; } return $index; } 1;