$ perl createblinker.pl 500000 -900000 100 >x.tmp 2>y.tmp
$ /opt/perl-5.26.0/bin/perl -I. tbench1.pl x.tmp 2 # pack i2
cell count at start = 1500000
run benchmark for 2 ticks
cell count at end = 1500000
time taken: 37 secs
time taken: 58 secs <- 32-bit Windows VM
$ /opt/perl-5.26.0/bin/perl -I. tbench1.pl x.tmp 2 # mapping
cell count at start = 1500000
run benchmark for 2 ticks
cell count at end = 1500000
time taken: 39 secs
time taken: 64 secs <- 32-bit Windows VM, applied 32-bit tip below
####
$ /opt/cperl-5.24.3c/bin/cperl -I. tbench1.pl x.tmp 2 # pack i2
cell count at start = 1500000
run benchmark for 2 ticks
cell count at end = 1500000
time taken: 37 secs
$ /opt/cperl-5.24.3c/bin/cperl -I. tbench1.pl x.tmp 2 # mapping
cell count at start = 1500000
run benchmark for 2 ticks
cell count at end = 1500000
time taken: 38 secs
##
##
bits 63-18 contains the $x value
bits 17-2 contains the $y value
bit 1 set when $y < 0
bit 0 set when $x < 0
##
##
bits 31-10 contains the $x value
bits 9-2 contains the $y value
bit 1 set when $y < 0
bit 0 set when $x < 0
##
##
package Organism;
use strict;
# use warnings;
sub _pack {
my ( $x, $y ) = @_;
# bits 0,1 negative flag for $x,$y respectively
return
( abs($x) << 18 ) + ( $x < 0 ? 1 : 0 ) +
( abs($y) << 2 ) + ( $y < 0 ? 2 : 0 );
}
sub _unpack {
my ( $n ) = @_;
# bits 0,1 negative flag for $x,$y respectively
return (
$n & 0x1 ? -($n >> 18 ) : $n >> 18,
$n & 0x2 ? -($n >> 2 & 0xFFFF) : $n >> 2 & 0xFFFF
);
}
sub count {
return scalar keys %{ shift->{Cells} };
}
# Input a list of [ x, y ] coords
sub insert_cells {
my $cells = shift->{Cells};
for my $r (@_) { $cells->{ _pack @{$r} } = undef }
}
# Return sorted list of cells in the Organism.
# Used for verification and testing the state of the organism.
sub get_live_cells {
sort { $a->[0] <=> $b->[0] || $a->[1] <=> $b->[1] }
map { [ _unpack $_ ] }
keys %{ shift->{Cells} };
}
sub tick {
my $self = shift;
my $cells = $self->{Cells};
my ( $k1, $k2, $k3, $k4, $k5, $k6, $k7, $k8,
$x0, $x1, $x2, $y0, $y1, $y2, %new_cells, %dead_cells );
for my $c (keys %{ $cells }) {
# Get the (up to 8) dead cells surrounding the cell
( $x0, $y0 ) = (
$c & 0x1 ? -($c >> 18 ) : $c >> 18,
$c & 0x2 ? -($c >> 2 & 0xFFFF) : $c >> 2 & 0xFFFF
);
( $x1, $x2, $y1, $y2 ) = ( $x0 - 1, $x0 + 1, $y0 - 1, $y0 + 1 );
$dead_cells{$_}++ for my @zcells = (
( $k1 = ( abs($x1) << 18 ) + ( $x1 < 0 ? 1 : 0 ) +
( abs($y1) << 2 ) + ( $y1 < 0 ? 2 : 0 )
) x !(exists $cells->{$k1}),
( $k2 = ( abs($x1) << 18 ) + ( $x1 < 0 ? 1 : 0 ) +
( abs($y0) << 2 ) + ( $y0 < 0 ? 2 : 0 )
) x !(exists $cells->{$k2}),
( $k3 = ( abs($x1) << 18 ) + ( $x1 < 0 ? 1 : 0 ) +
( abs($y2) << 2 ) + ( $y2 < 0 ? 2 : 0 )
) x !(exists $cells->{$k3}),
( $k4 = ( abs($x0) << 18 ) + ( $x0 < 0 ? 1 : 0 ) +
( abs($y1) << 2 ) + ( $y1 < 0 ? 2 : 0 )
) x !(exists $cells->{$k4}),
( $k5 = ( abs($x0) << 18 ) + ( $x0 < 0 ? 1 : 0 ) +
( abs($y2) << 2 ) + ( $y2 < 0 ? 2 : 0 )
) x !(exists $cells->{$k5}),
( $k6 = ( abs($x2) << 18 ) + ( $x2 < 0 ? 1 : 0 ) +
( abs($y1) << 2 ) + ( $y1 < 0 ? 2 : 0 )
) x !(exists $cells->{$k6}),
( $k7 = ( abs($x2) << 18 ) + ( $x2 < 0 ? 1 : 0 ) +
( abs($y0) << 2 ) + ( $y0 < 0 ? 2 : 0 )
) x !(exists $cells->{$k7}),
( $k8 = ( abs($x2) << 18 ) + ( $x2 < 0 ? 1 : 0 ) +
( abs($y2) << 2 ) + ( $y2 < 0 ? 2 : 0 )
) x !(exists $cells->{$k8})
);
# Check the live cell
# Note: next line equivalent to nlive == 2 || nlive == 3
@zcells == 5 || @zcells == 6 and $new_cells{$c} = undef;
}
$dead_cells{$_} == 3 and $new_cells{$_} = undef for keys %dead_cells;
$self->{Cells} = \%new_cells;
}
sub new {
my $class = shift;
my %init_self = ( Cells => {} );
bless \%init_self, $class;
}
1;