I don't understand your (($x^$y)<0).
Using
sub andNeg {
return (($_[0]^$_[1]) < 0);
}
and test harness
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), spaceshi
+p($x, $y), mult($x, $y), anchor($x, $y)), "</td></tr>\n";
}
print "</table>\n";
I get
x | y | xorNeg() | spaceship() | mult() | anchor() |
1 | 1 | | 1 | 1 | 1 |
-1 | 1 | | | | 0 |
1 | -1 | | | | 0 |
-1 | -1 | | 1 | 1 | 1 |
As for spaceship, multiplication, and logic, implemented as
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;
}
I get
unit square | spaceship | multiply | logic |
spaceship | -------- | worse 22.28% | worse 10.40% |
multiply | better 22.28% | -------- | better 13.26% |
logic | better 10.40% | worse 13.26% | -------- |
and
signed int | spaceship | multiply | logic |
spaceship | -------- | worse 21.43% | worse 7.65% |
multiply | better 21.43% | -------- | better 14.92% |
logic | better 7.65% | worse 14.92% | -------- |
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.
full test program (don't use this use Benchmark; instead)
#!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), spaceshi
+p($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), p
+retty($spaceship,$logic)), "\n";
print join("\t", "multiply ", pretty($multiple,$spaceship), '-'x8, p
+retty($multiple,$logic)), "\n";
print join("\t", "logic ", pretty($logic,$spaceship), pretty($log
+ic,$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;
}