note
WoodyWeaver
I don't understand your (($x^$y)<0).<p />
Using
<code>
sub andNeg {
return (($_[0]^$_[1]) < 0);
}
</code>
and test harness
<code>
print "<table border>\n<tr><td>", join("</td><td>", "x", "y", "andNeg()", "spaceship()", "mult()", "anchor()"), "</td></tr>\n";
for (0..3) {
my $x = 1 - 2 * ($_ % 2);
my $y = 1 - 2 * int($_ / 2);
print "<tr><td>", join("</td><td>", $x, $y, andNeg($x, $y), spaceship($x, $y), mult($x, $y), anchor($x, $y)), "</td></tr>\n";
}
print "</table>\n";
</code>
I get
<table border>
<tr><td>x</td><td>y</td><td>xorNeg()</td><td>spaceship()</td><td>mult()</td><td>anchor()</td></tr>
<tr><td>1</td><td>1</td><td></td><td>1</td><td>1</td><td>1</td></tr>
<tr><td>-1</td><td>1</td><td></td><td></td><td></td><td>0</td></tr>
<tr><td>1</td><td>-1</td><td></td><td></td><td></td><td>0</td></tr>
<tr><td>-1</td><td>-1</td><td></td><td>1</td><td>1</td><td>1</td></tr>
</table>
As for spaceship, multiplication, and logic, implemented as
<code>
sub spaceship {
(0 <=> $_[0]) == (0<=> $_[1]);
}
sub mult {
$_[0]*$_[1] > 0;
}
sub anchor {
if ($_[0] > 0) {
if ($_[1] > 0) { # both pos
return 1
}
} elsif ($_[0] < 0) {
if ($_[1] < 0) { # both neg
return 1
}
}
return 0;
}
</code>
I get
<table border>
<tr><td>unit square</td><td>spaceship</td><td>multiply</td><td>logic</td></tr>
<tr><td>spaceship</td><td>--------</td><td>worse 22.28%</td><td>worse 10.40%</td></tr>
<tr><td>multiply </td><td>better 22.28%</td><td>--------</td><td>better 13.26%</td></tr>
<tr><td>logic </td><td>better 10.40%</td><td>worse 13.26%</td><td>--------</td></tr>
</table>
and
<table border>
<tr><td>signed int</td><td>spaceship</td><td>multiply</td><td>logic</td></tr>
<tr><td>spaceship</td><td>--------</td><td>worse 21.43%</td><td>worse 7.65%</td></tr>
<tr><td>multiply </td><td>better 21.43%</td><td>--------</td><td>better 14.92%</td></tr>
<tr><td>logic </td><td>better 7.65%</td><td>worse 14.92%</td><td>--------</td></tr>
</table>
that is, if you take points (x,y) uniformly chosen from the unit disk [-1,1]x[-1,1], then spaceship is 22% worse than testing multiplication, multiplication is 13% better than using logic, etc; and if you take them as random unsigned ints, multiplication is (surprisingly!) even better.
<p />
full test program (don't use this use Benchmark; instead)
<readmore>
<code>
#!perl -w
#
use Time::HiRes qw(time);
print "<table border>\n<tr><td>", join("</td><td>", "x", "y", "andNeg()", "spaceship()", "mult()", "anchor()"), "</td></tr>\n";
for (0..3) {
my $x = 1 - 2 * ($_ % 2);
my $y = 1 - 2 * int($_ / 2);
print "<tr><td>", join("</td><td>", $x, $y, andNeg($x, $y), spaceship($x, $y), mult($x, $y), anchor($x, $y)), "</td></tr>\n";
}
print "</table>\n";
my $count = 1000000;
for ('unit square', 'signed int') {
doTimeTest($count, $_);
}
sub doTimeTest {
my $count = shift;
my $type = shift;
my @coordinates = primeCoordinates($count, $type );
my $time0 = Time::HiRes::time();
foreach (@coordinates) {
spaceship($_->[0],$_->[1]);
}
my $time1 = Time::HiRes::time();
foreach (@coordinates) {
mult($_->[0], $_->[1]);
}
my $time2 = Time::HiRes::time();
foreach (@coordinates) {
anchor($_->[0], $_->[1]);
}
my $time3 = Time::HiRes::time;
my $spaceship = $time1 - $time0;
my $multiple = $time2 - $time1;
my $logic = $time3 - $time2;
print join("\t", $type, "spaceship", "multiply", "logic"), "\n";
print join("\t", "spaceship", '-'x8, pretty($spaceship,$multiple), pretty($spaceship,$logic)), "\n";
print join("\t", "multiply ", pretty($multiple,$spaceship), '-'x8, pretty($multiple,$logic)), "\n";
print join("\t", "logic ", pretty($logic,$spaceship), pretty($logic,$multiple), '-'x8), "\n";
print "\n";
}
sub pretty {
my ($one, $two) = @_;
if ($one > $two) {
return sprintf("worse %.2f%%", ($one - $two) / $one * 100);
} else {
return sprintf("better %.2f%%", ($two - $one) / $two * 100);
}
}
sub spaceship {
(0 <=> $_[0]) == (0<=> $_[1]);
}
sub mult {
$_[0]*$_[1] > 0;
}
sub anchor {
if ($_[0] > 0) {
if ($_[1] > 0) { # both pos
return 1
}
} elsif ($_[0] < 0) {
if ($_[1] < 0) { # both neg
return 1
}
}
return 0;
}
sub andNeg {
return (($_[0]^$_[1]) < 0);
}
sub primeCoordinates {
my $count = shift;
my $type = shift;
my @retval;
if ($type eq 'unit square') {
for (0..$count-1) {
$retval[$_] = [ 1 - 2 * rand(), 1 - 2 * rand()];
}
} elsif ($type eq 'signed int') {
use POSIX;
for (0..$count-1) {
$retval[$_] = [ rand() > 0.5 ? rand(INT_MAX) : -1 * rand(INT_MAX),
rand() > 0.5 ? rand(INT_MAX) : -1 * rand(INT_MAX)];
}
} else {
die "Blue. No yel-- Auuuuuuuugh!\n";
}
return @retval;
}
</code>
</readmore>
661623
661703