Geo-Distance-XS
view release on metacpan or search on metacpan
- Remove deprecated usage defined(@array) from a test case.
- Optimized the case where both coordinates are identical.
- Updated ppport.h.
0.11 Sat Apr 14 03:45:08 UTC 2012
- Adjusted constants for better accuracy.
0.10 Fri Apr 13 11:57:14 UTC 2012
- Fixed floating point errors.
- Fixed for antipodal coordinates.
- Fixed formulas for use with multiple Geo::Distance objects.
- Added new formula- alt: Andoyer-Lambert-Thomas.
- Updated benchmarks.
0.09 Mon Aug 1 21:49:37 UTC 2011
- Required XSLoader; stopped falling back to DynaLoader.
0.08 Fri Oct 22 03:44:02 UTC 2010
- Added GIS::Distance::Fast to the benchmark.
0.07 Fri Oct 16 17:00:29 UTC 2009
- RT #50545: Set minimum required version of Geo::Distance to 0.16.
NV lat1
NV lon2
NV lat2
PREINIT:
SV **key;
int index = 1;
double (*func)(double, double, double, double);
CODE:
if (lat2 == lat1 && lon2 == lon1)
XSRETURN_NV(0.);
key = hv_fetchs((HV *)SvRV(self), "formula_index", 0);
if (key) index = SvIV(*key);
switch (index) {
case 1: func = &haversine; break;
case 2: func = &cosines; break;
case 3: func = &vincenty; break;
case 4: func = &great_circle; break;
case 5: func = &polar; break;
case 6: func = &andoyer_lambert_thomas; break;
}
XSRETURN_NV(_count_units(self, unit) * (*func)(lat1, lon1, lat2, lon2));
ex/benchmark.pl view on Meta::CPAN
sub geo {
my $d = $geo->distance(mile => @coord);
}
sub gis {
# Uses lat/lon instead of lon/lat
my $d = $gis->distance(@coord[ 1, 0, 3, 2 ]);
return $d->mile;
}
my %gis_formula = (
hsin => 'Haversine',
polar => 'Polar',
cos => 'Cosine',
gcd => 'GreatCircle',
mt => 'MathTrig',
tv => 'Vincenty',
);
for my $formula (qw(hsin tv polar cos gcd mt)) {
print "---- [ Formula: $formula ] ------------------------------------\n";
$geo->formula($formula);
$gis->formula($gis_formula{$formula});
Geo::Distance::XS->unimport;
printf "perl - distance from LA to NY: %s miles\n", geo();
Geo::Distance::XS->import;
printf "xs - distance from LA to NY: %s miles\n", geo();
printf "gis_fast - distance from LA to NY: %s miles\n", gis();
print "\n";
ex/benchmark2.pl view on Meta::CPAN
);
my @coords = (
[ -118.6414, 34.3502, -117.9739, 34.1607 ],
[ -118.243103, 34.159545, -73.987427, 40.853293 ],
[ 0., 0., -179., 1. ],
[ 175., 12., -5., -12. ],
[ 0., 90., 0., -90. ],
);
my %geos;
my @formulas = @Geo::Distance::XS::FORMULAS;
my $max_name_len = 0;
for my $f (@formulas) {
my $geo = Geo::Distance->new;
$geo->formula($f);
$geos{$f} = sub { $geo->distance(mile => @$_) for @coords };
$max_name_len = max $max_name_len, length($f);
}
cmpthese - 1, \%geos;
print "\n";
for my $idx (0 .. $#tests) {
print "Calculated length for $tests[$idx]:\n";
for my $f (@formulas) {
my $geo = Geo::Distance->new;
$geo->formula($f);
my $d = $geo->distance(mile => @{$coords[$idx]});
printf " %-*s: %s miles\n", $max_name_len, $f, $d;
}
print "\n";
}
lib/Geo/Distance/XS.pm view on Meta::CPAN
use Carp qw(croak);
use Geo::Distance;
use XSLoader;
our $VERSION = '0.13';
our $XS_VERSION = $VERSION;
$VERSION = eval $VERSION;
XSLoader::load(__PACKAGE__, $XS_VERSION);
my ($orig_distance_sub, $orig_formula_sub);
BEGIN {
$orig_distance_sub = \&Geo::Distance::distance;
$orig_formula_sub = \&Geo::Distance::formula;
}
my %formulas; @formulas{qw(hsin cos mt tv gcd polar alt)} = (1, 2, 2..6);
our @FORMULAS = sort keys %formulas;
sub import {
no warnings qw(redefine);
no strict qw(refs);
*Geo::Distance::distance = \&{__PACKAGE__.'::distance'};
*Geo::Distance::formula = sub {
my $self = shift;
if (@_) {
my $formula = shift;
croak "Invalid formula: $formula"
unless exists $formulas{$formula};
$self->{formula} = $formula;
$self->{formula_index} = $formulas{$formula};
}
return $self->{formula};
};
}
# Fall back to pure perl after calling 'no Geo::Distance::XS'.
sub unimport {
no warnings qw(redefine);
*Geo::Distance::formula = $orig_formula_sub;
*Geo::Distance::distance = $orig_distance_sub;
}
1;
__END__
=head1 NAME
lib/Geo/Distance/XS.pm view on Meta::CPAN
The C<Geo::Distance::XS> module provides faster C implementations of the
distance calculations found in C<Geo::Distance>. See the documentation for
that module for usage.
NOTE: As of version 0.13, Geo::Distance automatically uses this module if
it is installed.
=head1 FORMULAS
In addition to the formulas offered in C<Geo::Distance>, this module
implements the additional formulas:
=head2 alt: Andoyer-Lambert-Thomas Formula
This is faster than the Vincenty formula, but trades a bit of accuracy.
=head1 PERFORMANCE
This distribution contains a benchmarking script which compares
C<Geo::Distance::XS> with C<Geo::Distance> and C<GIS::Distance::Fast>. These
are the results on a MacBook 2GHz with Perl 5.14.2:
---- [ Formula: hsin ] ------------------------------------
perl - distance from LA to NY: 2443.08796228363 miles
xs - distance from LA to NY: 2443.08796228363 miles
lib/Geo/Distance/XS.pm view on Meta::CPAN
perl - distance from LA to NY: 2443.08796228363 miles
xs - distance from LA to NY: 2443.08796228363 miles
gis_fast - distance from LA to NY: 2443.08796228363 miles
Rate gis_fast perl xs
gis_fast 17935/s -- -75% -98%
perl 71739/s 300% -- -94%
xs 1135525/s 6231% 1483% --
This distribution contains another benchmarking script which compares
only the XS formulas over several different coordinates:
Rate tv hsin alt cos mt gcd polar
tv 16906/s -- -90% -90% -91% -91% -91% -92%
hsin 165414/s 878% -- -4% -8% -10% -13% -17%
alt 172032/s 918% 4% -- -5% -7% -9% -14%
cos 180326/s 967% 9% 5% -- -2% -5% -10%
mt 184357/s 991% 11% 7% 2% -- -3% -8%
gcd 189253/s 1019% 14% 10% 5% 3% -- -6%
polar 200386/s 1085% 21% 16% 11% 9% 6% --
use strict;
use warnings;
use Geo::Distance::XS;
use Test::More;
my $geo = Geo::Distance->new;
isa_ok $geo, 'Geo::Distance', 'new';
can_ok 'Geo::Distance', qw(distance formula);
cmp_ok scalar @Geo::Distance::XS::FORMULAS, '>', 2, '@FORMULAS exists';
done_testing;
t/03_methods.t view on Meta::CPAN
use strict;
use warnings;
use Geo::Distance::XS;
use Test::More;
my @formulas = @Geo::Distance::XS::FORMULAS;
for my $f (@formulas) {
my $geo = Geo::Distance->new;
$geo->formula($f);
my @coords = (-118.243103, 34.159545, -73.987427, 40.853293);
my %expected = (
map({ $_ => 2443 } @formulas), polar => 2766, tv => 2448, alt => 2448,
);
my $d = $geo->distance(mile => @coords);
is int $d, $expected{$f}, "$f: distance from LA to NY";
@coords = (175, 12, -5, -12);
$d = $geo->distance(mile => @coords);
ok $d == $d, "$f with antipodal coordinates is not NaN";
}
done_testing;
( run in 0.324 second using v1.01-cache-2.11-cpan-3cd7ad12f66 )