From 616ea9bb08c98f86375f9851e7e6e1d0792b7c11 Mon Sep 17 00:00:00 2001
From: Emre Hasegeli <emre@hasegeli.com>
Date: Mon, 20 Jun 2016 10:24:32 +0200
Subject: [PATCH 2/2] geo-ops-fpcomp-v02

---
 src/backend/access/gist/gistproc.c         |  102 +-
 src/backend/access/spgist/spgkdtreeproc.c  |   25 +-
 src/backend/utils/adt/geo_ops.c            | 1497 ++++++++++++++++------------
 src/backend/utils/adt/geo_spgist.c         |   26 +-
 src/include/utils/geo_decls.h              |   35 +-
 src/test/regress/expected/line.out         |   30 +-
 src/test/regress/expected/point.out        |    8 +-
 src/test/regress/expected/select_views.out |  335 +------
 src/test/regress/regress.c                 |   11 +-
 9 files changed, 944 insertions(+), 1125 deletions(-)

diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index c7ac033..7cd55c0 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -859,24 +859,20 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
 	v->spl_ldatum = PointerGetDatum(leftBox);
 	v->spl_rdatum = PointerGetDatum(rightBox);
 	PG_RETURN_POINTER(v);
 }
 
 /*
  * Equality method
  *
  * This is used for boxes, points, circles, and polygons, all of which store
  * boxes as GiST index entries.
- *
- * Returns true only when boxes are exactly the same.  We can't use fuzzy
- * comparisons here without breaking index consistency; therefore, this isn't
- * equivalent to box_same().
  */
 Datum
 gist_box_same(PG_FUNCTION_ARGS)
 {
 	BOX		   *b1 = PG_GETARG_BOX_P(0);
 	BOX		   *b2 = PG_GETARG_BOX_P(1);
 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
 
 	if (b1 && b2)
 		*result = (FLOAT_EQ(b1->low.x, b2->low.x) &&
@@ -1128,24 +1124,24 @@ gist_circle_compress(PG_FUNCTION_ARGS)
 {
 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 	GISTENTRY  *retval;
 
 	if (entry->leafkey)
 	{
 		CIRCLE	   *in = DatumGetCircleP(entry->key);
 		BOX		   *r;
 
 		r = (BOX *) palloc(sizeof(BOX));
-		r->high.x = in->center.x + in->radius;
-		r->low.x = in->center.x - in->radius;
-		r->high.y = in->center.y + in->radius;
-		r->low.y = in->center.y - in->radius;
+		FLOAT_PL(r->high.x, in->center.x, in->radius);
+		FLOAT_MI(r->low.x, in->center.x, in->radius);
+		FLOAT_PL(r->high.y, in->center.y, in->radius);
+		FLOAT_MI(r->low.y, in->center.y, in->radius);
 
 		retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
 		gistentryinit(*retval, PointerGetDatum(r),
 					  entry->rel, entry->page,
 					  entry->offset, FALSE);
 	}
 	else
 		retval = entry;
 	PG_RETURN_POINTER(retval);
 }
@@ -1169,24 +1165,24 @@ gist_circle_consistent(PG_FUNCTION_ARGS)
 	*recheck = true;
 
 	if (DatumGetBoxP(entry->key) == NULL || query == NULL)
 		PG_RETURN_BOOL(FALSE);
 
 	/*
 	 * Since the operators require recheck anyway, we can just use
 	 * rtree_internal_consistent even at leaf nodes.  (This works in part
 	 * because the index entries are bounding boxes not circles.)
 	 */
-	bbox.high.x = query->center.x + query->radius;
-	bbox.low.x = query->center.x - query->radius;
-	bbox.high.y = query->center.y + query->radius;
-	bbox.low.y = query->center.y - query->radius;
+	FLOAT_PL(bbox.high.x, query->center.x, query->radius);
+	FLOAT_MI(bbox.low.x, query->center.x, query->radius);
+	FLOAT_PL(bbox.high.y, query->center.y, query->radius);
+	FLOAT_MI(bbox.low.y, query->center.y, query->radius);
 
 	result = rtree_internal_consistent(DatumGetBoxP(entry->key),
 									   &bbox, strategy);
 
 	PG_RETURN_BOOL(result);
 }
 
 /**************************************************
  * Point ops
  **************************************************/
@@ -1247,109 +1243,113 @@ gist_point_fetch(PG_FUNCTION_ARGS)
 static double
 computeDistance(bool isLeaf, BOX *box, Point *point)
 {
 	double		result = 0.0;
 
 	if (isLeaf)
 	{
 		/* simple point to point distance */
 		result = point_point_distance(point, &box->low);
 	}
-	else if (point->x <= box->high.x && point->x >= box->low.x &&
-			 point->y <= box->high.y && point->y >= box->low.y)
+	else if (FLOAT_LE(point->x, box->high.x) &&
+			 FLOAT_GE(point->x, box->low.x) &&
+			 FLOAT_LE(point->y, box->high.y) &&
+			 FLOAT_GE(point->y, box->low.y))
 	{
 		/* point inside the box */
 		result = 0.0;
 	}
-	else if (point->x <= box->high.x && point->x >= box->low.x)
+	else if (FLOAT_LE(point->x, box->high.x) &&
+			 FLOAT_GE(point->x, box->low.x))
 	{
 		/* point is over or below box */
-		Assert(box->low.y <= box->high.y);
-		if (point->y > box->high.y)
-			result = point->y - box->high.y;
-		else if (point->y < box->low.y)
-			result = box->low.y - point->y;
+		Assert(FLOAT_LE(box->low.y, box->high.y));
+		if (FLOAT_GT(point->y, box->high.y))
+			FLOAT_MI(result, point->y, box->high.y);
+		else if (FLOAT_LT(point->y, box->low.y))
+			FLOAT_MI(result, box->low.y, point->y);
 		else
 			elog(ERROR, "inconsistent point values");
 	}
-	else if (point->y <= box->high.y && point->y >= box->low.y)
+	else if (FLOAT_LE(point->y, box->high.y) &&
+			 FLOAT_GE(point->y, box->low.y))
 	{
 		/* point is to left or right of box */
-		Assert(box->low.x <= box->high.x);
-		if (point->x > box->high.x)
-			result = point->x - box->high.x;
-		else if (point->x < box->low.x)
-			result = box->low.x - point->x;
+		Assert(FLOAT_LE(box->low.x, box->high.x));
+		if (FLOAT_GT(point->x, box->high.x))
+			FLOAT_MI(result, point->x, box->high.x);
+		else if (FLOAT_LT(point->x, box->low.x))
+			FLOAT_MI(result, box->low.x, point->x);
 		else
 			elog(ERROR, "inconsistent point values");
 	}
 	else
 	{
 		/* closest point will be a vertex */
 		Point		p;
 		double		subresult;
 
 		result = point_point_distance(point, &box->low);
 
 		subresult = point_point_distance(point, &box->high);
-		if (result > subresult)
+		if (FLOAT_GT(result, subresult))
 			result = subresult;
 
 		p.x = box->low.x;
 		p.y = box->high.y;
 		subresult = point_point_distance(point, &p);
-		if (result > subresult)
+		if (FLOAT_GT(result, subresult))
 			result = subresult;
 
 		p.x = box->high.x;
 		p.y = box->low.y;
 		subresult = point_point_distance(point, &p);
-		if (result > subresult)
+		if (FLOAT_GT(result, subresult))
 			result = subresult;
 	}
 
 	return result;
 }
 
 static bool
 gist_point_consistent_internal(StrategyNumber strategy,
 							   bool isLeaf, BOX *key, Point *query)
 {
 	bool		result = false;
 
 	switch (strategy)
 	{
 		case RTLeftStrategyNumber:
-			result = FPlt(key->low.x, query->x);
+			result = FLOAT_LT(key->low.x, query->x);
 			break;
 		case RTRightStrategyNumber:
-			result = FPgt(key->high.x, query->x);
+			result = FLOAT_GT(key->high.x, query->x);
 			break;
 		case RTAboveStrategyNumber:
-			result = FPgt(key->high.y, query->y);
+			result = FLOAT_GT(key->high.y, query->y);
 			break;
 		case RTBelowStrategyNumber:
-			result = FPlt(key->low.y, query->y);
+			result = FLOAT_LT(key->low.y, query->y);
 			break;
 		case RTSameStrategyNumber:
 			if (isLeaf)
 			{
 				/* key.high must equal key.low, so we can disregard it */
-				result = (FPeq(key->low.x, query->x) &&
-						  FPeq(key->low.y, query->y));
+				result = (FLOAT_EQ(key->low.x, query->x) &&
+						  FLOAT_EQ(key->low.y, query->y));
 			}
 			else
 			{
-				result = (FPle(query->x, key->high.x) &&
-						  FPge(query->x, key->low.x) &&
-						  FPle(query->y, key->high.y) &&
-						  FPge(query->y, key->low.y));
+				result = (FLOAT_LE(query->x, key->high.x) &&
+						  FLOAT_GE(query->x, key->low.x) &&
+						  FLOAT_LE(query->y, key->high.y) &&
+						  FLOAT_GE(query->y, key->low.y));
 			}
 			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
 			result = false;		/* keep compiler quiet */
 			break;
 	}
 
 	return result;
 }
@@ -1376,39 +1376,31 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 													GIST_LEAF(entry),
 													DatumGetBoxP(entry->key),
 													PG_GETARG_POINT_P(1));
 			*recheck = false;
 			break;
 		case BoxStrategyNumberGroup:
 			{
 				/*
 				 * The only operator in this group is point <@ box (on_pb), so
 				 * we needn't examine strategy again.
-				 *
-				 * For historical reasons, on_pb uses exact rather than fuzzy
-				 * comparisons.  We could use box_overlap when at an internal
-				 * page, but that would lead to possibly visiting child pages
-				 * uselessly, because box_overlap uses fuzzy comparisons.
-				 * Instead we write a non-fuzzy overlap test.  The same code
-				 * will also serve for leaf-page tests, since leaf keys have
-				 * high == low.
 				 */
 				BOX		   *query,
 						   *key;
 
 				query = PG_GETARG_BOX_P(1);
 				key = DatumGetBoxP(entry->key);
 
-				result = (key->high.x >= query->low.x &&
-						  key->low.x <= query->high.x &&
-						  key->high.y >= query->low.y &&
-						  key->low.y <= query->high.y);
+				result = (FLOAT_GE(key->high.x, query->low.x) &&
+						  FLOAT_LE(key->low.x, query->high.x) &&
+						  FLOAT_GE(key->high.y, query->low.y) &&
+						  FLOAT_LE(key->low.y, query->high.y));
 				*recheck = false;
 			}
 			break;
 		case PolygonStrategyNumberGroup:
 			{
 				POLYGON    *query = PG_GETARG_POLYGON_P(1);
 
 				result = DatumGetBool(DirectFunctionCall5(
 														gist_poly_consistent,
 													  PointerGetDatum(entry),
@@ -1417,22 +1409,22 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 											   0, PointerGetDatum(recheck)));
 
 				if (GIST_LEAF(entry) && result)
 				{
 					/*
 					 * We are on leaf page and quick check shows overlapping
 					 * of polygon's bounding box and point
 					 */
 					BOX		   *box = DatumGetBoxP(entry->key);
 
-					Assert(box->high.x == box->low.x
-						   && box->high.y == box->low.y);
+					Assert(FLOAT_EQ(box->high.x, box->low.x) &&
+						   FLOAT_EQ(box->high.y, box->low.y));
 					result = DatumGetBool(DirectFunctionCall2(
 															  poly_contain_pt,
 													 PolygonPGetDatum(query),
 												PointPGetDatum(&box->high)));
 					*recheck = false;
 				}
 			}
 			break;
 		case CircleStrategyNumberGroup:
 			{
@@ -1446,22 +1438,22 @@ gist_point_consistent(PG_FUNCTION_ARGS)
 											   0, PointerGetDatum(recheck)));
 
 				if (GIST_LEAF(entry) && result)
 				{
 					/*
 					 * We are on leaf page and quick check shows overlapping
 					 * of polygon's bounding box and point
 					 */
 					BOX		   *box = DatumGetBoxP(entry->key);
 
-					Assert(box->high.x == box->low.x
-						   && box->high.y == box->low.y);
+					Assert(FLOAT_EQ(box->high.x, box->low.x) &&
+						   FLOAT_EQ(box->high.y, box->low.y));
 					result = DatumGetBool(DirectFunctionCall2(
 														   circle_contain_pt,
 													  CirclePGetDatum(query),
 												PointPGetDatum(&box->high)));
 					*recheck = false;
 				}
 			}
 			break;
 		default:
 			elog(ERROR, "unrecognized strategy number: %d", strategy);
diff --git a/src/backend/access/spgist/spgkdtreeproc.c b/src/backend/access/spgist/spgkdtreeproc.c
index 1ab9335..10a08ed 100644
--- a/src/backend/access/spgist/spgkdtreeproc.c
+++ b/src/backend/access/spgist/spgkdtreeproc.c
@@ -12,20 +12,21 @@
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
 #include "access/spgist.h"
 #include "access/stratnum.h"
 #include "catalog/pg_type.h"
 #include "utils/builtins.h"
+#include "utils/float.h"
 #include "utils/geo_decls.h"
 
 
 Datum
 spg_kd_config(PG_FUNCTION_ARGS)
 {
 	/* spgConfigIn *cfgin = (spgConfigIn *) PG_GETARG_POINTER(0); */
 	spgConfigOut *cfg = (spgConfigOut *) PG_GETARG_POINTER(1);
 
 	cfg->prefixType = FLOAT8OID;
@@ -175,72 +176,72 @@ spg_kd_inner_consistent(PG_FUNCTION_ARGS)
 	which = (1 << 1) | (1 << 2);
 
 	for (i = 0; i < in->nkeys; i++)
 	{
 		Point	   *query = DatumGetPointP(in->scankeys[i].sk_argument);
 		BOX		   *boxQuery;
 
 		switch (in->scankeys[i].sk_strategy)
 		{
 			case RTLeftStrategyNumber:
-				if ((in->level % 2) != 0 && FPlt(query->x, coord))
+				if ((in->level % 2) != 0 && FLOAT_LT(query->x, coord))
 					which &= (1 << 1);
 				break;
 			case RTRightStrategyNumber:
-				if ((in->level % 2) != 0 && FPgt(query->x, coord))
+				if ((in->level % 2) != 0 && FLOAT_GT(query->x, coord))
 					which &= (1 << 2);
 				break;
 			case RTSameStrategyNumber:
 				if ((in->level % 2) != 0)
 				{
-					if (FPlt(query->x, coord))
+					if (FLOAT_LT(query->x, coord))
 						which &= (1 << 1);
-					else if (FPgt(query->x, coord))
+					else if (FLOAT_GT(query->x, coord))
 						which &= (1 << 2);
 				}
 				else
 				{
-					if (FPlt(query->y, coord))
+					if (FLOAT_LT(query->y, coord))
 						which &= (1 << 1);
-					else if (FPgt(query->y, coord))
+					else if (FLOAT_GT(query->y, coord))
 						which &= (1 << 2);
 				}
 				break;
 			case RTBelowStrategyNumber:
-				if ((in->level % 2) == 0 && FPlt(query->y, coord))
+				if ((in->level % 2) == 0 && FLOAT_LT(query->y, coord))
 					which &= (1 << 1);
 				break;
 			case RTAboveStrategyNumber:
-				if ((in->level % 2) == 0 && FPgt(query->y, coord))
+				if ((in->level % 2) == 0 && FLOAT_GT(query->y, coord))
 					which &= (1 << 2);
 				break;
 			case RTContainedByStrategyNumber:
 
 				/*
 				 * For this operator, the query is a box not a point.  We
 				 * cheat to the extent of assuming that DatumGetPointP won't
 				 * do anything that would be bad for a pointer-to-box.
 				 */
 				boxQuery = DatumGetBoxP(in->scankeys[i].sk_argument);
 
 				if ((in->level % 2) != 0)
 				{
-					if (FPlt(boxQuery->high.x, coord))
+					if (FLOAT_LT(boxQuery->high.x, coord))
 						which &= (1 << 1);
-					else if (FPgt(boxQuery->low.x, coord))
+					else if (FLOAT_GT(boxQuery->low.x, coord))
 						which &= (1 << 2);
 				}
 				else
 				{
-					if (FPlt(boxQuery->high.y, coord))
+					if (FLOAT_LT(boxQuery->high.y, coord))
 						which &= (1 << 1);
-					else if (FPgt(boxQuery->low.y, coord))
+					else if (FLOAT_GT(boxQuery->low.y, coord))
 						which &= (1 << 2);
 				}
 				break;
 			default:
 				elog(ERROR, "unrecognized strategy number: %d",
 					 in->scankeys[i].sk_strategy);
 				break;
 		}
 
 		if (which == 0)
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index efc81ab..3855c8e 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -36,50 +36,56 @@ enum path_delim
 
 static int	point_inside(Point *p, int npts, Point *plist);
 static int	lseg_crossing(double x, double y, double px, double py);
 static BOX *box_construct(double x1, double x2, double y1, double y2);
 static BOX *box_copy(BOX *box);
 static BOX *box_fill(BOX *result, double x1, double x2, double y1, double y2);
 static bool box_ov(BOX *box1, BOX *box2);
 static double box_ht(BOX *box);
 static double box_wd(BOX *box);
 static double circle_ar(CIRCLE *circle);
-static CIRCLE *circle_copy(CIRCLE *circle);
+static CIRCLE *circle_construct(double x, double y, double radius);
 static LINE *line_construct_pm(Point *pt, double m);
-static void line_construct_pts(LINE *line, Point *pt1, Point *pt2);
+static LINE *line_construct_pts(Point *pt1, Point *pt2);
 static bool lseg_intersect_internal(LSEG *l1, LSEG *l2);
 static double lseg_dt(LSEG *l1, LSEG *l2);
 static bool on_ps_internal(Point *pt, LSEG *lseg);
+static double point_on_line_value(Point *pt, LINE *line);
+static int point_lseg_cmp(Point *pt, LSEG *lseg);
 static void make_bound_box(POLYGON *poly);
 static bool plist_same(int npts, Point *p1, Point *p2);
 static Point *point_construct(double x, double y);
 static Point *point_copy(Point *pt);
+static double point_dt(Point *pt1, Point *pt2);
+static double slope(double x1, double x2, double y1, double y2);
 static double single_decode(char *num, char **endptr_p,
 			  const char *type_name, const char *orig_string);
 static void single_encode(float8 x, StringInfo str);
 static void pair_decode(char *str, double *x, double *y, char **endptr_p,
 			const char *type_name, const char *orig_string);
 static void pair_encode(float8 x, float8 y, StringInfo str);
 static int	pair_count(char *s, char delim);
 static void path_decode(char *str, bool opentype, int npts, Point *p,
 			bool *isopen, char **endptr_p,
 			const char *type_name, const char *orig_string);
 static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
 static void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
 static double box_ar(BOX *box);
 static void box_cn(Point *center, BOX *box);
 static Point *interpt_sl(LSEG *lseg, LINE *line);
 static bool has_interpt_sl(LSEG *lseg, LINE *line);
+static Point *close_pl_internal(Point *pt, LINE *line);
 static double dist_pl_internal(Point *pt, LINE *line);
 static double dist_ps_internal(Point *pt, LSEG *lseg);
 static Point *line_interpt_internal(LINE *l1, LINE *l2);
 static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
+static Point *lseg_center_internal(LSEG *lseg);
 static Point *lseg_interpt_internal(LSEG *l1, LSEG *l2);
 static double dist_ppoly_internal(Point *pt, POLYGON *poly);
 
 
 /*
  * Delimiters for input and output strings.
  * LDELIM, RDELIM, and DELIM are left, right, and separator delimiters, respectively.
  * LDELIM_EP, RDELIM_EP are left and right delimiters for paths with endpoints.
  */
 
@@ -349,27 +355,27 @@ box_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	BOX		   *box = (BOX *) palloc(sizeof(BOX));
 	bool		isopen;
 	double		x,
 				y;
 
 	path_decode(str, false, 2, &(box->high), &isopen, NULL, "box", str);
 
 	/* reorder corners if necessary... */
-	if (box->high.x < box->low.x)
+	if (FLOAT_LT(box->high.x, box->low.x))
 	{
 		x = box->high.x;
 		box->high.x = box->low.x;
 		box->low.x = x;
 	}
-	if (box->high.y < box->low.y)
+	if (FLOAT_LT(box->high.y, box->low.y))
 	{
 		y = box->high.y;
 		box->high.y = box->low.y;
 		box->low.y = y;
 	}
 
 	PG_RETURN_BOX_P(box);
 }
 
 /*		box_out -		convert a box to external form.
@@ -394,27 +400,27 @@ box_recv(PG_FUNCTION_ARGS)
 				y;
 
 	box = (BOX *) palloc(sizeof(BOX));
 
 	box->high.x = pq_getmsgfloat8(buf);
 	box->high.y = pq_getmsgfloat8(buf);
 	box->low.x = pq_getmsgfloat8(buf);
 	box->low.y = pq_getmsgfloat8(buf);
 
 	/* reorder corners if necessary... */
-	if (box->high.x < box->low.x)
+	if (FLOAT_LT(box->high.x, box->low.x))
 	{
 		x = box->high.x;
 		box->high.x = box->low.x;
 		box->low.x = x;
 	}
-	if (box->high.y < box->low.y)
+	if (FLOAT_LT(box->high.y, box->low.y))
 	{
 		y = box->high.y;
 		box->high.y = box->low.y;
 		box->low.y = y;
 	}
 
 	PG_RETURN_BOX_P(box);
 }
 
 /*
@@ -444,31 +450,31 @@ box_construct(double x1, double x2, double y1, double y2)
 
 	return box_fill(result, x1, x2, y1, y2);
 }
 
 
 /*		box_fill		-		fill in a given box struct
  */
 static BOX *
 box_fill(BOX *result, double x1, double x2, double y1, double y2)
 {
-	if (x1 > x2)
+	if (FLOAT_GT(x1, x2))
 	{
 		result->high.x = x1;
 		result->low.x = x2;
 	}
 	else
 	{
 		result->high.x = x2;
 		result->low.x = x1;
 	}
-	if (y1 > y2)
+	if (FLOAT_GT(y1, y2))
 	{
 		result->high.y = y1;
 		result->low.y = y2;
 	}
 	else
 	{
 		result->high.y = y2;
 		result->low.y = y1;
 	}
 
@@ -495,246 +501,246 @@ box_copy(BOX *box)
  *---------------------------------------------------------*/
 
 /*		box_same		-		are two boxes identical?
  */
 Datum
 box_same(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPeq(box1->high.x, box2->high.x) &&
-				   FPeq(box1->low.x, box2->low.x) &&
-				   FPeq(box1->high.y, box2->high.y) &&
-				   FPeq(box1->low.y, box2->low.y));
+	PG_RETURN_BOOL(FLOAT_EQ(box1->high.x, box2->high.x) &&
+				   FLOAT_EQ(box1->low.x, box2->low.x) &&
+				   FLOAT_EQ(box1->high.y, box2->high.y) &&
+				   FLOAT_EQ(box1->low.y, box2->low.y));
 }
 
 /*		box_overlap		-		does box1 overlap box2?
  */
 Datum
 box_overlap(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
 	PG_RETURN_BOOL(box_ov(box1, box2));
 }
 
 static bool
 box_ov(BOX *box1, BOX *box2)
 {
-	return (FPle(box1->low.x, box2->high.x) &&
-			FPle(box2->low.x, box1->high.x) &&
-			FPle(box1->low.y, box2->high.y) &&
-			FPle(box2->low.y, box1->high.y));
+	return (FLOAT_LE(box1->low.x, box2->high.x) &&
+			FLOAT_LE(box2->low.x, box1->high.x) &&
+			FLOAT_LE(box1->low.y, box2->high.y) &&
+			FLOAT_LE(box2->low.y, box1->high.y));
 }
 
 /*		box_left		-		is box1 strictly left of box2?
  */
 Datum
 box_left(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPlt(box1->high.x, box2->low.x));
+	PG_RETURN_BOOL(FLOAT_LT(box1->high.x, box2->low.x));
 }
 
 /*		box_overleft	-		is the right edge of box1 at or left of
  *								the right edge of box2?
  *
  *		This is "less than or equal" for the end of a time range,
  *		when time ranges are stored as rectangles.
  */
 Datum
 box_overleft(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPle(box1->high.x, box2->high.x));
+	PG_RETURN_BOOL(FLOAT_LE(box1->high.x, box2->high.x));
 }
 
 /*		box_right		-		is box1 strictly right of box2?
  */
 Datum
 box_right(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPgt(box1->low.x, box2->high.x));
+	PG_RETURN_BOOL(FLOAT_GT(box1->low.x, box2->high.x));
 }
 
 /*		box_overright	-		is the left edge of box1 at or right of
  *								the left edge of box2?
  *
  *		This is "greater than or equal" for time ranges, when time ranges
  *		are stored as rectangles.
  */
 Datum
 box_overright(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPge(box1->low.x, box2->low.x));
+	PG_RETURN_BOOL(FLOAT_GE(box1->low.x, box2->low.x));
 }
 
 /*		box_below		-		is box1 strictly below box2?
  */
 Datum
 box_below(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPlt(box1->high.y, box2->low.y));
+	PG_RETURN_BOOL(FLOAT_LT(box1->high.y, box2->low.y));
 }
 
 /*		box_overbelow	-		is the upper edge of box1 at or below
  *								the upper edge of box2?
  */
 Datum
 box_overbelow(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPle(box1->high.y, box2->high.y));
+	PG_RETURN_BOOL(FLOAT_LE(box1->high.y, box2->high.y));
 }
 
 /*		box_above		-		is box1 strictly above box2?
  */
 Datum
 box_above(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPgt(box1->low.y, box2->high.y));
+	PG_RETURN_BOOL(FLOAT_GT(box1->low.y, box2->high.y));
 }
 
 /*		box_overabove	-		is the lower edge of box1 at or above
  *								the lower edge of box2?
  */
 Datum
 box_overabove(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPge(box1->low.y, box2->low.y));
+	PG_RETURN_BOOL(FLOAT_GE(box1->low.y, box2->low.y));
 }
 
 /*		box_contained	-		is box1 contained by box2?
  */
 Datum
 box_contained(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPle(box1->high.x, box2->high.x) &&
-				   FPge(box1->low.x, box2->low.x) &&
-				   FPle(box1->high.y, box2->high.y) &&
-				   FPge(box1->low.y, box2->low.y));
+	PG_RETURN_BOOL(FLOAT_LE(box1->high.x, box2->high.x) &&
+				   FLOAT_GE(box1->low.x, box2->low.x) &&
+				   FLOAT_LE(box1->high.y, box2->high.y) &&
+				   FLOAT_GE(box1->low.y, box2->low.y));
 }
 
 /*		box_contain		-		does box1 contain box2?
  */
 Datum
 box_contain(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPge(box1->high.x, box2->high.x) &&
-				   FPle(box1->low.x, box2->low.x) &&
-				   FPge(box1->high.y, box2->high.y) &&
-				   FPle(box1->low.y, box2->low.y));
+	PG_RETURN_BOOL(FLOAT_GE(box1->high.x, box2->high.x) &&
+				   FLOAT_LE(box1->low.x, box2->low.x) &&
+				   FLOAT_GE(box1->high.y, box2->high.y) &&
+				   FLOAT_LE(box1->low.y, box2->low.y));
 }
 
 
 /*		box_positionop	-
  *				is box1 entirely {above,below} box2?
  *
  * box_below_eq and box_above_eq are obsolete versions that (probably
  * erroneously) accept the equal-boundaries case.  Since these are not
  * in sync with the box_left and box_right code, they are deprecated and
  * not supported in the PG 8.1 rtree operator class extension.
  */
 Datum
 box_below_eq(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPle(box1->high.y, box2->low.y));
+	PG_RETURN_BOOL(FLOAT_LE(box1->high.y, box2->low.y));
 }
 
 Datum
 box_above_eq(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPge(box1->low.y, box2->high.y));
+	PG_RETURN_BOOL(FLOAT_GE(box1->low.y, box2->high.y));
 }
 
 
 /*		box_relop		-		is area(box1) relop area(box2), within
  *								our accuracy constraint?
  */
 Datum
 box_lt(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPlt(box_ar(box1), box_ar(box2)));
+	PG_RETURN_BOOL(FLOAT_LT(box_ar(box1), box_ar(box2)));
 }
 
 Datum
 box_gt(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPgt(box_ar(box1), box_ar(box2)));
+	PG_RETURN_BOOL(FLOAT_GT(box_ar(box1), box_ar(box2)));
 }
 
 Datum
 box_eq(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPeq(box_ar(box1), box_ar(box2)));
+	PG_RETURN_BOOL(FLOAT_EQ(box_ar(box1), box_ar(box2)));
 }
 
 Datum
 box_le(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPle(box_ar(box1), box_ar(box2)));
+	PG_RETURN_BOOL(FLOAT_LE(box_ar(box1), box_ar(box2)));
 }
 
 Datum
 box_ge(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(FPge(box_ar(box1), box_ar(box2)));
+	PG_RETURN_BOOL(FLOAT_GE(box_ar(box1), box_ar(box2)));
 }
 
 
 /*----------------------------------------------------------
  *	"Arithmetic" operators on boxes.
  *---------------------------------------------------------*/
 
 /*		box_area		-		returns the area of the box.
  */
 Datum
@@ -777,21 +783,21 @@ Datum
 box_distance(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 	Point		a,
 				b;
 
 	box_cn(&a, box1);
 	box_cn(&b, box2);
 
-	PG_RETURN_FLOAT8(HYPOT(a.x - b.x, a.y - b.y));
+	PG_RETURN_FLOAT8(point_dt(&a, &b));
 }
 
 
 /*		box_center		-		returns the center point of the box.
  */
 Datum
 box_center(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	Point	   *result = (Point *) palloc(sizeof(Point));
@@ -809,22 +815,28 @@ box_ar(BOX *box)
 {
 	return box_wd(box) * box_ht(box);
 }
 
 
 /*		box_cn	-		stores the centerpoint of the box into *center.
  */
 static void
 box_cn(Point *center, BOX *box)
 {
-	center->x = (box->high.x + box->low.x) / 2.0;
-	center->y = (box->high.y + box->low.y) / 2.0;
+	double		sumx;
+	double		sumy;
+
+	FLOAT_PL(sumx, box->high.x, box->low.x);
+	FLOAT_DIV(center->x, sumx, 2.0);
+
+	FLOAT_PL(sumy, box->high.y, box->low.y);
+	FLOAT_DIV(center->y, sumy, 2.0);
 }
 
 
 /*		box_wd	-		returns the width (length) of the box
  *								  (horizontal magnitude).
  */
 static double
 box_wd(BOX *box)
 {
 	return box->high.x - box->low.x;
@@ -854,24 +866,24 @@ box_intersect(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0);
 	BOX		   *box2 = PG_GETARG_BOX_P(1);
 	BOX		   *result;
 
 	if (!box_ov(box1, box2))
 		PG_RETURN_NULL();
 
 	result = (BOX *) palloc(sizeof(BOX));
 
-	result->high.x = Min(box1->high.x, box2->high.x);
-	result->low.x = Max(box1->low.x, box2->low.x);
-	result->high.y = Min(box1->high.y, box2->high.y);
-	result->low.y = Max(box1->low.y, box2->low.y);
+	result->high.x = FLOAT_MIN(box1->high.x, box2->high.x);
+	result->low.x = FLOAT_MAX(box1->low.x, box2->low.x);
+	result->high.y = FLOAT_MIN(box1->high.y, box2->high.y);
+	result->low.y = FLOAT_MAX(box1->low.y, box2->low.y);
 
 	PG_RETURN_BOX_P(result);
 }
 
 
 /*		box_diagonal	-
  *				returns a line segment which happens to be the
  *				  positive-slope diagonal of "box".
  */
 Datum
@@ -908,48 +920,51 @@ line_decode(char *s, const char *str, LINE *line)
 		s++;
 	if (*s != '\0')
 		return false;
 	return true;
 }
 
 Datum
 line_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
-	LINE	   *line = (LINE *) palloc(sizeof(LINE));
+	LINE	   *line;
 	LSEG		lseg;
 	bool		isopen;
 	char	   *s;
 
 	s = str;
 	while (isspace((unsigned char) *s))
 		s++;
 	if (*s == '{')
 	{
+		line = (LINE *) palloc(sizeof(LINE));
+
 		if (!line_decode(s + 1, str, line))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
 							"line", str)));
-		if (FPzero(line->A) && FPzero(line->B))
+		if (FLOAT_EQ(line->A, 0.0) && FLOAT_EQ(line->B, 0.0))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid line specification: A and B cannot both be zero")));
 	}
 	else
 	{
 		path_decode(s, true, 2, &(lseg.p[0]), &isopen, NULL, "line", str);
-		if (FPeq(lseg.p[0].x, lseg.p[1].x) && FPeq(lseg.p[0].y, lseg.p[1].y))
+		if (FLOAT_EQ(lseg.p[0].x, lseg.p[1].x) &&
+			FLOAT_EQ(lseg.p[0].y, lseg.p[1].y))
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid line specification: must be two distinct points")));
-		line_construct_pts(line, &lseg.p[0], &lseg.p[1]);
+		line = line_construct_pts(&lseg.p[0], &lseg.p[1]);
 	}
 
 	PG_RETURN_LINE_P(line);
 }
 
 
 Datum
 line_out(PG_FUNCTION_ARGS)
 {
 	LINE	   *line = PG_GETARG_LINE_P(0);
@@ -968,20 +983,25 @@ line_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	LINE	   *line;
 
 	line = (LINE *) palloc(sizeof(LINE));
 
 	line->A = pq_getmsgfloat8(buf);
 	line->B = pq_getmsgfloat8(buf);
 	line->C = pq_getmsgfloat8(buf);
 
+	if (FLOAT_EQ(line->A, 0.0) && FLOAT_EQ(line->B, 0.0))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
+				 errmsg("invalid line specification: A and B cannot both be zero")));
+
 	PG_RETURN_LINE_P(line);
 }
 
 /*
  *		line_send			- converts line to binary format
  */
 Datum
 line_send(PG_FUNCTION_ARGS)
 {
 	LINE	   *line = PG_GETARG_LINE_P(0);
@@ -1000,93 +1020,101 @@ line_send(PG_FUNCTION_ARGS)
  *		Internal form:	Ax+By+C=0
  *---------------------------------------------------------*/
 
 /* line_construct_pm()
  * point-slope
  */
 static LINE *
 line_construct_pm(Point *pt, double m)
 {
 	LINE	   *result = (LINE *) palloc(sizeof(LINE));
+	double		val;
 
-	if (m == DBL_MAX)
+	if (FLOAT_EQ(m, DBL_MAX))
 	{
 		/* vertical - use "x = C" */
-		result->A = -1;
-		result->B = 0;
+		result->A = -1.0;
+		result->B = 0.0;
 		result->C = pt->x;
 	}
 	else
 	{
-		/* use "mx - y + yinter = 0" */
 		result->A = m;
 		result->B = -1.0;
-		result->C = pt->y - m * pt->x;
+		FLOAT_MUL(val, m, pt->x);
+		FLOAT_MI(result->C, pt->y, val);
 	}
 
 	return result;
 }
 
 /*
  * Fill already-allocated LINE struct from two points on the line
  */
-static void
-line_construct_pts(LINE *line, Point *pt1, Point *pt2)
+static LINE *
+line_construct_pts(Point *pt1, Point *pt2)
 {
-	if (FPeq(pt1->x, pt2->x))
+	LINE	   *result = (LINE *) palloc(sizeof(LINE));
+
+	if (FLOAT_EQ(pt1->x, pt2->x))
 	{							/* vertical */
 		/* use "x = C" */
-		line->A = -1;
-		line->B = 0;
-		line->C = pt1->x;
+		result->A = -1.0;
+		result->B = 0.0;
+		result->C = pt1->x;
 #ifdef GEODEBUG
 		printf("line_construct_pts- line is vertical\n");
 #endif
 	}
-	else if (FPeq(pt1->y, pt2->y))
+	else if (FLOAT_EQ(pt1->y, pt2->y))
 	{							/* horizontal */
 		/* use "y = C" */
-		line->A = 0;
-		line->B = -1;
-		line->C = pt1->y;
+		result->A = 0.0;
+		result->B = -1.0;
+		result->C = pt1->y;
 #ifdef GEODEBUG
 		printf("line_construct_pts- line is horizontal\n");
 #endif
 	}
 	else
 	{
-		/* use "mx - y + yinter = 0" */
-		line->A = (pt2->y - pt1->y) / (pt2->x - pt1->x);
-		line->B = -1.0;
-		line->C = pt1->y - line->A * pt1->x;
-		/* on some platforms, the preceding expression tends to produce -0 */
-		if (line->C == 0.0)
-			line->C = 0.0;
+		double		mul_x;
+		double		mul_y;
+
+		/* The equation is optimized to avoid losing precision by division. */
+		FLOAT_MI(result->A, pt2->y, pt1->y);
+		FLOAT_MI(result->B, pt1->x, pt2->x);
+		FLOAT_MUL(mul_x, pt1->x, result->A);
+		FLOAT_MUL(mul_y, pt1->y, result->B);
+		FLOAT_PL(result->C, mul_x, mul_y);
+		if (FLOAT_NE(result->C, 0.0))	/* We don't want to get -0. */
+			result->C = -result->C;
+
 #ifdef GEODEBUG
 		printf("line_construct_pts- line is neither vertical nor horizontal (diffs x=%.*g, y=%.*g\n",
 			   DBL_DIG, (pt2->x - pt1->x), DBL_DIG, (pt2->y - pt1->y));
 #endif
 	}
+
+	return result;
 }
 
 /* line_construct_pp()
  * two points
  */
 Datum
 line_construct_pp(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
-	LINE	   *result = (LINE *) palloc(sizeof(LINE));
 
-	line_construct_pts(result, pt1, pt2);
-	PG_RETURN_LINE_P(result);
+	PG_RETURN_LINE_P(line_construct_pts(pt1, pt2));
 }
 
 
 /*----------------------------------------------------------
  *	Relative position routines.
  *---------------------------------------------------------*/
 
 Datum
 line_intersect(PG_FUNCTION_ARGS)
 {
@@ -1096,102 +1124,139 @@ line_intersect(PG_FUNCTION_ARGS)
 	PG_RETURN_BOOL(!DatumGetBool(DirectFunctionCall2(line_parallel,
 													 LinePGetDatum(l1),
 													 LinePGetDatum(l2))));
 }
 
 Datum
 line_parallel(PG_FUNCTION_ARGS)
 {
 	LINE	   *l1 = PG_GETARG_LINE_P(0);
 	LINE	   *l2 = PG_GETARG_LINE_P(1);
+	double		mul12;
+	double		mul21;
 
-	if (FPzero(l1->B))
-		PG_RETURN_BOOL(FPzero(l2->B));
+	if (FLOAT_EQ(l1->A, 0.0))		/* horizontal? */
+		PG_RETURN_BOOL(FLOAT_EQ(l2->A, 0.0));
+	if (FLOAT_EQ(l1->B, 0.0))		/* vertical? */
+		PG_RETURN_BOOL(FLOAT_EQ(l2->B, 0.0));
 
-	PG_RETURN_BOOL(FPeq(l2->A, l1->A * (l2->B / l1->B)));
+	if (FLOAT_EQ(l2->A, 0.0) || FLOAT_EQ(l2->B, 0.0))
+		PG_RETURN_BOOL(false);
+
+	FLOAT_MUL(mul12, l1->A, l2->B);
+	FLOAT_MUL(mul21, l2->A, l1->B);
+
+	PG_RETURN_BOOL(FLOAT_EQ(mul12, mul21));
 }
 
 Datum
 line_perp(PG_FUNCTION_ARGS)
 {
 	LINE	   *l1 = PG_GETARG_LINE_P(0);
 	LINE	   *l2 = PG_GETARG_LINE_P(1);
+	double		val1;
+	double		val2;
 
-	if (FPzero(l1->A))
-		PG_RETURN_BOOL(FPzero(l2->B));
-	else if (FPzero(l1->B))
-		PG_RETURN_BOOL(FPzero(l2->A));
+	if (FLOAT_EQ(l1->A, 0.0))		/* horizontal? */
+		PG_RETURN_BOOL(FLOAT_EQ(l2->B, 0.0));
+	if (FLOAT_EQ(l1->B, 0.0))		/* vertical? */
+		PG_RETURN_BOOL(FLOAT_EQ(l2->A, 0.0));
 
-	PG_RETURN_BOOL(FPeq(((l1->A * l2->B) / (l1->B * l2->A)), -1.0));
+	if (FLOAT_EQ(l2->A, 0.0) || FLOAT_EQ(l2->B, 0.0))
+		PG_RETURN_BOOL(false);
+
+	FLOAT_MUL(val1, l1->A, l2->B);
+	FLOAT_MUL(val2, l2->A, l1->B);
+
+	PG_RETURN_BOOL(FLOAT_EQ(val1, -val2));
 }
 
 Datum
 line_vertical(PG_FUNCTION_ARGS)
 {
 	LINE	   *line = PG_GETARG_LINE_P(0);
 
-	PG_RETURN_BOOL(FPzero(line->B));
+	PG_RETURN_BOOL(FLOAT_EQ(line->B, 0.0));
 }
 
 Datum
 line_horizontal(PG_FUNCTION_ARGS)
 {
 	LINE	   *line = PG_GETARG_LINE_P(0);
 
-	PG_RETURN_BOOL(FPzero(line->A));
+	PG_RETURN_BOOL(FLOAT_EQ(line->A, 0.0));
 }
 
 Datum
 line_eq(PG_FUNCTION_ARGS)
 {
 	LINE	   *l1 = PG_GETARG_LINE_P(0);
 	LINE	   *l2 = PG_GETARG_LINE_P(1);
-	double		k;
+	double		mul12;
+	double		mul21;
 
-	if (!FPzero(l2->A))
-		k = l1->A / l2->A;
-	else if (!FPzero(l2->B))
-		k = l1->B / l2->B;
-	else if (!FPzero(l2->C))
-		k = l1->C / l2->C;
-	else
-		k = 1.0;
+	FLOAT_MUL(mul12, l1->A, l2->B);
+	FLOAT_MUL(mul21, l2->A, l1->B);
+	if (FLOAT_NE(mul12, mul21))
+		PG_RETURN_BOOL(false);
 
-	PG_RETURN_BOOL(FPeq(l1->A, k * l2->A) &&
-				   FPeq(l1->B, k * l2->B) &&
-				   FPeq(l1->C, k * l2->C));
+	if (FLOAT_NE(l1->A, 0.0))
+	{
+		if (FLOAT_EQ(l2->A, 0.0))
+			PG_RETURN_BOOL(false);
+
+		FLOAT_MUL(mul12, l1->A, l2->C);
+		FLOAT_MUL(mul21, l2->A, l1->C);
+	}
+	else /* (l1->A == 0.0 => l1->B != 0.0 => l2->A == 0.0) */
+	{
+		if (FLOAT_EQ(l2->B, 0.0))
+			PG_RETURN_BOOL(false);
+
+		FLOAT_MUL(mul12, l1->B, l2->C);
+		FLOAT_MUL(mul21, l2->B, l1->C);
+	}
+
+	PG_RETURN_BOOL(FLOAT_EQ(mul12, mul21));
 }
 
 
 /*----------------------------------------------------------
  *	Line arithmetic routines.
  *---------------------------------------------------------*/
 
 /* line_distance()
  * Distance between two lines.
  */
 Datum
 line_distance(PG_FUNCTION_ARGS)
 {
 	LINE	   *l1 = PG_GETARG_LINE_P(0);
 	LINE	   *l2 = PG_GETARG_LINE_P(1);
-	float8		result;
-	Point	   *tmp;
+	double		result;
+	double		y;
 
 	if (!DatumGetBool(DirectFunctionCall2(line_parallel,
 										  LinePGetDatum(l1),
 										  LinePGetDatum(l2))))
 		PG_RETURN_FLOAT8(0.0);
-	if (FPzero(l1->B))			/* vertical? */
-		PG_RETURN_FLOAT8(fabs(l1->C - l2->C));
-	tmp = point_construct(0.0, l1->C);
-	result = dist_pl_internal(tmp, l2);
+
+	if (FLOAT_EQ(l1->A, 0.0) || FLOAT_EQ(l1->B, 0.0))	/* horizontal or vertical? */
+	{
+		FLOAT_MI(result, l1->C, l2->C);
+	}
+	else
+	{
+		FLOAT_DIV(y, -l1->C, l1->B);
+		result = dist_pl_internal(point_construct(0.0, y), l2);
+	}
+
 	PG_RETURN_FLOAT8(result);
 }
 
 /* line_interpt()
  * Point where two lines l1, l2 intersect (if any)
  */
 Datum
 line_interpt(PG_FUNCTION_ARGS)
 {
 	LINE	   *l1 = PG_GETARG_LINE_P(0);
@@ -1207,48 +1272,69 @@ line_interpt(PG_FUNCTION_ARGS)
 
 /*
  * Internal version of line_interpt
  *
  * returns a NULL pointer if no intersection point
  */
 static Point *
 line_interpt_internal(LINE *l1, LINE *l2)
 {
 	Point	   *result;
+	double		val1;
+	double		val2;
 	double		x,
 				y;
 
 	/*
 	 * NOTE: if the lines are identical then we will find they are parallel
 	 * and report "no intersection".  This is a little weird, but since
 	 * there's no *unique* intersection, maybe it's appropriate behavior.
 	 */
 	if (DatumGetBool(DirectFunctionCall2(line_parallel,
 										 LinePGetDatum(l1),
 										 LinePGetDatum(l2))))
 		return NULL;
 
-	if (FPzero(l1->B))			/* l1 vertical? */
+	if (FLOAT_EQ(l1->B, 0.0))		/* l1 vertical? */
 	{
-		x = l1->C;
-		y = (l2->A * x + l2->C);
-	}
-	else if (FPzero(l2->B))		/* l2 vertical? */
-	{
-		x = l2->C;
-		y = (l1->A * x + l1->C);
+		FLOAT_DIV(x, -l1->C, l1->A);
+		FLOAT_MUL(val1, l2->A, x);
+		FLOAT_PL(val2, val1, l2->C);
+		FLOAT_DIV(y, -val2, l2->B);
 	}
 	else
 	{
-		x = (l1->C - l2->C) / (l2->A - l1->A);
-		y = (l1->A * x + l1->C);
+		if (FLOAT_EQ(l2->B, 0.0))	/* l2 vertical? */
+		{
+			FLOAT_DIV(x, -l2->C, l2->A);
+		}
+		else
+		{
+			double		mul12;
+			double		mul21;
+
+			FLOAT_MUL(mul12, l1->B, l2->C);
+			FLOAT_MUL(mul21, l2->B, l1->C);
+			FLOAT_MI(val1, mul12, mul21);
+
+			FLOAT_MUL(mul12, l1->A, l2->B);
+			FLOAT_MUL(mul21, l2->A, l1->B);
+			FLOAT_MI(val2, mul12, mul21);
+
+			FLOAT_DIV(x, val1, val2);
+		}
+
+		FLOAT_MUL(val1, l1->A, x);
+		FLOAT_PL(val2, val1, l1->C);
+		FLOAT_DIV(y, -val2, l1->B);
 	}
+
 	result = point_construct(x, y);
 
 #ifdef GEODEBUG
 	printf("line_interpt- lines are A=%.*g, B=%.*g, C=%.*g, A=%.*g, B=%.*g, C=%.*g\n",
 		   DBL_DIG, l1->A, DBL_DIG, l1->B, DBL_DIG, l1->C, DBL_DIG, l2->A, DBL_DIG, l2->B, DBL_DIG, l2->C);
 	printf("line_interpt- lines intersect at (%.*g,%.*g)\n", DBL_DIG, x, DBL_DIG, y);
 #endif
 
 	return result;
 }
@@ -1274,35 +1360,40 @@ line_interpt_internal(LINE *l1, LINE *l2)
  *				"[xcoord, ycoord,... ]"
  *		Also support older format:
  *				"(closed, npts, xcoord, ycoord,... )"
  *---------------------------------------------------------*/
 
 Datum
 path_area(PG_FUNCTION_ARGS)
 {
 	PATH	   *path = PG_GETARG_PATH_P(0);
 	double		area = 0.0;
+	double		mulxy;
+	double		mulyx;
+	double		new_area;
 	int			i,
 				j;
 
 	if (!path->closed)
 		PG_RETURN_NULL();
 
 	for (i = 0; i < path->npts; i++)
 	{
 		j = (i + 1) % path->npts;
-		area += path->p[i].x * path->p[j].y;
-		area -= path->p[i].y * path->p[j].x;
+		FLOAT_MUL(mulxy, path->p[i].x, path->p[j].y);
+		FLOAT_MUL(mulyx, path->p[i].y, path->p[j].x);
+		FLOAT_PL(new_area, area, mulxy);
+		FLOAT_MI(area, new_area, mulyx);
 	}
 
-	area *= 0.5;
-	PG_RETURN_FLOAT8(area < 0.0 ? -area : area);
+	FLOAT_MUL(new_area, area, 0.5);
+	PG_RETURN_FLOAT8(fabs(new_area));
 }
 
 
 Datum
 path_in(PG_FUNCTION_ARGS)
 {
 	char	   *str = PG_GETARG_CSTRING(0);
 	PATH	   *path;
 	bool		isopen;
 	char	   *s;
@@ -1322,21 +1413,21 @@ path_in(PG_FUNCTION_ARGS)
 		s++;
 
 	/* skip single leading paren */
 	if ((*s == LDELIM) && (strrchr(s, LDELIM) == s))
 	{
 		s++;
 		depth++;
 	}
 
 	base_size = sizeof(path->p[0]) * npts;
-	size = offsetof(PATH, p) +base_size;
+	size = offsetof(PATH, p) + base_size;
 
 	/* Check for integer overflow */
 	if (base_size / npts != sizeof(path->p[0]) || size <= base_size)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("too many points requested")));
 
 	path = (PATH *) palloc(size);
 
 	SET_VARSIZE(path, size);
@@ -1392,21 +1483,21 @@ path_recv(PG_FUNCTION_ARGS)
 	int32		i;
 	int			size;
 
 	closed = pq_getmsgbyte(buf);
 	npts = pq_getmsgint(buf, sizeof(int32));
 	if (npts <= 0 || npts >= (int32) ((INT_MAX - offsetof(PATH, p)) / sizeof(Point)))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 			 errmsg("invalid number of points in external \"path\" value")));
 
-	size = offsetof(PATH, p) +sizeof(path->p[0]) * npts;
+	size = offsetof(PATH, p) + sizeof(path->p[0]) * npts;
 	path = (PATH *) palloc(size);
 
 	SET_VARSIZE(path, size);
 	path->npts = npts;
 	path->closed = (closed ? 1 : 0);
 	/* prevent instability in unused pad bytes */
 	path->dummy = 0;
 
 	for (i = 0; i < npts; i++)
 	{
@@ -1519,31 +1610,31 @@ path_npoints(PG_FUNCTION_ARGS)
 
 	PG_RETURN_INT32(path->npts);
 }
 
 
 Datum
 path_close(PG_FUNCTION_ARGS)
 {
 	PATH	   *path = PG_GETARG_PATH_P_COPY(0);
 
-	path->closed = TRUE;
+	path->closed = true;
 
 	PG_RETURN_PATH_P(path);
 }
 
 Datum
 path_open(PG_FUNCTION_ARGS)
 {
 	PATH	   *path = PG_GETARG_PATH_P_COPY(0);
 
-	path->closed = FALSE;
+	path->closed = false;
 
 	PG_RETURN_PATH_P(path);
 }
 
 
 /* path_inter -
  *		Does p1 intersect p2 at any point?
  *		Use bounding boxes for a quick (O(n)) check, then do a
  *		O(n^2) iterative edge check.
  */
@@ -1559,33 +1650,33 @@ path_inter(PG_FUNCTION_ARGS)
 	LSEG		seg1,
 				seg2;
 
 	if (p1->npts <= 0 || p2->npts <= 0)
 		PG_RETURN_BOOL(false);
 
 	b1.high.x = b1.low.x = p1->p[0].x;
 	b1.high.y = b1.low.y = p1->p[0].y;
 	for (i = 1; i < p1->npts; i++)
 	{
-		b1.high.x = Max(p1->p[i].x, b1.high.x);
-		b1.high.y = Max(p1->p[i].y, b1.high.y);
-		b1.low.x = Min(p1->p[i].x, b1.low.x);
-		b1.low.y = Min(p1->p[i].y, b1.low.y);
+		b1.high.x = FLOAT_MAX(p1->p[i].x, b1.high.x);
+		b1.high.y = FLOAT_MAX(p1->p[i].y, b1.high.y);
+		b1.low.x = FLOAT_MIN(p1->p[i].x, b1.low.x);
+		b1.low.y = FLOAT_MIN(p1->p[i].y, b1.low.y);
 	}
 	b2.high.x = b2.low.x = p2->p[0].x;
 	b2.high.y = b2.low.y = p2->p[0].y;
 	for (i = 1; i < p2->npts; i++)
 	{
-		b2.high.x = Max(p2->p[i].x, b2.high.x);
-		b2.high.y = Max(p2->p[i].y, b2.high.y);
-		b2.low.x = Min(p2->p[i].x, b2.low.x);
-		b2.low.y = Min(p2->p[i].y, b2.low.y);
+		b2.high.x = FLOAT_MAX(p2->p[i].x, b2.high.x);
+		b2.high.y = FLOAT_MAX(p2->p[i].y, b2.high.y);
+		b2.low.x = FLOAT_MIN(p2->p[i].x, b2.low.x);
+		b2.low.y = FLOAT_MIN(p2->p[i].y, b2.low.y);
 	}
 	if (!box_ov(&b1, &b2))
 		PG_RETURN_BOOL(false);
 
 	/* pairwise check lseg intersections */
 	for (i = 0; i < p1->npts; i++)
 	{
 		int			iprev;
 
 		if (i > 0)
@@ -1663,21 +1754,21 @@ path_distance(PG_FUNCTION_ARGS)
 					continue;
 				jprev = p2->npts - 1;	/* include the closure segment */
 			}
 
 			statlseg_construct(&seg1, &p1->p[iprev], &p1->p[i]);
 			statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
 			tmp = DatumGetFloat8(DirectFunctionCall2(lseg_distance,
 													 LsegPGetDatum(&seg1),
 													 LsegPGetDatum(&seg2)));
-			if (!have_min || tmp < min)
+			if (!have_min || FLOAT_LT(tmp, min))
 			{
 				min = tmp;
 				have_min = true;
 			}
 		}
 	}
 
 	if (!have_min)
 		PG_RETURN_NULL();
 
@@ -1686,38 +1777,43 @@ path_distance(PG_FUNCTION_ARGS)
 
 
 /*----------------------------------------------------------
  *	"Arithmetic" operations.
  *---------------------------------------------------------*/
 
 Datum
 path_length(PG_FUNCTION_ARGS)
 {
 	PATH	   *path = PG_GETARG_PATH_P(0);
+	bool		has_inf = false;
+	float8		distance;
 	float8		result = 0.0;
 	int			i;
 
 	for (i = 0; i < path->npts; i++)
 	{
 		int			iprev;
 
 		if (i > 0)
 			iprev = i - 1;
 		else
 		{
 			if (!path->closed)
 				continue;
 			iprev = path->npts - 1;		/* include the closure segment */
 		}
 
-		result += point_dt(&path->p[iprev], &path->p[i]);
+		distance = point_dt(&path->p[iprev], &path->p[i]);
+		has_inf |= isinf(distance);
+		result += distance;
 	}
+	CHECKFLOATVAL(result, has_inf, true);
 
 	PG_RETURN_FLOAT8(result);
 }
 
 /***********************************************************************
  **
  **		Routines for 2D points.
  **
  ***********************************************************************/
 
@@ -1746,26 +1842,23 @@ point_out(PG_FUNCTION_ARGS)
 	PG_RETURN_CSTRING(path_encode(PATH_NONE, 1, pt));
 }
 
 /*
  *		point_recv			- converts external binary format to point
  */
 Datum
 point_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
-	Point	   *point;
 
-	point = (Point *) palloc(sizeof(Point));
-	point->x = pq_getmsgfloat8(buf);
-	point->y = pq_getmsgfloat8(buf);
-	PG_RETURN_POINT_P(point);
+	PG_RETURN_POINT_P(point_construct(pq_getmsgfloat8(buf),
+									  pq_getmsgfloat8(buf)));
 }
 
 /*
  *		point_send			- converts point to binary format
  */
 Datum
 point_send(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	StringInfoData buf;
@@ -1784,153 +1877,162 @@ point_construct(double x, double y)
 
 	result->x = x;
 	result->y = y;
 	return result;
 }
 
 
 static Point *
 point_copy(Point *pt)
 {
-	Point	   *result;
-
-	if (!PointerIsValid(pt))
-		return NULL;
-
-	result = (Point *) palloc(sizeof(Point));
-
-	result->x = pt->x;
-	result->y = pt->y;
-	return result;
+	return point_construct(pt->x, pt->y);
 }
 
 
 /*----------------------------------------------------------
  *	Relational operators for Points.
  *		Since we do have a sense of coordinates being
  *		"equal" to a given accuracy (point_vert, point_horiz),
  *		the other ops must preserve that sense.  This means
  *		that results may, strictly speaking, be a lie (unless
  *		EPSILON = 0.0).
  *---------------------------------------------------------*/
 
 Datum
 point_left(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPlt(pt1->x, pt2->x));
+	PG_RETURN_BOOL(FLOAT_LT(pt1->x, pt2->x));
 }
 
 Datum
 point_right(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPgt(pt1->x, pt2->x));
+	PG_RETURN_BOOL(FLOAT_GT(pt1->x, pt2->x));
 }
 
 Datum
 point_above(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPgt(pt1->y, pt2->y));
+	PG_RETURN_BOOL(FLOAT_GT(pt1->y, pt2->y));
 }
 
 Datum
 point_below(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPlt(pt1->y, pt2->y));
+	PG_RETURN_BOOL(FLOAT_LT(pt1->y, pt2->y));
 }
 
 Datum
 point_vert(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPeq(pt1->x, pt2->x));
+	PG_RETURN_BOOL(FLOAT_EQ(pt1->x, pt2->x));
 }
 
 Datum
 point_horiz(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPeq(pt1->y, pt2->y));
+	PG_RETURN_BOOL(FLOAT_EQ(pt1->y, pt2->y));
 }
 
 Datum
 point_eq(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPeq(pt1->x, pt2->x) && FPeq(pt1->y, pt2->y));
+	PG_RETURN_BOOL(FLOAT_EQ(pt1->x, pt2->x) && FLOAT_EQ(pt1->y, pt2->y));
 }
 
 Datum
 point_ne(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(FPne(pt1->x, pt2->x) || FPne(pt1->y, pt2->y));
+	PG_RETURN_BOOL(FLOAT_NE(pt1->x, pt2->x) || FLOAT_NE(pt1->y, pt2->y));
 }
 
 /*----------------------------------------------------------
  *	"Arithmetic" operators on points.
  *---------------------------------------------------------*/
 
 Datum
 point_distance(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_FLOAT8(HYPOT(pt1->x - pt2->x, pt1->y - pt2->y));
+	PG_RETURN_FLOAT8(point_dt(pt1, pt2));
 }
 
-double
+static double
 point_dt(Point *pt1, Point *pt2)
 {
+	double		xdiff,
+				ydiff,
+				result;
+
+	FLOAT_MI(xdiff, pt1->x, pt2->x);
+	FLOAT_MI(ydiff, pt1->y, pt2->y);
+	FLOAT_HYPOT(result, xdiff, ydiff);
+
 #ifdef GEODEBUG
 	printf("point_dt- segment (%f,%f),(%f,%f) length is %f\n",
-	pt1->x, pt1->y, pt2->x, pt2->y, HYPOT(pt1->x - pt2->x, pt1->y - pt2->y));
+		   pt1->x, pt1->y, pt2->x, pt2->y, result);
 #endif
-	return HYPOT(pt1->x - pt2->x, pt1->y - pt2->y);
+
+	return result;
 }
 
 Datum
 point_slope(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_FLOAT8(point_sl(pt1, pt2));
+	PG_RETURN_FLOAT8(slope(pt1->x, pt2->x, pt1->y, pt2->y));
 }
 
 
 double
-point_sl(Point *pt1, Point *pt2)
+slope(double x1, double x2, double y1, double y2)
 {
-	return (FPeq(pt1->x, pt2->x)
-			? (double) DBL_MAX
-			: (pt1->y - pt2->y) / (pt1->x - pt2->x));
+	double		xdiff;
+	double		ydiff;
+	double		result;
+
+	if (FLOAT_EQ(x1, x2))
+		return DBL_MAX;
+
+	FLOAT_MI(xdiff, x1, x2);
+	FLOAT_MI(ydiff, y1, y2);
+	FLOAT_DIV(result, ydiff, xdiff);
+
+	return result;
 }
 
 
 /***********************************************************************
  **
  **		Routines for 2D line segments.
  **
  ***********************************************************************/
 
 /*----------------------------------------------------------
@@ -2002,24 +2104,21 @@ lseg_send(PG_FUNCTION_ARGS)
 /* lseg_construct -
  *		form a LSEG from two Points.
  */
 Datum
 lseg_construct(PG_FUNCTION_ARGS)
 {
 	Point	   *pt1 = PG_GETARG_POINT_P(0);
 	Point	   *pt2 = PG_GETARG_POINT_P(1);
 	LSEG	   *result = (LSEG *) palloc(sizeof(LSEG));
 
-	result->p[0].x = pt1->x;
-	result->p[0].y = pt1->y;
-	result->p[1].x = pt2->x;
-	result->p[1].y = pt2->y;
+	statlseg_construct(result, pt1, pt2);
 
 	PG_RETURN_LSEG_P(result);
 }
 
 /* like lseg_construct, but assume space already allocated */
 static void
 statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2)
 {
 	lseg->p[0].x = pt1->x;
 	lseg->p[0].y = pt1->y;
@@ -2048,154 +2147,146 @@ lseg_intersect(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
 	PG_RETURN_BOOL(lseg_intersect_internal(l1, l2));
 }
 
 static bool
 lseg_intersect_internal(LSEG *l1, LSEG *l2)
 {
-	LINE		ln;
 	Point	   *interpt;
-	bool		retval;
 
-	line_construct_pts(&ln, &l2->p[0], &l2->p[1]);
-	interpt = interpt_sl(l1, &ln);
+	interpt = line_interpt_internal(line_construct_pts(&l1->p[0], &l1->p[1]),
+									line_construct_pts(&l2->p[0], &l2->p[1]));
 
-	if (interpt != NULL && on_ps_internal(interpt, l2))
-		retval = true;			/* interpt on l1 and l2 */
-	else
-		retval = false;
-	return retval;
+	return (interpt != NULL &&
+			point_lseg_cmp(interpt, l1) == 0 &&
+			point_lseg_cmp(interpt, l2) == 0);
 }
 
 Datum
 lseg_parallel(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(FPeq(point_sl(&l1->p[0], &l1->p[1]),
-						point_sl(&l2->p[0], &l2->p[1])));
+	PG_RETURN_BOOL(FLOAT_EQ(slope(l1->p[0].x, l1->p[1].x, l1->p[0].y, l1->p[1].y),
+							slope(l2->p[0].x, l2->p[1].x, l2->p[0].y, l2->p[1].y)));
 }
 
 /* lseg_perp()
  * Determine if two line segments are perpendicular.
  *
  * This code did not get the correct answer for
  *	'((0,0),(0,1))'::lseg ?-| '((0,0),(1,0))'::lseg
  * So, modified it to check explicitly for slope of vertical line
- *	returned by point_sl() and the results seem better.
+ *	returned by slope() and the results seem better.
  * - thomas 1998-01-31
  */
 Datum
 lseg_perp(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 	double		m1,
 				m2;
 
-	m1 = point_sl(&(l1->p[0]), &(l1->p[1]));
-	m2 = point_sl(&(l2->p[0]), &(l2->p[1]));
+	m1 = slope(l1->p[0].x, l1->p[1].x, l1->p[0].y, l1->p[1].y);
+	m2 = slope(l2->p[0].x, l2->p[1].x, l2->p[0].y, l2->p[1].y);
 
 #ifdef GEODEBUG
 	printf("lseg_perp- slopes are %g and %g\n", m1, m2);
 #endif
-	if (FPzero(m1))
-		PG_RETURN_BOOL(FPeq(m2, DBL_MAX));
-	else if (FPzero(m2))
-		PG_RETURN_BOOL(FPeq(m1, DBL_MAX));
 
-	PG_RETURN_BOOL(FPeq(m1 / m2, -1.0));
+	PG_RETURN_BOOL(FLOAT_EQ(m1, -m2));
 }
 
 Datum
 lseg_vertical(PG_FUNCTION_ARGS)
 {
 	LSEG	   *lseg = PG_GETARG_LSEG_P(0);
 
-	PG_RETURN_BOOL(FPeq(lseg->p[0].x, lseg->p[1].x));
+	PG_RETURN_BOOL(FLOAT_EQ(lseg->p[0].x, lseg->p[1].x));
 }
 
 Datum
 lseg_horizontal(PG_FUNCTION_ARGS)
 {
 	LSEG	   *lseg = PG_GETARG_LSEG_P(0);
 
-	PG_RETURN_BOOL(FPeq(lseg->p[0].y, lseg->p[1].y));
+	PG_RETURN_BOOL(FLOAT_EQ(lseg->p[0].y, lseg->p[1].y));
 }
 
 
 Datum
 lseg_eq(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(FPeq(l1->p[0].x, l2->p[0].x) &&
-				   FPeq(l1->p[0].y, l2->p[0].y) &&
-				   FPeq(l1->p[1].x, l2->p[1].x) &&
-				   FPeq(l1->p[1].y, l2->p[1].y));
+	PG_RETURN_BOOL(FLOAT_EQ(l1->p[0].x, l2->p[0].x) &&
+				   FLOAT_EQ(l1->p[0].y, l2->p[0].y) &&
+				   FLOAT_EQ(l1->p[1].x, l2->p[1].x) &&
+				   FLOAT_EQ(l1->p[1].y, l2->p[1].y));
 }
 
 Datum
 lseg_ne(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(!FPeq(l1->p[0].x, l2->p[0].x) ||
-				   !FPeq(l1->p[0].y, l2->p[0].y) ||
-				   !FPeq(l1->p[1].x, l2->p[1].x) ||
-				   !FPeq(l1->p[1].y, l2->p[1].y));
+	PG_RETURN_BOOL(FLOAT_NE(l1->p[0].x, l2->p[0].x) ||
+				   FLOAT_NE(l1->p[0].y, l2->p[0].y) ||
+				   FLOAT_NE(l1->p[1].x, l2->p[1].x) ||
+				   FLOAT_NE(l1->p[1].y, l2->p[1].y));
 }
 
 Datum
 lseg_lt(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(FPlt(point_dt(&l1->p[0], &l1->p[1]),
-						point_dt(&l2->p[0], &l2->p[1])));
+	PG_RETURN_BOOL(FLOAT_LT(point_dt(&l1->p[0], &l1->p[1]),
+							point_dt(&l2->p[0], &l2->p[1])));
 }
 
 Datum
 lseg_le(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(FPle(point_dt(&l1->p[0], &l1->p[1]),
-						point_dt(&l2->p[0], &l2->p[1])));
+	PG_RETURN_BOOL(FLOAT_LE(point_dt(&l1->p[0], &l1->p[1]),
+							point_dt(&l2->p[0], &l2->p[1])));
 }
 
 Datum
 lseg_gt(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(FPgt(point_dt(&l1->p[0], &l1->p[1]),
-						point_dt(&l2->p[0], &l2->p[1])));
+	PG_RETURN_BOOL(FLOAT_GT(point_dt(&l1->p[0], &l1->p[1]),
+							point_dt(&l2->p[0], &l2->p[1])));
 }
 
 Datum
 lseg_ge(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 
-	PG_RETURN_BOOL(FPge(point_dt(&l1->p[0], &l1->p[1]),
-						point_dt(&l2->p[0], &l2->p[1])));
+	PG_RETURN_BOOL(FLOAT_GE(point_dt(&l1->p[0], &l1->p[1]),
+							point_dt(&l2->p[0], &l2->p[1])));
 }
 
 
 /*----------------------------------------------------------
  *	Line arithmetic routines.
  *---------------------------------------------------------*/
 
 /* lseg_distance -
  *		If two segments don't intersect, then the closest
  *		point will be from one of the endpoints to the other
@@ -2217,92 +2308,78 @@ lseg_distance(PG_FUNCTION_ARGS)
  */
 static double
 lseg_dt(LSEG *l1, LSEG *l2)
 {
 	double		result,
 				d;
 
 	if (lseg_intersect_internal(l1, l2))
 		return 0.0;
 
-	d = dist_ps_internal(&l1->p[0], l2);
-	result = d;
+	result = dist_ps_internal(&l1->p[0], l2);
 	d = dist_ps_internal(&l1->p[1], l2);
-	result = Min(result, d);
+	if (FLOAT_LT(d, result))
+		result = d;
 	d = dist_ps_internal(&l2->p[0], l1);
-	result = Min(result, d);
+	if (FLOAT_LT(d, result))
+		result = d;
 	d = dist_ps_internal(&l2->p[1], l1);
-	result = Min(result, d);
+	if (FLOAT_LT(d, result))
+		result = d;
 
 	return result;
 }
 
 
 Datum
 lseg_center(PG_FUNCTION_ARGS)
 {
 	LSEG	   *lseg = PG_GETARG_LSEG_P(0);
-	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
+	PG_RETURN_POINT_P(lseg_center_internal(lseg));
+}
 
-	result->x = (lseg->p[0].x + lseg->p[1].x) / 2.0;
-	result->y = (lseg->p[0].y + lseg->p[1].y) / 2.0;
+static Point *
+lseg_center_internal(LSEG *lseg)
+{
+	double		xsum;
+	double		ysum;
+	double		x;
+	double		y;
 
-	PG_RETURN_POINT_P(result);
+	FLOAT_PL(xsum, lseg->p[0].x, lseg->p[1].x);
+	FLOAT_PL(ysum, lseg->p[0].y, lseg->p[1].y);
+	FLOAT_DIV(x, xsum, 2.0);
+	FLOAT_DIV(y, ysum, 2.0);
+
+	return point_construct(x, y);
 }
 
 static Point *
 lseg_interpt_internal(LSEG *l1, LSEG *l2)
 {
 	Point	   *result;
-	LINE		tmp1,
-				tmp2;
 
-	/*
-	 * Find the intersection of the appropriate lines, if any.
-	 */
-	line_construct_pts(&tmp1, &l1->p[0], &l1->p[1]);
-	line_construct_pts(&tmp2, &l2->p[0], &l2->p[1]);
-	result = line_interpt_internal(&tmp1, &tmp2);
+	/* Find the intersection of the appropriate lines, if any */
+	result = line_interpt_internal(line_construct_pts(&l1->p[0], &l1->p[1]),
+								   line_construct_pts(&l2->p[0], &l2->p[1]));
 	if (!PointerIsValid(result))
 		return NULL;
 
-	/*
-	 * If the line intersection point isn't within l1 (or equivalently l2),
-	 * there is no valid segment intersection point at all.
-	 */
-	if (!on_ps_internal(result, l1) ||
-		!on_ps_internal(result, l2))
+	/* Test if the point extend the segments of the lines */
+	if (point_lseg_cmp(result, l1) != 0 ||
+		point_lseg_cmp(result, l2) != 0)
 	{
 		pfree(result);
 		return NULL;
 	}
 
-	/*
-	 * If there is an intersection, then check explicitly for matching
-	 * endpoints since there may be rounding effects with annoying lsb
-	 * residue. - tgl 1997-07-09
-	 */
-	if ((FPeq(l1->p[0].x, l2->p[0].x) && FPeq(l1->p[0].y, l2->p[0].y)) ||
-		(FPeq(l1->p[0].x, l2->p[1].x) && FPeq(l1->p[0].y, l2->p[1].y)))
-	{
-		result->x = l1->p[0].x;
-		result->y = l1->p[0].y;
-	}
-	else if ((FPeq(l1->p[1].x, l2->p[0].x) && FPeq(l1->p[1].y, l2->p[0].y)) ||
-			 (FPeq(l1->p[1].x, l2->p[1].x) && FPeq(l1->p[1].y, l2->p[1].y)))
-	{
-		result->x = l1->p[1].x;
-		result->y = l1->p[1].y;
-	}
-
 	return result;
 }
 
 /* lseg_interpt -
  *		Find the intersection point of two segments (if any).
  */
 Datum
 lseg_interpt(PG_FUNCTION_ARGS)
 {
 	LSEG	   *l1 = PG_GETARG_LSEG_P(0);
@@ -2336,22 +2413,29 @@ dist_pl(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	LINE	   *line = PG_GETARG_LINE_P(1);
 
 	PG_RETURN_FLOAT8(dist_pl_internal(pt, line));
 }
 
 static double
 dist_pl_internal(Point *pt, LINE *line)
 {
-	return fabs((line->A * pt->x + line->B * pt->y + line->C) /
-				HYPOT(line->A, line->B));
+	double		val;
+	double		hyp;
+	double		result;
+
+	val = point_on_line_value(pt, line);
+	FLOAT_HYPOT(hyp, line->A, line->B);
+	FLOAT_DIV(result, val, hyp);
+
+	return fabs(result);
 }
 
 /*
  * Distance from a point to a lseg
  */
 Datum
 dist_ps(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	LSEG	   *lseg = PG_GETARG_LSEG_P(1);
@@ -2365,69 +2449,65 @@ dist_ps_internal(Point *pt, LSEG *lseg)
 	double		m;				/* slope of perp. */
 	LINE	   *ln;
 	double		result,
 				tmpdist;
 	Point	   *ip;
 
 	/*
 	 * Construct a line perpendicular to the input segment and through the
 	 * input point
 	 */
-	if (lseg->p[1].x == lseg->p[0].x)
-		m = 0;
-	else if (lseg->p[1].y == lseg->p[0].y)
-		m = (double) DBL_MAX;	/* slope is infinite */
-	else
-		m = (lseg->p[0].x - lseg->p[1].x) / (lseg->p[1].y - lseg->p[0].y);
+	m = slope(lseg->p[1].y, lseg->p[0].y, lseg->p[0].x, lseg->p[1].x);
 	ln = line_construct_pm(pt, m);
 
 #ifdef GEODEBUG
 	printf("dist_ps- line is A=%g B=%g C=%g from (point) slope (%f,%f) %g\n",
 		   ln->A, ln->B, ln->C, pt->x, pt->y, m);
 #endif
 
 	/*
 	 * Calculate distance to the line segment or to the nearest endpoint of
 	 * the segment.
 	 */
 
 	/* intersection is on the line segment? */
-	if ((ip = interpt_sl(lseg, ln)) != NULL)
+	ip = interpt_sl(lseg, ln);
+	if (ip != NULL)
 	{
 		/* yes, so use distance to the intersection point */
 		result = point_dt(pt, ip);
 #ifdef GEODEBUG
 		printf("dist_ps- distance is %f to intersection point is (%f,%f)\n",
 			   result, ip->x, ip->y);
 #endif
 	}
 	else
 	{
 		/* no, so use distance to the nearer endpoint */
 		result = point_dt(pt, &lseg->p[0]);
 		tmpdist = point_dt(pt, &lseg->p[1]);
-		if (tmpdist < result)
+		if (FLOAT_LT(tmpdist, result))
 			result = tmpdist;
 	}
 
 	return result;
 }
 
 /*
  * Distance from a point to a path
  */
 Datum
 dist_ppath(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	PATH	   *path = PG_GETARG_PATH_P(1);
-	float8		result = 0.0;	/* keep compiler quiet */
+	float8		result;
 	bool		have_min = false;
 	float8		tmp;
 	int			i;
 	LSEG		lseg;
 
 	switch (path->npts)
 	{
 		case 0:
 			/* no points in path? then result is undefined... */
 			PG_RETURN_NULL();
@@ -2436,36 +2516,37 @@ dist_ppath(PG_FUNCTION_ARGS)
 			result = point_dt(pt, &path->p[0]);
 			break;
 		default:
 			/* make sure the path makes sense... */
 			Assert(path->npts > 1);
 
 			/*
 			 * the distance from a point to a path is the smallest distance
 			 * from the point to any of its constituent segments.
 			 */
+			result = 0.0;
 			for (i = 0; i < path->npts; i++)
 			{
 				int			iprev;
 
 				if (i > 0)
 					iprev = i - 1;
 				else
 				{
 					if (!path->closed)
 						continue;
 					iprev = path->npts - 1;		/* include the closure segment */
 				}
 
 				statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
 				tmp = dist_ps_internal(pt, &lseg);
-				if (!have_min || tmp < result)
+				if (!have_min || FLOAT_LT(tmp, result))
 				{
 					result = tmp;
 					have_min = true;
 				}
 			}
 			break;
 	}
 	PG_RETURN_FLOAT8(result);
 }
 
@@ -2498,22 +2579,21 @@ dist_sl(PG_FUNCTION_ARGS)
 	LINE	   *line = PG_GETARG_LINE_P(1);
 	float8		result,
 				d2;
 
 	if (has_interpt_sl(lseg, line))
 		result = 0.0;
 	else
 	{
 		result = dist_pl_internal(&lseg->p[0], line);
 		d2 = dist_pl_internal(&lseg->p[1], line);
-		/* XXX shouldn't we take the min not max? */
-		if (d2 > result)
+		if (FLOAT_LT(d2, result))
 			result = d2;
 	}
 
 	PG_RETURN_FLOAT8(result);
 }
 
 /*
  * Distance from a lseg to a box
  */
 Datum
@@ -2554,28 +2634,28 @@ dist_lb(PG_FUNCTION_ARGS)
 }
 
 /*
  * Distance from a circle to a polygon
  */
 Datum
 dist_cpoly(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	POLYGON    *poly = PG_GETARG_POLYGON_P(1);
+	float8		dist;
 	float8		result;
 
 	/* calculate distance to center, and subtract radius */
-	result = dist_ppoly_internal(&circle->center, poly);
-
-	result -= circle->radius;
-	if (result < 0)
-		result = 0;
+	dist = dist_ppoly_internal(&circle->center, poly);
+	FLOAT_MI(result, dist, circle->radius);
+	if (FLOAT_LT(result, 0.0))
+		result = 0.0;
 
 	PG_RETURN_FLOAT8(result);
 }
 
 /*
  * Distance from a point to a polygon
  */
 Datum
 dist_ppoly(PG_FUNCTION_ARGS)
 {
@@ -2630,56 +2710,54 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
 	for (i = 0; (i < poly->npts - 1); i++)
 	{
 		seg.p[0].x = poly->p[i].x;
 		seg.p[0].y = poly->p[i].y;
 		seg.p[1].x = poly->p[i + 1].x;
 		seg.p[1].y = poly->p[i + 1].y;
 		d = dist_ps_internal(pt, &seg);
 #ifdef GEODEBUG
 		printf("dist_ppoly_internal- segment %d distance is %f\n", (i + 1), d);
 #endif
-		if (d < result)
+		if (FLOAT_LT(d, result))
 			result = d;
 	}
 
 	return result;
 }
 
 
 /*---------------------------------------------------------------------
  *		interpt_
  *				Intersection point of objects.
  *				We choose to ignore the "point" of intersection between
  *				  lines and boxes, since there are typically two.
  *-------------------------------------------------------------------*/
 
 /* Get intersection point of lseg and line; returns NULL if no intersection */
 static Point *
 interpt_sl(LSEG *lseg, LINE *line)
 {
-	LINE		tmp;
 	Point	   *p;
 
-	line_construct_pts(&tmp, &lseg->p[0], &lseg->p[1]);
-	p = line_interpt_internal(&tmp, line);
+	line_construct_pts(&lseg->p[0], &lseg->p[1]);
+	p = line_interpt_internal(line_construct_pts(&lseg->p[0], &lseg->p[1]),
+							  line);
 #ifdef GEODEBUG
 	printf("interpt_sl- segment is (%.*g %.*g) (%.*g %.*g)\n",
 		   DBL_DIG, lseg->p[0].x, DBL_DIG, lseg->p[0].y, DBL_DIG, lseg->p[1].x, DBL_DIG, lseg->p[1].y);
-	printf("interpt_sl- segment becomes line A=%.*g B=%.*g C=%.*g\n",
-		   DBL_DIG, tmp.A, DBL_DIG, tmp.B, DBL_DIG, tmp.C);
 #endif
 	if (PointerIsValid(p))
 	{
 #ifdef GEODEBUG
 		printf("interpt_sl- intersection point is (%.*g %.*g)\n", DBL_DIG, p->x, DBL_DIG, p->y);
 #endif
-		if (on_ps_internal(p, lseg))
+		if (point_lseg_cmp(p, lseg) == 0)
 		{
 #ifdef GEODEBUG
 			printf("interpt_sl- intersection point is on segment\n");
 #endif
 		}
 		else
 			p = NULL;
 	}
 
 	return p;
@@ -2704,174 +2782,81 @@ has_interpt_sl(LSEG *lseg, LINE *line)
 
 /* close_pl -
  *		The intersection point of a perpendicular of the line
  *		through the point.
  */
 Datum
 close_pl(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	LINE	   *line = PG_GETARG_LINE_P(1);
+
+	PG_RETURN_POINT_P(close_pl_internal(pt, line));
+}
+
+static Point *
+close_pl_internal(Point *pt, LINE *line)
+{
 	Point	   *result;
-	LINE	   *tmp;
-	double		invm;
+	double		val;
 
-	result = (Point *) palloc(sizeof(Point));
-
-	if (FPzero(line->B))		/* vertical? */
+	if (FLOAT_EQ(line->B, 0.0))			/* vertical? */
 	{
-		result->x = line->C;
-		result->y = pt->y;
-		PG_RETURN_POINT_P(result);
+		FLOAT_DIV(val, -line->C, line->A);
+		result = point_construct(val, pt->y);
 	}
-	if (FPzero(line->A))		/* horizontal? */
+	else if (FLOAT_EQ(line->A, 0.0))	/* horizontal? */
 	{
-		result->x = pt->x;
-		result->y = line->C;
-		PG_RETURN_POINT_P(result);
+		FLOAT_DIV(val, -line->C, line->B);
+		result = point_construct(val, pt->y);
+	}
+	else
+	{
+		/*
+		 * Drop a perpendicular and find the intersection point
+		 *
+		 * We need to invert and flip the sign on the slope to get
+		 * the perpendicular.  line_interpt_internal() returns NULL,
+		 * when the lines are parallel.  We might lose some precision
+		 * on the division, but it cannot be as much to turn the line.
+		 */
+		FLOAT_DIV(val, line->B, line->A);
+		result = line_interpt_internal(line_construct_pm(pt, val), line);
+		Assert(result != NULL);
 	}
-	/* drop a perpendicular and find the intersection point */
 
-	/* invert and flip the sign on the slope to get a perpendicular */
-	invm = line->B / line->A;
-	tmp = line_construct_pm(pt, invm);
-	result = line_interpt_internal(tmp, line);
-	Assert(result != NULL);
-	PG_RETURN_POINT_P(result);
+	return result;
 }
 
 
-/* close_ps()
- * Closest point on line segment to specified point.
- * Take the closest endpoint if the point is left, right,
- *	above, or below the segment, otherwise find the intersection
- *	point of the segment and its perpendicular through the point.
+/*
+ * Closest point on line segment to specified point
  *
- * Some tricky code here, relying on boolean expressions
- *	evaluating to only zero or one to use as an array index.
- *		bug fixes by gthaker@atl.lmco.com; May 1, 1998
+ * We find the closest point to the line, and then test if the point is
+ * on the line segment.  If it is not, we return the closest endpoint
+ * of the line segment.
  */
 Datum
 close_ps(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	LSEG	   *lseg = PG_GETARG_LSEG_P(1);
-	Point	   *result = NULL;
-	LINE	   *tmp;
-	double		invm;
-	int			xh,
-				yh;
+	Point	   *result;
+	int			order;
 
-#ifdef GEODEBUG
-	printf("close_sp:pt->x %f pt->y %f\nlseg(0).x %f lseg(0).y %f  lseg(1).x %f lseg(1).y %f\n",
-		   pt->x, pt->y, lseg->p[0].x, lseg->p[0].y,
-		   lseg->p[1].x, lseg->p[1].y);
-#endif
+	result = close_pl_internal(pt, line_construct_pts(&lseg->p[0], &lseg->p[1]));
+	order = point_lseg_cmp(result, lseg);
 
-	/* xh (or yh) is the index of upper x( or y) end point of lseg */
-	/* !xh (or !yh) is the index of lower x( or y) end point of lseg */
-	xh = lseg->p[0].x < lseg->p[1].x;
-	yh = lseg->p[0].y < lseg->p[1].y;
-
-	if (FPeq(lseg->p[0].x, lseg->p[1].x))		/* vertical? */
-	{
-#ifdef GEODEBUG
-		printf("close_ps- segment is vertical\n");
-#endif
-		/* first check if point is below or above the entire lseg. */
-		if (pt->y < lseg->p[!yh].y)
-			result = point_copy(&lseg->p[!yh]); /* below the lseg */
-		else if (pt->y > lseg->p[yh].y)
-			result = point_copy(&lseg->p[yh]);	/* above the lseg */
-		if (result != NULL)
-			PG_RETURN_POINT_P(result);
-
-		/* point lines along (to left or right) of the vertical lseg. */
-
-		result = (Point *) palloc(sizeof(Point));
-		result->x = lseg->p[0].x;
-		result->y = pt->y;
-		PG_RETURN_POINT_P(result);
-	}
-	else if (FPeq(lseg->p[0].y, lseg->p[1].y))	/* horizontal? */
-	{
-#ifdef GEODEBUG
-		printf("close_ps- segment is horizontal\n");
-#endif
-		/* first check if point is left or right of the entire lseg. */
-		if (pt->x < lseg->p[!xh].x)
-			result = point_copy(&lseg->p[!xh]); /* left of the lseg */
-		else if (pt->x > lseg->p[xh].x)
-			result = point_copy(&lseg->p[xh]);	/* right of the lseg */
-		if (result != NULL)
-			PG_RETURN_POINT_P(result);
-
-		/* point lines along (at top or below) the horiz. lseg. */
-		result = (Point *) palloc(sizeof(Point));
-		result->x = pt->x;
-		result->y = lseg->p[0].y;
-		PG_RETURN_POINT_P(result);
-	}
-
-	/*
-	 * vert. and horiz. cases are down, now check if the closest point is one
-	 * of the end points or someplace on the lseg.
-	 */
-
-	invm = -1.0 / point_sl(&(lseg->p[0]), &(lseg->p[1]));
-	tmp = line_construct_pm(&lseg->p[!yh], invm);		/* lower edge of the
-														 * "band" */
-	if (pt->y < (tmp->A * pt->x + tmp->C))
-	{							/* we are below the lower edge */
-		result = point_copy(&lseg->p[!yh]);		/* below the lseg, take lower
-												 * end pt */
-#ifdef GEODEBUG
-		printf("close_ps below: tmp A %f  B %f   C %f\n",
-			   tmp->A, tmp->B, tmp->C);
-#endif
-		PG_RETURN_POINT_P(result);
-	}
-	tmp = line_construct_pm(&lseg->p[yh], invm);		/* upper edge of the
-														 * "band" */
-	if (pt->y > (tmp->A * pt->x + tmp->C))
-	{							/* we are below the lower edge */
-		result = point_copy(&lseg->p[yh]);		/* above the lseg, take higher
-												 * end pt */
-#ifdef GEODEBUG
-		printf("close_ps above: tmp A %f  B %f   C %f\n",
-			   tmp->A, tmp->B, tmp->C);
-#endif
-		PG_RETURN_POINT_P(result);
-	}
-
-	/*
-	 * at this point the "normal" from point will hit lseg. The closest point
-	 * will be somewhere on the lseg
-	 */
-	tmp = line_construct_pm(pt, invm);
-#ifdef GEODEBUG
-	printf("close_ps- tmp A %f  B %f   C %f\n",
-		   tmp->A, tmp->B, tmp->C);
-#endif
-	result = interpt_sl(lseg, tmp);
-
-	/*
-	 * ordinarily we should always find an intersection point, but that could
-	 * fail in the presence of NaN coordinates, and perhaps even from simple
-	 * roundoff issues.  Return a SQL NULL if so.
-	 */
-	if (result == NULL)
-		PG_RETURN_NULL();
-
-#ifdef GEODEBUG
-	printf("close_ps- result.x %f  result.y %f\n", result->x, result->y);
-#endif
+	if (order < 0)
+		PG_RETURN_POINT_P(point_copy(&lseg->p[0]));
+	if (order > 0)
+		PG_RETURN_POINT_P(point_copy(&lseg->p[1]));
 	PG_RETURN_POINT_P(result);
 }
 
 
 /* close_lseg()
  * Closest point to l1 on l2.
  */
 Datum
 close_lseg(PG_FUNCTION_ARGS)
 {
@@ -2879,38 +2864,39 @@ close_lseg(PG_FUNCTION_ARGS)
 	LSEG	   *l2 = PG_GETARG_LSEG_P(1);
 	Point	   *result = NULL;
 	Point		point;
 	double		dist;
 	double		d;
 
 	d = dist_ps_internal(&l1->p[0], l2);
 	dist = d;
 	memcpy(&point, &l1->p[0], sizeof(Point));
 
-	if ((d = dist_ps_internal(&l1->p[1], l2)) < dist)
+	d = dist_ps_internal(&l1->p[1], l2);
+	if (FLOAT_LT(d, dist))
 	{
 		dist = d;
 		memcpy(&point, &l1->p[1], sizeof(Point));
 	}
 
-	if (dist_ps_internal(&l2->p[0], l1) < dist)
+	if (FLOAT_LT(dist_ps_internal(&l2->p[0], l1), dist))
 	{
 		result = DatumGetPointP(DirectFunctionCall2(close_ps,
 													PointPGetDatum(&l2->p[0]),
 													LsegPGetDatum(l1)));
 		memcpy(&point, result, sizeof(Point));
 		result = DatumGetPointP(DirectFunctionCall2(close_ps,
 													PointPGetDatum(&point),
 													LsegPGetDatum(l2)));
 	}
 
-	if (dist_ps_internal(&l2->p[1], l1) < dist)
+	if (FLOAT_LT(dist_ps_internal(&l2->p[1], l1), dist))
 	{
 		result = DatumGetPointP(DirectFunctionCall2(close_ps,
 													PointPGetDatum(&l2->p[1]),
 													LsegPGetDatum(l1)));
 		memcpy(&point, result, sizeof(Point));
 		result = DatumGetPointP(DirectFunctionCall2(close_ps,
 													PointPGetDatum(&point),
 													LsegPGetDatum(l2)));
 	}
 
@@ -2939,37 +2925,40 @@ close_pb(PG_FUNCTION_ARGS)
 										 BoxPGetDatum(box))))
 		PG_RETURN_POINT_P(pt);
 
 	/* pairwise check lseg distances */
 	point.x = box->low.x;
 	point.y = box->high.y;
 	statlseg_construct(&lseg, &box->low, &point);
 	dist = dist_ps_internal(pt, &lseg);
 
 	statlseg_construct(&seg, &box->high, &point);
-	if ((d = dist_ps_internal(pt, &seg)) < dist)
+	d = dist_ps_internal(pt, &seg);
+	if (FLOAT_LT(d, dist))
 	{
 		dist = d;
 		memcpy(&lseg, &seg, sizeof(lseg));
 	}
 
 	point.x = box->high.x;
 	point.y = box->low.y;
 	statlseg_construct(&seg, &box->low, &point);
-	if ((d = dist_ps_internal(pt, &seg)) < dist)
+	d = dist_ps_internal(pt, &seg);
+	if (FLOAT_LT(d, dist))
 	{
 		dist = d;
 		memcpy(&lseg, &seg, sizeof(lseg));
 	}
 
 	statlseg_construct(&seg, &box->high, &point);
-	if ((d = dist_ps_internal(pt, &seg)) < dist)
+	d = dist_ps_internal(pt, &seg);
+	if (FLOAT_LT(d, dist))
 	{
 		dist = d;
 		memcpy(&lseg, &seg, sizeof(lseg));
 	}
 
 	PG_RETURN_DATUM(DirectFunctionCall2(close_ps,
 										PointPGetDatum(pt),
 										LsegPGetDatum(&lseg)));
 }
 
@@ -2991,21 +2980,21 @@ close_sl(PG_FUNCTION_ARGS)
 	Point	   *result;
 	float8		d1,
 				d2;
 
 	result = interpt_sl(lseg, line);
 	if (result)
 		PG_RETURN_POINT_P(result);
 
 	d1 = dist_pl_internal(&lseg->p[0], line);
 	d2 = dist_pl_internal(&lseg->p[1], line);
-	if (d1 < d2)
+	if (FLOAT_LT(d1, d2))
 		result = point_copy(&lseg->p[0]);
 	else
 		result = point_copy(&lseg->p[1]);
 
 	PG_RETURN_POINT_P(result);
 #endif
 
 	ereport(ERROR,
 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			 errmsg("function \"close_sl\" not implemented")));
@@ -3024,21 +3013,21 @@ close_ls(PG_FUNCTION_ARGS)
 	Point	   *result;
 	float8		d1,
 				d2;
 
 	result = interpt_sl(lseg, line);
 	if (result)
 		PG_RETURN_POINT_P(result);
 
 	d1 = dist_pl_internal(&lseg->p[0], line);
 	d2 = dist_pl_internal(&lseg->p[1], line);
-	if (d1 < d2)
+	if (FLOAT_LT(d1, d2))
 		result = point_copy(&lseg->p[0]);
 	else
 		result = point_copy(&lseg->p[1]);
 
 	PG_RETURN_POINT_P(result);
 }
 
 /* close_sb()
  * Closest point on or in box to line segment.
  */
@@ -3064,37 +3053,40 @@ close_sb(PG_FUNCTION_ARGS)
 											LsegPGetDatum(lseg)));
 	}
 
 	/* pairwise check lseg distances */
 	point.x = box->low.x;
 	point.y = box->high.y;
 	statlseg_construct(&bseg, &box->low, &point);
 	dist = lseg_dt(lseg, &bseg);
 
 	statlseg_construct(&seg, &box->high, &point);
-	if ((d = lseg_dt(lseg, &seg)) < dist)
+	d = lseg_dt(lseg, &seg);
+	if (FLOAT_LT(d, dist))
 	{
 		dist = d;
 		memcpy(&bseg, &seg, sizeof(bseg));
 	}
 
 	point.x = box->high.x;
 	point.y = box->low.y;
 	statlseg_construct(&seg, &box->low, &point);
-	if ((d = lseg_dt(lseg, &seg)) < dist)
+	d = lseg_dt(lseg, &seg);
+	if (FLOAT_LE(d, dist))
 	{
 		dist = d;
 		memcpy(&bseg, &seg, sizeof(bseg));
 	}
 
 	statlseg_construct(&seg, &box->high, &point);
-	if ((d = lseg_dt(lseg, &seg)) < dist)
+	d = lseg_dt(lseg, &seg);
+	if (FLOAT_LE(d, dist))
 	{
 		dist = d;
 		memcpy(&bseg, &seg, sizeof(bseg));
 	}
 
 	/* OK, we now have the closest line segment on the box boundary */
 	PG_RETURN_DATUM(DirectFunctionCall2(close_lseg,
 										LsegPGetDatum(lseg),
 										LsegPGetDatum(&bseg)));
 }
@@ -3113,71 +3105,152 @@ close_lb(PG_FUNCTION_ARGS)
 			 errmsg("function \"close_lb\" not implemented")));
 
 	PG_RETURN_NULL();
 }
 
 /*---------------------------------------------------------------------
  *		on_
  *				Whether one object lies completely within another.
  *-------------------------------------------------------------------*/
 
-/* on_pl -
- *		Does the point satisfy the equation?
+/*
+ * Test if the point satisfies the line equation
  */
 Datum
 on_pl(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	LINE	   *line = PG_GETARG_LINE_P(1);
 
-	PG_RETURN_BOOL(FPzero(line->A * pt->x + line->B * pt->y + line->C));
+	PG_RETURN_BOOL(point_on_line_value(pt, line) == 0);
 }
 
-
-/* on_ps -
- *		Determine colinearity by detecting a triangle inequality.
- * This algorithm seems to behave nicely even with lsb residues - tgl 1997-07-09
- */
 Datum
 on_ps(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	LSEG	   *lseg = PG_GETARG_LSEG_P(1);
 
 	PG_RETURN_BOOL(on_ps_internal(pt, lseg));
 }
 
+/*
+ * Test if the point is on the line segment
+ *
+ * We are first comparing the point with the line segment, even though
+ * this comparison makes no sense when the point is not on the line.
+ * The reason of it is that this check is cheaper than constructing
+ * the line and validating the line equation.
+ */
 static bool
 on_ps_internal(Point *pt, LSEG *lseg)
 {
-	return FPeq(point_dt(pt, &lseg->p[0]) + point_dt(pt, &lseg->p[1]),
-				point_dt(&lseg->p[0], &lseg->p[1]));
+	return (point_lseg_cmp(pt, lseg) == 0 &&
+			FLOAT_EQ(point_on_line_value(pt,
+								line_construct_pts(&lseg->p[0], &lseg->p[1])),
+					 0.0));
+}
+
+/*
+ * Calculate the line equation for a point
+ *
+ * This returns the result of the line equation Ax + By + C.  The result
+ * needs to be 0 for the point to be on the line.
+ */
+static double
+point_on_line_value(Point *pt, LINE *line)
+{
+	double		mulx;
+	double		muly;
+	double		sumxy;
+	double		result;
+
+	FLOAT_MUL(mulx, line->A, pt->x);
+	FLOAT_MUL(muly, line->B, pt->y);
+	FLOAT_PL(sumxy, mulx, muly);
+	FLOAT_PL(result, sumxy, line->C);
+
+	return result;
+}
+
+/*
+ * Compare a point with a line segment
+ *
+ * This function is useful when the point and line segment are on
+ * the same line.  It returns
+ *
+ * * -1, if the point extends the first edge of the segment
+ * * 0, if the point is on the segment
+ * * 1, if the point extends the last edge of the segment.
+ *
+ * This check is not as trivial as checking if a point is inside a box,
+ * because the edges of the line segments are not normalised.  We are
+ * doing the same checks for both x and y coordinates, to be correct
+ * when one of the coordinates of the point is on one edge of the segment.
+ */
+static int
+point_lseg_cmp(Point *pt, LSEG *lseg)
+{
+	if (FLOAT_LT(lseg->p[0].x, lseg->p[1].x))
+	{
+		if (FLOAT_LT(pt->x, lseg->p[0].x))
+			return -1;
+		if (FLOAT_GT(pt->x, lseg->p[1].x))
+			return 1;
+	}
+	else if (FLOAT_GT(lseg->p[0].x, lseg->p[1].x))
+	{
+		if (FLOAT_GT(pt->x, lseg->p[0].x))
+			return -1;
+		if (FLOAT_LT(pt->x, lseg->p[1].x))
+			return 1;
+	}
+	else if (FLOAT_LE(lseg->p[0].y, lseg->p[1].y))
+	{
+		if (FLOAT_LT(pt->y, lseg->p[0].y))
+			return -1;
+		if (FLOAT_GT(pt->y, lseg->p[1].y))
+			return 1;
+	}
+	else
+	{
+		if (FLOAT_GT(pt->y, lseg->p[0].y))
+			return -1;
+		if (FLOAT_LT(pt->y, lseg->p[1].y))
+			return 1;
+	}
+
+	return 0;
 }
 
 Datum
 on_pb(PG_FUNCTION_ARGS)
 {
 	Point	   *pt = PG_GETARG_POINT_P(0);
 	BOX		   *box = PG_GETARG_BOX_P(1);
 
-	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
-				   pt->y <= box->high.y && pt->y >= box->low.y);
+	PG_RETURN_BOOL(FLOAT_LE(pt->x, box->high.x) &&
+				   FLOAT_GE(pt->x, box->low.x) &&
+				   FLOAT_LE(pt->y, box->high.y) &&
+				   FLOAT_GE(pt->y, box->low.y));
 }
 
 Datum
 box_contain_pt(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	Point	   *pt = PG_GETARG_POINT_P(1);
 
-	PG_RETURN_BOOL(pt->x <= box->high.x && pt->x >= box->low.x &&
-				   pt->y <= box->high.y && pt->y >= box->low.y);
+	PG_RETURN_BOOL(FLOAT_LE(pt->x, box->high.x) &&
+				   FLOAT_GE(pt->x, box->low.x) &&
+				   FLOAT_LE(pt->y, box->high.y) &&
+				   FLOAT_GE(pt->y, box->low.y));
 }
 
 /* on_ppath -
  *		Whether a point lies within (on) a polyline.
  *		If open, we have to (groan) check each segment.
  * (uses same algorithm as for point intersecting segment - tgl 1997-07-09)
  *		If closed, we use the old O(n) ray method for point-in-polygon.
  *				The ray is horizontal, from pt out to the right.
  *				Each segment that crosses the ray counts as an
  *				intersection; note that an endpoint or edge may touch
@@ -3195,22 +3268,21 @@ on_ppath(PG_FUNCTION_ARGS)
 				b;
 
 	/*-- OPEN --*/
 	if (!path->closed)
 	{
 		n = path->npts - 1;
 		a = point_dt(pt, &path->p[0]);
 		for (i = 0; i < n; i++)
 		{
 			b = point_dt(pt, &path->p[i + 1]);
-			if (FPeq(a + b,
-					 point_dt(&path->p[i], &path->p[i + 1])))
+			if (FLOAT_EQ(a + b, point_dt(&path->p[i], &path->p[i + 1])))
 				PG_RETURN_BOOL(true);
 			a = b;
 		}
 		PG_RETURN_BOOL(false);
 	}
 
 	/*-- CLOSED --*/
 	PG_RETURN_BOOL(point_inside(pt, path->npts, path->p) != 0);
 }
 
@@ -3268,24 +3340,24 @@ inter_sl(PG_FUNCTION_ARGS)
  */
 Datum
 inter_sb(PG_FUNCTION_ARGS)
 {
 	LSEG	   *lseg = PG_GETARG_LSEG_P(0);
 	BOX		   *box = PG_GETARG_BOX_P(1);
 	BOX			lbox;
 	LSEG		bseg;
 	Point		point;
 
-	lbox.low.x = Min(lseg->p[0].x, lseg->p[1].x);
-	lbox.low.y = Min(lseg->p[0].y, lseg->p[1].y);
-	lbox.high.x = Max(lseg->p[0].x, lseg->p[1].x);
-	lbox.high.y = Max(lseg->p[0].y, lseg->p[1].y);
+	lbox.low.x = FLOAT_MIN(lseg->p[0].x, lseg->p[1].x);
+	lbox.low.y = FLOAT_MIN(lseg->p[0].y, lseg->p[1].y);
+	lbox.high.x = FLOAT_MAX(lseg->p[0].x, lseg->p[1].x);
+	lbox.high.y = FLOAT_MAX(lseg->p[0].y, lseg->p[1].y);
 
 	/* nothing close to overlap? then not going to intersect */
 	if (!box_ov(&lbox, box))
 		PG_RETURN_BOOL(false);
 
 	/* an endpoint of segment is inside box? then clearly intersects */
 	if (DatumGetBool(DirectFunctionCall2(on_pb,
 										 PointPGetDatum(&lseg->p[0]),
 										 BoxPGetDatum(box))) ||
 		DatumGetBool(DirectFunctionCall2(on_pb,
@@ -3377,27 +3449,27 @@ make_bound_box(POLYGON *poly)
 				y1,
 				x2,
 				y2;
 
 	if (poly->npts > 0)
 	{
 		x2 = x1 = poly->p[0].x;
 		y2 = y1 = poly->p[0].y;
 		for (i = 1; i < poly->npts; i++)
 		{
-			if (poly->p[i].x < x1)
+			if (FLOAT_LT(poly->p[i].x, x1))
 				x1 = poly->p[i].x;
-			if (poly->p[i].x > x2)
+			if (FLOAT_GT(poly->p[i].x, x2))
 				x2 = poly->p[i].x;
-			if (poly->p[i].y < y1)
+			if (FLOAT_LT(poly->p[i].y, y1))
 				y1 = poly->p[i].y;
-			if (poly->p[i].y > y2)
+			if (FLOAT_GT(poly->p[i].y, y2))
 				y2 = poly->p[i].y;
 		}
 
 		box_fill(&(poly->boundbox), x1, x2, y1, y2);
 	}
 	else
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("cannot create bounding box for empty polygon")));
 }
@@ -3420,21 +3492,21 @@ poly_in(PG_FUNCTION_ARGS)
 	int			base_size;
 	bool		isopen;
 
 	if ((npts = pair_count(str, ',')) <= 0)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"polygon", str)));
 
 	base_size = sizeof(poly->p[0]) * npts;
-	size = offsetof(POLYGON, p) +base_size;
+	size = offsetof(POLYGON, p) + base_size;
 
 	/* Check for integer overflow */
 	if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("too many points requested")));
 
 	poly = (POLYGON *) palloc0(size);	/* zero any holes */
 
 	SET_VARSIZE(poly, size);
@@ -3475,21 +3547,21 @@ poly_recv(PG_FUNCTION_ARGS)
 	int32		npts;
 	int32		i;
 	int			size;
 
 	npts = pq_getmsgint(buf, sizeof(int32));
 	if (npts <= 0 || npts >= (int32) ((INT_MAX - offsetof(POLYGON, p)) / sizeof(Point)))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 		  errmsg("invalid number of points in external \"polygon\" value")));
 
-	size = offsetof(POLYGON, p) +sizeof(poly->p[0]) * npts;
+	size = offsetof(POLYGON, p) + sizeof(poly->p[0]) * npts;
 	poly = (POLYGON *) palloc0(size);	/* zero any holes */
 
 	SET_VARSIZE(poly, size);
 	poly->npts = npts;
 
 	for (i = 0; i < npts; i++)
 	{
 		poly->p[i].x = pq_getmsgfloat8(buf);
 		poly->p[i].y = pq_getmsgfloat8(buf);
 	}
@@ -3525,21 +3597,21 @@ poly_send(PG_FUNCTION_ARGS)
  * the right most point of A left of the left most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_left(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.high.x < polyb->boundbox.low.x;
+	result = FLOAT_LT(polya->boundbox.high.x, polyb->boundbox.low.x);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3548,21 +3620,21 @@ poly_left(PG_FUNCTION_ARGS)
  * the right most point of A at or left of the right most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_overleft(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.high.x <= polyb->boundbox.high.x;
+	result = FLOAT_LE(polya->boundbox.high.x, polyb->boundbox.high.x);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3571,21 +3643,21 @@ poly_overleft(PG_FUNCTION_ARGS)
  * the left most point of A right of the right most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_right(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.low.x > polyb->boundbox.high.x;
+	result = FLOAT_GT(polya->boundbox.low.x, polyb->boundbox.high.x);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3594,21 +3666,21 @@ poly_right(PG_FUNCTION_ARGS)
  * the left most point of A at or right of the left most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_overright(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.low.x >= polyb->boundbox.low.x;
+	result = FLOAT_GE(polya->boundbox.low.x, polyb->boundbox.low.x);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3617,21 +3689,21 @@ poly_overright(PG_FUNCTION_ARGS)
  * the upper most point of A below the lower most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_below(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.high.y < polyb->boundbox.low.y;
+	result = FLOAT_LT(polya->boundbox.high.y, polyb->boundbox.low.y);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3640,21 +3712,21 @@ poly_below(PG_FUNCTION_ARGS)
  * the upper most point of A at or below the upper most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_overbelow(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.high.y <= polyb->boundbox.high.y;
+	result = FLOAT_LE(polya->boundbox.high.y, polyb->boundbox.high.y);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3663,21 +3735,21 @@ poly_overbelow(PG_FUNCTION_ARGS)
  * the lower most point of A above the upper most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_above(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.low.y > polyb->boundbox.high.y;
+	result = FLOAT_GT(polya->boundbox.low.y, polyb->boundbox.high.y);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3686,21 +3758,21 @@ poly_above(PG_FUNCTION_ARGS)
  * the lower most point of A at or above the lower most point
  * of B?
  *-------------------------------------------------------*/
 Datum
 poly_overabove(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
-	result = polya->boundbox.low.y >= polyb->boundbox.low.y;
+	result = FLOAT_GE(polya->boundbox.low.y, polyb->boundbox.low.y);
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
 	PG_RETURN_BOOL(result);
 }
 
@@ -3738,21 +3810,21 @@ poly_same(PG_FUNCTION_ARGS)
  *-----------------------------------------------------------------*/
 Datum
 poly_overlap(PG_FUNCTION_ARGS)
 {
 	POLYGON    *polya = PG_GETARG_POLYGON_P(0);
 	POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
 	bool		result;
 
 	/* Quick check by bounding box */
 	result = (polya->npts > 0 && polyb->npts > 0 &&
-			  box_ov(&polya->boundbox, &polyb->boundbox)) ? true : false;
+			  box_ov(&polya->boundbox, &polyb->boundbox));
 
 	/*
 	 * Brute-force algorithm - try to find intersected edges, if so then
 	 * polygons are overlapped else check is one polygon inside other or not
 	 * by testing single point of them.
 	 */
 	if (result)
 	{
 		int			ia,
 					ib;
@@ -3779,22 +3851,21 @@ poly_overlap(PG_FUNCTION_ARGS)
 			}
 
 			/*
 			 * move current endpoint to the first point of next edge
 			 */
 			sa.p[0] = sa.p[1];
 		}
 
 		if (result == false)
 		{
-			result = (point_inside(polya->p, polyb->npts, polyb->p)
-					  ||
+			result = (point_inside(polya->p, polyb->npts, polyb->p) ||
 					  point_inside(polyb->p, polya->npts, polya->p));
 		}
 	}
 
 	/*
 	 * Avoid leaking memory for toasted inputs ... needed for rtree indexes
 	 */
 	PG_FREE_IF_COPY(polya, 0);
 	PG_FREE_IF_COPY(polyb, 1);
 
@@ -3814,21 +3885,21 @@ poly_overlap(PG_FUNCTION_ARGS)
 
 static bool
 touched_lseg_inside_poly(Point *a, Point *b, LSEG *s, POLYGON *poly, int start)
 {
 	/* point a is on s, b is not */
 	LSEG		t;
 
 	t.p[0] = *a;
 	t.p[1] = *b;
 
-#define POINTEQ(pt1, pt2)	(FPeq((pt1)->x, (pt2)->x) && FPeq((pt1)->y, (pt2)->y))
+#define POINTEQ(pt1, pt2) (FLOAT_EQ((pt1)->x, (pt2)->x) && FLOAT_EQ((pt1)->y, (pt2)->y))
 	if (POINTEQ(a, s->p))
 	{
 		if (on_ps_internal(s->p + 1, &t))
 			return lseg_inside_poly(b, s->p + 1, poly, start);
 	}
 	else if (POINTEQ(a, s->p + 1))
 	{
 		if (on_ps_internal(s->p, &t))
 			return lseg_inside_poly(b, s->p, poly, start);
 	}
@@ -3894,30 +3965,25 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
 			if (res)
 				res = lseg_inside_poly(t.p + 1, interpt, poly, i + 1);
 			pfree(interpt);
 		}
 
 		s.p[0] = s.p[1];
 	}
 
 	if (res && !intersection)
 	{
-		Point		p;
-
 		/*
 		 * if X-intersection wasn't found  then check central point of tested
 		 * segment. In opposite case we already check all subsegments
 		 */
-		p.x = (t.p[0].x + t.p[1].x) / 2.0;
-		p.y = (t.p[0].y + t.p[1].y) / 2.0;
-
-		res = point_inside(&p, poly->npts, poly->p);
+		res = point_inside(lseg_center_internal(&t), poly->npts, poly->p);
 	}
 
 	return res;
 }
 
 /*-----------------------------------------------------------------
  * Determine if polygon A contains polygon B.
  *-----------------------------------------------------------------*/
 Datum
 poly_contain(PG_FUNCTION_ARGS)
@@ -4013,92 +4079,102 @@ poly_distance(PG_FUNCTION_ARGS)
 
 /***********************************************************************
  **
  **		Routines for 2D points.
  **
  ***********************************************************************/
 
 Datum
 construct_point(PG_FUNCTION_ARGS)
 {
-	float8		x = PG_GETARG_FLOAT8(0);
-	float8		y = PG_GETARG_FLOAT8(1);
+	double		x = PG_GETARG_FLOAT8(0);
+	double		y = PG_GETARG_FLOAT8(1);
 
 	PG_RETURN_POINT_P(point_construct(x, y));
 }
 
 Datum
 point_add(PG_FUNCTION_ARGS)
 {
 	Point	   *p1 = PG_GETARG_POINT_P(0);
 	Point	   *p2 = PG_GETARG_POINT_P(1);
-	Point	   *result;
+	double		x;
+	double		y;
 
-	result = (Point *) palloc(sizeof(Point));
+	FLOAT_PL(x, p1->x, p2->x);
+	FLOAT_PL(y, p1->y, p2->y);
 
-	result->x = (p1->x + p2->x);
-	result->y = (p1->y + p2->y);
-
-	PG_RETURN_POINT_P(result);
+	PG_RETURN_POINT_P(point_construct(x, y));
 }
 
 Datum
 point_sub(PG_FUNCTION_ARGS)
 {
 	Point	   *p1 = PG_GETARG_POINT_P(0);
 	Point	   *p2 = PG_GETARG_POINT_P(1);
-	Point	   *result;
+	double		x;
+	double		y;
 
-	result = (Point *) palloc(sizeof(Point));
+	FLOAT_MI(x, p1->x, p2->x);
+	FLOAT_MI(y, p1->y, p2->y);
 
-	result->x = (p1->x - p2->x);
-	result->y = (p1->y - p2->y);
-
-	PG_RETURN_POINT_P(result);
+	PG_RETURN_POINT_P(point_construct(x, y));
 }
 
 Datum
 point_mul(PG_FUNCTION_ARGS)
 {
 	Point	   *p1 = PG_GETARG_POINT_P(0);
 	Point	   *p2 = PG_GETARG_POINT_P(1);
-	Point	   *result;
+	double		val1;
+	double		val2;
+	double		x;
+	double		y;
 
-	result = (Point *) palloc(sizeof(Point));
+	FLOAT_MUL(val1, p1->x, p2->x);
+	FLOAT_MUL(val2, p1->y, p2->y);
+	FLOAT_MI(x, val1, val2);
 
-	result->x = (p1->x * p2->x) - (p1->y * p2->y);
-	result->y = (p1->x * p2->y) + (p1->y * p2->x);
+	FLOAT_MUL(val1, p1->x, p2->y);
+	FLOAT_MUL(val2, p1->y, p2->x);
+	FLOAT_PL(y, val1, val2);
 
-	PG_RETURN_POINT_P(result);
+	PG_RETURN_POINT_P(point_construct(x, y));
 }
 
 Datum
 point_div(PG_FUNCTION_ARGS)
 {
 	Point	   *p1 = PG_GETARG_POINT_P(0);
 	Point	   *p2 = PG_GETARG_POINT_P(1);
-	Point	   *result;
+	double		mul1;
+	double		mul2;
 	double		div;
+	double		val;
+	double		x;
+	double		y;
 
-	result = (Point *) palloc(sizeof(Point));
+	FLOAT_MUL(mul1, p2->x, p2->x);
+	FLOAT_MUL(mul2, p2->y, p2->y);
+	FLOAT_PL(div, mul1, mul2);
 
-	div = (p2->x * p2->x) + (p2->y * p2->y);
+	FLOAT_MUL(mul1, p1->x, p2->x);
+	FLOAT_MUL(mul2, p1->y, p2->y);
+	FLOAT_PL(val, mul1, mul2);
+	FLOAT_DIV(x, val, div);
 
-	if (div == 0.0)
-		ereport(ERROR,
-				(errcode(ERRCODE_DIVISION_BY_ZERO),
-				 errmsg("division by zero")));
+	FLOAT_MUL(mul1, p1->y, p2->x);
+	FLOAT_MUL(mul2, p1->x, p2->y);
+	FLOAT_MI(val, mul1, mul2);
+	FLOAT_DIV(y, val, div);
 
-	result->x = ((p1->x * p2->x) + (p1->y * p2->y)) / div;
-	result->y = ((p2->x * p1->y) - (p2->y * p1->x)) / div;
-
-	PG_RETURN_POINT_P(result);
+	PG_RETURN_POINT_P(point_construct(x, y));
 }
 
 
 /***********************************************************************
  **
  **		Routines for 2D boxes.
  **
  ***********************************************************************/
 
 Datum
@@ -4108,37 +4184,49 @@ points_box(PG_FUNCTION_ARGS)
 	Point	   *p2 = PG_GETARG_POINT_P(1);
 
 	PG_RETURN_BOX_P(box_construct(p1->x, p2->x, p1->y, p2->y));
 }
 
 Datum
 box_add(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	Point	   *p = PG_GETARG_POINT_P(1);
+	double		highx;
+	double		lowx;
+	double		highy;
+	double		lowy;
 
-	PG_RETURN_BOX_P(box_construct((box->high.x + p->x),
-								  (box->low.x + p->x),
-								  (box->high.y + p->y),
-								  (box->low.y + p->y)));
+	FLOAT_PL(highx, box->high.x, p->x);
+	FLOAT_PL(lowx, box->low.x, p->x);
+	FLOAT_PL(highy, box->high.y, p->y);
+	FLOAT_PL(lowy, box->low.y, p->y);
+
+	PG_RETURN_BOX_P(box_construct(highx, lowx, highy, lowy));
 }
 
 Datum
 box_sub(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	Point	   *p = PG_GETARG_POINT_P(1);
+	double		highx;
+	double		lowx;
+	double		highy;
+	double		lowy;
 
-	PG_RETURN_BOX_P(box_construct((box->high.x - p->x),
-								  (box->low.x - p->x),
-								  (box->high.y - p->y),
-								  (box->low.y - p->y)));
+	FLOAT_MI(highx, box->high.x, p->x);
+	FLOAT_MI(lowx, box->low.x, p->x);
+	FLOAT_MI(highy, box->high.y, p->y);
+	FLOAT_MI(lowy, box->low.y, p->y);
+
+	PG_RETURN_BOX_P(box_construct(highx, lowx, highy, lowy));
 }
 
 Datum
 box_mul(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	Point	   *p = PG_GETARG_POINT_P(1);
 	BOX		   *result;
 	Point	   *high,
 			   *low;
@@ -4200,24 +4288,24 @@ point_box(PG_FUNCTION_ARGS)
  */
 Datum
 boxes_bound_box(PG_FUNCTION_ARGS)
 {
 	BOX		   *box1 = PG_GETARG_BOX_P(0),
 			   *box2 = PG_GETARG_BOX_P(1),
 			   *container;
 
 	container = (BOX *) palloc(sizeof(BOX));
 
-	container->high.x = Max(box1->high.x, box2->high.x);
-	container->low.x = Min(box1->low.x, box2->low.x);
-	container->high.y = Max(box1->high.y, box2->high.y);
-	container->low.y = Min(box1->low.y, box2->low.y);
+	container->high.x = FLOAT_MAX(box1->high.x, box2->high.x);
+	container->low.x = FLOAT_MIN(box1->low.x, box2->low.x);
+	container->high.y = FLOAT_MAX(box1->high.y, box2->high.y);
+	container->low.y = FLOAT_MIN(box1->low.y, box2->low.y);
 
 	PG_RETURN_BOX_P(container);
 }
 
 
 /***********************************************************************
  **
  **		Routines for 2D paths.
  **
  ***********************************************************************/
@@ -4272,41 +4360,49 @@ path_add(PG_FUNCTION_ARGS)
 
 /* path_add_pt()
  * Translation operators.
  */
 Datum
 path_add_pt(PG_FUNCTION_ARGS)
 {
 	PATH	   *path = PG_GETARG_PATH_P_COPY(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
 	int			i;
+	double		val;
 
 	for (i = 0; i < path->npts; i++)
 	{
-		path->p[i].x += point->x;
-		path->p[i].y += point->y;
+		FLOAT_PL(val, path->p[i].x, point->x);
+		path->p[i].x = val;
+
+		FLOAT_PL(val, path->p[i].y, point->y);
+		path->p[i].y = val;
 	}
 
 	PG_RETURN_PATH_P(path);
 }
 
 Datum
 path_sub_pt(PG_FUNCTION_ARGS)
 {
 	PATH	   *path = PG_GETARG_PATH_P_COPY(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
 	int			i;
+	double		val;
 
 	for (i = 0; i < path->npts; i++)
 	{
-		path->p[i].x -= point->x;
-		path->p[i].y -= point->y;
+		FLOAT_MI(val, path->p[i].x, point->x);
+		path->p[i].x = val;
+
+		FLOAT_MI(val, path->p[i].y, point->y);
+		path->p[i].y = val;
 	}
 
 	PG_RETURN_PATH_P(path);
 }
 
 /* path_mul_pt()
  * Rotation and scaling operators.
  */
 Datum
 path_mul_pt(PG_FUNCTION_ARGS)
@@ -4374,21 +4470,21 @@ path_poly(PG_FUNCTION_ARGS)
 	/* This is not very consistent --- other similar cases return NULL ... */
 	if (!path->closed)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("open path cannot be converted to polygon")));
 
 	/*
 	 * Never overflows: the old size fit in MaxAllocSize, and the new size is
 	 * just a small constant larger.
 	 */
-	size = offsetof(POLYGON, p) +sizeof(poly->p[0]) * path->npts;
+	size = offsetof(POLYGON, p) + sizeof(poly->p[0]) * path->npts;
 	poly = (POLYGON *) palloc(size);
 
 	SET_VARSIZE(poly, size);
 	poly->npts = path->npts;
 
 	for (i = 0; i < path->npts; i++)
 	{
 		poly->p[i].x = path->p[i].x;
 		poly->p[i].y = path->p[i].y;
 	}
@@ -4483,26 +4579,26 @@ poly_path(PG_FUNCTION_ARGS)
 {
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	PATH	   *path;
 	int			size;
 	int			i;
 
 	/*
 	 * Never overflows: the old size fit in MaxAllocSize, and the new size is
 	 * smaller by a small constant.
 	 */
-	size = offsetof(PATH, p) +sizeof(path->p[0]) * poly->npts;
+	size = offsetof(PATH, p) + sizeof(path->p[0]) * poly->npts;
 	path = (PATH *) palloc(size);
 
 	SET_VARSIZE(path, size);
 	path->npts = poly->npts;
-	path->closed = TRUE;
+	path->closed = true;
 	/* prevent instability in unused pad bytes */
 	path->dummy = 0;
 
 	for (i = 0; i < poly->npts; i++)
 	{
 		path->p[i].x = poly->p[i].x;
 		path->p[i].y = poly->p[i].y;
 	}
 
 	PG_RETURN_PATH_P(path);
@@ -4546,30 +4642,29 @@ circle_in(PG_FUNCTION_ARGS)
 		if (*cp == LDELIM)
 			s = cp;
 	}
 
 	pair_decode(s, &circle->center.x, &circle->center.y, &s, "circle", str);
 
 	if (*s == DELIM)
 		s++;
 
 	circle->radius = single_decode(s, &s, "circle", str);
-	if (circle->radius < 0)
+	if (FLOAT_LT(circle->radius, 0.0))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 				 errmsg("invalid input syntax for type %s: \"%s\"",
 						"circle", str)));
 
 	while (depth > 0)
 	{
-		if ((*s == RDELIM)
-			|| ((*s == RDELIM_C) && (depth == 1)))
+		if ((*s == RDELIM) || ((*s == RDELIM_C) && (depth == 1)))
 		{
 			depth--;
 			s++;
 			while (isspace((unsigned char) *s))
 				s++;
 		}
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
 					 errmsg("invalid input syntax for type %s: \"%s\"",
@@ -4614,21 +4709,21 @@ circle_recv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
 	CIRCLE	   *circle;
 
 	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
 
 	circle->center.x = pq_getmsgfloat8(buf);
 	circle->center.y = pq_getmsgfloat8(buf);
 	circle->radius = pq_getmsgfloat8(buf);
 
-	if (circle->radius < 0)
+	if (FLOAT_LT(circle->radius, 0.0))
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
 				 errmsg("invalid radius in external \"circle\" value")));
 
 	PG_RETURN_CIRCLE_P(circle);
 }
 
 /*
  *		circle_send			- converts circle to binary format
  */
@@ -4652,334 +4747,371 @@ circle_send(PG_FUNCTION_ARGS)
  *---------------------------------------------------------*/
 
 /*		circles identical?
  */
 Datum
 circle_same(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPeq(circle1->radius, circle2->radius) &&
-				   FPeq(circle1->center.x, circle2->center.x) &&
-				   FPeq(circle1->center.y, circle2->center.y));
+	PG_RETURN_BOOL(FLOAT_EQ(circle1->radius, circle2->radius) &&
+				   FLOAT_EQ(circle1->center.x, circle2->center.x) &&
+				   FLOAT_EQ(circle1->center.y, circle2->center.y));
 }
 
 /*		circle_overlap	-		does circle1 overlap circle2?
  */
 Datum
 circle_overlap(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		sum_radius;
 
-	PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center),
-						circle1->radius + circle2->radius));
+	FLOAT_PL(sum_radius, circle1->radius, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_LE(point_dt(&circle1->center, &circle2->center),
+							sum_radius));
 }
 
 /*		circle_overleft -		is the right edge of circle1 at or left of
  *								the right edge of circle2?
  */
 Datum
 circle_overleft(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		x1;
+	double		x2;
 
-	PG_RETURN_BOOL(FPle((circle1->center.x + circle1->radius),
-						(circle2->center.x + circle2->radius)));
+	FLOAT_PL(x1, circle1->center.x, circle1->radius);
+	FLOAT_PL(x2, circle2->center.x, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_LE(x1, x2));
 }
 
 /*		circle_left		-		is circle1 strictly left of circle2?
  */
 Datum
 circle_left(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		x1;
+	double		x2;
 
-	PG_RETURN_BOOL(FPlt((circle1->center.x + circle1->radius),
-						(circle2->center.x - circle2->radius)));
+	FLOAT_PL(x1, circle1->center.x, circle1->radius);
+	FLOAT_MI(x2, circle2->center.x, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_LT(x1, x2));
 }
 
 /*		circle_right	-		is circle1 strictly right of circle2?
  */
 Datum
 circle_right(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		x1;
+	double		x2;
 
-	PG_RETURN_BOOL(FPgt((circle1->center.x - circle1->radius),
-						(circle2->center.x + circle2->radius)));
+	FLOAT_MI(x1, circle1->center.x, circle1->radius);
+	FLOAT_PL(x2, circle2->center.x, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_GT(x1, x2));
 }
 
 /*		circle_overright	-	is the left edge of circle1 at or right of
  *								the left edge of circle2?
  */
 Datum
 circle_overright(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		x1;
+	double		x2;
 
-	PG_RETURN_BOOL(FPge((circle1->center.x - circle1->radius),
-						(circle2->center.x - circle2->radius)));
+	FLOAT_MI(x1, circle1->center.x, circle1->radius);
+	FLOAT_MI(x2, circle2->center.x, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_GE(x1, x2));
 }
 
 /*		circle_contained		-		is circle1 contained by circle2?
  */
 Datum
 circle_contained(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		radius_diff;
 
-	PG_RETURN_BOOL(FPle((point_dt(&circle1->center, &circle2->center) + circle1->radius), circle2->radius));
+	FLOAT_MI(radius_diff, circle2->radius, circle1->radius);
+
+	PG_RETURN_BOOL(FLOAT_LE(point_dt(&circle1->center, &circle2->center),
+							radius_diff));
 }
 
 /*		circle_contain	-		does circle1 contain circle2?
  */
 Datum
 circle_contain(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		radius_diff;
 
-	PG_RETURN_BOOL(FPle((point_dt(&circle1->center, &circle2->center) + circle2->radius), circle1->radius));
+	FLOAT_MI(radius_diff, circle1->radius, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_LE(point_dt(&circle1->center, &circle2->center),
+							radius_diff));
 }
 
 
 /*		circle_below		-		is circle1 strictly below circle2?
  */
 Datum
 circle_below(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		y1;
+	double		y2;
 
-	PG_RETURN_BOOL(FPlt((circle1->center.y + circle1->radius),
-						(circle2->center.y - circle2->radius)));
+	FLOAT_PL(y1, circle1->center.y, circle1->radius);
+	FLOAT_MI(y2, circle2->center.y, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_LT(y1, y2));
 }
 
 /*		circle_above	-		is circle1 strictly above circle2?
  */
 Datum
 circle_above(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		y1;
+	double		y2;
 
-	PG_RETURN_BOOL(FPgt((circle1->center.y - circle1->radius),
-						(circle2->center.y + circle2->radius)));
+	FLOAT_MI(y1, circle1->center.y, circle1->radius);
+	FLOAT_PL(y2, circle2->center.y, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_GT(y1, y2));
 }
 
 /*		circle_overbelow -		is the upper edge of circle1 at or below
  *								the upper edge of circle2?
  */
 Datum
 circle_overbelow(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		y1;
+	double		y2;
 
-	PG_RETURN_BOOL(FPle((circle1->center.y + circle1->radius),
-						(circle2->center.y + circle2->radius)));
+	FLOAT_PL(y1, circle1->center.y, circle1->radius);
+	FLOAT_PL(y2, circle2->center.y, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_LE(y1, y2));
 }
 
 /*		circle_overabove	-	is the lower edge of circle1 at or above
  *								the lower edge of circle2?
  */
 Datum
 circle_overabove(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
+	double		y1;
+	double		y2;
 
-	PG_RETURN_BOOL(FPge((circle1->center.y - circle1->radius),
-						(circle2->center.y - circle2->radius)));
+	FLOAT_MI(y1, circle1->center.y, circle1->radius);
+	FLOAT_MI(y2, circle2->center.y, circle2->radius);
+
+	PG_RETURN_BOOL(FLOAT_GE(y1, y2));
 }
 
 
 /*		circle_relop	-		is area(circle1) relop area(circle2), within
  *								our accuracy constraint?
  */
 Datum
 circle_eq(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPeq(circle_ar(circle1), circle_ar(circle2)));
+	PG_RETURN_BOOL(FLOAT_EQ(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
 circle_ne(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPne(circle_ar(circle1), circle_ar(circle2)));
+	PG_RETURN_BOOL(FLOAT_NE(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
 circle_lt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPlt(circle_ar(circle1), circle_ar(circle2)));
+	PG_RETURN_BOOL(FLOAT_LT(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
 circle_gt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPgt(circle_ar(circle1), circle_ar(circle2)));
+	PG_RETURN_BOOL(FLOAT_GT(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
 circle_le(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPle(circle_ar(circle1), circle_ar(circle2)));
+	PG_RETURN_BOOL(FLOAT_LE(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
 circle_ge(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
 
-	PG_RETURN_BOOL(FPge(circle_ar(circle1), circle_ar(circle2)));
+	PG_RETURN_BOOL(FLOAT_GE(circle_ar(circle1), circle_ar(circle2)));
 }
 
 
 /*----------------------------------------------------------
  *	"Arithmetic" operators on circles.
  *---------------------------------------------------------*/
 
 static CIRCLE *
-circle_copy(CIRCLE *circle)
+circle_construct(double x, double y, double radius)
 {
 	CIRCLE	   *result;
 
-	if (!PointerIsValid(circle))
-		return NULL;
-
 	result = (CIRCLE *) palloc(sizeof(CIRCLE));
-	memcpy((char *) result, (char *) circle, sizeof(CIRCLE));
+	result->center.x = x;
+	result->center.y = y;
+	result->radius = radius;
+
 	return result;
 }
 
 
 /* circle_add_pt()
  * Translation operator.
  */
 Datum
 circle_add_pt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
-	CIRCLE	   *result;
 
-	result = circle_copy(circle);
-
-	result->center.x += point->x;
-	result->center.y += point->y;
-
-	PG_RETURN_CIRCLE_P(result);
+	PG_RETURN_CIRCLE_P(circle_construct(point->x, point->y, circle->radius));
 }
 
 Datum
 circle_sub_pt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
-	CIRCLE	   *result;
+	double		x;
+	double		y;
 
-	result = circle_copy(circle);
+	FLOAT_MI(x, circle->center.x, point->x);
+	FLOAT_MI(y, circle->center.y, point->y);
 
-	result->center.x -= point->x;
-	result->center.y -= point->y;
-
-	PG_RETURN_CIRCLE_P(result);
+	PG_RETURN_CIRCLE_P(circle_construct(x, y, circle->radius));
 }
 
 
 /* circle_mul_pt()
  * Rotation and scaling operators.
  */
 Datum
 circle_mul_pt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
-	CIRCLE	   *result;
 	Point	   *p;
-
-	result = circle_copy(circle);
+	double		hyp;
+	double		radius;
 
 	p = DatumGetPointP(DirectFunctionCall2(point_mul,
 										   PointPGetDatum(&circle->center),
 										   PointPGetDatum(point)));
-	result->center.x = p->x;
-	result->center.y = p->y;
-	result->radius *= HYPOT(point->x, point->y);
 
-	PG_RETURN_CIRCLE_P(result);
+	FLOAT_HYPOT(hyp, point->x, point->y);
+	FLOAT_MUL(radius, circle->radius, hyp);
+
+	PG_RETURN_CIRCLE_P(circle_construct(p->x, p->y, radius));
 }
 
 Datum
 circle_div_pt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
-	CIRCLE	   *result;
 	Point	   *p;
-
-	result = circle_copy(circle);
+	double		hyp;
+	double		radius;
 
 	p = DatumGetPointP(DirectFunctionCall2(point_div,
 										   PointPGetDatum(&circle->center),
 										   PointPGetDatum(point)));
-	result->center.x = p->x;
-	result->center.y = p->y;
-	result->radius /= HYPOT(point->x, point->y);
 
-	PG_RETURN_CIRCLE_P(result);
+	FLOAT_HYPOT(hyp, point->x, point->y);
+	FLOAT_DIV(radius, circle->radius, hyp);
+
+	PG_RETURN_CIRCLE_P(circle_construct(p->x, p->y, radius));
 }
 
 
 /*		circle_area		-		returns the area of the circle.
  */
 Datum
 circle_area(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 
 	PG_RETURN_FLOAT8(circle_ar(circle));
 }
 
 
 /*		circle_diameter -		returns the diameter of the circle.
  */
 Datum
 circle_diameter(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
+	double		result;
 
-	PG_RETURN_FLOAT8(2 * circle->radius);
+	FLOAT_MUL(result, circle->radius, 2.0);
+
+	PG_RETURN_FLOAT8(result);
 }
 
 
 /*		circle_radius	-		returns the radius of the circle.
  */
 Datum
 circle_radius(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 
@@ -4988,253 +5120,284 @@ circle_radius(PG_FUNCTION_ARGS)
 
 
 /*		circle_distance -		returns the distance between
  *								  two circles.
  */
 Datum
 circle_distance(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle1 = PG_GETARG_CIRCLE_P(0);
 	CIRCLE	   *circle2 = PG_GETARG_CIRCLE_P(1);
-	float8		result;
+	double		d;
+	double		sum_radius;
+	double		result;
+
+	d = point_dt(&circle1->center, &circle2->center);
+	FLOAT_PL(sum_radius, circle1->radius, circle2->radius);
+	FLOAT_MI(result, d, sum_radius);
+	if (FLOAT_LT(result, 0.0))
+		result = 0.0;
 
-	result = point_dt(&circle1->center, &circle2->center)
-		- (circle1->radius + circle2->radius);
-	if (result < 0)
-		result = 0;
 	PG_RETURN_FLOAT8(result);
 }
 
 
 Datum
 circle_contain_pt(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
 	double		d;
 
 	d = point_dt(&circle->center, point);
-	PG_RETURN_BOOL(d <= circle->radius);
+	PG_RETURN_BOOL(FLOAT_LE(d, circle->radius));
 }
 
 
 Datum
 pt_contained_circle(PG_FUNCTION_ARGS)
 {
 	Point	   *point = PG_GETARG_POINT_P(0);
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(1);
 	double		d;
 
 	d = point_dt(&circle->center, point);
-	PG_RETURN_BOOL(d <= circle->radius);
+	PG_RETURN_BOOL(FLOAT_LE(d, circle->radius));
 }
 
 
 /*		dist_pc -		returns the distance between
  *						  a point and a circle.
  */
 Datum
 dist_pc(PG_FUNCTION_ARGS)
 {
 	Point	   *point = PG_GETARG_POINT_P(0);
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(1);
-	float8		result;
+	double		d;
+	double		result;
+
+	d = point_dt(point, &circle->center);
+	FLOAT_MI(result, d, circle->radius);
+	if (FLOAT_LT(result, 0.0))
+		result = 0.0;
 
-	result = point_dt(point, &circle->center) - circle->radius;
-	if (result < 0)
-		result = 0;
 	PG_RETURN_FLOAT8(result);
 }
 
 /*
  * Distance from a circle to a point
  */
 Datum
 dist_cpoint(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	Point	   *point = PG_GETARG_POINT_P(1);
-	float8		result;
+	double		d;
+	double		result;
+
+	d = point_dt(point, &circle->center);
+	FLOAT_MI(result, d, circle->radius);
+	if (FLOAT_LT(result, 0.0))
+		result = 0.0;
 
-	result = point_dt(point, &circle->center) - circle->radius;
-	if (result < 0)
-		result = 0;
 	PG_RETURN_FLOAT8(result);
 }
 
 /*		circle_center	-		returns the center point of the circle.
  */
 Datum
 circle_center(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
-	Point	   *result;
 
-	result = (Point *) palloc(sizeof(Point));
-	result->x = circle->center.x;
-	result->y = circle->center.y;
-
-	PG_RETURN_POINT_P(result);
+	PG_RETURN_POINT_P(point_copy(&circle->center));
 }
 
 
 /*		circle_ar		-		returns the area of the circle.
  */
 static double
 circle_ar(CIRCLE *circle)
 {
-	return M_PI * (circle->radius * circle->radius);
+	double		radius2;
+	double		result;
+
+	FLOAT_MUL(radius2, circle->radius, circle->radius);
+	FLOAT_MUL(result, radius2, M_PI);
+
+	return result;
 }
 
 
 /*----------------------------------------------------------
  *	Conversion operators.
  *---------------------------------------------------------*/
 
 Datum
 cr_circle(PG_FUNCTION_ARGS)
 {
 	Point	   *center = PG_GETARG_POINT_P(0);
-	float8		radius = PG_GETARG_FLOAT8(1);
-	CIRCLE	   *result;
+	double		radius = PG_GETARG_FLOAT8(1);
 
-	result = (CIRCLE *) palloc(sizeof(CIRCLE));
-
-	result->center.x = center->x;
-	result->center.y = center->y;
-	result->radius = radius;
-
-	PG_RETURN_CIRCLE_P(result);
+	PG_RETURN_CIRCLE_P(circle_construct(center->x, center->y, radius));
 }
 
 Datum
 circle_box(PG_FUNCTION_ARGS)
 {
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(0);
 	BOX		   *box;
 	double		delta;
 
 	box = (BOX *) palloc(sizeof(BOX));
 
-	delta = circle->radius / sqrt(2.0);
+	FLOAT_DIV(delta, circle->radius, sqrt(2.0));
 
-	box->high.x = circle->center.x + delta;
-	box->low.x = circle->center.x - delta;
-	box->high.y = circle->center.y + delta;
-	box->low.y = circle->center.y - delta;
+	FLOAT_PL(box->high.x, circle->center.x, delta);
+	FLOAT_MI(box->low.x, circle->center.x, delta);
+	FLOAT_PL(box->high.y, circle->center.y, delta);
+	FLOAT_MI(box->low.y, circle->center.y, delta);
 
 	PG_RETURN_BOX_P(box);
 }
 
 /* box_circle()
  * Convert a box to a circle.
  */
 Datum
 box_circle(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	CIRCLE	   *circle;
+	double		sum;
 
 	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
 
-	circle->center.x = (box->high.x + box->low.x) / 2;
-	circle->center.y = (box->high.y + box->low.y) / 2;
+	FLOAT_PL(sum, box->high.x, box->low.x);
+	FLOAT_DIV(circle->center.x, sum, 2.0);
+
+	FLOAT_PL(sum, box->high.y, box->low.y);
+	FLOAT_DIV(circle->center.y, sum, 2.0);
 
 	circle->radius = point_dt(&circle->center, &box->high);
 
 	PG_RETURN_CIRCLE_P(circle);
 }
 
 
 Datum
 circle_poly(PG_FUNCTION_ARGS)
 {
 	int32		npts = PG_GETARG_INT32(0);
 	CIRCLE	   *circle = PG_GETARG_CIRCLE_P(1);
 	POLYGON    *poly;
 	int			base_size,
 				size;
 	int			i;
 	double		angle;
 	double		anglestep;
+	double		mul;
 
-	if (FPzero(circle->radius))
+	if (circle->radius == 0.0)
 		ereport(ERROR,
 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 			   errmsg("cannot convert circle with radius zero to polygon")));
 
 	if (npts < 2)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("must request at least 2 points")));
 
 	base_size = sizeof(poly->p[0]) * npts;
-	size = offsetof(POLYGON, p) +base_size;
+	size = offsetof(POLYGON, p) + base_size;
 
 	/* Check for integer overflow */
 	if (base_size / npts != sizeof(poly->p[0]) || size <= base_size)
 		ereport(ERROR,
 				(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
 				 errmsg("too many points requested")));
 
 	poly = (POLYGON *) palloc0(size);	/* zero any holes */
 	SET_VARSIZE(poly, size);
 	poly->npts = npts;
 
-	anglestep = (2.0 * M_PI) / npts;
+	FLOAT_DIV(anglestep, 2.0 * M_PI, npts);
 
 	for (i = 0; i < npts; i++)
 	{
-		angle = i * anglestep;
-		poly->p[i].x = circle->center.x - (circle->radius * cos(angle));
-		poly->p[i].y = circle->center.y + (circle->radius * sin(angle));
+		FLOAT_MUL(angle, anglestep, i);
+
+		FLOAT_MUL(mul, circle->radius, cos(angle));
+		FLOAT_MI(poly->p[i].x, circle->center.x, mul);
+
+		FLOAT_MUL(mul, circle->radius, sin(angle));
+		FLOAT_PL(poly->p[i].y, circle->center.y, mul);
 	}
 
 	make_bound_box(poly);
 
 	PG_RETURN_POLYGON_P(poly);
 }
 
 /*		poly_circle		- convert polygon to circle
  *
  * XXX This algorithm should use weighted means of line segments
  *	rather than straight average values of points - tgl 97/01/21.
  */
 Datum
 poly_circle(PG_FUNCTION_ARGS)
 {
 	POLYGON    *poly = PG_GETARG_POLYGON_P(0);
 	CIRCLE	   *circle;
+	bool		has_inf;
 	int			i;
+	double		sum;
+	double		dist;
 
 	if (poly->npts < 1)
 		ereport(ERROR,
 				(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 				 errmsg("cannot convert empty polygon to circle")));
 
 	circle = (CIRCLE *) palloc(sizeof(CIRCLE));
 
-	circle->center.x = 0;
-	circle->center.y = 0;
-	circle->radius = 0;
-
+	has_inf = false;
+	sum = 0.0;
 	for (i = 0; i < poly->npts; i++)
 	{
-		circle->center.x += poly->p[i].x;
-		circle->center.y += poly->p[i].y;
+		has_inf |= isinf(poly->p[i].x);
+		sum += poly->p[i].x;
 	}
-	circle->center.x /= poly->npts;
-	circle->center.y /= poly->npts;
+	CHECKFLOATVAL(sum, has_inf, true);
+	FLOAT_DIV(circle->center.x, sum, poly->npts);
 
+	has_inf = false;
+	sum = 0.0;
 	for (i = 0; i < poly->npts; i++)
-		circle->radius += point_dt(&poly->p[i], &circle->center);
-	circle->radius /= poly->npts;
+	{
+		has_inf |= isinf(poly->p[i].y);
+		sum += poly->p[i].y;
+	}
+	CHECKFLOATVAL(sum, has_inf, true);
+	FLOAT_DIV(circle->center.y, sum, poly->npts);
+
+	has_inf = false;
+	sum = 0.0;
+	for (i = 0; i < poly->npts; i++)
+	{
+		dist = point_dt(&poly->p[i], &circle->center);
+		has_inf |= isinf(dist);
+		sum += dist;
+	}
+	CHECKFLOATVAL(sum, has_inf, true);
+	FLOAT_DIV(circle->radius, sum, poly->npts);
 
 	PG_RETURN_CIRCLE_P(circle);
 }
 
 
 /***********************************************************************
  **
  **		Private routines for multiple types.
  **
  ***********************************************************************/
@@ -5262,31 +5425,31 @@ point_inside(Point *p, int npts, Point *plist)
 	int			i = 0;
 	double		x,
 				y;
 	int			cross,
 				total_cross = 0;
 
 	if (npts <= 0)
 		return 0;
 
 	/* compute first polygon point relative to single point */
-	x0 = plist[0].x - p->x;
-	y0 = plist[0].y - p->y;
+	FLOAT_MI(x0, plist[0].x, p->x);
+	FLOAT_MI(y0, plist[0].y, p->y);
 
 	prev_x = x0;
 	prev_y = y0;
 	/* loop over polygon points and aggregate total_cross */
 	for (i = 1; i < npts; i++)
 	{
 		/* compute next polygon point relative to single point */
-		x = plist[i].x - p->x;
-		y = plist[i].y - p->y;
+		FLOAT_MI(x, plist[i].x, p->x);
+		FLOAT_MI(y, plist[i].y, p->y);
 
 		/* compute previous to current point crossing */
 		if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
 			return 2;
 		total_cross += cross;
 
 		prev_x = x;
 		prev_y = y;
 	}
 
@@ -5306,129 +5469,139 @@ point_inside(Point *p, int npts, Point *plist)
  * Returns +/-1 if one point is on the positive X-axis.
  * Returns 0 if both points are on the positive X-axis, or there is no crossing.
  * Returns POINT_ON_POLYGON if the segment contains (0,0).
  * Wow, that is one confusing API, but it is used above, and when summed,
  * can tell is if a point is in a polygon.
  */
 
 static int
 lseg_crossing(double x, double y, double prev_x, double prev_y)
 {
-	double		z;
 	int			y_sign;
+	double		xdiff;
+	double		ydiff;
+	double		mulxy;
+	double		mulyx;
 
-	if (FPzero(y))
+	if (FLOAT_EQ(y, 0.0))
 	{							/* y == 0, on X axis */
-		if (FPzero(x))			/* (x,y) is (0,0)? */
+		if (FLOAT_EQ(x, 0.0))			/* (x,y) is (0,0)? */
 			return POINT_ON_POLYGON;
-		else if (FPgt(x, 0))
+		else if (FLOAT_GT(x, 0.0))
 		{						/* x > 0 */
-			if (FPzero(prev_y)) /* y and prev_y are zero */
+			if (FLOAT_EQ(prev_y, 0.0)) /* y and prev_y are zero */
 				/* prev_x > 0? */
-				return FPgt(prev_x, 0) ? 0 : POINT_ON_POLYGON;
-			return FPlt(prev_y, 0) ? 1 : -1;
+				return FLOAT_GT(prev_x, 0.0) ? 0 : POINT_ON_POLYGON;
+			return FLOAT_LT(prev_y, 0.0) ? 1 : -1;
 		}
 		else
 		{						/* x < 0, x not on positive X axis */
-			if (FPzero(prev_y))
+			if (FLOAT_EQ(prev_y, 0.0))
 				/* prev_x < 0? */
-				return FPlt(prev_x, 0) ? 0 : POINT_ON_POLYGON;
+				return FLOAT_LT(prev_x, 0.0) ? 0 : POINT_ON_POLYGON;
 			return 0;
 		}
 	}
 	else
 	{							/* y != 0 */
 		/* compute y crossing direction from previous point */
-		y_sign = FPgt(y, 0) ? 1 : -1;
+		y_sign = FLOAT_GT(y, 0.0) ? 1 : -1;
 
-		if (FPzero(prev_y))
+		if (FLOAT_EQ(prev_y, 0.0))
 			/* previous point was on X axis, so new point is either off or on */
-			return FPlt(prev_x, 0) ? 0 : y_sign;
-		else if (FPgt(y_sign * prev_y, 0))
+			return prev_x < 0.0 ? 0 : y_sign;
+		else if ((y_sign < 0 && FLOAT_LT(prev_y, 0.0)) ||
+				 (y_sign > 0 && FLOAT_GT(prev_y, 0.0)))
 			/* both above or below X axis */
 			return 0;			/* same sign */
 		else
 		{						/* y and prev_y cross X-axis */
-			if (FPge(x, 0) && FPgt(prev_x, 0))
+			if (FLOAT_GE(x, 0.0) && FLOAT_GT(prev_x, 0.0))
 				/* both non-negative so cross positive X-axis */
 				return 2 * y_sign;
-			if (FPlt(x, 0) && FPle(prev_x, 0))
+			if (FLOAT_LT(x, 0.0) && FLOAT_LE(prev_x, 0.0))
 				/* both non-positive so do not cross positive X-axis */
 				return 0;
 
 			/* x and y cross axises, see URL above point_inside() */
-			z = (x - prev_x) * y - (y - prev_y) * x;
-			if (FPzero(z))
+			FLOAT_MI(xdiff, x, prev_x);
+			FLOAT_MI(ydiff, y, prev_y);
+			FLOAT_MUL(mulxy, xdiff, y);
+			FLOAT_MUL(mulyx, ydiff, x);
+			if (FLOAT_EQ(mulxy, mulyx))
 				return POINT_ON_POLYGON;
-			return FPgt((y_sign * z), 0) ? 0 : 2 * y_sign;
+			if ((y_sign < 0 && FLOAT_LT(mulxy, mulyx)) ||
+				(y_sign > 0 && FLOAT_GT(mulxy, mulyx)))
+				return 0;
+
+			return 2 * y_sign;
 		}
 	}
 }
 
 
 static bool
 plist_same(int npts, Point *p1, Point *p2)
 {
 	int			i,
 				ii,
 				j;
 
 	/* find match for first point */
 	for (i = 0; i < npts; i++)
 	{
-		if ((FPeq(p2[i].x, p1[0].x))
-			&& (FPeq(p2[i].y, p1[0].y)))
+		if (FLOAT_EQ(p2[i].x, p1[0].x) && FLOAT_EQ(p2[i].y, p1[0].y))
 		{
 
 			/* match found? then look forward through remaining points */
 			for (ii = 1, j = i + 1; ii < npts; ii++, j++)
 			{
 				if (j >= npts)
 					j = 0;
-				if ((!FPeq(p2[j].x, p1[ii].x))
-					|| (!FPeq(p2[j].y, p1[ii].y)))
+				if (FLOAT_NE(p2[j].x, p1[ii].x) ||
+					FLOAT_NE(p2[j].y, p1[ii].y))
 				{
 #ifdef GEODEBUG
 					printf("plist_same- %d failed forward match with %d\n", j, ii);
 #endif
 					break;
 				}
 			}
 #ifdef GEODEBUG
 			printf("plist_same- ii = %d/%d after forward match\n", ii, npts);
 #endif
 			if (ii == npts)
-				return TRUE;
+				return true;
 
 			/* match not found forwards? then look backwards */
 			for (ii = 1, j = i - 1; ii < npts; ii++, j--)
 			{
 				if (j < 0)
 					j = (npts - 1);
-				if ((!FPeq(p2[j].x, p1[ii].x))
-					|| (!FPeq(p2[j].y, p1[ii].y)))
+				if (FLOAT_NE(p2[j].x, p1[ii].x) ||
+					FLOAT_NE(p2[j].y, p1[ii].y))
 				{
 #ifdef GEODEBUG
 					printf("plist_same- %d failed reverse match with %d\n", j, ii);
 #endif
 					break;
 				}
 			}
 #ifdef GEODEBUG
 			printf("plist_same- ii = %d/%d after reverse match\n", ii, npts);
 #endif
 			if (ii == npts)
-				return TRUE;
+				return true;
 		}
 	}
 
-	return FALSE;
+	return false;
 }
 
 
 /*-------------------------------------------------------------------------
  * Determine the hypotenuse.
  *
  * If required, x and y are swapped to make x the larger number. The
  * traditional formula of x^2+y^2 is rearranged to factor x outside the
  * sqrt. This allows computation of the hypotenuse for significantly
  * larger values, and with a higher precision than when using the naive
diff --git a/src/backend/utils/adt/geo_spgist.c b/src/backend/utils/adt/geo_spgist.c
index 565a034..537414c 100644
--- a/src/backend/utils/adt/geo_spgist.c
+++ b/src/backend/utils/adt/geo_spgist.c
@@ -76,21 +76,21 @@
 #include "access/spgist.h"
 #include "access/stratnum.h"
 #include "catalog/pg_type.h"
 #include "utils/float.h"
 #include "utils/geo_decls.h"
 
 /*
  * Comparator for qsort
  *
  * We don't need to use the floating point macros in here, because this
- * is going only going to be used in a place to effect the performance
+ * is only going to be used in a place to effect the performance
  * of the index, not the correctness.
  */
 static int
 compareDoubles(const void *a, const void *b)
 {
 	double		x = *(double *) a;
 	double		y = *(double *) b;
 
 	if (x == y)
 		return 0;
@@ -225,80 +225,80 @@ nextRectBox(RectBox *rect_box, RangeBox *centroid, uint8 quadrant)
 	else
 		next_rect_box->range_box_y.right.high = centroid->right.high;
 
 	return next_rect_box;
 }
 
 /* Can any range from range_box overlap with this argument? */
 static bool
 overlap2D(RangeBox *range_box, Range *query)
 {
-	return FPge(range_box->right.high, query->low) &&
-		FPle(range_box->left.low, query->high);
+	return range_box->right.high >= query->low &&
+		   range_box->left.low <= query->high;
 }
 
 /* Can any rectangle from rect_box overlap with this argument? */
 static bool
 overlap4D(RectBox *rect_box, RangeBox *query)
 {
 	return overlap2D(&rect_box->range_box_x, &query->left) &&
 		overlap2D(&rect_box->range_box_y, &query->right);
 }
 
 /* Can any range from range_box contain this argument? */
 static bool
 contain2D(RangeBox *range_box, Range *query)
 {
-	return FPge(range_box->right.high, query->high) &&
-		FPle(range_box->left.low, query->low);
+	return range_box->right.high >= query->high &&
+		   range_box->left.low <= query->low;
 }
 
 /* Can any rectangle from rect_box contain this argument? */
 static bool
 contain4D(RectBox *rect_box, RangeBox *query)
 {
 	return contain2D(&rect_box->range_box_x, &query->left) &&
 		contain2D(&rect_box->range_box_y, &query->right);
 }
 
 /* Can any range from range_box be contained by this argument? */
 static bool
 contained2D(RangeBox *range_box, Range *query)
 {
-	return FPle(range_box->left.low, query->high) &&
-		FPge(range_box->left.high, query->low) &&
-		FPle(range_box->right.low, query->high) &&
-		FPge(range_box->right.high, query->low);
+	return range_box->left.low <= query->high &&
+		   range_box->left.high >= query->low &&
+		   range_box->right.low <= query->high &&
+		   range_box->right.high >= query->low;
 }
 
 /* Can any rectangle from rect_box be contained by this argument? */
 static bool
 contained4D(RectBox *rect_box, RangeBox *query)
 {
 	return contained2D(&rect_box->range_box_x, &query->left) &&
 		contained2D(&rect_box->range_box_y, &query->right);
 }
 
 /* Can any range from range_box to be lower than this argument? */
 static bool
 lower2D(RangeBox *range_box, Range *query)
 {
-	return FPlt(range_box->left.low, query->low) &&
-		FPlt(range_box->right.low, query->low);
+	return range_box->left.low < query->low &&
+		   range_box->right.low < query->low;
 }
 
 /* Can any range from range_box to be higher than this argument? */
 static bool
 higher2D(RangeBox *range_box, Range *query)
 {
-	return FPgt(range_box->left.high, query->high) &&
-		FPgt(range_box->right.high, query->high);
+	return range_box->left.high > query->high &&
+		   range_box->right.high > query->high;
 }
 
 /* Can any rectangle from rect_box be left of this argument? */
 static bool
 left4D(RectBox *rect_box, RangeBox *query)
 {
 	return lower2D(&rect_box->range_box_x, &query->left);
 }
 
 /* Can any rectangle from rect_box does not extend the right of this argument? */
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index fe9bc60..7a6f34b 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -1,63 +1,42 @@
 /*-------------------------------------------------------------------------
  *
  * geo_decls.h - Declarations for various 2D constructs.
  *
  *
  * Portions Copyright (c) 1996-2016, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * src/include/utils/geo_decls.h
  *
- * NOTE
- *	  These routines do *not* use the float types from adt/.
- *
- *	  XXX These routines were not written by a numerical analyst.
- *
  *	  XXX I have made some attempt to flesh out the operators
  *		and data types. There are still some more to do. - tgl 97/04/19
  *
  *-------------------------------------------------------------------------
  */
 #ifndef GEO_DECLS_H
 #define GEO_DECLS_H
 
 #include <math.h>
 
 #include "fmgr.h"
 
 /*--------------------------------------------------------------------
  * Useful floating point utilities and constants.
  *-------------------------------------------------------------------*/
 
-
-#define EPSILON					1.0E-06
-
-#ifdef EPSILON
-#define FPzero(A)				(fabs(A) <= EPSILON)
-#define FPeq(A,B)				(fabs((A) - (B)) <= EPSILON)
-#define FPne(A,B)				(fabs((A) - (B)) > EPSILON)
-#define FPlt(A,B)				((B) - (A) > EPSILON)
-#define FPle(A,B)				((A) - (B) <= EPSILON)
-#define FPgt(A,B)				((A) - (B) > EPSILON)
-#define FPge(A,B)				((B) - (A) <= EPSILON)
-#else
-#define FPzero(A)				((A) == 0)
-#define FPeq(A,B)				((A) == (B))
-#define FPne(A,B)				((A) != (B))
-#define FPlt(A,B)				((A) < (B))
-#define FPle(A,B)				((A) <= (B))
-#define FPgt(A,B)				((A) > (B))
-#define FPge(A,B)				((A) >= (B))
-#endif
-
-#define HYPOT(A, B)				pg_hypot(A, B)
+#define FLOAT_HYPOT(result, val1, val2)							\
+do {															\
+	result = pg_hypot(val1, val2);								\
+	CHECKFLOATVAL(result, isinf(val1) || isinf(val2),			\
+				  (val1) == 0.0 && (val2) == 0.0);				\
+} while(0)
 
 /*---------------------------------------------------------------------
  * Point - (x,y)
  *-------------------------------------------------------------------*/
 typedef struct
 {
 	double		x,
 				y;
 } Point;
 
@@ -193,22 +172,20 @@ extern Datum point_horiz(PG_FUNCTION_ARGS);
 extern Datum point_eq(PG_FUNCTION_ARGS);
 extern Datum point_ne(PG_FUNCTION_ARGS);
 extern Datum point_distance(PG_FUNCTION_ARGS);
 extern Datum point_slope(PG_FUNCTION_ARGS);
 extern Datum point_add(PG_FUNCTION_ARGS);
 extern Datum point_sub(PG_FUNCTION_ARGS);
 extern Datum point_mul(PG_FUNCTION_ARGS);
 extern Datum point_div(PG_FUNCTION_ARGS);
 
 /* private routines */
-extern double point_dt(Point *pt1, Point *pt2);
-extern double point_sl(Point *pt1, Point *pt2);
 extern double pg_hypot(double x, double y);
 
 /* public lseg routines */
 extern Datum lseg_in(PG_FUNCTION_ARGS);
 extern Datum lseg_out(PG_FUNCTION_ARGS);
 extern Datum lseg_recv(PG_FUNCTION_ARGS);
 extern Datum lseg_send(PG_FUNCTION_ARGS);
 extern Datum lseg_intersect(PG_FUNCTION_ARGS);
 extern Datum lseg_parallel(PG_FUNCTION_ARGS);
 extern Datum lseg_perp(PG_FUNCTION_ARGS);
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
index f20abdc..16ff522 100644
--- a/src/test/regress/expected/line.out
+++ b/src/test/regress/expected/line.out
@@ -32,56 +32,56 @@ LINE 1: INSERT INTO LINE_TBL VALUES ('[1,2,3, 4');
                                      ^
 INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
 ERROR:  invalid input syntax for type line: "[(,2),(3,4)]"
 LINE 1: INSERT INTO LINE_TBL VALUES ('[(,2),(3,4)]');
                                      ^
 INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
 ERROR:  invalid input syntax for type line: "[(1,2),(3,4)"
 LINE 1: INSERT INTO LINE_TBL VALUES ('[(1,2),(3,4)');
                                      ^
 select * from LINE_TBL;
-                      s                      
----------------------------------------------
+            s             
+--------------------------
  {1,-1,1}
- {1,-1,0}
- {-0.4,-1,-6}
- {-0.000184615384615385,-1,15.3846153846154}
- {1,-1,11}
+ {6,-6,0}
+ {6,15,90}
+ {-240,-1300000,20000000}
+ {22,-22,242}
  {0,-1,3}
  {-1,0,3}
 (7 rows)
 
 -- functions and operators
 SELECT * FROM LINE_TBL WHERE (s <-> line '[(1,2),(3,4)]') < 10;
-                      s                      
----------------------------------------------
+            s             
+--------------------------
  {1,-1,1}
- {1,-1,0}
- {-0.4,-1,-6}
- {-0.000184615384615385,-1,15.3846153846154}
- {1,-1,11}
+ {6,-6,0}
+ {6,15,90}
+ {-240,-1300000,20000000}
+ {22,-22,242}
  {0,-1,3}
  {-1,0,3}
 (7 rows)
 
 SELECT * FROM LINE_TBL WHERE (point '(0.1,0.1)' <-> s) < 1;
     s     
 ----------
  {1,-1,1}
- {1,-1,0}
+ {6,-6,0}
 (2 rows)
 
 SELECT * FROM LINE_TBL WHERE (lseg '[(0.1,0.1),(0.2,0.2)]' <-> s) < 1;
     s     
 ----------
  {1,-1,1}
- {1,-1,0}
+ {6,-6,0}
 (2 rows)
 
 SELECT line '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
  ?column? 
 ----------
         2
 (1 row)
 
 SELECT lseg '[(1,1),(2,1)]' <-> line '[(-1,-1),(-2,-1)]';
  ?column? 
@@ -247,21 +247,21 @@ SELECT ?| line '[(0,0),(0,1)]';  -- true
 
 SELECT ?| line '[(0,0),(1,1)]';  -- false
  ?column? 
 ----------
  f
 (1 row)
 
 SELECT line(point '(1,2)', point '(3,4)');
    line   
 ----------
- {1,-1,1}
+ {2,-2,2}
 (1 row)
 
 SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,5)]';  -- true
  ?column? 
 ----------
  t
 (1 row)
 
 SELECT line '[(1,2),(3,4)]' = line '[(3,4),(4,4)]';  -- false
  ?column? 
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index bfc0962..6319652 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -249,49 +249,49 @@ SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS dista
 CREATE TEMP TABLE point_gist_tbl(f1 point);
 INSERT INTO point_gist_tbl SELECT '(0,0)' FROM generate_series(0,1000);
 CREATE INDEX point_gist_tbl_index ON point_gist_tbl USING gist (f1);
 INSERT INTO point_gist_tbl VALUES ('(0.0000009,0.0000009)');
 SET enable_seqscan TO true;
 SET enable_indexscan TO false;
 SET enable_bitmapscan TO false;
 SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000009,0.0000009)'::point;
  count 
 -------
-  1002
+     1
 (1 row)
 
 SELECT COUNT(*) FROM point_gist_tbl WHERE f1 <@ '(0.0000009,0.0000009),(0.0000009,0.0000009)'::box;
  count 
 -------
      1
 (1 row)
 
 SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000018,0.0000018)'::point;
  count 
 -------
-     1
+     0
 (1 row)
 
 SET enable_seqscan TO false;
 SET enable_indexscan TO true;
 SET enable_bitmapscan TO true;
 SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000009,0.0000009)'::point;
  count 
 -------
-  1002
+     1
 (1 row)
 
 SELECT COUNT(*) FROM point_gist_tbl WHERE f1 <@ '(0.0000009,0.0000009),(0.0000009,0.0000009)'::box;
  count 
 -------
      1
 (1 row)
 
 SELECT COUNT(*) FROM point_gist_tbl WHERE f1 ~= '(0.0000018,0.0000018)'::point;
  count 
 -------
-     1
+     0
 (1 row)
 
 RESET enable_seqscan;
 RESET enable_indexscan;
 RESET enable_bitmapscan;
diff --git a/src/test/regress/expected/select_views.out b/src/test/regress/expected/select_views.out
index 7f57526..61f9fca 100644
--- a/src/test/regress/expected/select_views.out
+++ b/src/test/regress/expected/select_views.out
@@ -2,21 +2,20 @@
 -- SELECT_VIEWS
 -- test the views defined in CREATE_VIEWS
 --
 SELECT * FROM street;
                 name                |                                                                                                                                                                                                                   thepath                                                                                                                                                                                                                    |   cname   
 ------------------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+-----------
  Access Rd 25                       | [(-121.9283,37.894),(-121.9283,37.9)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Ada                           St   | [(-122.2487,37.398),(-122.2496,37.401)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Agua Fria Creek                    | [(-121.9254,37.922),(-121.9281,37.889)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Allen                         Ct   | [(-122.0131,37.602),(-122.0117,37.597)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
- Alvarado Niles                Road | [(-122.0325,37.903),(-122.0316,37.9)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
  Andrea                        Cir  | [(-121.733218,37.88641),(-121.733286,37.90617)]                                                                                                                                                                                                                                                                                                                                                                                              | Oakland
  Apricot                       Lane | [(-121.9471,37.401),(-121.9456,37.392)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Apricot                       Lane | [(-121.9471,37.401),(-121.9456,37.392)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Arden                         Road | [(-122.0978,37.177),(-122.1,37.177)]                                                                                                                                                                                                                                                                                                                                                                                                         | Oakland
  Arizona                       St   | [(-122.0381,37.901),(-122.0367,37.898)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Arlington                     Dr   | [(-121.8802,37.408),(-121.8807,37.394)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Arlington                     Dr   | [(-121.8802,37.408),(-121.8807,37.394)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Arlington                     Road | [(-121.7957,37.898),(-121.7956,37.906)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Arroyo Las Positas                 | [(-121.7973,37.997),(-121.7957,37.005)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Arroyo Las Positas                 | [(-121.7973,37.997),(-121.7957,37.005)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
@@ -41,21 +40,20 @@ SELECT * FROM street;
  Butterfield                   Dr   | [(-122.0838,37.002),(-122.0834,37.987)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Butterfield                   Dr   | [(-122.0838,37.002),(-122.0834,37.987)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  C                             St   | [(-122.1768,37.46),(-122.1749,37.435)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Calaveras Creek                    | [(-121.8203,37.035),(-121.8207,37.931)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Calaveras Creek                    | [(-121.8203,37.035),(-121.8207,37.931)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  California                    St   | [(-122.2032,37.005),(-122.2016,37.996)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  California                    St   | [(-122.2032,37.005),(-122.2016,37.996)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Cameron                       Ave  | [(-122.1316,37.502),(-122.1327,37.481)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Campus                        Dr   | [(-122.1704,37.905),(-122.1678,37.868),(-122.1671,37.865)]                                                                                                                                                                                                                                                                                                                                                                                   | Berkeley
  Capricorn                     Ave  | [(-122.2176,37.404),(-122.2164,37.384)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
- Carson                        St   | [(-122.1846,37.9),(-122.1843,37.901)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
  Cedar                         Blvd | [(-122.0282,37.446),(-122.0265,37.43)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Cedar                         St   | [(-122.3011,37.737),(-122.2999,37.739)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Celia                         St   | [(-122.0611,37.3),(-122.0616,37.299)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Central                       Ave  | [(-122.2343,37.602),(-122.2331,37.595)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Chambers                      Dr   | [(-122.2004,37.352),(-122.1972,37.368)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Chambers                      Lane | [(-122.2001,37.359),(-122.1975,37.371)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Champion                      St   | [(-122.214,37.991),(-122.2147,37.002)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
  Champion                      St   | [(-122.214,37.991),(-122.2147,37.002)]                                                                                                                                                                                                                                                                                                                                                                                                       | Lafayette
  Chapman                       Dr   | [(-122.0421,37.504),(-122.0414,37.498)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Charles                       St   | [(-122.0255,37.505),(-122.0252,37.499)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
@@ -66,21 +64,20 @@ SELECT * FROM street;
  Coliseum                      Way  | [(-122.2001,37.47),(-122.1978,37.516)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Coliseum                      Way  | [(-122.2113,37.626),(-122.2085,37.592),(-122.2063,37.568)]                                                                                                                                                                                                                                                                                                                                                                                   | Berkeley
  Coolidge                      Ave  | [(-122.2007,37.058),(-122.1992,37.06)]                                                                                                                                                                                                                                                                                                                                                                                                       | Lafayette
  Cornell                       Ave  | [(-122.2956,37.925),(-122.2949,37.906),(-122.2939,37.875)]                                                                                                                                                                                                                                                                                                                                                                                   | Berkeley
  Corriea                       Way  | [(-121.9501,37.402),(-121.9505,37.398)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Corriea                       Way  | [(-121.9501,37.402),(-121.9505,37.398)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Cowing                        Road | [(-122.0002,37.934),(-121.9772,37.782)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Creston                       Road | [(-122.2639,37.002),(-122.2613,37.986),(-122.2602,37.978),(-122.2598,37.973)]                                                                                                                                                                                                                                                                                                                                                                | Berkeley
  Creston                       Road | [(-122.2639,37.002),(-122.2613,37.986),(-122.2602,37.978),(-122.2598,37.973)]                                                                                                                                                                                                                                                                                                                                                                | Lafayette
  Crow Canyon Creek                  | [(-122.043,37.905),(-122.0368,37.71)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
- Crystaline                    Dr   | [(-121.925856,37),(-121.925869,37.00527)]                                                                                                                                                                                                                                                                                                                                                                                                    | Oakland
  Cull Canyon                   Road | [(-122.0536,37.435),(-122.0499,37.315)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Cull Creek                         | [(-122.0624,37.875),(-122.0582,37.527)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  D                             St   | [(-122.1811,37.505),(-122.1805,37.497)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Decoto                        Road | [(-122.0159,37.006),(-122.016,37.002),(-122.0164,37.993)]                                                                                                                                                                                                                                                                                                                                                                                    | Oakland
  Decoto                        Road | [(-122.0159,37.006),(-122.016,37.002),(-122.0164,37.993)]                                                                                                                                                                                                                                                                                                                                                                                    | Oakland
  Decoto                        Road | [(-122.0159,37.006),(-122.016,37.002),(-122.0164,37.993)]                                                                                                                                                                                                                                                                                                                                                                                    | Berkeley
  Deering                       St   | [(-122.2146,37.904),(-122.2126,37.897)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Dimond                        Ave  | [(-122.2167,37.994),(-122.2162,37.006)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Dimond                        Ave  | [(-122.2167,37.994),(-122.2162,37.006)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Donna                         Way  | [(-122.1333,37.606),(-122.1316,37.599)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
@@ -182,21 +179,20 @@ SELECT * FROM street;
  I- 880                        Ramp | [(-122.0618,37.011),(-122.0631,37.982),(-122.0585,37.967)]                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
  I- 880                        Ramp | [(-122.0618,37.011),(-122.0631,37.982),(-122.0585,37.967)]                                                                                                                                                                                                                                                                                                                                                                                   | Berkeley
  I- 880                        Ramp | [(-122.085,37.34),(-122.0801,37.316),(-122.081,37.285)]                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  I- 880                        Ramp | [(-122.085,37.34),(-122.0801,37.316),(-122.081,37.285)]                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  I- 880                        Ramp | [(-122.085,37.34),(-122.0866,37.316),(-122.0819,37.296)]                                                                                                                                                                                                                                                                                                                                                                                     | Oakland
  I- 880                        Ramp | [(-122.085,37.34),(-122.0866,37.316),(-122.0819,37.296)]                                                                                                                                                                                                                                                                                                                                                                                     | Oakland
  I- 880                        Ramp | [(-122.1029,37.61),(-122.1013,37.587),(-122.0999,37.569)]                                                                                                                                                                                                                                                                                                                                                                                    | Berkeley
  I- 880                        Ramp | [(-122.1379,37.891),(-122.1383,37.897),(-122.1377,37.902)]                                                                                                                                                                                                                                                                                                                                                                                   | Berkeley
  I- 880                        Ramp | [(-122.1379,37.931),(-122.137597,37.92736),(-122.1374,37.925),(-122.1373,37.924),(-122.1369,37.914),(-122.1358,37.905),(-122.1365,37.908),(-122.1358,37.898)]                                                                                                                                                                                                                                                                                | Berkeley
  I- 880                        Ramp | [(-122.2536,37.898),(-122.254,37.902)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
- I- 880                        Ramp | [(-122.2771,37.002),(-122.278,37)]                                                                                                                                                                                                                                                                                                                                                                                                           | Lafayette
  Indian                        Way  | [(-122.2066,37.398),(-122.2045,37.411)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Jackson                       St   | [(-122.0845,37.6),(-122.0842,37.606)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
  Johnson                       Dr   | [(-121.9145,37.901),(-121.915,37.877)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Joyce                         St   | [(-122.0792,37.604),(-122.0774,37.581)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Juniper                       St   | [(-121.7823,37.897),(-121.7815,37.9)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Kaiser                        Dr   | [(-122.067163,37.47821),(-122.060402,37.51961)]                                                                                                                                                                                                                                                                                                                                                                                              | Oakland
  Keeler                        Ave  | [(-122.2578,37.906),(-122.2579,37.899)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Kildare                       Road | [(-122.0968,37.016),(-122.0959,37)]                                                                                                                                                                                                                                                                                                                                                                                                          | Oakland
  La Playa                      Dr   | [(-122.1039,37.545),(-122.101,37.493)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Laguna                        Ave  | [(-122.2099,37.989),(-122.2089,37)]                                                                                                                                                                                                                                                                                                                                                                                                          | Berkeley
@@ -234,21 +230,20 @@ SELECT * FROM street;
  Mission                       Blvd | [(-122.0006,37.896),(-121.9989,37.88)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
  Moores                        Ave  | [(-122.0087,37.301),(-122.0094,37.292)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  National                      Ave  | [(-122.1192,37.5),(-122.1281,37.489)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Navajo                        Ct   | [(-121.8779,37.901),(-121.8783,37.9)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Newark                        Blvd | [(-122.0352,37.438),(-122.0341,37.423)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Oakland Inner Harbor               | [(-122.2625,37.913),(-122.260016,37.89484)]                                                                                                                                                                                                                                                                                                                                                                                                  | Berkeley
  Oakridge                      Road | [(-121.8316,37.049),(-121.828382,37)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Oneil                         Ave  | [(-122.076754,37.62476),(-122.0745,37.595)]                                                                                                                                                                                                                                                                                                                                                                                                  | Berkeley
  Parkridge                     Dr   | [(-122.1438,37.884),(-122.1428,37.9)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
  Parkside                      Dr   | [(-122.0475,37.603),(-122.0443,37.596)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
- Paseo Padre                   Pkwy | [(-121.9143,37.005),(-121.913522,37)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Paseo Padre                   Pkwy | [(-122.0021,37.639),(-121.996,37.628)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Paseo Padre                   Pkwy | [(-122.0021,37.639),(-121.996,37.628)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
  Pearl                         St   | [(-122.2383,37.594),(-122.2366,37.615)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Periwinkle                    Road | [(-122.0451,37.301),(-122.044758,37.29844)]                                                                                                                                                                                                                                                                                                                                                                                                  | Oakland
  Pimlico                       Dr   | [(-121.8616,37.998),(-121.8618,37.008)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Pimlico                       Dr   | [(-121.8616,37.998),(-121.8618,37.008)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Portsmouth                    Ave  | [(-122.1064,37.315),(-122.1064,37.308)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Proctor                       Ave  | [(-122.2267,37.406),(-122.2251,37.386)]                                                                                                                                                                                                                                                                                                                                                                                                      | Lafayette
  Railroad                      Ave  | [(-122.0245,37.013),(-122.0234,37.003),(-122.0223,37.993)]                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
  Railroad                      Ave  | [(-122.0245,37.013),(-122.0234,37.003),(-122.0223,37.993)]                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
@@ -263,39 +258,36 @@ SELECT * FROM street;
  Rosedale                      Ct   | [(-121.9232,37.9),(-121.924,37.897)]                                                                                                                                                                                                                                                                                                                                                                                                         | Oakland
  Sacramento                    St   | [(-122.2799,37.606),(-122.2797,37.597)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Saddle Brook                  Dr   | [(-122.1478,37.909),(-122.1454,37.904),(-122.1451,37.888)]                                                                                                                                                                                                                                                                                                                                                                                   | Berkeley
  Saginaw                       Ct   | [(-121.8803,37.898),(-121.8806,37.901)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  San Andreas                   Dr   | [(-122.0609,37.9),(-122.0614,37.895)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
  Santa Maria                   Ave  | [(-122.0773,37),(-122.0773,37.98)]                                                                                                                                                                                                                                                                                                                                                                                                           | Oakland
  Santa Maria                   Ave  | [(-122.0773,37),(-122.0773,37.98)]                                                                                                                                                                                                                                                                                                                                                                                                           | Oakland
  Santa Maria                   Ave  | [(-122.0773,37),(-122.0773,37.98)]                                                                                                                                                                                                                                                                                                                                                                                                           | Berkeley
  Shattuck                      Ave  | [(-122.2686,37.904),(-122.2686,37.897)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Sheridan                      Road | [(-122.2279,37.425),(-122.2253,37.411),(-122.2223,37.377)]                                                                                                                                                                                                                                                                                                                                                                                   | Lafayette
- Shoreline                     Dr   | [(-122.2657,37.603),(-122.2648,37.6)]                                                                                                                                                                                                                                                                                                                                                                                                        | Berkeley
  Skyline                       Blvd | [(-122.1738,37.01),(-122.1714,37.996)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  Skyline                       Blvd | [(-122.1738,37.01),(-122.1714,37.996)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
- Skyline                       Dr   | [(-122.0277,37.5),(-122.0284,37.498)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Skywest                       Dr   | [(-122.1161,37.62),(-122.1123,37.586)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
  Southern Pacific Railroad          | [(-122.3002,37.674),(-122.2999,37.661)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Sp Railroad                        | [(-121.893564,37.99009),(-121.897,37.016)]                                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
  Sp Railroad                        | [(-121.893564,37.99009),(-121.897,37.016)]                                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
  Sp Railroad                        | [(-121.9565,37.898),(-121.9562,37.9)]                                                                                                                                                                                                                                                                                                                                                                                                        | Oakland
  Sp Railroad                        | [(-122.0734,37.001),(-122.0734,37.997)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Sp Railroad                        | [(-122.0734,37.001),(-122.0734,37.997)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  Sp Railroad                        | [(-122.0734,37.001),(-122.0734,37.997)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  Sp Railroad                        | [(-122.0914,37.601),(-122.087,37.56),(-122.086408,37.5551)]                                                                                                                                                                                                                                                                                                                                                                                  | Berkeley
  Sp Railroad                        | [(-122.137792,37.003),(-122.1365,37.992),(-122.131257,37.94612)]                                                                                                                                                                                                                                                                                                                                                                             | Oakland
  Sp Railroad                        | [(-122.137792,37.003),(-122.1365,37.992),(-122.131257,37.94612)]                                                                                                                                                                                                                                                                                                                                                                             | Berkeley
  Sp Railroad                        | [(-122.1947,37.497),(-122.193328,37.4848)]                                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
  Stanton                       Ave  | [(-122.100392,37.0697),(-122.099513,37.06052)]                                                                                                                                                                                                                                                                                                                                                                                               | Oakland
  State Hwy 123                      | [(-122.3004,37.986),(-122.2998,37.969),(-122.2995,37.962),(-122.2992,37.952),(-122.299,37.942),(-122.2987,37.935),(-122.2984,37.924),(-122.2982,37.92),(-122.2976,37.904),(-122.297,37.88),(-122.2966,37.869),(-122.2959,37.848),(-122.2961,37.843)]                                                                                                                                                                                         | Berkeley
- State Hwy 13                       | [(-122.1797,37.943),(-122.179871,37.91849),(-122.18,37.9),(-122.179023,37.86615),(-122.1787,37.862),(-122.1781,37.851),(-122.1777,37.845),(-122.1773,37.839),(-122.177,37.833)]                                                                                                                                                                                                                                                              | Berkeley
  State Hwy 13                       | [(-122.2049,37.2),(-122.20328,37.17975),(-122.1989,37.125),(-122.198078,37.11641),(-122.1975,37.11)]                                                                                                                                                                                                                                                                                                                                         | Lafayette
  State Hwy 13                  Ramp | [(-122.2244,37.427),(-122.223,37.414),(-122.2214,37.396),(-122.2213,37.388)]                                                                                                                                                                                                                                                                                                                                                                 | Lafayette
  State Hwy 238                      | ((-122.098,37.908),(-122.0983,37.907),(-122.099,37.905),(-122.101,37.898),(-122.101535,37.89711),(-122.103173,37.89438),(-122.1046,37.892),(-122.106,37.89))                                                                                                                                                                                                                                                                                 | Berkeley
  State Hwy 238                 Ramp | [(-122.1288,37.9),(-122.1293,37.895),(-122.1296,37.906)]                                                                                                                                                                                                                                                                                                                                                                                     | Berkeley
  State Hwy 24                       | [(-122.2674,37.246),(-122.2673,37.248),(-122.267,37.261),(-122.2668,37.271),(-122.2663,37.298),(-122.2659,37.315),(-122.2655,37.336),(-122.265007,37.35882),(-122.264443,37.37286),(-122.2641,37.381),(-122.2638,37.388),(-122.2631,37.396),(-122.2617,37.405),(-122.2615,37.407),(-122.2605,37.412)]                                                                                                                                        | Lafayette
  State Hwy 84                       | [(-121.9565,37.898),(-121.956589,37.89911),(-121.9569,37.903),(-121.956,37.91),(-121.9553,37.919)]                                                                                                                                                                                                                                                                                                                                           | Oakland
  State Hwy 84                       | [(-122.0671,37.426),(-122.07,37.402),(-122.074,37.37),(-122.0773,37.338)]                                                                                                                                                                                                                                                                                                                                                                    | Oakland
  State Hwy 92                       | [(-122.1085,37.326),(-122.1095,37.322),(-122.1111,37.316),(-122.1119,37.313),(-122.1125,37.311),(-122.1131,37.308),(-122.1167,37.292),(-122.1187,37.285),(-122.12,37.28)]                                                                                                                                                                                                                                                                    | Oakland
  State Hwy 92                  Ramp | [(-122.1086,37.321),(-122.1089,37.315),(-122.1111,37.316)]                                                                                                                                                                                                                                                                                                                                                                                   | Oakland
  Stuart                        St   | [(-122.2518,37.6),(-122.2507,37.601),(-122.2491,37.606)]                                                                                                                                                                                                                                                                                                                                                                                     | Berkeley
@@ -331,148 +323,104 @@ SELECT * FROM street;
  19th                          Ave  | [(-122.2366,37.897),(-122.2359,37.905)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  1st                           St   | [(-121.75508,37.89294),(-121.753581,37.90031)]                                                                                                                                                                                                                                                                                                                                                                                               | Oakland
  5th                           St   | [(-122.278,37),(-122.2792,37.005),(-122.2803,37.009)]                                                                                                                                                                                                                                                                                                                                                                                        | Lafayette
  5th                           St   | [(-122.296,37.615),(-122.2953,37.598)]                                                                                                                                                                                                                                                                                                                                                                                                       | Berkeley
  82nd                          Ave  | [(-122.1695,37.596),(-122.1681,37.603)]                                                                                                                                                                                                                                                                                                                                                                                                      | Berkeley
  85th                          Ave  | [(-122.1877,37.466),(-122.186,37.476)]                                                                                                                                                                                                                                                                                                                                                                                                       | Oakland
  89th                          Ave  | [(-122.1822,37.459),(-122.1803,37.471)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  98th                          Ave  | [(-122.1568,37.498),(-122.1558,37.502)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  98th                          Ave  | [(-122.1693,37.438),(-122.1682,37.444)]                                                                                                                                                                                                                                                                                                                                                                                                      | Oakland
  98th                          Ave  | [(-122.2001,37.258),(-122.1974,37.27)]                                                                                                                                                                                                                                                                                                                                                                                                       | Lafayette
-(333 rows)
+(325 rows)
 
 SELECT name, #thepath FROM iexit ORDER BY 1, 2;
                 name                | ?column? 
 ------------------------------------+----------
  I- 580                             |        2
  I- 580                             |        2
  I- 580                             |        2
  I- 580                             |        2
  I- 580                             |        2
  I- 580                             |        2
- I- 580                             |        2
- I- 580                             |        2
- I- 580                             |        2
- I- 580                             |        2
- I- 580                             |        2
- I- 580                             |        3
- I- 580                             |        3
- I- 580                             |        3
- I- 580                             |        3
- I- 580                             |        3
- I- 580                             |        3
- I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        3
  I- 580                             |        4
  I- 580                             |        4
- I- 580                             |        4
- I- 580                             |        4
  I- 580                             |        5
  I- 580                             |        5
  I- 580                             |        5
  I- 580                             |        5
- I- 580                             |        5
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
- I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        6
  I- 580                             |        7
  I- 580                             |        7
  I- 580                             |        7
  I- 580                             |        7
- I- 580                             |        7
- I- 580                             |        7
- I- 580                             |        7
- I- 580                             |        8
- I- 580                             |        8
- I- 580                             |        8
  I- 580                             |        8
  I- 580                             |        8
  I- 580                             |        8
  I- 580                             |        8
  I- 580                             |        8
  I- 580                             |        8
  I- 580                             |        9
  I- 580                             |        9
- I- 580                             |        9
- I- 580                             |        9
- I- 580                             |        9
  I- 580                             |       12
  I- 580                             |       12
  I- 580                             |       12
  I- 580                             |       12
  I- 580                             |       12
  I- 580                             |       12
  I- 580                             |       12
- I- 580                             |       12
- I- 580                             |       12
- I- 580                             |       12
- I- 580                             |       13
  I- 580                             |       13
  I- 580                             |       13
  I- 580                             |       13
  I- 580                             |       13
  I- 580                             |       13
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       14
  I- 580                             |       18
  I- 580                             |       18
  I- 580                             |       18
  I- 580                             |       18
  I- 580                             |       18
- I- 580                             |       18
  I- 580                             |       21
  I- 580                             |       21
  I- 580                             |       21
  I- 580                             |       21
  I- 580                             |       21
  I- 580                             |       21
- I- 580                             |       21
- I- 580                             |       21
- I- 580                             |       21
- I- 580                             |       21
- I- 580                             |       22
  I- 580                             |       22
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
@@ -502,50 +450,20 @@ SELECT name, #thepath FROM iexit ORDER BY 1, 2;
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
  I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
- I- 580                        Ramp |        2
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
@@ -587,90 +505,20 @@ SELECT name, #thepath FROM iexit ORDER BY 1, 2;
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
  I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        3
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
- I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
  I- 580                        Ramp |        4
@@ -698,336 +546,231 @@ SELECT name, #thepath FROM iexit ORDER BY 1, 2;
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
  I- 580                        Ramp |        5
- I- 580                        Ramp |        5
- I- 580                        Ramp |        5
- I- 580                        Ramp |        6
- I- 580                        Ramp |        6
  I- 580                        Ramp |        6
  I- 580                        Ramp |        7
  I- 580                        Ramp |        8
  I- 580                        Ramp |        8
  I- 580                        Ramp |        8
  I- 580                        Ramp |        8
  I- 580                        Ramp |        8
  I- 580                        Ramp |        8
  I- 580/I-680                  Ramp |        2
  I- 580/I-680                  Ramp |        2
  I- 580/I-680                  Ramp |        2
  I- 580/I-680                  Ramp |        2
  I- 580/I-680                  Ramp |        2
  I- 580/I-680                  Ramp |        2
  I- 580/I-680                  Ramp |        4
  I- 580/I-680                  Ramp |        4
  I- 580/I-680                  Ramp |        4
- I- 580/I-680                  Ramp |        4
  I- 580/I-680                  Ramp |        5
  I- 580/I-680                  Ramp |        6
  I- 580/I-680                  Ramp |        6
- I- 580/I-680                  Ramp |        6
- I- 680                             |        2
- I- 680                             |        2
- I- 680                             |        2
- I- 680                             |        2
- I- 680                             |        2
- I- 680                             |        2
  I- 680                             |        2
  I- 680                             |        3
- I- 680                             |        3
- I- 680                             |        3
- I- 680                             |        4
- I- 680                             |        4
  I- 680                             |        4
  I- 680                             |        5
  I- 680                             |        5
- I- 680                             |        5
- I- 680                             |        7
  I- 680                             |        7
  I- 680                             |        7
  I- 680                             |        7
  I- 680                             |        8
  I- 680                             |        8
  I- 680                             |        8
- I- 680                             |        8
- I- 680                             |       10
- I- 680                             |       10
  I- 680                             |       10
  I- 680                             |       10
  I- 680                             |       10
  I- 680                             |       10
  I- 680                             |       10
  I- 680                             |       16
  I- 680                             |       16
  I- 680                             |       16
  I- 680                             |       16
  I- 680                             |       16
- I- 680                             |       16
- I- 680                             |       16
- I- 680                             |       16
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
  I- 680                        Ramp |        2
- I- 680                        Ramp |        2
- I- 680                        Ramp |        2
- I- 680                        Ramp |        2
- I- 680                        Ramp |        2
- I- 680                        Ramp |        2
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
- I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        3
  I- 680                        Ramp |        4
  I- 680                        Ramp |        4
- I- 680                        Ramp |        4
  I- 680                        Ramp |        5
  I- 680                        Ramp |        5
  I- 680                        Ramp |        5
  I- 680                        Ramp |        5
  I- 680                        Ramp |        5
  I- 680                        Ramp |        5
  I- 680                        Ramp |        6
  I- 680                        Ramp |        6
- I- 680                        Ramp |        6
- I- 680                        Ramp |        6
- I- 680                        Ramp |        7
  I- 680                        Ramp |        7
  I- 680                        Ramp |        7
  I- 680                        Ramp |        7
  I- 680                        Ramp |        8
  I- 680                        Ramp |        8
  I- 680                        Ramp |        8
- I- 680                        Ramp |        8
  I- 80                              |        2
  I- 80                              |        2
  I- 80                              |        2
  I- 80                              |        2
  I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        2
- I- 80                              |        3
- I- 80                              |        3
  I- 80                              |        3
  I- 80                              |        4
  I- 80                              |        4
  I- 80                              |        4
  I- 80                              |        4
  I- 80                              |        4
  I- 80                              |        5
  I- 80                              |        5
  I- 80                              |        5
  I- 80                              |        5
  I- 80                              |        5
  I- 80                              |        5
  I- 80                              |        5
  I- 80                              |        5
- I- 80                              |        5
- I- 80                              |       11
- I- 80                              |       11
  I- 80                              |       11
  I- 80                              |       11
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
  I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        2
- I- 80                         Ramp |        3
- I- 80                         Ramp |        3
- I- 80                         Ramp |        3
  I- 80                         Ramp |        3
  I- 80                         Ramp |        3
  I- 80                         Ramp |        3
  I- 80                         Ramp |        3
  I- 80                         Ramp |        3
  I- 80                         Ramp |        3
  I- 80                         Ramp |        4
  I- 80                         Ramp |        4
  I- 80                         Ramp |        4
  I- 80                         Ramp |        4
  I- 80                         Ramp |        5
  I- 80                         Ramp |        5
  I- 80                         Ramp |        5
  I- 80                         Ramp |        5
  I- 80                         Ramp |        5
- I- 80                         Ramp |        5
- I- 80                         Ramp |        5
  I- 80                         Ramp |        7
  I- 80                         Ramp |        7
  I- 80                         Ramp |        7
  I- 80                         Ramp |        7
  I- 880                             |        2
  I- 880                             |        2
- I- 880                             |        2
- I- 880                             |        2
- I- 880                             |        2
- I- 880                             |        5
- I- 880                             |        5
- I- 880                             |        5
  I- 880                             |        5
  I- 880                             |        5
  I- 880                             |        5
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
  I- 880                             |        6
- I- 880                             |        6
- I- 880                             |        6
- I- 880                             |        6
- I- 880                             |        7
- I- 880                             |        7
  I- 880                             |        7
  I- 880                             |        7
  I- 880                             |        7
  I- 880                             |        7
  I- 880                             |        7
  I- 880                             |        9
  I- 880                             |        9
  I- 880                             |        9
- I- 880                             |        9
- I- 880                             |        9
- I- 880                             |        9
- I- 880                             |        9
- I- 880                             |       10
- I- 880                             |       10
- I- 880                             |       10
- I- 880                             |       10
- I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       10
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
  I- 880                             |       12
- I- 880                             |       12
- I- 880                             |       13
- I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       13
  I- 880                             |       14
  I- 880                             |       14
  I- 880                             |       14
  I- 880                             |       14
- I- 880                             |       14
- I- 880                             |       14
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
- I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       17
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
  I- 880                             |       19
- I- 880                             |       19
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
@@ -1039,58 +782,20 @@ SELECT name, #thepath FROM iexit ORDER BY 1, 2;
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
  I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        2
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
- I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
  I- 880                        Ramp |        3
@@ -1138,31 +843,20 @@ SELECT name, #thepath FROM iexit ORDER BY 1, 2;
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
  I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
- I- 880                        Ramp |        4
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
@@ -1172,81 +866,56 @@ SELECT name, #thepath FROM iexit ORDER BY 1, 2;
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
  I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        5
- I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        6
  I- 880                        Ramp |        8
  I- 880                        Ramp |        8
- I- 880                        Ramp |        8
  I- 980                             |        2
  I- 980                             |        2
  I- 980                             |        2
- I- 980                             |        2
- I- 980                             |        2
- I- 980                             |        2
- I- 980                             |        2
- I- 980                             |        2
- I- 980                             |        3
- I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        3
  I- 980                             |        4
  I- 980                             |        4
  I- 980                             |        5
  I- 980                             |        5
  I- 980                             |        7
  I- 980                             |        7
- I- 980                             |        7
- I- 980                             |        7
  I- 980                             |       12
  I- 980                        Ramp |        3
- I- 980                        Ramp |        3
- I- 980                        Ramp |        3
- I- 980                        Ramp |        7
-(896 rows)
+(573 rows)
 
 SELECT * FROM toyemp WHERE name = 'sharon';
   name  | age | location | annualsal 
 --------+-----+----------+-----------
  sharon |  25 | (15,12)  |     12000
 (1 row)
 
 --
 -- Test for Leaky view scenario
 --
diff --git a/src/test/regress/regress.c b/src/test/regress/regress.c
index e7826a4..3cd8427 100644
--- a/src/test/regress/regress.c
+++ b/src/test/regress/regress.c
@@ -66,21 +66,23 @@ regress_dist_ptpath(PG_FUNCTION_ARGS)
 	float8		result = 0.0;	/* keep compiler quiet */
 	float8		tmp;
 	int			i;
 	LSEG		lseg;
 
 	switch (path->npts)
 	{
 		case 0:
 			PG_RETURN_NULL();
 		case 1:
-			result = point_dt(pt, &path->p[0]);
+			result = DatumGetFloat8(DirectFunctionCall2(point_distance,
+														PointPGetDatum(pt),
+												PointPGetDatum(&path->p[0])));
 			break;
 		default:
 
 			/*
 			 * the distance from a point to a path is the smallest distance
 			 * from the point to any of its constituent segments.
 			 */
 			Assert(path->npts > 1);
 			for (i = 0; i < path->npts - 1; ++i)
 			{
@@ -280,22 +282,27 @@ widget_out(WIDGET *widget)
 					widget->center.x, widget->center.y, widget->radius);
 }
 
 PG_FUNCTION_INFO_V1(pt_in_widget);
 
 Datum
 pt_in_widget(PG_FUNCTION_ARGS)
 {
 	Point	   *point = PG_GETARG_POINT_P(0);
 	WIDGET	   *widget = (WIDGET *) PG_GETARG_POINTER(1);
+	float8		distance;
 
-	PG_RETURN_BOOL(point_dt(point, &widget->center) < widget->radius);
+	distance = DatumGetFloat8(DirectFunctionCall2(point_distance,
+												  PointPGetDatum(point),
+											PointPGetDatum(&widget->center)));
+
+	PG_RETURN_BOOL(distance < widget->radius);
 }
 
 PG_FUNCTION_INFO_V1(boxarea);
 
 Datum
 boxarea(PG_FUNCTION_ARGS)
 {
 	BOX		   *box = PG_GETARG_BOX_P(0);
 	double		width,
 				height;
-- 
2.7.4 (Apple Git-66)

