1- /* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.c,v 1.14 2008/04/20 01:05:52 tgl Exp $ */
1+ /* $PostgreSQL: pgsql/contrib/earthdistance/earthdistance.c,v 1.15 2008/04/21 01:11:43 tgl Exp $ */
22
33#include "postgres.h"
44
@@ -17,10 +17,6 @@ PG_MODULE_MAGIC;
1717static const double EARTH_RADIUS = 3958.747716 ;
1818static const double TWO_PI = 2.0 * M_PI ;
1919
20- PG_FUNCTION_INFO_V1 (geo_distance );
21-
22- Datum geo_distance (PG_FUNCTION_ARGS );
23-
2420
2521/******************************************************
2622 *
@@ -37,26 +33,22 @@ degtorad(double degrees)
3733return (degrees /360.0 )* TWO_PI ;
3834}
3935
40-
4136/******************************************************
4237 *
43- *geo_distance - distance between points
38+ *geo_distance_internal - distance between points
4439 *
4540 * args:
4641 * a pair of points - for each point,
4742 * x-coordinate is longitude in degrees west of Greenwich
4843 * y-coordinate is latitude in degrees above equator
4944 *
50- * returns:float8
45+ * returns:double
5146 * distance between the points in miles on earth's surface
5247 ******************************************************/
5348
54- Datum
55- geo_distance ( PG_FUNCTION_ARGS )
49+ static double
50+ geo_distance_internal ( Point * pt1 , Point * pt2 )
5651{
57- Point * pt1 = PG_GETARG_POINT_P (0 );
58- Point * pt2 = PG_GETARG_POINT_P (1 );
59- float8 result ;
6052double long1 ,
6153lat1 ,
6254long2 ,
@@ -81,7 +73,57 @@ geo_distance(PG_FUNCTION_ARGS)
8173cos (lat1 )* cos (lat2 )* sin (longdiff /2. )* sin (longdiff /2. ));
8274if (sino > 1. )
8375sino = 1. ;
84- result = 2. * EARTH_RADIUS * asin (sino );
8576
77+ return 2. * EARTH_RADIUS * asin (sino );
78+ }
79+
80+
81+ /******************************************************
82+ *
83+ * geo_distance - distance between points
84+ *
85+ * args:
86+ * a pair of points - for each point,
87+ * x-coordinate is longitude in degrees west of Greenwich
88+ * y-coordinate is latitude in degrees above equator
89+ *
90+ * returns: float8
91+ * distance between the points in miles on earth's surface
92+ *
93+ * If float8 is passed-by-value, the oldstyle version-0 calling convention
94+ * is unportable, so we use version-1. However, if it's passed-by-reference,
95+ * continue to use oldstyle. This is just because we'd like earthdistance
96+ * to serve as a canary for any unintentional breakage of version-0 functions
97+ * with float8 results.
98+ ******************************************************/
99+
100+ #ifdef USE_FLOAT8_BYVAL
101+
102+ Datum geo_distance (PG_FUNCTION_ARGS );
103+ PG_FUNCTION_INFO_V1 (geo_distance );
104+
105+ Datum
106+ geo_distance (PG_FUNCTION_ARGS )
107+ {
108+ Point * pt1 = PG_GETARG_POINT_P (0 );
109+ Point * pt2 = PG_GETARG_POINT_P (1 );
110+ float8 result ;
111+
112+ result = geo_distance_internal (pt1 ,pt2 );
86113PG_RETURN_FLOAT8 (result );
87114}
115+
116+ #else /* !USE_FLOAT8_BYVAL */
117+
118+ double * geo_distance (Point * pt1 ,Point * pt2 );
119+
120+ double *
121+ geo_distance (Point * pt1 ,Point * pt2 )
122+ {
123+ double * resultp = palloc (sizeof (double ));
124+
125+ * resultp = geo_distance_internal (pt1 ,pt2 );
126+ return resultp ;
127+ }
128+
129+ #endif /* USE_FLOAT8_BYVAL */