Thread: Strange behavior with polygon and NaN

Strange behavior with polygon and NaN

From
Jesse Zhang
Date:
Hi hackers,

While working with Chris Hajas on merging Postgres 12 with Greenplum
Database we stumbled upon the following strange behavior in the geometry
type polygon:

------ >8 --------

CREATE TEMP TABLE foo (p point);
CREATE INDEX ON foo USING gist(p);

INSERT INTO foo VALUES ('0,0'), ('1,1'), ('NaN,NaN');

SELECT $q$
SELECT * FROM foo WHERE p <@ polygon '(0,0), (0, 100), (100, 100), (100, 0)'
$q$ AS qry \gset

BEGIN;
SAVEPOINT yolo;
SET LOCAL enable_seqscan TO off;
:qry;

ROLLBACK TO SAVEPOINT yolo;
SET LOCAL enable_indexscan TO off;
SET LOCAL enable_bitmapscan TO off;
:qry;

------ 8< --------

If you run the above repro SQL in HEAD (and 12, and likely all older
versions), you get the following output:

CREATE TABLE
CREATE INDEX
INSERT 0 3
BEGIN
SAVEPOINT
SET
   p
-------
 (0,0)
 (1,1)
(2 rows)

ROLLBACK
SET
SET
     p
-----------
 (0,0)
 (1,1)
 (NaN,NaN)
(3 rows)


At first glance, you'd think this is the gist AM's bad, but on a second
thought, something else is strange here. The following query returns
true:

SELECT point '(NaN, NaN)' <@ polygon '(0,0), (0, 100), (100, 100), (100, 0)'

The above behavior of the "contained in" operator is surprising, and
it's probably not what the GiST AM is expecting. I took a look at
point_inside() in geo_ops.c, and it doesn't seem well equipped to handle
NaN. Similary ill-equipped is dist_ppoly_internal() which underlies the
distnace operator for polygon. It gives the following interesting
output:

SELECT *, c <-> polygon '(0,0),(0,100),(100,100),(100,0)' as distance
FROM (
  SELECT circle(point(100 * i, 'NaN'), 50) AS c
  FROM generate_series(-2, 4) i
) t(c)
ORDER BY 2;

        c        | distance
-----------------+----------
 <(-200,NaN),50> |        0
 <(-100,NaN),50> |        0
 <(0,NaN),50>    |        0
 <(100,NaN),50>  |        0
 <(200,NaN),50>  |      NaN
 <(300,NaN),50>  |      NaN
 <(400,NaN),50>  |      NaN
(7 rows)

Should they all be NaN? Am I alone in thinking the index is right but
the operators are wrong? Or should we call the indexes wrong here?

Cheers,
Jesse and Chris



Re: Strange behavior with polygon and NaN

From
Bruce Momjian
Date:
I can confirm that this two-month old email report still produces
different results with indexes on/off in git master, which I don't think
is ever correct behavior.

---------------------------------------------------------------------------

On Wed, Jun 24, 2020 at 03:11:03PM -0700, Jesse Zhang wrote:
> Hi hackers,
> 
> While working with Chris Hajas on merging Postgres 12 with Greenplum
> Database we stumbled upon the following strange behavior in the geometry
> type polygon:
> 
> ------ >8 --------
> 
> CREATE TEMP TABLE foo (p point);
> CREATE INDEX ON foo USING gist(p);
> 
> INSERT INTO foo VALUES ('0,0'), ('1,1'), ('NaN,NaN');
> 
> SELECT $q$
> SELECT * FROM foo WHERE p <@ polygon '(0,0), (0, 100), (100, 100), (100, 0)'
> $q$ AS qry \gset
> 
> BEGIN;
> SAVEPOINT yolo;
> SET LOCAL enable_seqscan TO off;
> :qry;
> 
> ROLLBACK TO SAVEPOINT yolo;
> SET LOCAL enable_indexscan TO off;
> SET LOCAL enable_bitmapscan TO off;
> :qry;
> 
> ------ 8< --------
> 
> If you run the above repro SQL in HEAD (and 12, and likely all older
> versions), you get the following output:
> 
> CREATE TABLE
> CREATE INDEX
> INSERT 0 3
> BEGIN
> SAVEPOINT
> SET
>    p
> -------
>  (0,0)
>  (1,1)
> (2 rows)
> 
> ROLLBACK
> SET
> SET
>      p
> -----------
>  (0,0)
>  (1,1)
>  (NaN,NaN)
> (3 rows)
> 
> 
> At first glance, you'd think this is the gist AM's bad, but on a second
> thought, something else is strange here. The following query returns
> true:
> 
> SELECT point '(NaN, NaN)' <@ polygon '(0,0), (0, 100), (100, 100), (100, 0)'
> 
> The above behavior of the "contained in" operator is surprising, and
> it's probably not what the GiST AM is expecting. I took a look at
> point_inside() in geo_ops.c, and it doesn't seem well equipped to handle
> NaN. Similary ill-equipped is dist_ppoly_internal() which underlies the
> distnace operator for polygon. It gives the following interesting
> output:
> 
> SELECT *, c <-> polygon '(0,0),(0,100),(100,100),(100,0)' as distance
> FROM (
>   SELECT circle(point(100 * i, 'NaN'), 50) AS c
>   FROM generate_series(-2, 4) i
> ) t(c)
> ORDER BY 2;
> 
>         c        | distance
> -----------------+----------
>  <(-200,NaN),50> |        0
>  <(-100,NaN),50> |        0
>  <(0,NaN),50>    |        0
>  <(100,NaN),50>  |        0
>  <(200,NaN),50>  |      NaN
>  <(300,NaN),50>  |      NaN
>  <(400,NaN),50>  |      NaN
> (7 rows)
> 
> Should they all be NaN? Am I alone in thinking the index is right but
> the operators are wrong? Or should we call the indexes wrong here?
> 
> Cheers,
> Jesse and Chris
> 
> 

-- 
  Bruce Momjian  <bruce@momjian.us>        https://momjian.us
  EnterpriseDB                             https://enterprisedb.com

  The usefulness of a cup is in its emptiness, Bruce Lee




Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian <bruce@momjian.us> wrote in 
> 
> I can confirm that this two-month old email report still produces
> different results with indexes on/off in git master, which I don't think
> is ever correct behavior.

I agree to that the behavior is broken. 

> ---------------------------------------------------------------------------
> 
> On Wed, Jun 24, 2020 at 03:11:03PM -0700, Jesse Zhang wrote:
> > Hi hackers,
> > 
> > While working with Chris Hajas on merging Postgres 12 with Greenplum
> > Database we stumbled upon the following strange behavior in the geometry
> > type polygon:
> > 
> > ------ >8 --------
> > 
> > CREATE TEMP TABLE foo (p point);
> > CREATE INDEX ON foo USING gist(p);
> > 
> > INSERT INTO foo VALUES ('0,0'), ('1,1'), ('NaN,NaN');
> > 
> > SELECT $q$
> > SELECT * FROM foo WHERE p <@ polygon '(0,0), (0, 100), (100, 100), (100, 0)'
> > $q$ AS qry \gset
> > 
> > BEGIN;
> > SAVEPOINT yolo;
> > SET LOCAL enable_seqscan TO off;
> > :qry;
> > 
> > ROLLBACK TO SAVEPOINT yolo;
> > SET LOCAL enable_indexscan TO off;
> > SET LOCAL enable_bitmapscan TO off;
> > :qry;
> > 
> > ------ 8< --------
> > 
> > If you run the above repro SQL in HEAD (and 12, and likely all older
> > versions), you get the following output:
> > 
> > CREATE TABLE
> > CREATE INDEX
> > INSERT 0 3
> > BEGIN
> > SAVEPOINT
> > SET
> >    p
> > -------
> >  (0,0)
> >  (1,1)
> > (2 rows)
> > 
> > ROLLBACK
> > SET
> > SET
> >      p
> > -----------
> >  (0,0)
> >  (1,1)
> >  (NaN,NaN)
> > (3 rows)
> > 
> > 
> > At first glance, you'd think this is the gist AM's bad, but on a second
> > thought, something else is strange here. The following query returns
> > true:
> > 
> > SELECT point '(NaN, NaN)' <@ polygon '(0,0), (0, 100), (100, 100), (100, 0)'
> > 
> > The above behavior of the "contained in" operator is surprising, and
> > it's probably not what the GiST AM is expecting. I took a look at
> > point_inside() in geo_ops.c, and it doesn't seem well equipped to handle
> > NaN. Similary ill-equipped is dist_ppoly_internal() which underlies the
> > distnace operator for polygon. It gives the following interesting
> > output:
> > 
> > SELECT *, c <-> polygon '(0,0),(0,100),(100,100),(100,0)' as distance
> > FROM (
> >   SELECT circle(point(100 * i, 'NaN'), 50) AS c
> >   FROM generate_series(-2, 4) i
> > ) t(c)
> > ORDER BY 2;
> > 
> >         c        | distance
> > -----------------+----------
> >  <(-200,NaN),50> |        0
> >  <(-100,NaN),50> |        0
> >  <(0,NaN),50>    |        0
> >  <(100,NaN),50>  |        0
> >  <(200,NaN),50>  |      NaN
> >  <(300,NaN),50>  |      NaN
> >  <(400,NaN),50>  |      NaN
> > (7 rows)
> > 
> > Should they all be NaN? Am I alone in thinking the index is right but
> > the operators are wrong? Or should we call the indexes wrong here?


There may be other places that NaN is not fully considered. For
example, the following (perpendicular op) returns true.

SELECT lseg '[(0,0),(0,NaN)]' ?-| lseg '[(0,0),(10,0)]';

It is quite hard to fix all of the defect..

For the above cases, it's enough to make sure that point_inside don't
pass NaN's to lseg_crossing(), but it's much of labor to fill all
holes reasonable and principled way..

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..1875f8d436 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -5350,6 +5350,9 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    if (isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5359,6 +5362,9 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        if (isnan(x) || isnan(y))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;

Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes:
> At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian <bruce@momjian.us> wrote in
>> I can confirm that this two-month old email report still produces
>> different results with indexes on/off in git master, which I don't think
>> is ever correct behavior.

> I agree to that the behavior is broken.

Yeah, but ... what is "non broken" in this case?  I'm not convinced
that having point_inside() return zero for any case involving NaN
is going to lead to noticeably saner behavior than today.

            regards, tom lane



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Wed, 26 Aug 2020 08:18:49 -0400, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes:
> > At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian <bruce@momjian.us> wrote in 
> >> I can confirm that this two-month old email report still produces
> >> different results with indexes on/off in git master, which I don't think
> >> is ever correct behavior.
> 
> > I agree to that the behavior is broken. 
> 
> Yeah, but ... what is "non broken" in this case?  I'm not convinced
> that having point_inside() return zero for any case involving NaN
> is going to lead to noticeably saner behavior than today.

Yes, just doing that leaves many unfixed behavior come from NaNs, but
at least it seems to me one of sane definition candidates that a point
cannot be inside a polygon when NaN is involved. It's similar to
Fpxx() returns false if NaN is involved. As mentioned, I had't fully
checked and haven't considered this seriously, but I changed my mind
to check all the callers. I started checking all the callers of
point_inside, then finally I had to check all functions in geo_ops.c:(

The attached is the result as of now.

=== Resulting behavior

With the attached:

 - All boolean functions return false if NaN is involved.
 - All float8 functions return NaN if NaN is involved.
 - All geometric arithmetics return NaN as output if NaN is involved.

With some exceptions:
 - line_eq: needs to consider that NaNs are equal each other.
 - point_eq/ne (point_eq_pint): ditto
 - lseg_eq/ne: ditto

The change makes some difference in the regression test.
For example,

<obj containing NaN> <-> <any obj> changed from 0 to NaN. (distance)
<obj containing NaN> <@  <any obj> changed from true to false. (contained)
<obj containing NaN> <-> <any obj> changed from 0 to NaN. (distance)
<obj containing NaN> ?#  <any obj> changed from true to false (overlaps)


=== pg_hypot mistake?

I noticed that pg_hypot returns inf for the parameters (NaN, Inf) but
I think NaN is appropriate here since other operators behaves that
way. This change causes a change of distance between point(1e+300,Inf)
and line (1,-1,0) from infinity to NaN, which I think is correct
because the arithmetic generates NaN as an intermediate value.


=== Infinity annoyances

Infinity makes some not-great changes in regresssion results. For example:

- point '(1e+300,Infinity)' <-> path '((10,20))' returns
  NaN(previously Infinity), but point '(1e+300,Infinity)' <-> path
  '[(1,2),(3,4)]' returns Infinity.  The difference of the two
  expressions is whether (0 * Inf = NaN) is performed or not. The
  former performs it but that was concealed by not propagating NaN to
  upper layer without the patch.

- Without the patch, point '(1e+300,Infinity)' ## box '(2,2),(0,0)'
  generates '(0,2)', which is utterly wrong. It is because
  box_closept_point evaluates float8_lt(Inf, NaN) as true(!) and sets
  the wrong point for distance=NaN is set. With the patch, the NaN
  makes the result NULL.

- This is not a difference caused by this patch, but for both patched
  and unpatched, point '(1e+300,Inf)' <-> line '{3,0,0}' returns NaN,
  which should be 1e+300. However, the behavior comes from arithmetic
  reasons and wouldn't be a problem.

create_index.out is changed since point(NaN,NaN) <@ polygon changed
from true to false, which seems rather saner.

I haven't checked unchanged results but at least changed results seems
saner to me.


regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From 432a671517e78061edc87d18aec291f5629fcbe6 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Thu, 27 Aug 2020 14:49:21 +0900
Subject: [PATCH v1] Fix NaN handling of some geometric operators and functions

Some geometric operators shows somewhat odd behavior comes from NaN
handling and that leads to inconsistency between index scan and seq
scan on geometric conditions.

For example:
  point '(NaN,NaN)' <-> polygon '((0,0),(0,1),(1,1))' => 0, not NaN
  point '(0.3,0.5)' <-> polygon '((0,0),(0,NaN),(1,1))' => 1.14, not NaN
  point '(NaN,NaN)' <@ polygon '((0,0),(0,1),(1,1))'  => true, not false

Some other functions returned totally wrong result like this:
 point '(1e+300,Infinity)' ## box '(2,2),(0,0)' => '(0,2)'

Fix NaN handling of geo_ops.c so that these generates saner results.
---
 src/backend/utils/adt/geo_ops.c            | 183 ++++++++++++++++--
 src/test/regress/expected/create_index.out |   2 +-
 src/test/regress/expected/geometry.out     | 209 +++++++++------------
 3 files changed, 248 insertions(+), 146 deletions(-)

diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..916ae87d05 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,19 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    /* float8_min conceals NaN, check separately for NaNs */
+    if (unlikely(isnan(box1->high.x) || isnan(box2->high.x)))
+        result->high.x = get_float8_nan();
+    else
+        result->high.x = float8_min(box1->high.x, box2->high.x);
+
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+
+    if (unlikely(isnan(box1->high.y) || isnan(box2->high.y)))
+        result->high.x = get_float8_nan();
+    else
+        result->high.y = float8_min(box1->high.y, box2->high.y);
+
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,6 +1071,10 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->y)))
+            result->C = get_float8_nan();
     }
     else
     {
@@ -1084,6 +1098,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1104,8 +1119,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1123,14 +1142,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1141,7 +1163,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1149,7 +1171,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1195,9 +1217,19 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(line->A, -line->B);
 }
 
@@ -1209,9 +1241,19 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1224,14 +1266,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2))    /* intersecting? */
+    {
+        /* return NaN if NaN was involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1626,18 +1677,32 @@ path_inter(PG_FUNCTION_ARGS)
     b1.high.y = b1.low.y = p1->p[0].y;
     for (i = 1; i < p1->npts; i++)
     {
+        /* float8_min conceals NaN, check separately for NaNs */
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
+        if (unlikely(isnan(p1->p[i].x)))
+            b1.low.x = p1->p[i].x;
+        else
+            b1.low.x = float8_min(p1->p[i].x, b1.low.x);
+        if (unlikely(isnan(p1->p[i].y)))
+            b1.low.x = p1->p[i].y;
+        else
         b1.low.y = float8_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++)
     {
+        /* float8_min conceals NaN, check separately for NaNs */
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
+        if (unlikely(isnan(p2->p[i].x)))
+            b2.low.x = p2->p[i].x;
+        else
+            b2.low.x = float8_min(p2->p[i].x, b2.low.x);
+        if (unlikely(isnan(p2->p[i].y)))
+            b2.low.y = p1->p[i].y;
+        else
         b2.low.y = float8_min(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
@@ -1728,6 +1793,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1980,9 +2050,17 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -1996,9 +2074,17 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2414,6 +2500,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2645,6 +2736,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2674,7 +2767,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2803,6 +2897,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        isnan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2814,6 +2909,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    isnan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2823,6 +2919,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2830,6 +2927,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2837,6 +2935,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2873,6 +2977,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        isnan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2887,9 +2992,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    isnan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2901,6 +3007,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2910,6 +3017,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2917,6 +3025,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -2988,6 +3103,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3010,6 +3126,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3436,6 +3560,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3911,6 +4041,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5350,6 +5485,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5359,6 +5498,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
@@ -5517,12 +5660,12 @@ pg_hypot(float8 x, float8 y)
                 result;
 
     /* Handle INF and NaN properly */
-    if (isinf(x) || isinf(y))
+    if (unlikely(isnan(x) || isnan(y)))
+        return get_float8_nan();
+
+    if (unlikely(isinf(x) || isinf(y)))
         return get_float8_infinity();
 
-    if (isnan(x) || isnan(y))
-        return get_float8_nan();
-
     /* Else, drop any minus signs */
     x = fabs(x);
     y = fabs(y);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index e3e6634d7e..5382259159 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..cad0716915 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -494,9 +494,9 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
- (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
+ (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
@@ -580,9 +580,9 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
  (1e+300,Infinity) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
- (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (1e+300,Infinity) | [(-10,2),(-10,3)]             |                NaN |                NaN
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -635,11 +635,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e-300,-1e-300)  | (-2,2),(-8,-10)     |                  2 |                  2
  (1e-300,-1e-300)  | (2.5,3.5),(2.5,2.5) |      3.53553390593 |      3.53553390593
  (1e-300,-1e-300)  | (3,3),(3,3)         |      4.24264068712 |      4.24264068712
- (1e+300,Infinity) | (2,2),(0,0)         |           Infinity |           Infinity
- (1e+300,Infinity) | (3,3),(1,1)         |           Infinity |           Infinity
- (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
- (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
- (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (1e+300,Infinity) | (2,2),(0,0)         |                NaN |                NaN
+ (1e+300,Infinity) | (3,3),(1,1)         |                NaN |                NaN
+ (1e+300,Infinity) | (-2,2),(-8,-10)     |                NaN |                NaN
+ (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |                NaN |                NaN
+ (1e+300,Infinity) | (3,3),(3,3)         |                NaN |                NaN
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -716,7 +716,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((1,2),(3,4))             |           Infinity |           Infinity
  (1e+300,Infinity) | ((1,2),(3,4))             |           Infinity |           Infinity
  (1e+300,Infinity) | [(1,2),(3,4)]             |           Infinity |           Infinity
- (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
+ (1e+300,Infinity) | ((10,20))                 |                NaN |                NaN
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
@@ -785,20 +785,20 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e-300,-1e-300)  | ((1,2),(7,8),(5,6),(3,-4)) | 1.58113883008 | 1.58113883008
  (1e-300,-1e-300)  | ((0,0))                    |             0 |             0
  (1e-300,-1e-300)  | ((0,1),(0,1))              |             1 |             1
- (1e+300,Infinity) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
- (1e+300,Infinity) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (1e+300,Infinity) | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (1e+300,Infinity) | ((3,1),(3,3),(1,0))        |           NaN |           NaN
  (1e+300,Infinity) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
  (1e+300,Infinity) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
- (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
- (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (1e+300,Infinity) | ((0,0))                    |           NaN |           NaN
+ (1e+300,Infinity) | ((0,1),(0,1))              |           NaN |           NaN
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -875,9 +875,9 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               | 
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | 
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | 
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | 
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
@@ -961,9 +961,9 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(10,-10),(-3,-4)]            | (-3,-4)
  (1e+300,Infinity) | [(-1000000,200),(300000,-40)] | (300000,-40)
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
- (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
+ (1e+300,Infinity) | [(-10,2),(-10,3)]             | 
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
  (NaN,NaN)         | [(1,2),(3,4)]                 | 
  (NaN,NaN)         | [(0,0),(6,6)]                 | 
  (NaN,NaN)         | [(10,-10),(-3,-4)]            | 
@@ -1016,11 +1016,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e-300,-1e-300)  | (-2,2),(-8,-10)     | (-2,-1e-300)
  (1e-300,-1e-300)  | (2.5,3.5),(2.5,2.5) | (2.5,2.5)
  (1e-300,-1e-300)  | (3,3),(3,3)         | (3,3)
- (1e+300,Infinity) | (2,2),(0,0)         | (0,2)
- (1e+300,Infinity) | (3,3),(1,1)         | (1,3)
- (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
- (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
- (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (1e+300,Infinity) | (2,2),(0,0)         | 
+ (1e+300,Infinity) | (3,3),(1,1)         | 
+ (1e+300,Infinity) | (-2,2),(-8,-10)     | 
+ (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | 
+ (1e+300,Infinity) | (3,3),(3,3)         | 
  (NaN,NaN)         | (2,2),(0,0)         | 
  (NaN,NaN)         | (3,3),(1,1)         | 
  (NaN,NaN)         | (-2,2),(-8,-10)     | 
@@ -1060,12 +1060,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1153,8 +1148,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1163,8 +1158,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1173,8 +1168,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1183,8 +1178,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1193,8 +1188,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1203,38 +1198,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1243,8 +1238,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1262,31 +1257,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1294,8 +1281,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1303,46 +1288,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -3467,13 +3426,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3536,13 +3495,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
-- 
2.18.4


Re: Strange behavior with polygon and NaN

From
gkokolatos@pm.me
Date:




‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Thursday, 27 August 2020 14:24, Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote:

> At Wed, 26 Aug 2020 08:18:49 -0400, Tom Lane tgl@sss.pgh.pa.us wrote in
>
> > Kyotaro Horiguchi horikyota.ntt@gmail.com writes:
> >
> > > At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian bruce@momjian.us wrote in
> > >
> > > > I can confirm that this two-month old email report still produces
> > > > different results with indexes on/off in git master, which I don't think
> > > > is ever correct behavior.
> >
> > > I agree to that the behavior is broken.
> >
> > Yeah, but ... what is "non broken" in this case? I'm not convinced
> > that having point_inside() return zero for any case involving NaN
> > is going to lead to noticeably saner behavior than today.
>
> Yes, just doing that leaves many unfixed behavior come from NaNs, but
> at least it seems to me one of sane definition candidates that a point
> cannot be inside a polygon when NaN is involved. It's similar to
> Fpxx() returns false if NaN is involved. As mentioned, I had't fully
> checked and haven't considered this seriously, but I changed my mind
> to check all the callers. I started checking all the callers of
> point_inside, then finally I had to check all functions in geo_ops.c:(
>

For what is worth, I agree with this definition.


> The attached is the result as of now.
>
> === Resulting behavior
>
> With the attached:
>
> -   All boolean functions return false if NaN is involved.
> -   All float8 functions return NaN if NaN is involved.
> -   All geometric arithmetics return NaN as output if NaN is involved.

Agreed! As in both this behaviour conforms to the definition above and the patch provides this behaviour with the
exceptionsbelow. 

>
>     With some exceptions:
>
> -   line_eq: needs to consider that NaNs are equal each other.
> -   point_eq/ne (point_eq_pint): ditto
> -   lseg_eq/ne: ditto
>
>     The change makes some difference in the regression test.
>     For example,
>
>     <obj containing NaN> <-> <any obj> changed from 0 to NaN. (distance)
>
>
> <obj containing NaN> <@ <any obj> changed from true to false. (contained)
> <obj containing NaN> <-> <any obj> changed from 0 to NaN. (distance)
> <obj containing NaN> ?# <any obj> changed from true to false (overlaps)
>
> === pg_hypot mistake?
>
> I noticed that pg_hypot returns inf for the parameters (NaN, Inf) but
> I think NaN is appropriate here since other operators behaves that
> way. This change causes a change of distance between point(1e+300,Inf)
> and line (1,-1,0) from infinity to NaN, which I think is correct
> because the arithmetic generates NaN as an intermediate value.
>
> === Infinity annoyances
>
> Infinity makes some not-great changes in regresssion results. For example:
>
> -   point '(1e+300,Infinity)' <-> path '((10,20))' returns
>     NaN(previously Infinity), but point '(1e+300,Infinity)' <-> path
>     '[(1,2),(3,4)]' returns Infinity. The difference of the two
>     expressions is whether (0 * Inf = NaN) is performed or not. The
>     former performs it but that was concealed by not propagating NaN to
>     upper layer without the patch.

Although I understand the reasoning for this change. I am not certain I agree with the result. I feel that:
    point '(1e+300,Infinity)' <-> path '((10,20))'
should return Infinity. Even if I am wrong to think that, the two results should be expected to behave the same. Am I
wrongon that too? 


>
> -   Without the patch, point '(1e+300,Infinity)' ## box '(2,2),(0,0)'
>     generates '(0,2)', which is utterly wrong. It is because
>     box_closept_point evaluates float8_lt(Inf, NaN) as true(!) and sets
>     the wrong point for distance=NaN is set. With the patch, the NaN
>     makes the result NULL.

Agreed.

>
> -   This is not a difference caused by this patch, but for both patched
>     and unpatched, point '(1e+300,Inf)' <-> line '{3,0,0}' returns NaN,
>     which should be 1e+300. However, the behavior comes from arithmetic
>     reasons and wouldn't be a problem.
>
>     create_index.out is changed since point(NaN,NaN) <@ polygon changed
>     from true to false, which seems rather saner.
>
>     I haven't checked unchanged results but at least changed results seems
>     saner to me.

All in all a great patch!

It is clean, well reasoned and carefully crafted.

Do you think that the documentation needs to get updated to the 'new' behaviour?


//Georgios


>
>     regards.
>
>     --
>     Kyotaro Horiguchi
>     NTT Open Source Software Center
>


Attachment

Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
Hello, Georgios.

At Mon, 07 Sep 2020 12:46:50 +0000, gkokolatos@pm.me wrote in 
> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Thursday, 27 August 2020 14:24, Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote:
> 
> > At Wed, 26 Aug 2020 08:18:49 -0400, Tom Lane tgl@sss.pgh.pa.us wrote in
> >
> > > Kyotaro Horiguchi horikyota.ntt@gmail.com writes:
> > >
> > > > At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian bruce@momjian.us wrote in
> > > >
> > > > > I can confirm that this two-month old email report still produces
> > > > > different results with indexes on/off in git master, which I don't think
> > > > > is ever correct behavior.
> > >
> > > > I agree to that the behavior is broken.
> > >
> > > Yeah, but ... what is "non broken" in this case? I'm not convinced
> > > that having point_inside() return zero for any case involving NaN
> > > is going to lead to noticeably saner behavior than today.
> >
> > Yes, just doing that leaves many unfixed behavior come from NaNs, but
> > at least it seems to me one of sane definition candidates that a point
> > cannot be inside a polygon when NaN is involved. It's similar to
> > Fpxx() returns false if NaN is involved. As mentioned, I had't fully
> > checked and haven't considered this seriously, but I changed my mind
> > to check all the callers. I started checking all the callers of
> > point_inside, then finally I had to check all functions in geo_ops.c:(
> >
> 
> For what is worth, I agree with this definition.

Thanks.

> > The attached is the result as of now.
> >
> > === Resulting behavior
> >
> > With the attached:
> >
> > -   All boolean functions return false if NaN is involved.
> > -   All float8 functions return NaN if NaN is involved.
> > -   All geometric arithmetics return NaN as output if NaN is involved.
> 
> Agreed! As in both this behaviour conforms to the definition above and the patch provides this behaviour with the
exceptionsbelow.
 
> 
> >
> >     With some exceptions:
> >
> > -   line_eq: needs to consider that NaNs are equal each other.
> > -   point_eq/ne (point_eq_pint): ditto
> > -   lseg_eq/ne: ditto
...
> > === pg_hypot mistake?
> >
> > I noticed that pg_hypot returns inf for the parameters (NaN, Inf) but
> > I think NaN is appropriate here since other operators behaves that
> > way. This change causes a change of distance between point(1e+300,Inf)
> > and line (1,-1,0) from infinity to NaN, which I think is correct
> > because the arithmetic generates NaN as an intermediate value.
> >
> > === Infinity annoyances
> >
> > Infinity makes some not-great changes in regresssion results. For example:
> >
> > -   point '(1e+300,Infinity)' <-> path '((10,20))' returns
> >     NaN(previously Infinity), but point '(1e+300,Infinity)' <-> path
> >     '[(1,2),(3,4)]' returns Infinity. The difference of the two
> >     expressions is whether (0 * Inf = NaN) is performed or not. The
> >     former performs it but that was concealed by not propagating NaN to
> >     upper layer without the patch.
> 
> Although I understand the reasoning for this change. I am not certain I agree with the result. I feel that:
>     point '(1e+300,Infinity)' <-> path '((10,20))'
> should return Infinity. Even if I am wrong to think that, the two results should be expected to behave the same. Am I
wrongon that too?
 

No. Actually that's not correct and that just comes from avoiding
special code paths for Infinity.  I put more thought on
line_interpt_line and found that that issue is "fixed" by just
simplifying formulas by removing invariants. But one more if-block is
needed to make the function work a symmetrical way, though..

However, still we have a similar issue.

point '(Infinity,1e+300)' <-> line '{-1,0,5}' => Infinity
point '(Infinity,1e+300)' <-> line '{0,-1,5}' => NaN
point '(Infinity,1e+300)' <-> line '{1,1,5}' => NaN

The second should be 1e+300 and the third infinity. This is because
line_closept_point taking the distance between the foot of the
perpendicular line from the point and the point. We can fix the second
case by adding special code paths for vertical and horizontal lines,
but the third needs another special code path explicitly identifying
Infinity. It seems a kind of too-much..

Finally, I gave up fixing that and added doucmentation.

As another issue, (point '(Infinity, 1e+300)' <-> path '((10,20))')
results in NaN. That is "fixed" by adding a special path for "m ==
0.0" case, but I'm not sure it's worth doing..

By the way I found that float8_div(<normal number>, infinity) erros
out as underflow. It is inconsistent with the behavior that float8_mul
doesn't error-out as overflow when Infinity is given. So fixed it.

> > -   This is not a difference caused by this patch, but for both patched
> >     and unpatched, point '(1e+300,Inf)' <-> line '{3,0,0}' returns NaN,
> >     which should be 1e+300. However, the behavior comes from arithmetic
> >     reasons and wouldn't be a problem.
> >
> >     create_index.out is changed since point(NaN,NaN) <@ polygon changed
> >     from true to false, which seems rather saner.
> >
> >     I haven't checked unchanged results but at least changed results seems
> >     saner to me.
> 
> All in all a great patch!
> 
> It is clean, well reasoned and carefully crafted.
> 
> Do you think that the documentation needs to get updated to the 'new' behaviour?

Hmm. I'm not sure we can guarantee the behavior as documented, but I
tried writing in functions-geometry.html.

> NaN and Infinity make geometric functions and operators behave
> inconsistently. Geometric operators or functions that return a boolean
> return false for operands that contain NaNs. Number-returning
> functions and operators return the NaN in most cases but sometimes
> return a valid value if no NaNs are met while
> calculation. Object-returning ones yield an object that contain NaNs
> depending to the operation. Likewise the objects containing Infinity
> can make geometric operators and functions behave inconsistently. For
> example (point '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity
> but (point '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can
> never be a value other than these, but you should consider it
> uncertain how geometric operators behave for objects containing
> Infinity.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From 2e6d3bd2e29c3e4f89fce6dca9e0175029b6fd94 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Thu, 27 Aug 2020 14:49:21 +0900
Subject: [PATCH v2] Fix NaN handling of some geometric operators and functions

Some geometric operators shows somewhat odd behavior comes from NaN
handling and that leads to inconsistency between index scan and seq
scan on geometric conditions.

For example:
  point '(NaN,NaN)' <-> polygon '((0,0),(0,1),(1,1))' => 0, not NaN
  point '(0.3,0.5)' <-> polygon '((0,0),(0,NaN),(1,1))' => 1.14, not NaN
  point '(NaN,NaN)' <@ polygon '((0,0),(0,1),(1,1))'  => true, not false

Some other functions returned totally wrong result like this:
 point '(1e+300,Infinity)' ## box '(2,2),(0,0)' => '(0,2)'

Fix NaN and Infinity handling of geo_ops.c so that these generates
saner results. However, the behavioral inconsistency that comes from
Infinity cannot be eliminated with a moderate amount of additional
code against the benefit so they are left alone and added
documentation instead.
---
 doc/src/sgml/func.sgml                     |  16 +
 src/backend/utils/adt/geo_ops.c            | 215 ++++++++--
 src/include/utils/float.h                  |   8 +-
 src/test/regress/expected/create_index.out |  24 +-
 src/test/regress/expected/geometry.out     | 458 ++++++++++++++-------
 src/test/regress/expected/point.out        | 138 +++++--
 src/test/regress/sql/point.sql             |   2 +
 7 files changed, 633 insertions(+), 228 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index e2e618791e..d8638c06b8 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10924,6 +10924,22 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
      on), where available for these types, likewise compare areas.
     </para>
    </caution>
+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return the NaN in most cases but sometimes return a valid
+       value if no NaNs are met while calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
 
    <note>
     <para>
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..06deeb6d12 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,19 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    /* float8_min conceals NaN, check separately for NaNs */
+    if (unlikely(isnan(box1->high.x) || isnan(box2->high.x)))
+        result->high.x = get_float8_nan();
+    else
+        result->high.x = float8_min(box1->high.x, box2->high.x);
+
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+
+    if (unlikely(isnan(box1->high.y) || isnan(box2->high.y)))
+        result->high.x = get_float8_nan();
+    else
+        result->high.y = float8_min(box1->high.y, box2->high.y);
+
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,6 +1071,21 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->y)))
+            result->C = get_float8_nan();
+    }
+    else if (m == 0.0)
+    {
+        /* use "mx - y + yinter = 0" */
+        result->A = 0.0;
+        result->B = -1.0;
+        result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->x)))
+            result->C = get_float8_nan();
     }
     else
     {
@@ -1084,6 +1109,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1104,8 +1130,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1123,14 +1153,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1141,7 +1174,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1149,7 +1182,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1195,9 +1228,19 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(line->A, -line->B);
 }
 
@@ -1209,9 +1252,19 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1224,14 +1277,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2))    /* intersecting? */
+    {
+        /* return NaN if NaN was involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1291,14 +1353,19 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
     }
     else if (!FPzero(l2->B))
     {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
-
-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
-                       float8_mi(float8_mul(l2->A, l1->B),
-                                 float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+        /*
+         * We know that l1->B is zero, which means l1 is vertical. The lines
+         * cannot be parallel and the x-coord of the cross point is -C/A of l1.
+         */
+        x = -float8_div(l1->C, l1->A);
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
     }
     else
         return false;
@@ -1626,18 +1693,32 @@ path_inter(PG_FUNCTION_ARGS)
     b1.high.y = b1.low.y = p1->p[0].y;
     for (i = 1; i < p1->npts; i++)
     {
+        /* float8_min conceals NaN, check separately for NaNs */
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
+        if (unlikely(isnan(p1->p[i].x)))
+            b1.low.x = p1->p[i].x;
+        else
+            b1.low.x = float8_min(p1->p[i].x, b1.low.x);
+        if (unlikely(isnan(p1->p[i].y)))
+            b1.low.x = p1->p[i].y;
+        else
         b1.low.y = float8_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++)
     {
+        /* float8_min conceals NaN, check separately for NaNs */
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
+        if (unlikely(isnan(p2->p[i].x)))
+            b2.low.x = p2->p[i].x;
+        else
+            b2.low.x = float8_min(p2->p[i].x, b2.low.x);
+        if (unlikely(isnan(p2->p[i].y)))
+            b2.low.y = p1->p[i].y;
+        else
         b2.low.y = float8_min(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
@@ -1728,6 +1809,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1980,9 +2066,17 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -1996,9 +2090,17 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2414,6 +2516,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2645,6 +2752,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2674,7 +2783,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2803,6 +2913,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        isnan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2814,6 +2925,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    isnan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2823,6 +2935,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2830,6 +2943,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2837,6 +2951,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2873,6 +2993,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        isnan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2887,9 +3008,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    isnan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2901,6 +3023,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2910,6 +3033,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2917,6 +3041,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -2988,6 +3119,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3010,6 +3142,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3436,6 +3576,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3911,6 +4057,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5350,6 +5501,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5359,6 +5514,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
@@ -5517,12 +5676,12 @@ pg_hypot(float8 x, float8 y)
                 result;
 
     /* Handle INF and NaN properly */
-    if (isinf(x) || isinf(y))
+    if (unlikely(isnan(x) || isnan(y)))
+        return get_float8_nan();
+
+    if (unlikely(isinf(x) || isinf(y)))
         return get_float8_infinity();
 
-    if (isnan(x) || isnan(y))
-        return get_float8_nan();
-
     /* Else, drop any minus signs */
     x = fabs(x);
     y = fabs(y);
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index e2aae8ef17..79bf8daca8 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -225,9 +225,9 @@ float4_div(const float4 val1, const float4 val2)
     if (unlikely(val2 == 0.0f) && !isnan(val1))
         float_zero_divide_error();
     result = val1 / val2;
-    if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+    if (unlikely(isinf(result)) && !isinf(val1))
         float_overflow_error();
-    if (unlikely(result == 0.0f) && val1 != 0.0f)
+    if (unlikely(result == 0.0f) && val1 != 0.0f && !isinf(val2))
         float_underflow_error();
 
     return result;
@@ -241,9 +241,9 @@ float8_div(const float8 val1, const float8 val2)
     if (unlikely(val2 == 0.0) && !isnan(val1))
         float_zero_divide_error();
     result = val1 / val2;
-    if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+    if (unlikely(isinf(result)) && !isinf(val1))
         float_overflow_error();
-    if (unlikely(result == 0.0) && val1 != 0.0)
+    if (unlikely(result == 0.0) && val1 != 0.0 && !isinf(val2))
         float_underflow_error();
 
     return result;
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 64c0c66859..dd521923dd 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
@@ -157,7 +157,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count 
 -------
-     3
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
@@ -169,7 +169,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count 
 -------
-     4
+     5
 (1 row)
 
 SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
@@ -188,10 +188,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
  
-(10 rows)
+(11 rows)
 
 SELECT * FROM point_tbl WHERE f1 IS NULL;
  f1 
@@ -202,16 +203,17 @@ SELECT * FROM point_tbl WHERE f1 IS NULL;
 SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
         f1         
 -------------------
- (1e-300,-1e-300)
  (0,0)
+ (1e-300,-1e-300)
  (-3,4)
  (-10,0)
  (10,10)
  (-5,-12)
  (5.1,34.5)
  (1e+300,Infinity)
+ (Infinity,1e+300)
  (NaN,NaN)
-(9 rows)
+(10 rows)
 
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
         f1        
@@ -464,7 +466,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count 
 -------
-     3
+     4
 (1 row)
 
 EXPLAIN (COSTS OFF)
@@ -494,7 +496,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count 
 -------
-     4
+     5
 (1 row)
 
 EXPLAIN (COSTS OFF)
@@ -530,10 +532,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
  
-(10 rows)
+(11 rows)
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 IS NULL;
@@ -568,9 +571,10 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
-(9 rows)
+(10 rows)
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..20acb0b0b4 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -120,6 +120,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          |                2.4
  (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
  (0,0)             | (1e+300,Infinity) |           Infinity
+ (0,0)             | (Infinity,1e+300) |                  0
  (0,0)             | (NaN,NaN)         |                NaN
  (0,0)             | (10,10)           |                  1
  (-10,0)           | (0,0)             |                  0
@@ -129,6 +130,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          |               -2.4
  (-10,0)           | (1e-300,-1e-300)  |                  0
  (-10,0)           | (1e+300,Infinity) |           Infinity
+ (-10,0)           | (Infinity,1e+300) |                  0
  (-10,0)           | (NaN,NaN)         |                NaN
  (-10,0)           | (10,10)           |                0.5
  (-3,4)            | (0,0)             |     -1.33333333333
@@ -138,6 +140,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          |                  8
  (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
  (-3,4)            | (1e+300,Infinity) |           Infinity
+ (-3,4)            | (Infinity,1e+300) |                  0
  (-3,4)            | (NaN,NaN)         |                NaN
  (-3,4)            | (10,10)           |     0.461538461538
  (5.1,34.5)        | (0,0)             |      6.76470588235
@@ -147,6 +150,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          |      4.60396039604
  (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
  (5.1,34.5)        | (1e+300,Infinity) |           Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |                  0
  (5.1,34.5)        | (NaN,NaN)         |                NaN
  (5.1,34.5)        | (10,10)           |                 -5
  (-5,-12)          | (0,0)             |                2.4
@@ -156,6 +160,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | 1.79769313486e+308
  (-5,-12)          | (1e-300,-1e-300)  |                2.4
  (-5,-12)          | (1e+300,Infinity) |           Infinity
+ (-5,-12)          | (Infinity,1e+300) |                  0
  (-5,-12)          | (NaN,NaN)         |                NaN
  (-5,-12)          | (10,10)           |      1.46666666667
  (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
@@ -165,6 +170,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          |                2.4
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
  (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
  (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
  (1e-300,-1e-300)  | (10,10)           |                  1
  (1e+300,Infinity) | (0,0)             |           Infinity
@@ -174,8 +180,19 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          |           Infinity
  (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
  (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
+ (1e+300,Infinity) | (Infinity,1e+300) |                NaN
  (1e+300,Infinity) | (NaN,NaN)         |                NaN
  (1e+300,Infinity) | (10,10)           |           Infinity
+ (Infinity,1e+300) | (0,0)             |                  0
+ (Infinity,1e+300) | (-10,0)           |                  0
+ (Infinity,1e+300) | (-3,4)            |                  0
+ (Infinity,1e+300) | (5.1,34.5)        |                  0
+ (Infinity,1e+300) | (-5,-12)          |                  0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
+ (Infinity,1e+300) | (1e+300,Infinity) |                NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |                  0
+ (Infinity,1e+300) | (NaN,NaN)         |                NaN
+ (Infinity,1e+300) | (10,10)           |                  0
  (NaN,NaN)         | (0,0)             |                NaN
  (NaN,NaN)         | (-10,0)           |                NaN
  (NaN,NaN)         | (-3,4)            |                NaN
@@ -183,6 +200,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          |                NaN
  (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
  (NaN,NaN)         | (1e+300,Infinity) |                NaN
+ (NaN,NaN)         | (Infinity,1e+300) |                NaN
  (NaN,NaN)         | (NaN,NaN)         |                NaN
  (NaN,NaN)         | (10,10)           |                NaN
  (10,10)           | (0,0)             |                  1
@@ -192,14 +210,15 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          |      1.46666666667
  (10,10)           | (1e-300,-1e-300)  |                  1
  (10,10)           | (1e+300,Infinity) |           Infinity
+ (10,10)           | (Infinity,1e+300) |                  0
  (10,10)           | (NaN,NaN)         |                NaN
  (10,10)           | (10,10)           | 1.79769313486e+308
-(81 rows)
+(100 rows)
 
 -- Add point
 SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |     ?column?      
--------------------+-------------------+-------------------
+        f1         |        f1         |      ?column?       
+-------------------+-------------------+---------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (-10,0)
  (0,0)             | (-3,4)            | (-3,4)
@@ -207,6 +226,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (-5,-12)
  (0,0)             | (1e-300,-1e-300)  | (1e-300,-1e-300)
  (0,0)             | (1e+300,Infinity) | (1e+300,Infinity)
+ (0,0)             | (Infinity,1e+300) | (Infinity,1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (10,10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -216,6 +236,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-15,-12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,-1e-300)
  (-10,0)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (-10,0)           | (Infinity,1e+300) | (Infinity,1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (0,10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -225,6 +246,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (-8,-8)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (1e+300,Infinity)
+ (-3,4)            | (Infinity,1e+300) | (Infinity,1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (7,14)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -234,6 +256,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (0.1,22.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (1e+300,Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (Infinity,1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (15.1,44.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -243,6 +266,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (-10,-24)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (1e+300,Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (Infinity,1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (5,-2)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -252,6 +276,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (-5,-12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (2e-300,-2e-300)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (1e+300,Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (Infinity,1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (10,10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -261,8 +286,19 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (2e+300,Infinity)
+ (1e+300,Infinity) | (Infinity,1e+300) | (Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (Infinity,2e+300)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -270,6 +306,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -279,14 +316,15 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (5,-2)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (10,10)           | (Infinity,1e+300) | (Infinity,1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (20,20)
-(81 rows)
+(100 rows)
 
 -- Subtract point
 SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |      ?column?       
--------------------+-------------------+---------------------
+        f1         |        f1         |       ?column?       
+-------------------+-------------------+----------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (10,0)
  (0,0)             | (-3,4)            | (3,-4)
@@ -294,6 +332,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (5,12)
  (0,0)             | (1e-300,-1e-300)  | (-1e-300,1e-300)
  (0,0)             | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (0,0)             | (Infinity,1e+300) | (-Infinity,-1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (-10,-10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -303,6 +342,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-5,12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,1e-300)
  (-10,0)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-10,0)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (-20,-10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -312,6 +352,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (2,16)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-3,4)            | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (-13,-6)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -321,6 +362,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (10.1,46.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (-Infinity,-1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (-4.9,24.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -330,6 +372,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (0,0)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (-15,-22)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -339,6 +382,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (5,12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (0,0)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (-Infinity,-1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (-10,-10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -348,8 +392,19 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (0,NaN)
+ (1e+300,Infinity) | (Infinity,1e+300) | (-Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (NaN,0)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -357,6 +412,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -366,9 +422,10 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (15,22)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (10,10)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (0,0)
-(81 rows)
+(100 rows)
 
 -- Multiply with point
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -388,11 +445,13 @@ SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0
  (10,10)    | (1e-300,-1e-300)  | (2e-299,0)
  (5.1,34.5) | (1e+300,Infinity) | (-Infinity,Infinity)
  (10,10)    | (1e+300,Infinity) | (-Infinity,Infinity)
+ (5.1,34.5) | (Infinity,1e+300) | (Infinity,Infinity)
+ (10,10)    | (Infinity,1e+300) | (Infinity,Infinity)
  (5.1,34.5) | (NaN,NaN)         | (NaN,NaN)
  (10,10)    | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5) | (10,10)           | (-294,396)
  (10,10)    | (10,10)           | (0,200)
-(18 rows)
+(20 rows)
 
 -- Underflow error
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] < 1;
@@ -415,11 +474,13 @@ SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0
  (1e-300,-1e-300)  | (10,10)    | (0,-1e-301)
  (1e+300,Infinity) | (5.1,34.5) | (Infinity,Infinity)
  (1e+300,Infinity) | (10,10)    | (Infinity,Infinity)
+ (Infinity,1e+300) | (5.1,34.5) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (10,10)    | (Infinity,-Infinity)
  (NaN,NaN)         | (5.1,34.5) | (NaN,NaN)
  (NaN,NaN)         | (10,10)    | (NaN,NaN)
  (10,10)           | (5.1,34.5) | (0.325588278822,-0.241724631247)
  (10,10)           | (10,10)    | (1,0)
-(18 rows)
+(20 rows)
 
 -- Overflow error
 SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0] > 1000;
@@ -494,13 +555,23 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
- (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
+ (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
+ (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -521,7 +592,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
  (10,10)           | {-1,0,3}                              |                  7 |                  7
-(90 rows)
+(100 rows)
 
 -- Distance to line segment
 SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
@@ -582,7 +653,15 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
+ (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |                NaN |                NaN
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -599,7 +678,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (10,10)           | [(-10,2),(-10,3)]             |      21.1896201004 |      21.1896201004
  (10,10)           | [(0,-20),(30,-20)]            |                 30 |                 30
  (10,10)           | [(NaN,1),(NaN,90)]            |                NaN |                NaN
-(72 rows)
+(80 rows)
 
 -- Distance to box
 SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT_TBL p, BOX_TBL b;
@@ -640,6 +719,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |                NaN |                NaN
+ (Infinity,1e+300) | (3,3),(1,1)         |                NaN |                NaN
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |                NaN |                NaN
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -650,7 +734,7 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (10,10)           | (-2,2),(-8,-10)     |      14.4222051019 |      14.4222051019
  (10,10)           | (2.5,3.5),(2.5,2.5) |      9.92471662064 |      9.92471662064
  (10,10)           | (3,3),(3,3)         |      9.89949493661 |      9.89949493661
-(45 rows)
+(50 rows)
 
 -- Distance to path
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp FROM POINT_TBL p, PATH_TBL p1;
@@ -719,6 +803,15 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((10,20))                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,12),(13,14)]         |           Infinity |           Infinity
+ (Infinity,1e+300) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
  (NaN,NaN)         | ((1,2),(3,4))             |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
@@ -737,7 +830,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (10,10)           | ((10,20))                 |                 10 |                 10
  (10,10)           | [(11,12),(13,14)]         |       2.2360679775 |       2.2360679775
  (10,10)           | ((11,12),(13,14))         |       2.2360679775 |       2.2360679775
-(81 rows)
+(90 rows)
 
 -- Distance to polygon
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp FROM POINT_TBL p, POLYGON_TBL p1;
@@ -792,13 +885,20 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (Infinity,1e+300) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -806,7 +906,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | 3.60555127546 | 3.60555127546
  (10,10)           | ((0,0))                    | 14.1421356237 | 14.1421356237
  (10,10)           | ((0,1),(0,1))              | 13.4536240471 | 13.4536240471
-(63 rows)
+(70 rows)
 
 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -875,13 +975,23 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               | 
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | 
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | 
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | 
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              | 
+ (Infinity,1e+300) | {0,-1,5}                              | 
+ (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
+ (Infinity,1e+300) | {0,3,0}                               | 
+ (Infinity,1e+300) | {1,-1,0}                              | 
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | 
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (Infinity,1e+300) | {3,NaN,5}                             | 
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
+ (Infinity,1e+300) | {0,-1,3}                              | 
+ (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
  (NaN,NaN)         | {0,3,0}                               | 
@@ -902,7 +1012,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (10,10)           | {NaN,NaN,NaN}                         | 
  (10,10)           | {0,-1,3}                              | (10,3)
  (10,10)           | {-1,0,3}                              | (3,10)
-(90 rows)
+(100 rows)
 
 -- Closest point to line segment
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
@@ -963,7 +1073,15 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
+ (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
+ (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
+ (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            | 
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            | 
  (NaN,NaN)         | [(1,2),(3,4)]                 | 
  (NaN,NaN)         | [(0,0),(6,6)]                 | 
  (NaN,NaN)         | [(10,-10),(-3,-4)]            | 
@@ -980,7 +1098,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (10,10)           | [(-10,2),(-10,3)]             | (-10,3)
  (10,10)           | [(0,-20),(30,-20)]            | (10,-20)
  (10,10)           | [(NaN,1),(NaN,90)]            | 
-(72 rows)
+(80 rows)
 
 -- Closest point to box
 SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
@@ -1021,6 +1139,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (Infinity,1e+300) | (2,2),(0,0)         | 
+ (Infinity,1e+300) | (3,3),(1,1)         | 
+ (Infinity,1e+300) | (-2,2),(-8,-10)     | 
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
+ (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         | 
  (NaN,NaN)         | (3,3),(1,1)         | 
  (NaN,NaN)         | (-2,2),(-8,-10)     | 
@@ -1031,7 +1154,7 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (10,10)           | (-2,2),(-8,-10)     | (-2,2)
  (10,10)           | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (10,10)           | (3,3),(3,3)         | (3,3)
-(45 rows)
+(50 rows)
 
 -- On line
 SELECT p.f1, l.s FROM POINT_TBL p, LINE_TBL l WHERE p.f1 <@ l.s;
@@ -1060,12 +1183,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1153,8 +1271,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1163,8 +1281,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1173,8 +1291,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1183,8 +1301,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1193,8 +1311,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1203,38 +1321,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1243,8 +1361,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1262,31 +1380,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1294,8 +1404,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1303,46 +1411,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1383,8 +1465,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | (-5,NaN)
+ {1,0,5}                               | {NaN,NaN,NaN}                         | (-5,NaN)
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              | 
  {0,3,0}                               | {0,-1,5}                              | 
@@ -1463,8 +1545,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | (3,NaN)
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | (3,NaN)
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              | 
 (100 rows)
@@ -2347,6 +2429,11 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2357,7 +2444,7 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (8,12),(2,0)
             | (12.5,13.5),(12.5,12.5)
             | (13,13),(13,13)
-(45 rows)
+(50 rows)
 
 SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
    FROM BOX_TBL b, POINT_TBL p;
@@ -2398,6 +2485,11 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2408,7 +2500,7 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-12,-8),(-18,-20)
             | (-7.5,-6.5),(-7.5,-7.5)
             | (-7,-7),(-7,-7)
-(45 rows)
+(50 rows)
 
 -- Multiply with point
 SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2431,16 +2523,21 @@ SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] > 1000;
          f1          |        f1         |                  ?column?                  
 ---------------------+-------------------+--------------------------------------------
  (2,2),(0,0)         | (1e+300,Infinity) | (NaN,NaN),(-Infinity,Infinity)
+ (2,2),(0,0)         | (Infinity,1e+300) | (NaN,NaN),(Infinity,Infinity)
  (2,2),(0,0)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(1,1)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(1,1)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(1,1)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (-2,2),(-8,-10)     | (1e+300,Infinity) | (Infinity,-Infinity),(-Infinity,-Infinity)
+ (-2,2),(-8,-10)     | (Infinity,1e+300) | (-Infinity,Infinity),(-Infinity,-Infinity)
  (-2,2),(-8,-10)     | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (2.5,3.5),(2.5,2.5) | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (2.5,3.5),(2.5,2.5) | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (2.5,3.5),(2.5,2.5) | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(3,3)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(3,3)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(3,3)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
-(10 rows)
+(15 rows)
 
 -- Divide by point
 SELECT b.f1, p.f1, b.f1 / p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2470,9 +2567,10 @@ SELECT f1::box
  (-5,-12),(-5,-12)
  (1e-300,-1e-300),(1e-300,-1e-300)
  (1e+300,Infinity),(1e+300,Infinity)
+ (Infinity,1e+300),(Infinity,1e+300)
  (NaN,NaN),(NaN,NaN)
  (10,10),(10,10)
-(9 rows)
+(10 rows)
 
 SELECT bound_box(a.f1, b.f1)
     FROM BOX_TBL a, BOX_TBL b;
@@ -3102,6 +3200,15 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((1e+300,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(1e+300,Infinity),(1e+300,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((1e+300,Infinity),(1e+300,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3120,7 +3227,7 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((20,30))
  [(11,12),(13,14)]         | (10,10)           | [(21,22),(23,24)]
  ((11,12),(13,14))         | (10,10)           | ((21,22),(23,24))
-(81 rows)
+(90 rows)
 
 -- Subtract point
 SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3189,6 +3296,15 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-1e+300,-Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-1e+300,-Infinity),(-1e+300,-Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-1e+300,-Infinity),(-1e+300,-Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((-Infinity,-1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3207,7 +3323,7 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((0,10))
  [(11,12),(13,14)]         | (10,10)           | [(1,2),(3,4)]
  ((11,12),(13,14))         | (10,10)           | ((1,2),(3,4))
-(81 rows)
+(90 rows)
 
 -- Multiply with point
 SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3276,6 +3392,15 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-Infinity,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-Infinity,Infinity),(-Infinity,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-Infinity,Infinity),(-Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) | [(NaN,NaN),(Infinity,NaN),(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,Infinity))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3294,7 +3419,7 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((-100,300))
  [(11,12),(13,14)]         | (10,10)           | [(-10,230),(-10,270)]
  ((11,12),(13,14))         | (10,10)           | ((-10,230),(-10,270))
-(81 rows)
+(90 rows)
 
 -- Divide by point
 SELECT p.f1, p1.f1, p.f1 / p1.f1 FROM PATH_TBL p, POINT_TBL p1 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -3467,13 +3592,20 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3481,7 +3613,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)
 
 SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
    FROM POLYGON_TBL poly, POINT_TBL p;
@@ -3536,13 +3668,20 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3550,7 +3689,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)
 
 SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon
    FROM POLYGON_TBL;
@@ -3929,9 +4068,10 @@ SELECT '' AS six, circle(f1, 50.0)
      | <(-5,-12),50>
      | <(1e-300,-1e-300),50>
      | <(1e+300,Infinity),50>
+     | <(Infinity,1e+300),50>
      | <(NaN,NaN),50>
      | <(10,10),50>
-(9 rows)
+(10 rows)
 
 SELECT '' AS four, circle(f1)
    FROM BOX_TBL;
@@ -3993,12 +4133,19 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(100,200),10> | (-10,0)           |  218.25424421
             | <(100,200),10> | (-5,-12)          | 226.577682802
             | <(3,5),0>      | (1e+300,Infinity) |      Infinity
+            | <(3,5),0>      | (Infinity,1e+300) |      Infinity
             | <(1,2),3>      | (1e+300,Infinity) |      Infinity
             | <(5,1),3>      | (1e+300,Infinity) |      Infinity
+            | <(5,1),3>      | (Infinity,1e+300) |      Infinity
+            | <(1,2),3>      | (Infinity,1e+300) |      Infinity
             | <(1,3),5>      | (1e+300,Infinity) |      Infinity
+            | <(1,3),5>      | (Infinity,1e+300) |      Infinity
             | <(100,200),10> | (1e+300,Infinity) |      Infinity
+            | <(100,200),10> | (Infinity,1e+300) |      Infinity
             | <(1,2),100>    | (1e+300,Infinity) |      Infinity
+            | <(1,2),100>    | (Infinity,1e+300) |      Infinity
             | <(100,1),115>  | (1e+300,Infinity) |      Infinity
+            | <(100,1),115>  | (Infinity,1e+300) |      Infinity
             | <(3,5),0>      | (NaN,NaN)         |           NaN
             | <(1,2),3>      | (NaN,NaN)         |           NaN
             | <(5,1),3>      | (NaN,NaN)         |           NaN
@@ -4014,8 +4161,9 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(3,5),NaN>    | (5.1,34.5)        |           NaN
             | <(3,5),NaN>    | (10,10)           |           NaN
             | <(3,5),NaN>    | (1e+300,Infinity) |           NaN
+            | <(3,5),NaN>    | (Infinity,1e+300) |           NaN
             | <(3,5),NaN>    | (NaN,NaN)         |           NaN
-(53 rows)
+(61 rows)
 
 -- To polygon
 SELECT f1, f1::polygon FROM CIRCLE_TBL WHERE f1 >= '<(0,0),1>';
@@ -4626,6 +4774,14 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(1e+300,Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(1e+300,Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(1e+300,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4642,7 +4798,7 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(110,11),115>
  <(3,5),0>      | (10,10)           | <(13,15),0>
  <(3,5),NaN>    | (10,10)           | <(13,15),NaN>
-(72 rows)
+(80 rows)
 
 -- Subtract point
 SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4704,6 +4860,14 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-1e+300,-Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(-1e+300,-Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-1e+300,-Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(-Infinity,-1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(-Infinity,-1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(-Infinity,-1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(-Infinity,-1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(-Infinity,-1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(-Infinity,-1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4720,7 +4884,7 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(90,-9),115>
  <(3,5),0>      | (10,10)           | <(-7,-5),0>
  <(3,5),NaN>    | (10,10)           | <(-7,-5),NaN>
-(72 rows)
+(80 rows)
 
 -- Multiply with point
 SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4782,6 +4946,14 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-Infinity,Infinity),Infinity>
  <(3,5),0>      | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),NaN>
@@ -4798,7 +4970,7 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(990,1010),1626.34559673>
  <(3,5),0>      | (10,10)           | <(-20,80),0>
  <(3,5),NaN>    | (10,10)           | <(-20,80),NaN>
-(72 rows)
+(80 rows)
 
 -- Divide by point
 SELECT c.f1, p.f1, c.f1 / p.f1 FROM CIRCLE_TBL c, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 15e3b83b37..77e250fc3e 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -11,6 +11,7 @@ INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 -- bad format points
 INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
@@ -44,9 +45,10 @@ SELECT '' AS six, * FROM POINT_TBL;
      | (-5,-12)
      | (1e-300,-1e-300)
      | (1e+300,Infinity)
+     | (Infinity,1e+300)
      | (NaN,NaN)
      | (10,10)
-(9 rows)
+(10 rows)
 
 -- left of
 SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)';
@@ -115,8 +117,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)
 
 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -136,8 +139,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)
 
 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
@@ -152,8 +156,9 @@ SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
      | (10,10)           |      14.142135623731
      | (5.1,34.5)        |     34.8749193547455
      | (1e+300,Infinity) |             Infinity
+     | (Infinity,1e+300) |             Infinity
      | (NaN,NaN)         |                  NaN
-(9 rows)
+(10 rows)
 
 SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist
    FROM POINT_TBL p1, POINT_TBL p2
@@ -210,12 +215,19 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (-5,-12)          | (5.1,34.5)        |     47.5842410888311
            | (5.1,34.5)        | (-5,-12)          |     47.5842410888311
            | (-10,0)           | (1e+300,Infinity) |             Infinity
+           | (-10,0)           | (Infinity,1e+300) |             Infinity
            | (-5,-12)          | (1e+300,Infinity) |             Infinity
+           | (-5,-12)          | (Infinity,1e+300) |             Infinity
            | (-3,4)            | (1e+300,Infinity) |             Infinity
+           | (-3,4)            | (Infinity,1e+300) |             Infinity
            | (0,0)             | (1e+300,Infinity) |             Infinity
+           | (0,0)             | (Infinity,1e+300) |             Infinity
            | (1e-300,-1e-300)  | (1e+300,Infinity) |             Infinity
+           | (1e-300,-1e-300)  | (Infinity,1e+300) |             Infinity
            | (5.1,34.5)        | (1e+300,Infinity) |             Infinity
+           | (5.1,34.5)        | (Infinity,1e+300) |             Infinity
            | (10,10)           | (1e+300,Infinity) |             Infinity
+           | (10,10)           | (Infinity,1e+300) |             Infinity
            | (1e+300,Infinity) | (-10,0)           |             Infinity
            | (1e+300,Infinity) | (-5,-12)          |             Infinity
            | (1e+300,Infinity) | (-3,4)            |             Infinity
@@ -223,6 +235,15 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (1e+300,Infinity) | (1e-300,-1e-300)  |             Infinity
            | (1e+300,Infinity) | (5.1,34.5)        |             Infinity
            | (1e+300,Infinity) | (10,10)           |             Infinity
+           | (1e+300,Infinity) | (Infinity,1e+300) |             Infinity
+           | (Infinity,1e+300) | (-10,0)           |             Infinity
+           | (Infinity,1e+300) | (-5,-12)          |             Infinity
+           | (Infinity,1e+300) | (-3,4)            |             Infinity
+           | (Infinity,1e+300) | (0,0)             |             Infinity
+           | (Infinity,1e+300) | (1e-300,-1e-300)  |             Infinity
+           | (Infinity,1e+300) | (5.1,34.5)        |             Infinity
+           | (Infinity,1e+300) | (10,10)           |             Infinity
+           | (Infinity,1e+300) | (1e+300,Infinity) |             Infinity
            | (-10,0)           | (NaN,NaN)         |                  NaN
            | (-5,-12)          | (NaN,NaN)         |                  NaN
            | (-3,4)            | (NaN,NaN)         |                  NaN
@@ -232,6 +253,8 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (10,10)           | (NaN,NaN)         |                  NaN
            | (1e+300,Infinity) | (1e+300,Infinity) |                  NaN
            | (1e+300,Infinity) | (NaN,NaN)         |                  NaN
+           | (Infinity,1e+300) | (Infinity,1e+300) |                  NaN
+           | (Infinity,1e+300) | (NaN,NaN)         |                  NaN
            | (NaN,NaN)         | (-10,0)           |                  NaN
            | (NaN,NaN)         | (-5,-12)          |                  NaN
            | (NaN,NaN)         | (-3,4)            |                  NaN
@@ -240,8 +263,9 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (NaN,NaN)         | (5.1,34.5)        |                  NaN
            | (NaN,NaN)         | (10,10)           |                  NaN
            | (NaN,NaN)         | (1e+300,Infinity) |                  NaN
+           | (NaN,NaN)         | (Infinity,1e+300) |                  NaN
            | (NaN,NaN)         | (NaN,NaN)         |                  NaN
-(81 rows)
+(100 rows)
 
 SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
    FROM POINT_TBL p1, POINT_TBL p2
@@ -253,6 +277,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (0,0)             | (5.1,34.5)
         | (0,0)             | (-5,-12)
         | (0,0)             | (1e+300,Infinity)
+        | (0,0)             | (Infinity,1e+300)
         | (0,0)             | (NaN,NaN)
         | (0,0)             | (10,10)
         | (-10,0)           | (0,0)
@@ -261,6 +286,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-10,0)           | (-5,-12)
         | (-10,0)           | (1e-300,-1e-300)
         | (-10,0)           | (1e+300,Infinity)
+        | (-10,0)           | (Infinity,1e+300)
         | (-10,0)           | (NaN,NaN)
         | (-10,0)           | (10,10)
         | (-3,4)            | (0,0)
@@ -269,6 +295,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-3,4)            | (-5,-12)
         | (-3,4)            | (1e-300,-1e-300)
         | (-3,4)            | (1e+300,Infinity)
+        | (-3,4)            | (Infinity,1e+300)
         | (-3,4)            | (NaN,NaN)
         | (-3,4)            | (10,10)
         | (5.1,34.5)        | (0,0)
@@ -277,6 +304,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (5.1,34.5)        | (-5,-12)
         | (5.1,34.5)        | (1e-300,-1e-300)
         | (5.1,34.5)        | (1e+300,Infinity)
+        | (5.1,34.5)        | (Infinity,1e+300)
         | (5.1,34.5)        | (NaN,NaN)
         | (5.1,34.5)        | (10,10)
         | (-5,-12)          | (0,0)
@@ -285,6 +313,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-5,-12)          | (5.1,34.5)
         | (-5,-12)          | (1e-300,-1e-300)
         | (-5,-12)          | (1e+300,Infinity)
+        | (-5,-12)          | (Infinity,1e+300)
         | (-5,-12)          | (NaN,NaN)
         | (-5,-12)          | (10,10)
         | (1e-300,-1e-300)  | (-10,0)
@@ -292,6 +321,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e-300,-1e-300)  | (5.1,34.5)
         | (1e-300,-1e-300)  | (-5,-12)
         | (1e-300,-1e-300)  | (1e+300,Infinity)
+        | (1e-300,-1e-300)  | (Infinity,1e+300)
         | (1e-300,-1e-300)  | (NaN,NaN)
         | (1e-300,-1e-300)  | (10,10)
         | (1e+300,Infinity) | (0,0)
@@ -301,8 +331,19 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e+300,Infinity) | (-5,-12)
         | (1e+300,Infinity) | (1e-300,-1e-300)
         | (1e+300,Infinity) | (1e+300,Infinity)
+        | (1e+300,Infinity) | (Infinity,1e+300)
         | (1e+300,Infinity) | (NaN,NaN)
         | (1e+300,Infinity) | (10,10)
+        | (Infinity,1e+300) | (0,0)
+        | (Infinity,1e+300) | (-10,0)
+        | (Infinity,1e+300) | (-3,4)
+        | (Infinity,1e+300) | (5.1,34.5)
+        | (Infinity,1e+300) | (-5,-12)
+        | (Infinity,1e+300) | (1e-300,-1e-300)
+        | (Infinity,1e+300) | (1e+300,Infinity)
+        | (Infinity,1e+300) | (Infinity,1e+300)
+        | (Infinity,1e+300) | (NaN,NaN)
+        | (Infinity,1e+300) | (10,10)
         | (NaN,NaN)         | (0,0)
         | (NaN,NaN)         | (-10,0)
         | (NaN,NaN)         | (-3,4)
@@ -310,6 +351,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (NaN,NaN)         | (-5,-12)
         | (NaN,NaN)         | (1e-300,-1e-300)
         | (NaN,NaN)         | (1e+300,Infinity)
+        | (NaN,NaN)         | (Infinity,1e+300)
         | (NaN,NaN)         | (NaN,NaN)
         | (NaN,NaN)         | (10,10)
         | (10,10)           | (0,0)
@@ -319,57 +361,67 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (10,10)           | (-5,-12)
         | (10,10)           | (1e-300,-1e-300)
         | (10,10)           | (1e+300,Infinity)
+        | (10,10)           | (Infinity,1e+300)
         | (10,10)           | (NaN,NaN)
-(72 rows)
+(91 rows)
 
 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1
    ORDER BY distance, p1.f1[0], p2.f1[0];
- fifteen |      point1      |      point2       |     distance     
----------+------------------+-------------------+------------------
-         | (-3,4)           | (0,0)             |                5
-         | (-3,4)           | (1e-300,-1e-300)  |                5
-         | (-10,0)          | (-3,4)            | 8.06225774829855
-         | (-10,0)          | (0,0)             |               10
-         | (-10,0)          | (1e-300,-1e-300)  |               10
-         | (-10,0)          | (-5,-12)          |               13
-         | (-5,-12)         | (0,0)             |               13
-         | (-5,-12)         | (1e-300,-1e-300)  |               13
-         | (0,0)            | (10,10)           |  14.142135623731
-         | (1e-300,-1e-300) | (10,10)           |  14.142135623731
-         | (-3,4)           | (10,10)           | 14.3178210632764
-         | (-5,-12)         | (-3,4)            | 16.1245154965971
-         | (-10,0)          | (10,10)           | 22.3606797749979
-         | (5.1,34.5)       | (10,10)           | 24.9851956166046
-         | (-5,-12)         | (10,10)           | 26.6270539113887
-         | (-3,4)           | (5.1,34.5)        | 31.5572495632937
-         | (0,0)            | (5.1,34.5)        | 34.8749193547455
-         | (1e-300,-1e-300) | (5.1,34.5)        | 34.8749193547455
-         | (-10,0)          | (5.1,34.5)        | 37.6597928831267
-         | (-5,-12)         | (5.1,34.5)        | 47.5842410888311
-         | (-10,0)          | (1e+300,Infinity) |         Infinity
-         | (-5,-12)         | (1e+300,Infinity) |         Infinity
-         | (-3,4)           | (1e+300,Infinity) |         Infinity
-         | (0,0)            | (1e+300,Infinity) |         Infinity
-         | (1e-300,-1e-300) | (1e+300,Infinity) |         Infinity
-         | (5.1,34.5)       | (1e+300,Infinity) |         Infinity
-         | (10,10)          | (1e+300,Infinity) |         Infinity
-(27 rows)
+ fifteen |      point1       |      point2       |     distance     
+---------+-------------------+-------------------+------------------
+         | (-3,4)            | (0,0)             |                5
+         | (-3,4)            | (1e-300,-1e-300)  |                5
+         | (-10,0)           | (-3,4)            | 8.06225774829855
+         | (-10,0)           | (0,0)             |               10
+         | (-10,0)           | (1e-300,-1e-300)  |               10
+         | (-10,0)           | (-5,-12)          |               13
+         | (-5,-12)          | (0,0)             |               13
+         | (-5,-12)          | (1e-300,-1e-300)  |               13
+         | (0,0)             | (10,10)           |  14.142135623731
+         | (1e-300,-1e-300)  | (10,10)           |  14.142135623731
+         | (-3,4)            | (10,10)           | 14.3178210632764
+         | (-5,-12)          | (-3,4)            | 16.1245154965971
+         | (-10,0)           | (10,10)           | 22.3606797749979
+         | (5.1,34.5)        | (10,10)           | 24.9851956166046
+         | (-5,-12)          | (10,10)           | 26.6270539113887
+         | (-3,4)            | (5.1,34.5)        | 31.5572495632937
+         | (0,0)             | (5.1,34.5)        | 34.8749193547455
+         | (1e-300,-1e-300)  | (5.1,34.5)        | 34.8749193547455
+         | (-10,0)           | (5.1,34.5)        | 37.6597928831267
+         | (-5,-12)          | (5.1,34.5)        | 47.5842410888311
+         | (-10,0)           | (1e+300,Infinity) |         Infinity
+         | (-10,0)           | (Infinity,1e+300) |         Infinity
+         | (-5,-12)          | (1e+300,Infinity) |         Infinity
+         | (-5,-12)          | (Infinity,1e+300) |         Infinity
+         | (-3,4)            | (1e+300,Infinity) |         Infinity
+         | (-3,4)            | (Infinity,1e+300) |         Infinity
+         | (0,0)             | (1e+300,Infinity) |         Infinity
+         | (0,0)             | (Infinity,1e+300) |         Infinity
+         | (1e-300,-1e-300)  | (1e+300,Infinity) |         Infinity
+         | (1e-300,-1e-300)  | (Infinity,1e+300) |         Infinity
+         | (5.1,34.5)        | (1e+300,Infinity) |         Infinity
+         | (5.1,34.5)        | (Infinity,1e+300) |         Infinity
+         | (10,10)           | (1e+300,Infinity) |         Infinity
+         | (10,10)           | (Infinity,1e+300) |         Infinity
+         | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(35 rows)
 
 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1
    ORDER BY distance;
- three |   point1   |      point2      |     distance     
--------+------------+------------------+------------------
-       | (-3,4)     | (0,0)            |                5
-       | (-3,4)     | (1e-300,-1e-300) |                5
-       | (-10,0)    | (-5,-12)         |               13
-       | (5.1,34.5) | (10,10)          | 24.9851956166046
-(4 rows)
+ three |      point1       |      point2       |     distance     
+-------+-------------------+-------------------+------------------
+       | (-3,4)            | (0,0)             |                5
+       | (-3,4)            | (1e-300,-1e-300)  |                5
+       | (-10,0)           | (-5,-12)          |               13
+       | (5.1,34.5)        | (10,10)           | 24.9851956166046
+       | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(5 rows)
 
 -- Test that GiST indexes provide same behavior as sequential scan
 CREATE TEMP TABLE point_gist_tbl(f1 point);
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 7f8504dbd1..6a1ca12d5c 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -21,6 +21,8 @@ INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
 
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
+
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 
 -- bad format points
-- 
2.18.4


Re: Strange behavior with polygon and NaN

From
Georgios Kokolatos
Date:
Hi,

apologies for the very, very late reply to your fixes.

You have answered/addressed all my questions concerns. The added documentation
reads well, at least to a non native English speaker.

The patch still applies and as far as I can see the tests are passing.

It gets my :+1: and I am changing the status to "Ready for Committer".

For what little is worth, I learned a lot from this patch, thank you.

Cheers,
Georgios

The new status of this patch is: Ready for Committer

Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Mon, 02 Nov 2020 14:43:32 +0000, Georgios Kokolatos <gkokolatos@protonmail.com> wrote in 
> Hi,
> 
> apologies for the very, very late reply to your fixes.
> 
> You have answered/addressed all my questions concerns. The added documentation
> reads well, at least to a non native English speaker.
> 
> The patch still applies and as far as I can see the tests are passing.
> 
> It gets my :+1: and I am changing the status to "Ready for Committer".
> 
> For what little is worth, I learned a lot from this patch, thank you.
> 
> Cheers,
> Georgios
> 
> The new status of this patch is: Ready for Committer

Oh! Thanks. Since a part of this patch is committed (Thanks to Tom.)
this is a rebased version on the commit.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From 1005fb2d992c115a5881892d273fed865a6c73d4 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Thu, 5 Nov 2020 14:01:16 +0900
Subject: [PATCH v3] Fix NaN handling of some geometric operators and functions

Some geometric operators shows somewhat odd behavior comes from NaN
handling and that leads to inconsistency between index scan and seq
scan on geometric conditions.

For example:
  point '(NaN,NaN)' <-> polygon '((0,0),(0,1),(1,1))' => 0, not NaN
  point '(0.3,0.5)' <-> polygon '((0,0),(0,NaN),(1,1))' => 1.14, not NaN
  point '(NaN,NaN)' <@ polygon '((0,0),(0,1),(1,1))'  => true, not false

Some other functions returned totally wrong result like this:
 point '(1e+300,Infinity)' ## box '(2,2),(0,0)' => '(0,2)'

Fix NaN and Infinity handling of geo_ops.c so that these generates
saner results. However, the behavioral inconsistency that comes from
Infinity cannot be eliminated with a moderate amount of additional
code against the benefit so they are left alone and added
documentation instead.
---
 doc/src/sgml/func.sgml                     |  16 +
 src/backend/utils/adt/geo_ops.c            | 215 ++++++++--
 src/test/regress/expected/create_index.out |  24 +-
 src/test/regress/expected/geometry.out     | 458 ++++++++++++++-------
 src/test/regress/expected/point.out        | 138 +++++--
 src/test/regress/sql/point.sql             |   2 +
 6 files changed, 629 insertions(+), 224 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7b1dc264f6..1aeeb48585 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10889,6 +10889,22 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
      on), where available for these types, likewise compare areas.
     </para>
    </caution>
+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
 
    <table id="functions-geometry-func-table">
     <title>Geometric Functions</title>
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..06deeb6d12 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,19 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    /* float8_min conceals NaN, check separately for NaNs */
+    if (unlikely(isnan(box1->high.x) || isnan(box2->high.x)))
+        result->high.x = get_float8_nan();
+    else
+        result->high.x = float8_min(box1->high.x, box2->high.x);
+
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+
+    if (unlikely(isnan(box1->high.y) || isnan(box2->high.y)))
+        result->high.x = get_float8_nan();
+    else
+        result->high.y = float8_min(box1->high.y, box2->high.y);
+
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,6 +1071,21 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->y)))
+            result->C = get_float8_nan();
+    }
+    else if (m == 0.0)
+    {
+        /* use "mx - y + yinter = 0" */
+        result->A = 0.0;
+        result->B = -1.0;
+        result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->x)))
+            result->C = get_float8_nan();
     }
     else
     {
@@ -1084,6 +1109,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1104,8 +1130,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1123,14 +1153,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1141,7 +1174,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1149,7 +1182,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1195,9 +1228,19 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(line->A, -line->B);
 }
 
@@ -1209,9 +1252,19 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1224,14 +1277,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2))    /* intersecting? */
+    {
+        /* return NaN if NaN was involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1291,14 +1353,19 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
     }
     else if (!FPzero(l2->B))
     {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
-
-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
-                       float8_mi(float8_mul(l2->A, l1->B),
-                                 float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+        /*
+         * We know that l1->B is zero, which means l1 is vertical. The lines
+         * cannot be parallel and the x-coord of the cross point is -C/A of l1.
+         */
+        x = -float8_div(l1->C, l1->A);
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
     }
     else
         return false;
@@ -1626,18 +1693,32 @@ path_inter(PG_FUNCTION_ARGS)
     b1.high.y = b1.low.y = p1->p[0].y;
     for (i = 1; i < p1->npts; i++)
     {
+        /* float8_min conceals NaN, check separately for NaNs */
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
+        if (unlikely(isnan(p1->p[i].x)))
+            b1.low.x = p1->p[i].x;
+        else
+            b1.low.x = float8_min(p1->p[i].x, b1.low.x);
+        if (unlikely(isnan(p1->p[i].y)))
+            b1.low.x = p1->p[i].y;
+        else
         b1.low.y = float8_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++)
     {
+        /* float8_min conceals NaN, check separately for NaNs */
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
+        if (unlikely(isnan(p2->p[i].x)))
+            b2.low.x = p2->p[i].x;
+        else
+            b2.low.x = float8_min(p2->p[i].x, b2.low.x);
+        if (unlikely(isnan(p2->p[i].y)))
+            b2.low.y = p1->p[i].y;
+        else
         b2.low.y = float8_min(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
@@ -1728,6 +1809,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1980,9 +2066,17 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -1996,9 +2090,17 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2414,6 +2516,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2645,6 +2752,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2674,7 +2783,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2803,6 +2913,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        isnan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2814,6 +2925,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    isnan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2823,6 +2935,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2830,6 +2943,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2837,6 +2951,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2873,6 +2993,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        isnan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2887,9 +3008,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    isnan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2901,6 +3023,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2910,6 +3033,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2917,6 +3041,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -2988,6 +3119,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3010,6 +3142,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3436,6 +3576,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3911,6 +4057,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5350,6 +5501,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5359,6 +5514,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
@@ -5517,12 +5676,12 @@ pg_hypot(float8 x, float8 y)
                 result;
 
     /* Handle INF and NaN properly */
-    if (isinf(x) || isinf(y))
+    if (unlikely(isnan(x) || isnan(y)))
+        return get_float8_nan();
+
+    if (unlikely(isinf(x) || isinf(y)))
         return get_float8_infinity();
 
-    if (isnan(x) || isnan(y))
-        return get_float8_nan();
-
     /* Else, drop any minus signs */
     x = fabs(x);
     y = fabs(y);
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 93a8736a3f..581bf414f2 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
@@ -157,7 +157,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count 
 -------
-     3
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
@@ -169,7 +169,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count 
 -------
-     4
+     5
 (1 row)
 
 SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
@@ -188,10 +188,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
  
-(10 rows)
+(11 rows)
 
 SELECT * FROM point_tbl WHERE f1 IS NULL;
  f1 
@@ -202,16 +203,17 @@ SELECT * FROM point_tbl WHERE f1 IS NULL;
 SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
         f1         
 -------------------
- (1e-300,-1e-300)
  (0,0)
+ (1e-300,-1e-300)
  (-3,4)
  (-10,0)
  (10,10)
  (-5,-12)
  (5.1,34.5)
  (1e+300,Infinity)
+ (Infinity,1e+300)
  (NaN,NaN)
-(9 rows)
+(10 rows)
 
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
         f1        
@@ -464,7 +466,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count 
 -------
-     3
+     4
 (1 row)
 
 EXPLAIN (COSTS OFF)
@@ -494,7 +496,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count 
 -------
-     4
+     5
 (1 row)
 
 EXPLAIN (COSTS OFF)
@@ -530,10 +532,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
  
-(10 rows)
+(11 rows)
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 IS NULL;
@@ -568,9 +571,10 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
-(9 rows)
+(10 rows)
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..20acb0b0b4 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -120,6 +120,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          |                2.4
  (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
  (0,0)             | (1e+300,Infinity) |           Infinity
+ (0,0)             | (Infinity,1e+300) |                  0
  (0,0)             | (NaN,NaN)         |                NaN
  (0,0)             | (10,10)           |                  1
  (-10,0)           | (0,0)             |                  0
@@ -129,6 +130,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          |               -2.4
  (-10,0)           | (1e-300,-1e-300)  |                  0
  (-10,0)           | (1e+300,Infinity) |           Infinity
+ (-10,0)           | (Infinity,1e+300) |                  0
  (-10,0)           | (NaN,NaN)         |                NaN
  (-10,0)           | (10,10)           |                0.5
  (-3,4)            | (0,0)             |     -1.33333333333
@@ -138,6 +140,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          |                  8
  (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
  (-3,4)            | (1e+300,Infinity) |           Infinity
+ (-3,4)            | (Infinity,1e+300) |                  0
  (-3,4)            | (NaN,NaN)         |                NaN
  (-3,4)            | (10,10)           |     0.461538461538
  (5.1,34.5)        | (0,0)             |      6.76470588235
@@ -147,6 +150,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          |      4.60396039604
  (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
  (5.1,34.5)        | (1e+300,Infinity) |           Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |                  0
  (5.1,34.5)        | (NaN,NaN)         |                NaN
  (5.1,34.5)        | (10,10)           |                 -5
  (-5,-12)          | (0,0)             |                2.4
@@ -156,6 +160,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | 1.79769313486e+308
  (-5,-12)          | (1e-300,-1e-300)  |                2.4
  (-5,-12)          | (1e+300,Infinity) |           Infinity
+ (-5,-12)          | (Infinity,1e+300) |                  0
  (-5,-12)          | (NaN,NaN)         |                NaN
  (-5,-12)          | (10,10)           |      1.46666666667
  (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
@@ -165,6 +170,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          |                2.4
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
  (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
  (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
  (1e-300,-1e-300)  | (10,10)           |                  1
  (1e+300,Infinity) | (0,0)             |           Infinity
@@ -174,8 +180,19 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          |           Infinity
  (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
  (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
+ (1e+300,Infinity) | (Infinity,1e+300) |                NaN
  (1e+300,Infinity) | (NaN,NaN)         |                NaN
  (1e+300,Infinity) | (10,10)           |           Infinity
+ (Infinity,1e+300) | (0,0)             |                  0
+ (Infinity,1e+300) | (-10,0)           |                  0
+ (Infinity,1e+300) | (-3,4)            |                  0
+ (Infinity,1e+300) | (5.1,34.5)        |                  0
+ (Infinity,1e+300) | (-5,-12)          |                  0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
+ (Infinity,1e+300) | (1e+300,Infinity) |                NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |                  0
+ (Infinity,1e+300) | (NaN,NaN)         |                NaN
+ (Infinity,1e+300) | (10,10)           |                  0
  (NaN,NaN)         | (0,0)             |                NaN
  (NaN,NaN)         | (-10,0)           |                NaN
  (NaN,NaN)         | (-3,4)            |                NaN
@@ -183,6 +200,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          |                NaN
  (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
  (NaN,NaN)         | (1e+300,Infinity) |                NaN
+ (NaN,NaN)         | (Infinity,1e+300) |                NaN
  (NaN,NaN)         | (NaN,NaN)         |                NaN
  (NaN,NaN)         | (10,10)           |                NaN
  (10,10)           | (0,0)             |                  1
@@ -192,14 +210,15 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          |      1.46666666667
  (10,10)           | (1e-300,-1e-300)  |                  1
  (10,10)           | (1e+300,Infinity) |           Infinity
+ (10,10)           | (Infinity,1e+300) |                  0
  (10,10)           | (NaN,NaN)         |                NaN
  (10,10)           | (10,10)           | 1.79769313486e+308
-(81 rows)
+(100 rows)
 
 -- Add point
 SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |     ?column?      
--------------------+-------------------+-------------------
+        f1         |        f1         |      ?column?       
+-------------------+-------------------+---------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (-10,0)
  (0,0)             | (-3,4)            | (-3,4)
@@ -207,6 +226,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (-5,-12)
  (0,0)             | (1e-300,-1e-300)  | (1e-300,-1e-300)
  (0,0)             | (1e+300,Infinity) | (1e+300,Infinity)
+ (0,0)             | (Infinity,1e+300) | (Infinity,1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (10,10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -216,6 +236,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-15,-12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,-1e-300)
  (-10,0)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (-10,0)           | (Infinity,1e+300) | (Infinity,1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (0,10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -225,6 +246,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (-8,-8)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (1e+300,Infinity)
+ (-3,4)            | (Infinity,1e+300) | (Infinity,1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (7,14)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -234,6 +256,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (0.1,22.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (1e+300,Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (Infinity,1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (15.1,44.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -243,6 +266,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (-10,-24)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (1e+300,Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (Infinity,1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (5,-2)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -252,6 +276,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (-5,-12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (2e-300,-2e-300)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (1e+300,Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (Infinity,1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (10,10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -261,8 +286,19 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (2e+300,Infinity)
+ (1e+300,Infinity) | (Infinity,1e+300) | (Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (Infinity,2e+300)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -270,6 +306,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -279,14 +316,15 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (5,-2)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (10,10)           | (Infinity,1e+300) | (Infinity,1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (20,20)
-(81 rows)
+(100 rows)
 
 -- Subtract point
 SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |      ?column?       
--------------------+-------------------+---------------------
+        f1         |        f1         |       ?column?       
+-------------------+-------------------+----------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (10,0)
  (0,0)             | (-3,4)            | (3,-4)
@@ -294,6 +332,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (5,12)
  (0,0)             | (1e-300,-1e-300)  | (-1e-300,1e-300)
  (0,0)             | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (0,0)             | (Infinity,1e+300) | (-Infinity,-1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (-10,-10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -303,6 +342,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-5,12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,1e-300)
  (-10,0)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-10,0)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (-20,-10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -312,6 +352,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (2,16)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-3,4)            | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (-13,-6)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -321,6 +362,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (10.1,46.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (-Infinity,-1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (-4.9,24.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -330,6 +372,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (0,0)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (-15,-22)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -339,6 +382,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (5,12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (0,0)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (-Infinity,-1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (-10,-10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -348,8 +392,19 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (0,NaN)
+ (1e+300,Infinity) | (Infinity,1e+300) | (-Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (NaN,0)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -357,6 +412,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -366,9 +422,10 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (15,22)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (10,10)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (0,0)
-(81 rows)
+(100 rows)
 
 -- Multiply with point
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -388,11 +445,13 @@ SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0
  (10,10)    | (1e-300,-1e-300)  | (2e-299,0)
  (5.1,34.5) | (1e+300,Infinity) | (-Infinity,Infinity)
  (10,10)    | (1e+300,Infinity) | (-Infinity,Infinity)
+ (5.1,34.5) | (Infinity,1e+300) | (Infinity,Infinity)
+ (10,10)    | (Infinity,1e+300) | (Infinity,Infinity)
  (5.1,34.5) | (NaN,NaN)         | (NaN,NaN)
  (10,10)    | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5) | (10,10)           | (-294,396)
  (10,10)    | (10,10)           | (0,200)
-(18 rows)
+(20 rows)
 
 -- Underflow error
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] < 1;
@@ -415,11 +474,13 @@ SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0
  (1e-300,-1e-300)  | (10,10)    | (0,-1e-301)
  (1e+300,Infinity) | (5.1,34.5) | (Infinity,Infinity)
  (1e+300,Infinity) | (10,10)    | (Infinity,Infinity)
+ (Infinity,1e+300) | (5.1,34.5) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (10,10)    | (Infinity,-Infinity)
  (NaN,NaN)         | (5.1,34.5) | (NaN,NaN)
  (NaN,NaN)         | (10,10)    | (NaN,NaN)
  (10,10)           | (5.1,34.5) | (0.325588278822,-0.241724631247)
  (10,10)           | (10,10)    | (1,0)
-(18 rows)
+(20 rows)
 
 -- Overflow error
 SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0] > 1000;
@@ -494,13 +555,23 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
- (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
+ (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
+ (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -521,7 +592,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
  (10,10)           | {-1,0,3}                              |                  7 |                  7
-(90 rows)
+(100 rows)
 
 -- Distance to line segment
 SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
@@ -582,7 +653,15 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
+ (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |                NaN |                NaN
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -599,7 +678,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (10,10)           | [(-10,2),(-10,3)]             |      21.1896201004 |      21.1896201004
  (10,10)           | [(0,-20),(30,-20)]            |                 30 |                 30
  (10,10)           | [(NaN,1),(NaN,90)]            |                NaN |                NaN
-(72 rows)
+(80 rows)
 
 -- Distance to box
 SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT_TBL p, BOX_TBL b;
@@ -640,6 +719,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |                NaN |                NaN
+ (Infinity,1e+300) | (3,3),(1,1)         |                NaN |                NaN
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |                NaN |                NaN
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -650,7 +734,7 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (10,10)           | (-2,2),(-8,-10)     |      14.4222051019 |      14.4222051019
  (10,10)           | (2.5,3.5),(2.5,2.5) |      9.92471662064 |      9.92471662064
  (10,10)           | (3,3),(3,3)         |      9.89949493661 |      9.89949493661
-(45 rows)
+(50 rows)
 
 -- Distance to path
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp FROM POINT_TBL p, PATH_TBL p1;
@@ -719,6 +803,15 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((10,20))                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,12),(13,14)]         |           Infinity |           Infinity
+ (Infinity,1e+300) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
  (NaN,NaN)         | ((1,2),(3,4))             |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
@@ -737,7 +830,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (10,10)           | ((10,20))                 |                 10 |                 10
  (10,10)           | [(11,12),(13,14)]         |       2.2360679775 |       2.2360679775
  (10,10)           | ((11,12),(13,14))         |       2.2360679775 |       2.2360679775
-(81 rows)
+(90 rows)
 
 -- Distance to polygon
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp FROM POINT_TBL p, POLYGON_TBL p1;
@@ -792,13 +885,20 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (Infinity,1e+300) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -806,7 +906,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | 3.60555127546 | 3.60555127546
  (10,10)           | ((0,0))                    | 14.1421356237 | 14.1421356237
  (10,10)           | ((0,1),(0,1))              | 13.4536240471 | 13.4536240471
-(63 rows)
+(70 rows)
 
 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -875,13 +975,23 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               | 
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | 
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | 
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | 
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              | 
+ (Infinity,1e+300) | {0,-1,5}                              | 
+ (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
+ (Infinity,1e+300) | {0,3,0}                               | 
+ (Infinity,1e+300) | {1,-1,0}                              | 
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | 
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (Infinity,1e+300) | {3,NaN,5}                             | 
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
+ (Infinity,1e+300) | {0,-1,3}                              | 
+ (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
  (NaN,NaN)         | {0,3,0}                               | 
@@ -902,7 +1012,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (10,10)           | {NaN,NaN,NaN}                         | 
  (10,10)           | {0,-1,3}                              | (10,3)
  (10,10)           | {-1,0,3}                              | (3,10)
-(90 rows)
+(100 rows)
 
 -- Closest point to line segment
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
@@ -963,7 +1073,15 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
+ (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
+ (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
+ (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            | 
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            | 
  (NaN,NaN)         | [(1,2),(3,4)]                 | 
  (NaN,NaN)         | [(0,0),(6,6)]                 | 
  (NaN,NaN)         | [(10,-10),(-3,-4)]            | 
@@ -980,7 +1098,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (10,10)           | [(-10,2),(-10,3)]             | (-10,3)
  (10,10)           | [(0,-20),(30,-20)]            | (10,-20)
  (10,10)           | [(NaN,1),(NaN,90)]            | 
-(72 rows)
+(80 rows)
 
 -- Closest point to box
 SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
@@ -1021,6 +1139,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (Infinity,1e+300) | (2,2),(0,0)         | 
+ (Infinity,1e+300) | (3,3),(1,1)         | 
+ (Infinity,1e+300) | (-2,2),(-8,-10)     | 
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
+ (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         | 
  (NaN,NaN)         | (3,3),(1,1)         | 
  (NaN,NaN)         | (-2,2),(-8,-10)     | 
@@ -1031,7 +1154,7 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (10,10)           | (-2,2),(-8,-10)     | (-2,2)
  (10,10)           | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (10,10)           | (3,3),(3,3)         | (3,3)
-(45 rows)
+(50 rows)
 
 -- On line
 SELECT p.f1, l.s FROM POINT_TBL p, LINE_TBL l WHERE p.f1 <@ l.s;
@@ -1060,12 +1183,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1153,8 +1271,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1163,8 +1281,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1173,8 +1291,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1183,8 +1301,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1193,8 +1311,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1203,38 +1321,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1243,8 +1361,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1262,31 +1380,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1294,8 +1404,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1303,46 +1411,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1383,8 +1465,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | (-5,NaN)
+ {1,0,5}                               | {NaN,NaN,NaN}                         | (-5,NaN)
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              | 
  {0,3,0}                               | {0,-1,5}                              | 
@@ -1463,8 +1545,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | (3,NaN)
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | (3,NaN)
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              | 
 (100 rows)
@@ -2347,6 +2429,11 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2357,7 +2444,7 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (8,12),(2,0)
             | (12.5,13.5),(12.5,12.5)
             | (13,13),(13,13)
-(45 rows)
+(50 rows)
 
 SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
    FROM BOX_TBL b, POINT_TBL p;
@@ -2398,6 +2485,11 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2408,7 +2500,7 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-12,-8),(-18,-20)
             | (-7.5,-6.5),(-7.5,-7.5)
             | (-7,-7),(-7,-7)
-(45 rows)
+(50 rows)
 
 -- Multiply with point
 SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2431,16 +2523,21 @@ SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] > 1000;
          f1          |        f1         |                  ?column?                  
 ---------------------+-------------------+--------------------------------------------
  (2,2),(0,0)         | (1e+300,Infinity) | (NaN,NaN),(-Infinity,Infinity)
+ (2,2),(0,0)         | (Infinity,1e+300) | (NaN,NaN),(Infinity,Infinity)
  (2,2),(0,0)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(1,1)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(1,1)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(1,1)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (-2,2),(-8,-10)     | (1e+300,Infinity) | (Infinity,-Infinity),(-Infinity,-Infinity)
+ (-2,2),(-8,-10)     | (Infinity,1e+300) | (-Infinity,Infinity),(-Infinity,-Infinity)
  (-2,2),(-8,-10)     | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (2.5,3.5),(2.5,2.5) | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (2.5,3.5),(2.5,2.5) | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (2.5,3.5),(2.5,2.5) | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(3,3)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(3,3)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(3,3)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
-(10 rows)
+(15 rows)
 
 -- Divide by point
 SELECT b.f1, p.f1, b.f1 / p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2470,9 +2567,10 @@ SELECT f1::box
  (-5,-12),(-5,-12)
  (1e-300,-1e-300),(1e-300,-1e-300)
  (1e+300,Infinity),(1e+300,Infinity)
+ (Infinity,1e+300),(Infinity,1e+300)
  (NaN,NaN),(NaN,NaN)
  (10,10),(10,10)
-(9 rows)
+(10 rows)
 
 SELECT bound_box(a.f1, b.f1)
     FROM BOX_TBL a, BOX_TBL b;
@@ -3102,6 +3200,15 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((1e+300,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(1e+300,Infinity),(1e+300,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((1e+300,Infinity),(1e+300,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3120,7 +3227,7 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((20,30))
  [(11,12),(13,14)]         | (10,10)           | [(21,22),(23,24)]
  ((11,12),(13,14))         | (10,10)           | ((21,22),(23,24))
-(81 rows)
+(90 rows)
 
 -- Subtract point
 SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3189,6 +3296,15 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-1e+300,-Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-1e+300,-Infinity),(-1e+300,-Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-1e+300,-Infinity),(-1e+300,-Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((-Infinity,-1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3207,7 +3323,7 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((0,10))
  [(11,12),(13,14)]         | (10,10)           | [(1,2),(3,4)]
  ((11,12),(13,14))         | (10,10)           | ((1,2),(3,4))
-(81 rows)
+(90 rows)
 
 -- Multiply with point
 SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3276,6 +3392,15 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-Infinity,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-Infinity,Infinity),(-Infinity,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-Infinity,Infinity),(-Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) | [(NaN,NaN),(Infinity,NaN),(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,Infinity))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3294,7 +3419,7 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((-100,300))
  [(11,12),(13,14)]         | (10,10)           | [(-10,230),(-10,270)]
  ((11,12),(13,14))         | (10,10)           | ((-10,230),(-10,270))
-(81 rows)
+(90 rows)
 
 -- Divide by point
 SELECT p.f1, p1.f1, p.f1 / p1.f1 FROM PATH_TBL p, POINT_TBL p1 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -3467,13 +3592,20 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3481,7 +3613,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)
 
 SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
    FROM POLYGON_TBL poly, POINT_TBL p;
@@ -3536,13 +3668,20 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3550,7 +3689,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)
 
 SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon
    FROM POLYGON_TBL;
@@ -3929,9 +4068,10 @@ SELECT '' AS six, circle(f1, 50.0)
      | <(-5,-12),50>
      | <(1e-300,-1e-300),50>
      | <(1e+300,Infinity),50>
+     | <(Infinity,1e+300),50>
      | <(NaN,NaN),50>
      | <(10,10),50>
-(9 rows)
+(10 rows)
 
 SELECT '' AS four, circle(f1)
    FROM BOX_TBL;
@@ -3993,12 +4133,19 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(100,200),10> | (-10,0)           |  218.25424421
             | <(100,200),10> | (-5,-12)          | 226.577682802
             | <(3,5),0>      | (1e+300,Infinity) |      Infinity
+            | <(3,5),0>      | (Infinity,1e+300) |      Infinity
             | <(1,2),3>      | (1e+300,Infinity) |      Infinity
             | <(5,1),3>      | (1e+300,Infinity) |      Infinity
+            | <(5,1),3>      | (Infinity,1e+300) |      Infinity
+            | <(1,2),3>      | (Infinity,1e+300) |      Infinity
             | <(1,3),5>      | (1e+300,Infinity) |      Infinity
+            | <(1,3),5>      | (Infinity,1e+300) |      Infinity
             | <(100,200),10> | (1e+300,Infinity) |      Infinity
+            | <(100,200),10> | (Infinity,1e+300) |      Infinity
             | <(1,2),100>    | (1e+300,Infinity) |      Infinity
+            | <(1,2),100>    | (Infinity,1e+300) |      Infinity
             | <(100,1),115>  | (1e+300,Infinity) |      Infinity
+            | <(100,1),115>  | (Infinity,1e+300) |      Infinity
             | <(3,5),0>      | (NaN,NaN)         |           NaN
             | <(1,2),3>      | (NaN,NaN)         |           NaN
             | <(5,1),3>      | (NaN,NaN)         |           NaN
@@ -4014,8 +4161,9 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(3,5),NaN>    | (5.1,34.5)        |           NaN
             | <(3,5),NaN>    | (10,10)           |           NaN
             | <(3,5),NaN>    | (1e+300,Infinity) |           NaN
+            | <(3,5),NaN>    | (Infinity,1e+300) |           NaN
             | <(3,5),NaN>    | (NaN,NaN)         |           NaN
-(53 rows)
+(61 rows)
 
 -- To polygon
 SELECT f1, f1::polygon FROM CIRCLE_TBL WHERE f1 >= '<(0,0),1>';
@@ -4626,6 +4774,14 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(1e+300,Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(1e+300,Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(1e+300,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4642,7 +4798,7 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(110,11),115>
  <(3,5),0>      | (10,10)           | <(13,15),0>
  <(3,5),NaN>    | (10,10)           | <(13,15),NaN>
-(72 rows)
+(80 rows)
 
 -- Subtract point
 SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4704,6 +4860,14 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-1e+300,-Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(-1e+300,-Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-1e+300,-Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(-Infinity,-1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(-Infinity,-1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(-Infinity,-1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(-Infinity,-1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(-Infinity,-1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(-Infinity,-1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4720,7 +4884,7 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(90,-9),115>
  <(3,5),0>      | (10,10)           | <(-7,-5),0>
  <(3,5),NaN>    | (10,10)           | <(-7,-5),NaN>
-(72 rows)
+(80 rows)
 
 -- Multiply with point
 SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4782,6 +4946,14 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-Infinity,Infinity),Infinity>
  <(3,5),0>      | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),NaN>
@@ -4798,7 +4970,7 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(990,1010),1626.34559673>
  <(3,5),0>      | (10,10)           | <(-20,80),0>
  <(3,5),NaN>    | (10,10)           | <(-20,80),NaN>
-(72 rows)
+(80 rows)
 
 -- Divide by point
 SELECT c.f1, p.f1, c.f1 / p.f1 FROM CIRCLE_TBL c, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 15e3b83b37..77e250fc3e 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -11,6 +11,7 @@ INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 -- bad format points
 INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
@@ -44,9 +45,10 @@ SELECT '' AS six, * FROM POINT_TBL;
      | (-5,-12)
      | (1e-300,-1e-300)
      | (1e+300,Infinity)
+     | (Infinity,1e+300)
      | (NaN,NaN)
      | (10,10)
-(9 rows)
+(10 rows)
 
 -- left of
 SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)';
@@ -115,8 +117,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)
 
 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -136,8 +139,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)
 
 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
@@ -152,8 +156,9 @@ SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
      | (10,10)           |      14.142135623731
      | (5.1,34.5)        |     34.8749193547455
      | (1e+300,Infinity) |             Infinity
+     | (Infinity,1e+300) |             Infinity
      | (NaN,NaN)         |                  NaN
-(9 rows)
+(10 rows)
 
 SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist
    FROM POINT_TBL p1, POINT_TBL p2
@@ -210,12 +215,19 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (-5,-12)          | (5.1,34.5)        |     47.5842410888311
            | (5.1,34.5)        | (-5,-12)          |     47.5842410888311
            | (-10,0)           | (1e+300,Infinity) |             Infinity
+           | (-10,0)           | (Infinity,1e+300) |             Infinity
            | (-5,-12)          | (1e+300,Infinity) |             Infinity
+           | (-5,-12)          | (Infinity,1e+300) |             Infinity
            | (-3,4)            | (1e+300,Infinity) |             Infinity
+           | (-3,4)            | (Infinity,1e+300) |             Infinity
            | (0,0)             | (1e+300,Infinity) |             Infinity
+           | (0,0)             | (Infinity,1e+300) |             Infinity
            | (1e-300,-1e-300)  | (1e+300,Infinity) |             Infinity
+           | (1e-300,-1e-300)  | (Infinity,1e+300) |             Infinity
            | (5.1,34.5)        | (1e+300,Infinity) |             Infinity
+           | (5.1,34.5)        | (Infinity,1e+300) |             Infinity
            | (10,10)           | (1e+300,Infinity) |             Infinity
+           | (10,10)           | (Infinity,1e+300) |             Infinity
            | (1e+300,Infinity) | (-10,0)           |             Infinity
            | (1e+300,Infinity) | (-5,-12)          |             Infinity
            | (1e+300,Infinity) | (-3,4)            |             Infinity
@@ -223,6 +235,15 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (1e+300,Infinity) | (1e-300,-1e-300)  |             Infinity
            | (1e+300,Infinity) | (5.1,34.5)        |             Infinity
            | (1e+300,Infinity) | (10,10)           |             Infinity
+           | (1e+300,Infinity) | (Infinity,1e+300) |             Infinity
+           | (Infinity,1e+300) | (-10,0)           |             Infinity
+           | (Infinity,1e+300) | (-5,-12)          |             Infinity
+           | (Infinity,1e+300) | (-3,4)            |             Infinity
+           | (Infinity,1e+300) | (0,0)             |             Infinity
+           | (Infinity,1e+300) | (1e-300,-1e-300)  |             Infinity
+           | (Infinity,1e+300) | (5.1,34.5)        |             Infinity
+           | (Infinity,1e+300) | (10,10)           |             Infinity
+           | (Infinity,1e+300) | (1e+300,Infinity) |             Infinity
            | (-10,0)           | (NaN,NaN)         |                  NaN
            | (-5,-12)          | (NaN,NaN)         |                  NaN
            | (-3,4)            | (NaN,NaN)         |                  NaN
@@ -232,6 +253,8 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (10,10)           | (NaN,NaN)         |                  NaN
            | (1e+300,Infinity) | (1e+300,Infinity) |                  NaN
            | (1e+300,Infinity) | (NaN,NaN)         |                  NaN
+           | (Infinity,1e+300) | (Infinity,1e+300) |                  NaN
+           | (Infinity,1e+300) | (NaN,NaN)         |                  NaN
            | (NaN,NaN)         | (-10,0)           |                  NaN
            | (NaN,NaN)         | (-5,-12)          |                  NaN
            | (NaN,NaN)         | (-3,4)            |                  NaN
@@ -240,8 +263,9 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (NaN,NaN)         | (5.1,34.5)        |                  NaN
            | (NaN,NaN)         | (10,10)           |                  NaN
            | (NaN,NaN)         | (1e+300,Infinity) |                  NaN
+           | (NaN,NaN)         | (Infinity,1e+300) |                  NaN
            | (NaN,NaN)         | (NaN,NaN)         |                  NaN
-(81 rows)
+(100 rows)
 
 SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
    FROM POINT_TBL p1, POINT_TBL p2
@@ -253,6 +277,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (0,0)             | (5.1,34.5)
         | (0,0)             | (-5,-12)
         | (0,0)             | (1e+300,Infinity)
+        | (0,0)             | (Infinity,1e+300)
         | (0,0)             | (NaN,NaN)
         | (0,0)             | (10,10)
         | (-10,0)           | (0,0)
@@ -261,6 +286,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-10,0)           | (-5,-12)
         | (-10,0)           | (1e-300,-1e-300)
         | (-10,0)           | (1e+300,Infinity)
+        | (-10,0)           | (Infinity,1e+300)
         | (-10,0)           | (NaN,NaN)
         | (-10,0)           | (10,10)
         | (-3,4)            | (0,0)
@@ -269,6 +295,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-3,4)            | (-5,-12)
         | (-3,4)            | (1e-300,-1e-300)
         | (-3,4)            | (1e+300,Infinity)
+        | (-3,4)            | (Infinity,1e+300)
         | (-3,4)            | (NaN,NaN)
         | (-3,4)            | (10,10)
         | (5.1,34.5)        | (0,0)
@@ -277,6 +304,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (5.1,34.5)        | (-5,-12)
         | (5.1,34.5)        | (1e-300,-1e-300)
         | (5.1,34.5)        | (1e+300,Infinity)
+        | (5.1,34.5)        | (Infinity,1e+300)
         | (5.1,34.5)        | (NaN,NaN)
         | (5.1,34.5)        | (10,10)
         | (-5,-12)          | (0,0)
@@ -285,6 +313,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-5,-12)          | (5.1,34.5)
         | (-5,-12)          | (1e-300,-1e-300)
         | (-5,-12)          | (1e+300,Infinity)
+        | (-5,-12)          | (Infinity,1e+300)
         | (-5,-12)          | (NaN,NaN)
         | (-5,-12)          | (10,10)
         | (1e-300,-1e-300)  | (-10,0)
@@ -292,6 +321,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e-300,-1e-300)  | (5.1,34.5)
         | (1e-300,-1e-300)  | (-5,-12)
         | (1e-300,-1e-300)  | (1e+300,Infinity)
+        | (1e-300,-1e-300)  | (Infinity,1e+300)
         | (1e-300,-1e-300)  | (NaN,NaN)
         | (1e-300,-1e-300)  | (10,10)
         | (1e+300,Infinity) | (0,0)
@@ -301,8 +331,19 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e+300,Infinity) | (-5,-12)
         | (1e+300,Infinity) | (1e-300,-1e-300)
         | (1e+300,Infinity) | (1e+300,Infinity)
+        | (1e+300,Infinity) | (Infinity,1e+300)
         | (1e+300,Infinity) | (NaN,NaN)
         | (1e+300,Infinity) | (10,10)
+        | (Infinity,1e+300) | (0,0)
+        | (Infinity,1e+300) | (-10,0)
+        | (Infinity,1e+300) | (-3,4)
+        | (Infinity,1e+300) | (5.1,34.5)
+        | (Infinity,1e+300) | (-5,-12)
+        | (Infinity,1e+300) | (1e-300,-1e-300)
+        | (Infinity,1e+300) | (1e+300,Infinity)
+        | (Infinity,1e+300) | (Infinity,1e+300)
+        | (Infinity,1e+300) | (NaN,NaN)
+        | (Infinity,1e+300) | (10,10)
         | (NaN,NaN)         | (0,0)
         | (NaN,NaN)         | (-10,0)
         | (NaN,NaN)         | (-3,4)
@@ -310,6 +351,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (NaN,NaN)         | (-5,-12)
         | (NaN,NaN)         | (1e-300,-1e-300)
         | (NaN,NaN)         | (1e+300,Infinity)
+        | (NaN,NaN)         | (Infinity,1e+300)
         | (NaN,NaN)         | (NaN,NaN)
         | (NaN,NaN)         | (10,10)
         | (10,10)           | (0,0)
@@ -319,57 +361,67 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (10,10)           | (-5,-12)
         | (10,10)           | (1e-300,-1e-300)
         | (10,10)           | (1e+300,Infinity)
+        | (10,10)           | (Infinity,1e+300)
         | (10,10)           | (NaN,NaN)
-(72 rows)
+(91 rows)
 
 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1
    ORDER BY distance, p1.f1[0], p2.f1[0];
- fifteen |      point1      |      point2       |     distance     
----------+------------------+-------------------+------------------
-         | (-3,4)           | (0,0)             |                5
-         | (-3,4)           | (1e-300,-1e-300)  |                5
-         | (-10,0)          | (-3,4)            | 8.06225774829855
-         | (-10,0)          | (0,0)             |               10
-         | (-10,0)          | (1e-300,-1e-300)  |               10
-         | (-10,0)          | (-5,-12)          |               13
-         | (-5,-12)         | (0,0)             |               13
-         | (-5,-12)         | (1e-300,-1e-300)  |               13
-         | (0,0)            | (10,10)           |  14.142135623731
-         | (1e-300,-1e-300) | (10,10)           |  14.142135623731
-         | (-3,4)           | (10,10)           | 14.3178210632764
-         | (-5,-12)         | (-3,4)            | 16.1245154965971
-         | (-10,0)          | (10,10)           | 22.3606797749979
-         | (5.1,34.5)       | (10,10)           | 24.9851956166046
-         | (-5,-12)         | (10,10)           | 26.6270539113887
-         | (-3,4)           | (5.1,34.5)        | 31.5572495632937
-         | (0,0)            | (5.1,34.5)        | 34.8749193547455
-         | (1e-300,-1e-300) | (5.1,34.5)        | 34.8749193547455
-         | (-10,0)          | (5.1,34.5)        | 37.6597928831267
-         | (-5,-12)         | (5.1,34.5)        | 47.5842410888311
-         | (-10,0)          | (1e+300,Infinity) |         Infinity
-         | (-5,-12)         | (1e+300,Infinity) |         Infinity
-         | (-3,4)           | (1e+300,Infinity) |         Infinity
-         | (0,0)            | (1e+300,Infinity) |         Infinity
-         | (1e-300,-1e-300) | (1e+300,Infinity) |         Infinity
-         | (5.1,34.5)       | (1e+300,Infinity) |         Infinity
-         | (10,10)          | (1e+300,Infinity) |         Infinity
-(27 rows)
+ fifteen |      point1       |      point2       |     distance     
+---------+-------------------+-------------------+------------------
+         | (-3,4)            | (0,0)             |                5
+         | (-3,4)            | (1e-300,-1e-300)  |                5
+         | (-10,0)           | (-3,4)            | 8.06225774829855
+         | (-10,0)           | (0,0)             |               10
+         | (-10,0)           | (1e-300,-1e-300)  |               10
+         | (-10,0)           | (-5,-12)          |               13
+         | (-5,-12)          | (0,0)             |               13
+         | (-5,-12)          | (1e-300,-1e-300)  |               13
+         | (0,0)             | (10,10)           |  14.142135623731
+         | (1e-300,-1e-300)  | (10,10)           |  14.142135623731
+         | (-3,4)            | (10,10)           | 14.3178210632764
+         | (-5,-12)          | (-3,4)            | 16.1245154965971
+         | (-10,0)           | (10,10)           | 22.3606797749979
+         | (5.1,34.5)        | (10,10)           | 24.9851956166046
+         | (-5,-12)          | (10,10)           | 26.6270539113887
+         | (-3,4)            | (5.1,34.5)        | 31.5572495632937
+         | (0,0)             | (5.1,34.5)        | 34.8749193547455
+         | (1e-300,-1e-300)  | (5.1,34.5)        | 34.8749193547455
+         | (-10,0)           | (5.1,34.5)        | 37.6597928831267
+         | (-5,-12)          | (5.1,34.5)        | 47.5842410888311
+         | (-10,0)           | (1e+300,Infinity) |         Infinity
+         | (-10,0)           | (Infinity,1e+300) |         Infinity
+         | (-5,-12)          | (1e+300,Infinity) |         Infinity
+         | (-5,-12)          | (Infinity,1e+300) |         Infinity
+         | (-3,4)            | (1e+300,Infinity) |         Infinity
+         | (-3,4)            | (Infinity,1e+300) |         Infinity
+         | (0,0)             | (1e+300,Infinity) |         Infinity
+         | (0,0)             | (Infinity,1e+300) |         Infinity
+         | (1e-300,-1e-300)  | (1e+300,Infinity) |         Infinity
+         | (1e-300,-1e-300)  | (Infinity,1e+300) |         Infinity
+         | (5.1,34.5)        | (1e+300,Infinity) |         Infinity
+         | (5.1,34.5)        | (Infinity,1e+300) |         Infinity
+         | (10,10)           | (1e+300,Infinity) |         Infinity
+         | (10,10)           | (Infinity,1e+300) |         Infinity
+         | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(35 rows)
 
 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1
    ORDER BY distance;
- three |   point1   |      point2      |     distance     
--------+------------+------------------+------------------
-       | (-3,4)     | (0,0)            |                5
-       | (-3,4)     | (1e-300,-1e-300) |                5
-       | (-10,0)    | (-5,-12)         |               13
-       | (5.1,34.5) | (10,10)          | 24.9851956166046
-(4 rows)
+ three |      point1       |      point2       |     distance     
+-------+-------------------+-------------------+------------------
+       | (-3,4)            | (0,0)             |                5
+       | (-3,4)            | (1e-300,-1e-300)  |                5
+       | (-10,0)           | (-5,-12)          |               13
+       | (5.1,34.5)        | (10,10)           | 24.9851956166046
+       | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(5 rows)
 
 -- Test that GiST indexes provide same behavior as sequential scan
 CREATE TEMP TABLE point_gist_tbl(f1 point);
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 7f8504dbd1..6a1ca12d5c 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -21,6 +21,8 @@ INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
 
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
+
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 
 -- bad format points
-- 
2.18.4


Re: Strange behavior with polygon and NaN

From
gkokolatos@pm.me
Date:




‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Thursday, November 5, 2020 6:07 AM, Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote:

> At Mon, 02 Nov 2020 14:43:32 +0000, Georgios Kokolatos gkokolatos@protonmail.com wrote in
>
> > Hi,
> > apologies for the very, very late reply to your fixes.
> > You have answered/addressed all my questions concerns. The added documentation
> > reads well, at least to a non native English speaker.
> > The patch still applies and as far as I can see the tests are passing.
> > It gets my :+1: and I am changing the status to "Ready for Committer".
> > For what little is worth, I learned a lot from this patch, thank you.
> > Cheers,
> > Georgios
> > The new status of this patch is: Ready for Committer
>
> Oh! Thanks. Since a part of this patch is committed (Thanks to Tom.)
> this is a rebased version on the commit.

I completely missed that a part got committed.

Thank you for your rebased version of the rest. I went through it
and my initial assessement of '+1' still stands.

The status remains to: Ready for Committer.

//Georgios

>
> regards.
>
>
--------------------------------------------------------------------------------------------------------------------------
>
> Kyotaro Horiguchi
> NTT Open Source Software Center


Attachment

Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
I spent some time looking this over, and have a few thoughts:

1. I think it's useful to split the test changes into two patches,
as I've done below: first, just add the additional row in point_tbl
and let the fallout from that happen, and then in the second patch
make the code changes.  This way, it's much clearer what the actual
behavioral changes are.  Some of them don't look right, either.
For instance, in the very first hunk in geometry.out, we have
this:

- (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity

which seems right, and also this:

- (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
+ (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN

which does not.  Why aren't these distances infinite as well?
For instance, {1,-1,0} is the line "x = y".  We could argue about
whether it'd be sensible to return zero for the distance between that
and the point (inf,inf), but surely any point with one inf and one
finite coordinate must be an infinite distance away from that line.
There's nothing ill-defined about that situation.

2. Rather than coding around undesirable behavior of float8_min,
it seems like it's better to add a primitive to float.h that
does what you want, ie "NaN if either input is NaN, else the
smaller input".  This is more readable, and possibly more efficient
(depending on whether the compiler is smart enough to optimize
away redundant isnan checks).  I did that in the attached.

3. Looking for other calls of float8_min, I wonder why you did not
touch the bounding-box calculations in box_interpt_lseg() or
boxes_bound_box().

4. The line changes feel a bit weird, like there's no clear idea
of what a "valid" or "invalid" line is.  For instance the first
hunk in line_construct():

+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->y)))
+            result->C = get_float8_nan();

Why's it appropriate to set C and only C to NaN?

5. But actually there's a bigger issue with that particular hunk.
This code branch is dealing with "draw a vertical line through this
point", so why should we care what the point's y coordinate is --- that
is, why is this particular change appropriate at all?  The usual rule as
I understand it is that if a function's result is determined by some of
its arguments independently of what another argument's value is, then it
doesn't matter if that one is NaN, you can still return the same result.

6. I'm a bit uncomfortable with the use of "bool isnan" in a couple
of places.  I think it's confusing to use that alongside the isnan()
macro.  Moreover, it's at least possible that some platforms implement
isnan() in a way that would break this usage.  The C spec specifically
says that isnan() is a macro not a function ... but it doesn't commit
to it being a macro-with-arguments.  I think "anynan" or something
like that would be a better choice of name.

[ a bit later... ] Indeed, I get a compile failure on gaur:

geo_ops.c: In function 'lseg_closept_lseg':
geo_ops.c:2906:17: error: called object 'isnan' is not a function
geo_ops.c:2906:32: error: called object 'isnan' is not a function
geo_ops.c:2916:16: error: called object 'isnan' is not a function
geo_ops.c:2924:16: error: called object 'isnan' is not a function
geo_ops.c: In function 'box_closept_point':
geo_ops.c:2989:16: error: called object 'isnan' is not a function
geo_ops.c:2992:16: error: called object 'isnan' is not a function
geo_ops.c:3004:16: error: called object 'isnan' is not a function
geo_ops.c:3014:16: error: called object 'isnan' is not a function
make: *** [geo_ops.o] Error 1

So that scenario isn't hypothetical.  Please rename the variables.

            regards, tom lane

diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 93a8736a3f..76679bae8d 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -157,7 +157,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count
 -------
-     3
+     4
 (1 row)

 SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
@@ -169,7 +169,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count
 -------
-     4
+     5
 (1 row)

 SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
@@ -188,10 +188,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)

-(10 rows)
+(11 rows)

 SELECT * FROM point_tbl WHERE f1 IS NULL;
  f1
@@ -202,16 +203,17 @@ SELECT * FROM point_tbl WHERE f1 IS NULL;
 SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
         f1
 -------------------
- (1e-300,-1e-300)
  (0,0)
+ (1e-300,-1e-300)
  (-3,4)
  (-10,0)
  (10,10)
  (-5,-12)
  (5.1,34.5)
  (1e+300,Infinity)
+ (Infinity,1e+300)
  (NaN,NaN)
-(9 rows)
+(10 rows)

 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
         f1
@@ -464,7 +466,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count
 -------
-     3
+     4
 (1 row)

 EXPLAIN (COSTS OFF)
@@ -494,7 +496,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count
 -------
-     4
+     5
 (1 row)

 EXPLAIN (COSTS OFF)
@@ -530,10 +532,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)

-(10 rows)
+(11 rows)

 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 IS NULL;
@@ -568,9 +571,10 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
-(9 rows)
+(10 rows)

 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..81202a4c33 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -120,6 +120,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          |                2.4
  (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
  (0,0)             | (1e+300,Infinity) |           Infinity
+ (0,0)             | (Infinity,1e+300) |                  0
  (0,0)             | (NaN,NaN)         |                NaN
  (0,0)             | (10,10)           |                  1
  (-10,0)           | (0,0)             |                  0
@@ -129,6 +130,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          |               -2.4
  (-10,0)           | (1e-300,-1e-300)  |                  0
  (-10,0)           | (1e+300,Infinity) |           Infinity
+ (-10,0)           | (Infinity,1e+300) |                  0
  (-10,0)           | (NaN,NaN)         |                NaN
  (-10,0)           | (10,10)           |                0.5
  (-3,4)            | (0,0)             |     -1.33333333333
@@ -138,6 +140,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          |                  8
  (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
  (-3,4)            | (1e+300,Infinity) |           Infinity
+ (-3,4)            | (Infinity,1e+300) |                  0
  (-3,4)            | (NaN,NaN)         |                NaN
  (-3,4)            | (10,10)           |     0.461538461538
  (5.1,34.5)        | (0,0)             |      6.76470588235
@@ -147,6 +150,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          |      4.60396039604
  (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
  (5.1,34.5)        | (1e+300,Infinity) |           Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |                  0
  (5.1,34.5)        | (NaN,NaN)         |                NaN
  (5.1,34.5)        | (10,10)           |                 -5
  (-5,-12)          | (0,0)             |                2.4
@@ -156,6 +160,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | 1.79769313486e+308
  (-5,-12)          | (1e-300,-1e-300)  |                2.4
  (-5,-12)          | (1e+300,Infinity) |           Infinity
+ (-5,-12)          | (Infinity,1e+300) |                  0
  (-5,-12)          | (NaN,NaN)         |                NaN
  (-5,-12)          | (10,10)           |      1.46666666667
  (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
@@ -165,6 +170,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          |                2.4
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
  (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
  (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
  (1e-300,-1e-300)  | (10,10)           |                  1
  (1e+300,Infinity) | (0,0)             |           Infinity
@@ -174,8 +180,19 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          |           Infinity
  (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
  (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
+ (1e+300,Infinity) | (Infinity,1e+300) |                NaN
  (1e+300,Infinity) | (NaN,NaN)         |                NaN
  (1e+300,Infinity) | (10,10)           |           Infinity
+ (Infinity,1e+300) | (0,0)             |                  0
+ (Infinity,1e+300) | (-10,0)           |                  0
+ (Infinity,1e+300) | (-3,4)            |                  0
+ (Infinity,1e+300) | (5.1,34.5)        |                  0
+ (Infinity,1e+300) | (-5,-12)          |                  0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
+ (Infinity,1e+300) | (1e+300,Infinity) |                NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |                  0
+ (Infinity,1e+300) | (NaN,NaN)         |                NaN
+ (Infinity,1e+300) | (10,10)           |                  0
  (NaN,NaN)         | (0,0)             |                NaN
  (NaN,NaN)         | (-10,0)           |                NaN
  (NaN,NaN)         | (-3,4)            |                NaN
@@ -183,6 +200,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          |                NaN
  (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
  (NaN,NaN)         | (1e+300,Infinity) |                NaN
+ (NaN,NaN)         | (Infinity,1e+300) |                NaN
  (NaN,NaN)         | (NaN,NaN)         |                NaN
  (NaN,NaN)         | (10,10)           |                NaN
  (10,10)           | (0,0)             |                  1
@@ -192,14 +210,15 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          |      1.46666666667
  (10,10)           | (1e-300,-1e-300)  |                  1
  (10,10)           | (1e+300,Infinity) |           Infinity
+ (10,10)           | (Infinity,1e+300) |                  0
  (10,10)           | (NaN,NaN)         |                NaN
  (10,10)           | (10,10)           | 1.79769313486e+308
-(81 rows)
+(100 rows)

 -- Add point
 SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |     ?column?
--------------------+-------------------+-------------------
+        f1         |        f1         |      ?column?
+-------------------+-------------------+---------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (-10,0)
  (0,0)             | (-3,4)            | (-3,4)
@@ -207,6 +226,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (-5,-12)
  (0,0)             | (1e-300,-1e-300)  | (1e-300,-1e-300)
  (0,0)             | (1e+300,Infinity) | (1e+300,Infinity)
+ (0,0)             | (Infinity,1e+300) | (Infinity,1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (10,10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -216,6 +236,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-15,-12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,-1e-300)
  (-10,0)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (-10,0)           | (Infinity,1e+300) | (Infinity,1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (0,10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -225,6 +246,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (-8,-8)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (1e+300,Infinity)
+ (-3,4)            | (Infinity,1e+300) | (Infinity,1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (7,14)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -234,6 +256,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (0.1,22.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (1e+300,Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (Infinity,1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (15.1,44.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -243,6 +266,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (-10,-24)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (1e+300,Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (Infinity,1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (5,-2)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -252,6 +276,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (-5,-12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (2e-300,-2e-300)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (1e+300,Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (Infinity,1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (10,10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -261,8 +286,19 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (2e+300,Infinity)
+ (1e+300,Infinity) | (Infinity,1e+300) | (Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (Infinity,2e+300)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -270,6 +306,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -279,14 +316,15 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (5,-2)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (10,10)           | (Infinity,1e+300) | (Infinity,1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (20,20)
-(81 rows)
+(100 rows)

 -- Subtract point
 SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |      ?column?
--------------------+-------------------+---------------------
+        f1         |        f1         |       ?column?
+-------------------+-------------------+----------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (10,0)
  (0,0)             | (-3,4)            | (3,-4)
@@ -294,6 +332,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (5,12)
  (0,0)             | (1e-300,-1e-300)  | (-1e-300,1e-300)
  (0,0)             | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (0,0)             | (Infinity,1e+300) | (-Infinity,-1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (-10,-10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -303,6 +342,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-5,12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,1e-300)
  (-10,0)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-10,0)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (-20,-10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -312,6 +352,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (2,16)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-3,4)            | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (-13,-6)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -321,6 +362,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (10.1,46.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (-Infinity,-1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (-4.9,24.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -330,6 +372,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (0,0)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (-15,-22)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -339,6 +382,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (5,12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (0,0)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (-Infinity,-1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (-10,-10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -348,8 +392,19 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (0,NaN)
+ (1e+300,Infinity) | (Infinity,1e+300) | (-Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (NaN,0)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -357,6 +412,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -366,9 +422,10 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (15,22)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (10,10)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (0,0)
-(81 rows)
+(100 rows)

 -- Multiply with point
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -388,11 +445,13 @@ SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0
  (10,10)    | (1e-300,-1e-300)  | (2e-299,0)
  (5.1,34.5) | (1e+300,Infinity) | (-Infinity,Infinity)
  (10,10)    | (1e+300,Infinity) | (-Infinity,Infinity)
+ (5.1,34.5) | (Infinity,1e+300) | (Infinity,Infinity)
+ (10,10)    | (Infinity,1e+300) | (Infinity,Infinity)
  (5.1,34.5) | (NaN,NaN)         | (NaN,NaN)
  (10,10)    | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5) | (10,10)           | (-294,396)
  (10,10)    | (10,10)           | (0,200)
-(18 rows)
+(20 rows)

 -- Underflow error
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] < 1;
@@ -415,11 +474,13 @@ SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0
  (1e-300,-1e-300)  | (10,10)    | (0,-1e-301)
  (1e+300,Infinity) | (5.1,34.5) | (Infinity,Infinity)
  (1e+300,Infinity) | (10,10)    | (Infinity,Infinity)
+ (Infinity,1e+300) | (5.1,34.5) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (10,10)    | (Infinity,-Infinity)
  (NaN,NaN)         | (5.1,34.5) | (NaN,NaN)
  (NaN,NaN)         | (10,10)    | (NaN,NaN)
  (10,10)           | (5.1,34.5) | (0.325588278822,-0.241724631247)
  (10,10)           | (10,10)    | (1,0)
-(18 rows)
+(20 rows)

 -- Overflow error
 SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0] > 1000;
@@ -501,6 +562,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -521,7 +592,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
  (10,10)           | {-1,0,3}                              |                  7 |                  7
-(90 rows)
+(100 rows)

 -- Distance to line segment
 SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
@@ -583,6 +654,14 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -599,7 +678,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (10,10)           | [(-10,2),(-10,3)]             |      21.1896201004 |      21.1896201004
  (10,10)           | [(0,-20),(30,-20)]            |                 30 |                 30
  (10,10)           | [(NaN,1),(NaN,90)]            |                NaN |                NaN
-(72 rows)
+(80 rows)

 -- Distance to box
 SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT_TBL p, BOX_TBL b;
@@ -640,6 +719,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(1,1)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |           Infinity |           Infinity
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -650,7 +734,7 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (10,10)           | (-2,2),(-8,-10)     |      14.4222051019 |      14.4222051019
  (10,10)           | (2.5,3.5),(2.5,2.5) |      9.92471662064 |      9.92471662064
  (10,10)           | (3,3),(3,3)         |      9.89949493661 |      9.89949493661
-(45 rows)
+(50 rows)

 -- Distance to path
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp FROM POINT_TBL p, PATH_TBL p1;
@@ -719,6 +803,15 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((10,20))                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,12),(13,14)]         |           Infinity |           Infinity
+ (Infinity,1e+300) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
  (NaN,NaN)         | ((1,2),(3,4))             |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
@@ -737,7 +830,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (10,10)           | ((10,20))                 |                 10 |                 10
  (10,10)           | [(11,12),(13,14)]         |       2.2360679775 |       2.2360679775
  (10,10)           | ((11,12),(13,14))         |       2.2360679775 |       2.2360679775
-(81 rows)
+(90 rows)

 -- Distance to polygon
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp FROM POINT_TBL p, POLYGON_TBL p1;
@@ -792,6 +885,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
+ (Infinity,1e+300) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
  (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
  (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
  (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
@@ -806,7 +906,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | 3.60555127546 | 3.60555127546
  (10,10)           | ((0,0))                    | 14.1421356237 | 14.1421356237
  (10,10)           | ((0,1),(0,1))              | 13.4536240471 | 13.4536240471
-(63 rows)
+(70 rows)

 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -882,6 +982,16 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              |
+ (Infinity,1e+300) | {0,-1,5}                              |
+ (Infinity,1e+300) | {1,0,5}                               |
+ (Infinity,1e+300) | {0,3,0}                               |
+ (Infinity,1e+300) | {1,-1,0}                              |
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |
+ (Infinity,1e+300) | {3,NaN,5}                             |
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |
+ (Infinity,1e+300) | {0,-1,3}                              |
+ (Infinity,1e+300) | {-1,0,3}                              |
  (NaN,NaN)         | {0,-1,5}                              |
  (NaN,NaN)         | {1,0,5}                               |
  (NaN,NaN)         | {0,3,0}                               |
@@ -902,7 +1012,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (10,10)           | {NaN,NaN,NaN}                         |
  (10,10)           | {0,-1,3}                              | (10,3)
  (10,10)           | {-1,0,3}                              | (3,10)
-(90 rows)
+(100 rows)

 -- Closest point to line segment
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
@@ -964,6 +1074,14 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
+ (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
+ (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            | (30,-20)
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |
  (NaN,NaN)         | [(1,2),(3,4)]                 |
  (NaN,NaN)         | [(0,0),(6,6)]                 |
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |
@@ -980,7 +1098,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (10,10)           | [(-10,2),(-10,3)]             | (-10,3)
  (10,10)           | [(0,-20),(30,-20)]            | (10,-20)
  (10,10)           | [(NaN,1),(NaN,90)]            |
-(72 rows)
+(80 rows)

 -- Closest point to box
 SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
@@ -1021,6 +1139,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (Infinity,1e+300) | (2,2),(0,0)         | (0,2)
+ (Infinity,1e+300) | (3,3),(1,1)         | (1,3)
+ (Infinity,1e+300) | (-2,2),(-8,-10)     | (-8,2)
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
+ (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         |
  (NaN,NaN)         | (3,3),(1,1)         |
  (NaN,NaN)         | (-2,2),(-8,-10)     |
@@ -1031,7 +1154,7 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (10,10)           | (-2,2),(-8,-10)     | (-2,2)
  (10,10)           | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (10,10)           | (3,3),(3,3)         | (3,3)
-(45 rows)
+(50 rows)

 -- On line
 SELECT p.f1, l.s FROM POINT_TBL p, LINE_TBL l WHERE p.f1 <@ l.s;
@@ -2347,6 +2470,11 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2357,7 +2485,7 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (8,12),(2,0)
             | (12.5,13.5),(12.5,12.5)
             | (13,13),(13,13)
-(45 rows)
+(50 rows)

 SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
    FROM BOX_TBL b, POINT_TBL p;
@@ -2398,6 +2526,11 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2408,7 +2541,7 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-12,-8),(-18,-20)
             | (-7.5,-6.5),(-7.5,-7.5)
             | (-7,-7),(-7,-7)
-(45 rows)
+(50 rows)

 -- Multiply with point
 SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2431,16 +2564,21 @@ SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] > 1000;
          f1          |        f1         |                  ?column?
 ---------------------+-------------------+--------------------------------------------
  (2,2),(0,0)         | (1e+300,Infinity) | (NaN,NaN),(-Infinity,Infinity)
+ (2,2),(0,0)         | (Infinity,1e+300) | (NaN,NaN),(Infinity,Infinity)
  (2,2),(0,0)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(1,1)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(1,1)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(1,1)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (-2,2),(-8,-10)     | (1e+300,Infinity) | (Infinity,-Infinity),(-Infinity,-Infinity)
+ (-2,2),(-8,-10)     | (Infinity,1e+300) | (-Infinity,Infinity),(-Infinity,-Infinity)
  (-2,2),(-8,-10)     | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (2.5,3.5),(2.5,2.5) | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (2.5,3.5),(2.5,2.5) | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (2.5,3.5),(2.5,2.5) | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(3,3)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(3,3)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(3,3)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
-(10 rows)
+(15 rows)

 -- Divide by point
 SELECT b.f1, p.f1, b.f1 / p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2470,9 +2608,10 @@ SELECT f1::box
  (-5,-12),(-5,-12)
  (1e-300,-1e-300),(1e-300,-1e-300)
  (1e+300,Infinity),(1e+300,Infinity)
+ (Infinity,1e+300),(Infinity,1e+300)
  (NaN,NaN),(NaN,NaN)
  (10,10),(10,10)
-(9 rows)
+(10 rows)

 SELECT bound_box(a.f1, b.f1)
     FROM BOX_TBL a, BOX_TBL b;
@@ -3102,6 +3241,15 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((1e+300,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(1e+300,Infinity),(1e+300,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((1e+300,Infinity),(1e+300,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3120,7 +3268,7 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((20,30))
  [(11,12),(13,14)]         | (10,10)           | [(21,22),(23,24)]
  ((11,12),(13,14))         | (10,10)           | ((21,22),(23,24))
-(81 rows)
+(90 rows)

 -- Subtract point
 SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3189,6 +3337,15 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-1e+300,-Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-1e+300,-Infinity),(-1e+300,-Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-1e+300,-Infinity),(-1e+300,-Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((-Infinity,-1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3207,7 +3364,7 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((0,10))
  [(11,12),(13,14)]         | (10,10)           | [(1,2),(3,4)]
  ((11,12),(13,14))         | (10,10)           | ((1,2),(3,4))
-(81 rows)
+(90 rows)

 -- Multiply with point
 SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3276,6 +3433,15 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-Infinity,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-Infinity,Infinity),(-Infinity,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-Infinity,Infinity),(-Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) | [(NaN,NaN),(Infinity,NaN),(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,Infinity))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3294,7 +3460,7 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((-100,300))
  [(11,12),(13,14)]         | (10,10)           | [(-10,230),(-10,270)]
  ((11,12),(13,14))         | (10,10)           | ((-10,230),(-10,270))
-(81 rows)
+(90 rows)

 -- Divide by point
 SELECT p.f1, p1.f1, p.f1 / p1.f1 FROM PATH_TBL p, POINT_TBL p1 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -3467,6 +3633,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3481,7 +3654,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)

 SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
    FROM POLYGON_TBL poly, POINT_TBL p;
@@ -3536,6 +3709,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3550,7 +3730,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)

 SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon
    FROM POLYGON_TBL;
@@ -3929,9 +4109,10 @@ SELECT '' AS six, circle(f1, 50.0)
      | <(-5,-12),50>
      | <(1e-300,-1e-300),50>
      | <(1e+300,Infinity),50>
+     | <(Infinity,1e+300),50>
      | <(NaN,NaN),50>
      | <(10,10),50>
-(9 rows)
+(10 rows)

 SELECT '' AS four, circle(f1)
    FROM BOX_TBL;
@@ -3993,12 +4174,19 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(100,200),10> | (-10,0)           |  218.25424421
             | <(100,200),10> | (-5,-12)          | 226.577682802
             | <(3,5),0>      | (1e+300,Infinity) |      Infinity
+            | <(3,5),0>      | (Infinity,1e+300) |      Infinity
             | <(1,2),3>      | (1e+300,Infinity) |      Infinity
             | <(5,1),3>      | (1e+300,Infinity) |      Infinity
+            | <(5,1),3>      | (Infinity,1e+300) |      Infinity
+            | <(1,2),3>      | (Infinity,1e+300) |      Infinity
             | <(1,3),5>      | (1e+300,Infinity) |      Infinity
+            | <(1,3),5>      | (Infinity,1e+300) |      Infinity
             | <(100,200),10> | (1e+300,Infinity) |      Infinity
+            | <(100,200),10> | (Infinity,1e+300) |      Infinity
             | <(1,2),100>    | (1e+300,Infinity) |      Infinity
+            | <(1,2),100>    | (Infinity,1e+300) |      Infinity
             | <(100,1),115>  | (1e+300,Infinity) |      Infinity
+            | <(100,1),115>  | (Infinity,1e+300) |      Infinity
             | <(3,5),0>      | (NaN,NaN)         |           NaN
             | <(1,2),3>      | (NaN,NaN)         |           NaN
             | <(5,1),3>      | (NaN,NaN)         |           NaN
@@ -4014,8 +4202,9 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(3,5),NaN>    | (5.1,34.5)        |           NaN
             | <(3,5),NaN>    | (10,10)           |           NaN
             | <(3,5),NaN>    | (1e+300,Infinity) |           NaN
+            | <(3,5),NaN>    | (Infinity,1e+300) |           NaN
             | <(3,5),NaN>    | (NaN,NaN)         |           NaN
-(53 rows)
+(61 rows)

 -- To polygon
 SELECT f1, f1::polygon FROM CIRCLE_TBL WHERE f1 >= '<(0,0),1>';
@@ -4626,6 +4815,14 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(1e+300,Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(1e+300,Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(1e+300,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4642,7 +4839,7 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(110,11),115>
  <(3,5),0>      | (10,10)           | <(13,15),0>
  <(3,5),NaN>    | (10,10)           | <(13,15),NaN>
-(72 rows)
+(80 rows)

 -- Subtract point
 SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4704,6 +4901,14 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-1e+300,-Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(-1e+300,-Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-1e+300,-Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(-Infinity,-1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(-Infinity,-1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(-Infinity,-1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(-Infinity,-1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(-Infinity,-1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(-Infinity,-1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4720,7 +4925,7 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(90,-9),115>
  <(3,5),0>      | (10,10)           | <(-7,-5),0>
  <(3,5),NaN>    | (10,10)           | <(-7,-5),NaN>
-(72 rows)
+(80 rows)

 -- Multiply with point
 SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4782,6 +4987,14 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-Infinity,Infinity),Infinity>
  <(3,5),0>      | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),NaN>
@@ -4798,7 +5011,7 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(990,1010),1626.34559673>
  <(3,5),0>      | (10,10)           | <(-20,80),0>
  <(3,5),NaN>    | (10,10)           | <(-20,80),NaN>
-(72 rows)
+(80 rows)

 -- Divide by point
 SELECT c.f1, p.f1, c.f1 / p.f1 FROM CIRCLE_TBL c, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 15e3b83b37..77e250fc3e 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -11,6 +11,7 @@ INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 -- bad format points
 INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
@@ -44,9 +45,10 @@ SELECT '' AS six, * FROM POINT_TBL;
      | (-5,-12)
      | (1e-300,-1e-300)
      | (1e+300,Infinity)
+     | (Infinity,1e+300)
      | (NaN,NaN)
      | (10,10)
-(9 rows)
+(10 rows)

 -- left of
 SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)';
@@ -115,8 +117,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)

 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -136,8 +139,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)

 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
@@ -152,8 +156,9 @@ SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
      | (10,10)           |      14.142135623731
      | (5.1,34.5)        |     34.8749193547455
      | (1e+300,Infinity) |             Infinity
+     | (Infinity,1e+300) |             Infinity
      | (NaN,NaN)         |                  NaN
-(9 rows)
+(10 rows)

 SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist
    FROM POINT_TBL p1, POINT_TBL p2
@@ -210,12 +215,19 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (-5,-12)          | (5.1,34.5)        |     47.5842410888311
            | (5.1,34.5)        | (-5,-12)          |     47.5842410888311
            | (-10,0)           | (1e+300,Infinity) |             Infinity
+           | (-10,0)           | (Infinity,1e+300) |             Infinity
            | (-5,-12)          | (1e+300,Infinity) |             Infinity
+           | (-5,-12)          | (Infinity,1e+300) |             Infinity
            | (-3,4)            | (1e+300,Infinity) |             Infinity
+           | (-3,4)            | (Infinity,1e+300) |             Infinity
            | (0,0)             | (1e+300,Infinity) |             Infinity
+           | (0,0)             | (Infinity,1e+300) |             Infinity
            | (1e-300,-1e-300)  | (1e+300,Infinity) |             Infinity
+           | (1e-300,-1e-300)  | (Infinity,1e+300) |             Infinity
            | (5.1,34.5)        | (1e+300,Infinity) |             Infinity
+           | (5.1,34.5)        | (Infinity,1e+300) |             Infinity
            | (10,10)           | (1e+300,Infinity) |             Infinity
+           | (10,10)           | (Infinity,1e+300) |             Infinity
            | (1e+300,Infinity) | (-10,0)           |             Infinity
            | (1e+300,Infinity) | (-5,-12)          |             Infinity
            | (1e+300,Infinity) | (-3,4)            |             Infinity
@@ -223,6 +235,15 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (1e+300,Infinity) | (1e-300,-1e-300)  |             Infinity
            | (1e+300,Infinity) | (5.1,34.5)        |             Infinity
            | (1e+300,Infinity) | (10,10)           |             Infinity
+           | (1e+300,Infinity) | (Infinity,1e+300) |             Infinity
+           | (Infinity,1e+300) | (-10,0)           |             Infinity
+           | (Infinity,1e+300) | (-5,-12)          |             Infinity
+           | (Infinity,1e+300) | (-3,4)            |             Infinity
+           | (Infinity,1e+300) | (0,0)             |             Infinity
+           | (Infinity,1e+300) | (1e-300,-1e-300)  |             Infinity
+           | (Infinity,1e+300) | (5.1,34.5)        |             Infinity
+           | (Infinity,1e+300) | (10,10)           |             Infinity
+           | (Infinity,1e+300) | (1e+300,Infinity) |             Infinity
            | (-10,0)           | (NaN,NaN)         |                  NaN
            | (-5,-12)          | (NaN,NaN)         |                  NaN
            | (-3,4)            | (NaN,NaN)         |                  NaN
@@ -232,6 +253,8 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (10,10)           | (NaN,NaN)         |                  NaN
            | (1e+300,Infinity) | (1e+300,Infinity) |                  NaN
            | (1e+300,Infinity) | (NaN,NaN)         |                  NaN
+           | (Infinity,1e+300) | (Infinity,1e+300) |                  NaN
+           | (Infinity,1e+300) | (NaN,NaN)         |                  NaN
            | (NaN,NaN)         | (-10,0)           |                  NaN
            | (NaN,NaN)         | (-5,-12)          |                  NaN
            | (NaN,NaN)         | (-3,4)            |                  NaN
@@ -240,8 +263,9 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (NaN,NaN)         | (5.1,34.5)        |                  NaN
            | (NaN,NaN)         | (10,10)           |                  NaN
            | (NaN,NaN)         | (1e+300,Infinity) |                  NaN
+           | (NaN,NaN)         | (Infinity,1e+300) |                  NaN
            | (NaN,NaN)         | (NaN,NaN)         |                  NaN
-(81 rows)
+(100 rows)

 SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
    FROM POINT_TBL p1, POINT_TBL p2
@@ -253,6 +277,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (0,0)             | (5.1,34.5)
         | (0,0)             | (-5,-12)
         | (0,0)             | (1e+300,Infinity)
+        | (0,0)             | (Infinity,1e+300)
         | (0,0)             | (NaN,NaN)
         | (0,0)             | (10,10)
         | (-10,0)           | (0,0)
@@ -261,6 +286,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-10,0)           | (-5,-12)
         | (-10,0)           | (1e-300,-1e-300)
         | (-10,0)           | (1e+300,Infinity)
+        | (-10,0)           | (Infinity,1e+300)
         | (-10,0)           | (NaN,NaN)
         | (-10,0)           | (10,10)
         | (-3,4)            | (0,0)
@@ -269,6 +295,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-3,4)            | (-5,-12)
         | (-3,4)            | (1e-300,-1e-300)
         | (-3,4)            | (1e+300,Infinity)
+        | (-3,4)            | (Infinity,1e+300)
         | (-3,4)            | (NaN,NaN)
         | (-3,4)            | (10,10)
         | (5.1,34.5)        | (0,0)
@@ -277,6 +304,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (5.1,34.5)        | (-5,-12)
         | (5.1,34.5)        | (1e-300,-1e-300)
         | (5.1,34.5)        | (1e+300,Infinity)
+        | (5.1,34.5)        | (Infinity,1e+300)
         | (5.1,34.5)        | (NaN,NaN)
         | (5.1,34.5)        | (10,10)
         | (-5,-12)          | (0,0)
@@ -285,6 +313,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-5,-12)          | (5.1,34.5)
         | (-5,-12)          | (1e-300,-1e-300)
         | (-5,-12)          | (1e+300,Infinity)
+        | (-5,-12)          | (Infinity,1e+300)
         | (-5,-12)          | (NaN,NaN)
         | (-5,-12)          | (10,10)
         | (1e-300,-1e-300)  | (-10,0)
@@ -292,6 +321,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e-300,-1e-300)  | (5.1,34.5)
         | (1e-300,-1e-300)  | (-5,-12)
         | (1e-300,-1e-300)  | (1e+300,Infinity)
+        | (1e-300,-1e-300)  | (Infinity,1e+300)
         | (1e-300,-1e-300)  | (NaN,NaN)
         | (1e-300,-1e-300)  | (10,10)
         | (1e+300,Infinity) | (0,0)
@@ -301,8 +331,19 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e+300,Infinity) | (-5,-12)
         | (1e+300,Infinity) | (1e-300,-1e-300)
         | (1e+300,Infinity) | (1e+300,Infinity)
+        | (1e+300,Infinity) | (Infinity,1e+300)
         | (1e+300,Infinity) | (NaN,NaN)
         | (1e+300,Infinity) | (10,10)
+        | (Infinity,1e+300) | (0,0)
+        | (Infinity,1e+300) | (-10,0)
+        | (Infinity,1e+300) | (-3,4)
+        | (Infinity,1e+300) | (5.1,34.5)
+        | (Infinity,1e+300) | (-5,-12)
+        | (Infinity,1e+300) | (1e-300,-1e-300)
+        | (Infinity,1e+300) | (1e+300,Infinity)
+        | (Infinity,1e+300) | (Infinity,1e+300)
+        | (Infinity,1e+300) | (NaN,NaN)
+        | (Infinity,1e+300) | (10,10)
         | (NaN,NaN)         | (0,0)
         | (NaN,NaN)         | (-10,0)
         | (NaN,NaN)         | (-3,4)
@@ -310,6 +351,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (NaN,NaN)         | (-5,-12)
         | (NaN,NaN)         | (1e-300,-1e-300)
         | (NaN,NaN)         | (1e+300,Infinity)
+        | (NaN,NaN)         | (Infinity,1e+300)
         | (NaN,NaN)         | (NaN,NaN)
         | (NaN,NaN)         | (10,10)
         | (10,10)           | (0,0)
@@ -319,57 +361,67 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (10,10)           | (-5,-12)
         | (10,10)           | (1e-300,-1e-300)
         | (10,10)           | (1e+300,Infinity)
+        | (10,10)           | (Infinity,1e+300)
         | (10,10)           | (NaN,NaN)
-(72 rows)
+(91 rows)

 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1
    ORDER BY distance, p1.f1[0], p2.f1[0];
- fifteen |      point1      |      point2       |     distance
----------+------------------+-------------------+------------------
-         | (-3,4)           | (0,0)             |                5
-         | (-3,4)           | (1e-300,-1e-300)  |                5
-         | (-10,0)          | (-3,4)            | 8.06225774829855
-         | (-10,0)          | (0,0)             |               10
-         | (-10,0)          | (1e-300,-1e-300)  |               10
-         | (-10,0)          | (-5,-12)          |               13
-         | (-5,-12)         | (0,0)             |               13
-         | (-5,-12)         | (1e-300,-1e-300)  |               13
-         | (0,0)            | (10,10)           |  14.142135623731
-         | (1e-300,-1e-300) | (10,10)           |  14.142135623731
-         | (-3,4)           | (10,10)           | 14.3178210632764
-         | (-5,-12)         | (-3,4)            | 16.1245154965971
-         | (-10,0)          | (10,10)           | 22.3606797749979
-         | (5.1,34.5)       | (10,10)           | 24.9851956166046
-         | (-5,-12)         | (10,10)           | 26.6270539113887
-         | (-3,4)           | (5.1,34.5)        | 31.5572495632937
-         | (0,0)            | (5.1,34.5)        | 34.8749193547455
-         | (1e-300,-1e-300) | (5.1,34.5)        | 34.8749193547455
-         | (-10,0)          | (5.1,34.5)        | 37.6597928831267
-         | (-5,-12)         | (5.1,34.5)        | 47.5842410888311
-         | (-10,0)          | (1e+300,Infinity) |         Infinity
-         | (-5,-12)         | (1e+300,Infinity) |         Infinity
-         | (-3,4)           | (1e+300,Infinity) |         Infinity
-         | (0,0)            | (1e+300,Infinity) |         Infinity
-         | (1e-300,-1e-300) | (1e+300,Infinity) |         Infinity
-         | (5.1,34.5)       | (1e+300,Infinity) |         Infinity
-         | (10,10)          | (1e+300,Infinity) |         Infinity
-(27 rows)
+ fifteen |      point1       |      point2       |     distance
+---------+-------------------+-------------------+------------------
+         | (-3,4)            | (0,0)             |                5
+         | (-3,4)            | (1e-300,-1e-300)  |                5
+         | (-10,0)           | (-3,4)            | 8.06225774829855
+         | (-10,0)           | (0,0)             |               10
+         | (-10,0)           | (1e-300,-1e-300)  |               10
+         | (-10,0)           | (-5,-12)          |               13
+         | (-5,-12)          | (0,0)             |               13
+         | (-5,-12)          | (1e-300,-1e-300)  |               13
+         | (0,0)             | (10,10)           |  14.142135623731
+         | (1e-300,-1e-300)  | (10,10)           |  14.142135623731
+         | (-3,4)            | (10,10)           | 14.3178210632764
+         | (-5,-12)          | (-3,4)            | 16.1245154965971
+         | (-10,0)           | (10,10)           | 22.3606797749979
+         | (5.1,34.5)        | (10,10)           | 24.9851956166046
+         | (-5,-12)          | (10,10)           | 26.6270539113887
+         | (-3,4)            | (5.1,34.5)        | 31.5572495632937
+         | (0,0)             | (5.1,34.5)        | 34.8749193547455
+         | (1e-300,-1e-300)  | (5.1,34.5)        | 34.8749193547455
+         | (-10,0)           | (5.1,34.5)        | 37.6597928831267
+         | (-5,-12)          | (5.1,34.5)        | 47.5842410888311
+         | (-10,0)           | (1e+300,Infinity) |         Infinity
+         | (-10,0)           | (Infinity,1e+300) |         Infinity
+         | (-5,-12)          | (1e+300,Infinity) |         Infinity
+         | (-5,-12)          | (Infinity,1e+300) |         Infinity
+         | (-3,4)            | (1e+300,Infinity) |         Infinity
+         | (-3,4)            | (Infinity,1e+300) |         Infinity
+         | (0,0)             | (1e+300,Infinity) |         Infinity
+         | (0,0)             | (Infinity,1e+300) |         Infinity
+         | (1e-300,-1e-300)  | (1e+300,Infinity) |         Infinity
+         | (1e-300,-1e-300)  | (Infinity,1e+300) |         Infinity
+         | (5.1,34.5)        | (1e+300,Infinity) |         Infinity
+         | (5.1,34.5)        | (Infinity,1e+300) |         Infinity
+         | (10,10)           | (1e+300,Infinity) |         Infinity
+         | (10,10)           | (Infinity,1e+300) |         Infinity
+         | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(35 rows)

 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1
    ORDER BY distance;
- three |   point1   |      point2      |     distance
--------+------------+------------------+------------------
-       | (-3,4)     | (0,0)            |                5
-       | (-3,4)     | (1e-300,-1e-300) |                5
-       | (-10,0)    | (-5,-12)         |               13
-       | (5.1,34.5) | (10,10)          | 24.9851956166046
-(4 rows)
+ three |      point1       |      point2       |     distance
+-------+-------------------+-------------------+------------------
+       | (-3,4)            | (0,0)             |                5
+       | (-3,4)            | (1e-300,-1e-300)  |                5
+       | (-10,0)           | (-5,-12)          |               13
+       | (5.1,34.5)        | (10,10)           | 24.9851956166046
+       | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(5 rows)

 -- Test that GiST indexes provide same behavior as sequential scan
 CREATE TEMP TABLE point_gist_tbl(f1 point);
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 7f8504dbd1..6a1ca12d5c 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -21,6 +21,8 @@ INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow

 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow

+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
+
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');

 -- bad format points
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 2783985b55..78f943b960 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10890,6 +10890,23 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
     </para>
    </caution>

+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
+
    <table id="functions-geometry-func-table">
     <title>Geometric Functions</title>
     <tgroup cols="1">
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..99d149c948 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,9 @@ box_intersect(PG_FUNCTION_ARGS)

     result = (BOX *) palloc(sizeof(BOX));

-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    result->high.x = float8_min_nan(box1->high.x, box2->high.x);
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+    result->high.y = float8_min_nan(box1->high.y, box2->high.y);
     result->low.y = float8_max(box1->low.y, box2->low.y);

     PG_RETURN_BOX_P(result);
@@ -1061,6 +1061,21 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->y)))
+            result->C = get_float8_nan();
+    }
+    else if (m == 0.0)
+    {
+        /* use "mx - y + yinter = 0" */
+        result->A = 0.0;
+        result->B = -1.0;
+        result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (unlikely(isnan(pt->x)))
+            result->C = get_float8_nan();
     }
     else
     {
@@ -1084,6 +1099,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));

+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1104,8 +1120,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;

-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }

 Datum
@@ -1123,14 +1143,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);

+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));

     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1141,7 +1164,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);

-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }

 Datum
@@ -1149,7 +1172,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);

-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }


@@ -1195,9 +1218,19 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(line->A, -line->B);
 }

@@ -1209,9 +1242,19 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }

@@ -1224,14 +1267,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;

-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2)) /* intersecting? */
+    {
+        /* return NaN if NaN was involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }

-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1291,14 +1343,21 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
     }
     else if (!FPzero(l2->B))
     {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
+        /*
+         * We know that l1->B is zero, which means l1 is vertical. The lines
+         * cannot be parallel and the x-coord of the cross point is -C/A of
+         * l1.
+         */
+        x = -float8_div(l1->C, l1->A);

-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
-                       float8_mi(float8_mul(l2->A, l1->B),
-                                 float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
     }
     else
         return false;
@@ -1628,8 +1687,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
-        b1.low.y = float8_min(p1->p[i].y, b1.low.y);
+        b1.low.x = float8_min_nan(p1->p[i].x, b1.low.x);
+        b1.low.y = float8_min_nan(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;
@@ -1637,8 +1696,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
-        b2.low.y = float8_min(p2->p[i].y, b2.low.y);
+        b2.low.x = float8_min_nan(p2->p[i].x, b2.low.x);
+        b2.low.y = float8_min_nan(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
         PG_RETURN_BOOL(false);
@@ -1728,6 +1787,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);

             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1980,9 +2044,17 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }

@@ -1996,9 +2068,17 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }

@@ -2414,6 +2494,11 @@ dist_ppath_internal(Point *pt, PATH *path)

         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2645,6 +2730,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }

     return result;
@@ -2674,7 +2761,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;

     /*
@@ -2803,6 +2891,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        isnan = false;

     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2814,6 +2903,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    isnan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2823,6 +2913,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)

     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2830,6 +2921,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2837,6 +2929,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }

+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }

@@ -2873,6 +2971,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        isnan = false;

     if (box_contain_point(box, pt))
     {
@@ -2887,9 +2986,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    isnan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2901,6 +3001,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2910,6 +3011,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)

     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    isnan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2917,6 +3019,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }

+    if (unlikely(isnan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }

@@ -2988,6 +3097,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3010,6 +3120,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];

@@ -3436,6 +3554,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3911,6 +4035,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];

+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5350,6 +5479,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);

+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5359,6 +5492,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);

+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
@@ -5517,12 +5654,12 @@ pg_hypot(float8 x, float8 y)
                 result;

     /* Handle INF and NaN properly */
-    if (isinf(x) || isinf(y))
-        return get_float8_infinity();
-
-    if (isnan(x) || isnan(y))
+    if (unlikely(isnan(x) || isnan(y)))
         return get_float8_nan();

+    if (unlikely(isinf(x) || isinf(y)))
+        return get_float8_infinity();
+
     /* Else, drop any minus signs */
     x = fabs(x);
     y = fabs(y);
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 79bf8daca8..52bcf853f2 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -353,4 +353,26 @@ float8_max(const float8 val1, const float8 val2)
     return float8_gt(val1, val2) ? val1 : val2;
 }

+/*
+ * These two functions return NaN if either input is NaN, else the smaller
+ * of the two inputs.  This does NOT follow our usual sort rule, but it is
+ * convenient in some places.  (Note that float4_max and float8_max act this
+ * way anyway, so no similar variant is needed for them.)
+ */
+static inline float4
+float4_min_nan(const float4 val1, const float4 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
+static inline float8
+float8_min_nan(const float8 val1, const float8 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
 #endif                            /* FLOAT_H */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 76679bae8d..581bf414f2 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count
 -------
-     5
+     4
 (1 row)

 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 81202a4c33..20acb0b0b4 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -555,15 +555,15 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
- (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
+ (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
  (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
- (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
  (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
  (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
  (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
@@ -571,7 +571,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -653,14 +653,14 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
  (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
  (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
- (Infinity,1e+300) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |                NaN |                NaN
  (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
@@ -719,9 +719,9 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
- (Infinity,1e+300) | (2,2),(0,0)         |           Infinity |           Infinity
- (Infinity,1e+300) | (3,3),(1,1)         |           Infinity |           Infinity
- (Infinity,1e+300) | (-2,2),(-8,-10)     |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |                NaN |                NaN
+ (Infinity,1e+300) | (3,3),(1,1)         |                NaN |                NaN
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |                NaN |                NaN
  (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
@@ -805,7 +805,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
  (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
  (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
- (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
  (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
  (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
  (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
@@ -892,13 +892,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -975,15 +975,15 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               |
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              |
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |
  (1e+300,Infinity) | {3,NaN,5}                             |
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              |
  (Infinity,1e+300) | {0,-1,5}                              |
- (Infinity,1e+300) | {1,0,5}                               |
+ (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
  (Infinity,1e+300) | {0,3,0}                               |
  (Infinity,1e+300) | {1,-1,0}                              |
  (Infinity,1e+300) | {-0.4,-1,-6}                          |
@@ -991,7 +991,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (Infinity,1e+300) | {3,NaN,5}                             |
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |
  (Infinity,1e+300) | {0,-1,3}                              |
- (Infinity,1e+300) | {-1,0,3}                              |
+ (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              |
  (NaN,NaN)         | {1,0,5}                               |
  (NaN,NaN)         | {0,3,0}                               |
@@ -1073,14 +1073,14 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |
  (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
  (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
  (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
  (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
  (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
- (Infinity,1e+300) | [(0,-20),(30,-20)]            | (30,-20)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |
  (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |
  (NaN,NaN)         | [(1,2),(3,4)]                 |
  (NaN,NaN)         | [(0,0),(6,6)]                 |
@@ -1139,9 +1139,9 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
- (Infinity,1e+300) | (2,2),(0,0)         | (0,2)
- (Infinity,1e+300) | (3,3),(1,1)         | (1,3)
- (Infinity,1e+300) | (-2,2),(-8,-10)     | (-8,2)
+ (Infinity,1e+300) | (2,2),(0,0)         |
+ (Infinity,1e+300) | (3,3),(1,1)         |
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |
  (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         |
@@ -1183,12 +1183,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)

 --
 -- Lines
@@ -1276,8 +1271,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1286,8 +1281,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1296,8 +1291,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1306,8 +1301,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1316,8 +1311,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1326,38 +1321,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1366,8 +1361,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1385,31 +1380,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1417,8 +1404,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1426,46 +1411,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)

 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1506,8 +1465,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | (-5,NaN)
+ {1,0,5}                               | {NaN,NaN,NaN}                         | (-5,NaN)
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              |
  {0,3,0}                               | {0,-1,5}                              |
@@ -1586,8 +1545,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | (3,NaN)
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | (3,NaN)
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              |
 (100 rows)
@@ -3640,13 +3599,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (Infinity,1e+300) | ((0,0))                    | f
             | (Infinity,1e+300) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3716,13 +3675,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (Infinity,1e+300) | ((0,0))                    | f
             | (Infinity,1e+300) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f

Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
Thank you for the review, Georgios and Tom.

At Tue, 10 Nov 2020 14:30:08 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> I spent some time looking this over, and have a few thoughts:
> 
> 1. I think it's useful to split the test changes into two patches,
> as I've done below: first, just add the additional row in point_tbl
> and let the fallout from that happen, and then in the second patch
> make the code changes.  This way, it's much clearer what the actual
> behavioral changes are.  Some of them don't look right, either.
> For instance, in the very first hunk in geometry.out, we have
> this:
> 
> - (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
> + (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
> 
> which seems right, and also this:

For example, ('Infinity', 1e300) <-> {1,0,5}, that is:

   line "x = -5" <-> point(1e300, Inf)

So sqrt((1e300 - 5)^2 + Inf^2) = Inf, which looks right.


> - (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
> - (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
> - (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
> + (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
> + (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
> + (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
> 
> which does not.  Why aren't these distances infinite as well?
> 
> For instance, {1,-1,0} is the line "x = y".  We could argue about
> whether it'd be sensible to return zero for the distance between that
> and the point (inf,inf), but surely any point with one inf and one
> finite coordinate must be an infinite distance away from that line.
> There's nothing ill-defined about that situation.

Mmm... (swinging my arms to mimic lines..)
dist(x = y, (1e300, Inf)) looks indeterminant to me..

The calcuation is performed in the following steps.

1. construct the perpendicular line for the line.
     perpine(1e300, 'Infinity') => {-1, -1, Inf}

2. calculate the cross point.
     corsspoint({-1, -1, Inf}, {1,-1,0}) => (Inf, NaN)

3. calculte the distance from the crosspoint to the point.
     point_dt((Inf, NaN), (1e300, 'Infinity'))
   = HYPOT(Inf - 1e300, NaN - Inf);
   = HYPOT(Inf, NaN);

4. HYPOT changed the behavior by the patch

   Before: HYPOT(Inf, NaN) = Inf
   After : HYPOT(Inf, NaN) = NaN    - Result A


So if we will "fix" that, we should fix any, some, or all of 1-3.

1. seems to have no other way than the result.

2. crosspoint (x = - y + Inf, x = y)  could be (Inf, Inf)?

3.    point_dt((Inf, Inf), (1e300, Inf))
   = HYPOT(Inf - 1e300, Inf - Inf)
   = HYPOT(Inf, -NaN)
   = NaN.                           - Result B

  I'm not sure why Inf - Inf is negative, but |Inf-Inf| = NaN is
  reasonable.

That is, we don't get a "reasonable" result this way.


The formula for the distance((x0,y0) - (ax + by + c = 0)) is

  |ax0 + by0 + c|/sqrt(a^2 + b^2)

 where a = -1, b = -1, c = Inf, x0 = 1e300, y0 = Inf,

    abs(-1 * 1e300 + -1 * Inf + Inf) / sqrt(1 + 1)
  = abs(-1e300 -Inf + Inf) / C
  = NaN.                           - Result C

All of the Result A - C is NaN. At last NaN looks to be the right
result.

By the way that the formula is far simple than what we are doing
now. Is there any reason to take the above steps for the calculation?


> 2. Rather than coding around undesirable behavior of float8_min,
> it seems like it's better to add a primitive to float.h that
> does what you want, ie "NaN if either input is NaN, else the
> smaller input".  This is more readable, and possibly more efficient
> (depending on whether the compiler is smart enough to optimize
> away redundant isnan checks).  I did that in the attached.

Sounds reasonable. I found that I forgot to do the same thing to y
coordinate.

> 3. Looking for other calls of float8_min, I wonder why you did not
> touch the bounding-box calculations in box_interpt_lseg() or
> boxes_bound_box().

While doing that, I didn't make changes just by looking a code locally
since I thought that that might be looked as overdone.  Maybe, for
example box_interpt_lseg, even if bounding-box check overlooked NaNs,
I thought that the following calcualaions reflect any involved NaNs to
the result. (But I'm not confident that that is perfect, though..)

> 4. The line changes feel a bit weird, like there's no clear idea
> of what a "valid" or "invalid" line is.  For instance the first
> hunk in line_construct():
> 
> +        /* Avoid creating a valid line from an invalid point */
> +        if (unlikely(isnan(pt->y)))
> +            result->C = get_float8_nan();
> 
> Why's it appropriate to set C and only C to NaN?

Not limited to here, I intended to reduce the patch footprint as much
as possible and it seemed that only set C to NaN is sufficient. (But
I'm not con<snip..>) I don't object to make that change more
comprehensively. Do we go that direction?

> 5. But actually there's a bigger issue with that particular hunk.
> This code branch is dealing with "draw a vertical line through this
> point", so why should we care what the point's y coordinate is --- that
> is, why is this particular change appropriate at all?  The usual rule as

The calculation mess comes from omitting a part of the component
values during calculation.  So:

+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning one
+       yield an object that contain NaNs depending to the operation.  Likewise

The code is following this policy. A point containing NaN yields an
"invalid" line, that is, a line containg NaN.

> I understand it is that if a function's result is determined by some of
> its arguments independently of what another argument's value is, then it
> doesn't matter if that one is NaN, you can still return the same result.

That's true looking from pure calculation point of view, which caused
some of the messes.

> 6. I'm a bit uncomfortable with the use of "bool isnan" in a couple
> of places.  I think it's confusing to use that alongside the isnan()
> macro.  Moreover, it's at least possible that some platforms implement
> isnan() in a way that would break this usage.  The C spec specifically
> says that isnan() is a macro not a function ... but it doesn't commit
> to it being a macro-with-arguments.  I think "anynan" or something
> like that would be a better choice of name.

Ooo! Rright. I agreed to that. Will fix them.

> [ a bit later... ] Indeed, I get a compile failure on gaur:
> 
> geo_ops.c: In function 'lseg_closept_lseg':
> geo_ops.c:2906:17: error: called object 'isnan' is not a function
> geo_ops.c:2906:32: error: called object 'isnan' is not a function
> geo_ops.c:2916:16: error: called object 'isnan' is not a function
> geo_ops.c:2924:16: error: called object 'isnan' is not a function
> geo_ops.c: In function 'box_closept_point':
> geo_ops.c:2989:16: error: called object 'isnan' is not a function
> geo_ops.c:2992:16: error: called object 'isnan' is not a function
> geo_ops.c:3004:16: error: called object 'isnan' is not a function
> geo_ops.c:3014:16: error: called object 'isnan' is not a function
> make: *** [geo_ops.o] Error 1
> 
> So that scenario isn't hypothetical.  Please rename the variables.

lol! gaur looks like coal mine canary.

1. Won't fix the dist_pl/lp's changed behavior.
2. (already fixed?) Will find other instances.
3. Will do more comprehensive NaN-detection (as another patch)
4. Ditto.
5. Keep the curent state. Do we revert that?
6. Will fix.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Fri, 13 Nov 2020 15:35:58 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in 
> Thank you for the review, Georgios and Tom.
> 
> At Tue, 10 Nov 2020 14:30:08 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> > I spent some time looking this over, and have a few thoughts:
> > 
> > 1. I think it's useful to split the test changes into two patches,
> > as I've done below: first, just add the additional row in point_tbl
> > and let the fallout from that happen, and then in the second patch
> > make the code changes.  This way, it's much clearer what the actual
> > behavioral changes are.  Some of them don't look right, either.
> > For instance, in the very first hunk in geometry.out, we have
> > this:
> > 
> > - (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
> > + (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
> > 
> > which seems right, and also this:
> 
> For example, ('Infinity', 1e300) <-> {1,0,5}, that is:
> 
>    line "x = -5" <-> point(1e300, Inf)
> 
> So sqrt((1e300 - 5)^2 + Inf^2) = Inf, which looks right.

??! Correction:

 It's sqrt((1e300 - 5)^2 + 0^2) = Inf, which looks right.

reagrds.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes:
> At Tue, 10 Nov 2020 14:30:08 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
>> For instance, {1,-1,0} is the line "x = y".  We could argue about
>> whether it'd be sensible to return zero for the distance between that
>> and the point (inf,inf), but surely any point with one inf and one
>> finite coordinate must be an infinite distance away from that line.
>> There's nothing ill-defined about that situation.

> Mmm... (swinging my arms to mimic lines..)
> dist(x = y, (1e300, Inf)) looks indeterminant to me..

Well, what you're showing is that we get an internal overflow,
essentially, on the way to calculating the result.  Which is true,
so it's sort of accidental that we got a sensible result before.
Nonetheless, we *did* get a sensible result, so producing NaN
instead seems like a regression.

We might need to introduce special-case handling to protect the
low-level calculations from ever seeing NaN or Inf in their inputs.
Getting the right answer to "just fall out" of those calculations
might be an unreasonable hope.

For example, for a line with positive slope (A and B of opposite
signs), I think that the right answer for points (Inf,Inf) and
(-Inf,-Inf) should be NaN, on much the same grounds that Inf
minus Inf is NaN not zero.  But all other points involving any Inf
coordinates are clearly an infinite distance away from that line.

            regards, tom lane



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Fri, 13 Nov 2020 11:26:21 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes:
> > At Tue, 10 Nov 2020 14:30:08 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> >> For instance, {1,-1,0} is the line "x = y".  We could argue about
> >> whether it'd be sensible to return zero for the distance between that
> >> and the point (inf,inf), but surely any point with one inf and one
> >> finite coordinate must be an infinite distance away from that line.
> >> There's nothing ill-defined about that situation.
> 
> > Mmm... (swinging my arms to mimic lines..)
> > dist(x = y, (1e300, Inf)) looks indeterminant to me..
> 
> Well, what you're showing is that we get an internal overflow,
> essentially, on the way to calculating the result.  Which is true,
> so it's sort of accidental that we got a sensible result before.
> Nonetheless, we *did* get a sensible result, so producing NaN
> instead seems like a regression.

Independently from the discussion, the following was wrong.

> 2. calculate the cross point.
>      corsspoint({-1, -1, Inf}, {1,-1,0}) => (Inf, NaN)

The Corss point must be on the line 2, that is, x equas to y.  If we
avoid using x to calcualte y, the result gets right. But that doesn't
"fix" the result.

> We might need to introduce special-case handling to protect the
> low-level calculations from ever seeing NaN or Inf in their inputs.
> Getting the right answer to "just fall out" of those calculations
> might be an unreasonable hope.

However, as far as we we calculate the distance between the point and
the foot of the perpendicular line from the point to the line, (inf -
inf) is inevitable and we cannot avoid that "wrong" result.

> For example, for a line with positive slope (A and B of opposite
> signs), I think that the right answer for points (Inf,Inf) and
> (-Inf,-Inf) should be NaN, on much the same grounds that Inf
> minus Inf is NaN not zero.  But all other points involving any Inf
> coordinates are clearly an infinite distance away from that line.

After some checking I noticed that the calculation with the well-known
formula was wrong.

> The formula for the distance((x0,y0) - (ax + by + c = 0)) is
> 
>   |ax0 + by0 + c|/sqrt(a^2 + b^2)
> 
>  where a = -1, b = -1, c = Inf, x0 = 1e300, y0 = Inf,

a = -1, b = -1, c = "0", x0=1e300, y0=Inf results in Inf. Sorry for
the mistake.

So, we can recalculate the result using the formula if get NaN based
on the perpendicular foot. The reason I left the existing calculation
is the consistency between the returned perpendicular foot and the
distance value, and for the reduced complexity in the major code path.

1. So the attached yeilds "Inf" in that cases.

2. Independently from the point, I noticed that the y-coord of the
 perpendicular foot is miscalculated as NaN instead of Inf for the
 cases that are discussed here. (line_interpt_line)

3. I fixed line_construct to construct (NaN, NaN, NaN) if the input
 containsNaNs.

4. Renamed the variable "isnan" to "anynan" in lseg_closept_lseg() and
 box_closept_point().

5. (not in the past comments) line_interpt() needs to check if any of
 the coordinates is NaN since line_interpt_line() is defined to return
 such a result.

A. I'm not sure how to treat addtion/subtruct/multiply between
  points. But thinking that operations as vector calculation returning
  such values are valid. So I left them as it is.

  -- Add point
  SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
   (NaN,NaN)         | (0,0)             | (NaN,NaN)

B. @@ lseg (center) returns NaN-containing results. I'm not sure this
 is regarded whether as a vector calculation or as a geometric
 operation. If it is the former we don't fix it and otherwise we
 should reutrn NULL for such input.

  =# select @@ lseg('[(NaN,1),(NaN,90)]');
    ?column?  
  ------------
   (NaN,45.5)
  (1 row)


== Changes in the result ============

1 and 2 above cause visible diffence in some results at the least
significant digit in mantissa, but that difference doesn't matter.

> - (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690368 |      11.3851690368
> + (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690367 |      11.3851690367

1 restored the previous results.

> - (1e+300,Infinity) | {1,-1,0}                              |                NaN |                NaN
> - (1e+300,Infinity) | {-0.4,-1,-6}                          |                NaN |                NaN
> - (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
> + (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
> + (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
> + (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
> 
> 
> - (Infinity,1e+300) | [(0,-20),(30,-20)]            |                NaN |                NaN
> + (Infinity,1e+300) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
> - (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
> + (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |           Infinity |           Infinity

Looks fine.

> -- Closest point to line
> SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
> - (1e+300,Infinity) | {1,-1,0}                              | 
> - (1e+300,Infinity) | {-0.4,-1,-6}                          | 
> - (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | 
> + (1e+300,Infinity) | {1,-1,0}                              | (Infinity,Infinity)
> + (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,Infinity)
> + (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,Infinity)
> 
> -- Distance to line segment
> SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
> - (Infinity,1e+300) | [(0,-20),(30,-20)]            | 
> + (Infinity,1e+300) | [(0,-20),(30,-20)]            | (30,-20)
> 
> -- Intersection point with line
> SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
> - {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,-1.7763568394e-15)
> + {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,0)

These are fixed by 2.


> -- Distance to line
> SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TBL p, LINE_TBL l;
>  (1e+300,Infinity) | {-1,0,3}    |         NaN |                NaN

This should be 1e+300, not NaN, but 1 nor 2 doesn't fix this.  The
reasonis line->B(0) * point->y(Infinity) results in NaN.  But from the
meaning of the this sexpression, it should be 0.

I made line_closept_point() to do that but I found a similar issue in
line_interpt_line().

> -- Closest point to line
> SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
>  (1e+300,Infinity) | {1,0,5}                               | (NaN,Infinity)

So, what is needed here is we have special multiplication function
that supercedes 0*Inf = NaN rule by "0"*Inf = 0.  I introduced that
function as float8_coef_mul().  The reason that the function is in
geo_ops.c is that it is geo_ops specific and using ZPzere(), which is
not used in float.h.  By using the function the results are fixed as:

> -- Distance to line
> SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TBL p, LINE_TBL l;
>  (1e+300,Infinity) | {-1,0,3}       |       1e+300 |             1e+300
>  (Infinity,1e+300) | {0,-1,5}       |       1e+300 |             1e+300
> 
> -- Closest point to line
> SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
>  (1e+300,Infinity) | {1,0,5}                               | (-5,Infinity)

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From d6b6041f25ca8c3f4c77d5822d1dd7ac47ddaccf Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Fri, 13 Nov 2020 13:31:00 +0900
Subject: [PATCH v4 1/2] add morepoint tests

---
 src/test/regress/expected/create_index.out |  22 +-
 src/test/regress/expected/geometry.out     | 275 ++++++++++++++++++---
 src/test/regress/expected/point.out        | 138 +++++++----
 src/test/regress/sql/point.sql             |   2 +
 4 files changed, 354 insertions(+), 83 deletions(-)

diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 93a8736a3f..76679bae8d 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -157,7 +157,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count 
 -------
-     3
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
@@ -169,7 +169,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count 
 -------
-     4
+     5
 (1 row)
 
 SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
@@ -188,10 +188,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
  
-(10 rows)
+(11 rows)
 
 SELECT * FROM point_tbl WHERE f1 IS NULL;
  f1 
@@ -202,16 +203,17 @@ SELECT * FROM point_tbl WHERE f1 IS NULL;
 SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
         f1         
 -------------------
- (1e-300,-1e-300)
  (0,0)
+ (1e-300,-1e-300)
  (-3,4)
  (-10,0)
  (10,10)
  (-5,-12)
  (5.1,34.5)
  (1e+300,Infinity)
+ (Infinity,1e+300)
  (NaN,NaN)
-(9 rows)
+(10 rows)
 
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
         f1        
@@ -464,7 +466,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count 
 -------
-     3
+     4
 (1 row)
 
 EXPLAIN (COSTS OFF)
@@ -494,7 +496,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count 
 -------
-     4
+     5
 (1 row)
 
 EXPLAIN (COSTS OFF)
@@ -530,10 +532,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
  
-(10 rows)
+(11 rows)
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 IS NULL;
@@ -568,9 +571,10 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
-(9 rows)
+(10 rows)
 
 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..81202a4c33 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -120,6 +120,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          |                2.4
  (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
  (0,0)             | (1e+300,Infinity) |           Infinity
+ (0,0)             | (Infinity,1e+300) |                  0
  (0,0)             | (NaN,NaN)         |                NaN
  (0,0)             | (10,10)           |                  1
  (-10,0)           | (0,0)             |                  0
@@ -129,6 +130,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          |               -2.4
  (-10,0)           | (1e-300,-1e-300)  |                  0
  (-10,0)           | (1e+300,Infinity) |           Infinity
+ (-10,0)           | (Infinity,1e+300) |                  0
  (-10,0)           | (NaN,NaN)         |                NaN
  (-10,0)           | (10,10)           |                0.5
  (-3,4)            | (0,0)             |     -1.33333333333
@@ -138,6 +140,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          |                  8
  (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
  (-3,4)            | (1e+300,Infinity) |           Infinity
+ (-3,4)            | (Infinity,1e+300) |                  0
  (-3,4)            | (NaN,NaN)         |                NaN
  (-3,4)            | (10,10)           |     0.461538461538
  (5.1,34.5)        | (0,0)             |      6.76470588235
@@ -147,6 +150,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          |      4.60396039604
  (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
  (5.1,34.5)        | (1e+300,Infinity) |           Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |                  0
  (5.1,34.5)        | (NaN,NaN)         |                NaN
  (5.1,34.5)        | (10,10)           |                 -5
  (-5,-12)          | (0,0)             |                2.4
@@ -156,6 +160,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | 1.79769313486e+308
  (-5,-12)          | (1e-300,-1e-300)  |                2.4
  (-5,-12)          | (1e+300,Infinity) |           Infinity
+ (-5,-12)          | (Infinity,1e+300) |                  0
  (-5,-12)          | (NaN,NaN)         |                NaN
  (-5,-12)          | (10,10)           |      1.46666666667
  (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
@@ -165,6 +170,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          |                2.4
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
  (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
  (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
  (1e-300,-1e-300)  | (10,10)           |                  1
  (1e+300,Infinity) | (0,0)             |           Infinity
@@ -174,8 +180,19 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          |           Infinity
  (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
  (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
+ (1e+300,Infinity) | (Infinity,1e+300) |                NaN
  (1e+300,Infinity) | (NaN,NaN)         |                NaN
  (1e+300,Infinity) | (10,10)           |           Infinity
+ (Infinity,1e+300) | (0,0)             |                  0
+ (Infinity,1e+300) | (-10,0)           |                  0
+ (Infinity,1e+300) | (-3,4)            |                  0
+ (Infinity,1e+300) | (5.1,34.5)        |                  0
+ (Infinity,1e+300) | (-5,-12)          |                  0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
+ (Infinity,1e+300) | (1e+300,Infinity) |                NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |                  0
+ (Infinity,1e+300) | (NaN,NaN)         |                NaN
+ (Infinity,1e+300) | (10,10)           |                  0
  (NaN,NaN)         | (0,0)             |                NaN
  (NaN,NaN)         | (-10,0)           |                NaN
  (NaN,NaN)         | (-3,4)            |                NaN
@@ -183,6 +200,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          |                NaN
  (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
  (NaN,NaN)         | (1e+300,Infinity) |                NaN
+ (NaN,NaN)         | (Infinity,1e+300) |                NaN
  (NaN,NaN)         | (NaN,NaN)         |                NaN
  (NaN,NaN)         | (10,10)           |                NaN
  (10,10)           | (0,0)             |                  1
@@ -192,14 +210,15 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          |      1.46666666667
  (10,10)           | (1e-300,-1e-300)  |                  1
  (10,10)           | (1e+300,Infinity) |           Infinity
+ (10,10)           | (Infinity,1e+300) |                  0
  (10,10)           | (NaN,NaN)         |                NaN
  (10,10)           | (10,10)           | 1.79769313486e+308
-(81 rows)
+(100 rows)
 
 -- Add point
 SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |     ?column?      
--------------------+-------------------+-------------------
+        f1         |        f1         |      ?column?       
+-------------------+-------------------+---------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (-10,0)
  (0,0)             | (-3,4)            | (-3,4)
@@ -207,6 +226,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (-5,-12)
  (0,0)             | (1e-300,-1e-300)  | (1e-300,-1e-300)
  (0,0)             | (1e+300,Infinity) | (1e+300,Infinity)
+ (0,0)             | (Infinity,1e+300) | (Infinity,1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (10,10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -216,6 +236,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-15,-12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,-1e-300)
  (-10,0)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (-10,0)           | (Infinity,1e+300) | (Infinity,1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (0,10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -225,6 +246,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (-8,-8)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (1e+300,Infinity)
+ (-3,4)            | (Infinity,1e+300) | (Infinity,1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (7,14)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -234,6 +256,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (0.1,22.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (1e+300,Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (Infinity,1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (15.1,44.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -243,6 +266,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (-10,-24)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (1e+300,Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (Infinity,1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (5,-2)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -252,6 +276,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (-5,-12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (2e-300,-2e-300)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (1e+300,Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (Infinity,1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (10,10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -261,8 +286,19 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (2e+300,Infinity)
+ (1e+300,Infinity) | (Infinity,1e+300) | (Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (Infinity,2e+300)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -270,6 +306,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -279,14 +316,15 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (5,-2)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (10,10)           | (Infinity,1e+300) | (Infinity,1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (20,20)
-(81 rows)
+(100 rows)
 
 -- Subtract point
 SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |      ?column?       
--------------------+-------------------+---------------------
+        f1         |        f1         |       ?column?       
+-------------------+-------------------+----------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (10,0)
  (0,0)             | (-3,4)            | (3,-4)
@@ -294,6 +332,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (5,12)
  (0,0)             | (1e-300,-1e-300)  | (-1e-300,1e-300)
  (0,0)             | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (0,0)             | (Infinity,1e+300) | (-Infinity,-1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (-10,-10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -303,6 +342,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-5,12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,1e-300)
  (-10,0)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-10,0)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (-20,-10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -312,6 +352,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (2,16)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-3,4)            | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (-13,-6)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -321,6 +362,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (10.1,46.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (-Infinity,-1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (-4.9,24.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -330,6 +372,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (0,0)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (-15,-22)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -339,6 +382,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (5,12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (0,0)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (-Infinity,-1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (-10,-10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -348,8 +392,19 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (0,NaN)
+ (1e+300,Infinity) | (Infinity,1e+300) | (-Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (NaN,0)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -357,6 +412,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -366,9 +422,10 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (15,22)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (10,10)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (0,0)
-(81 rows)
+(100 rows)
 
 -- Multiply with point
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -388,11 +445,13 @@ SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0
  (10,10)    | (1e-300,-1e-300)  | (2e-299,0)
  (5.1,34.5) | (1e+300,Infinity) | (-Infinity,Infinity)
  (10,10)    | (1e+300,Infinity) | (-Infinity,Infinity)
+ (5.1,34.5) | (Infinity,1e+300) | (Infinity,Infinity)
+ (10,10)    | (Infinity,1e+300) | (Infinity,Infinity)
  (5.1,34.5) | (NaN,NaN)         | (NaN,NaN)
  (10,10)    | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5) | (10,10)           | (-294,396)
  (10,10)    | (10,10)           | (0,200)
-(18 rows)
+(20 rows)
 
 -- Underflow error
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] < 1;
@@ -415,11 +474,13 @@ SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0
  (1e-300,-1e-300)  | (10,10)    | (0,-1e-301)
  (1e+300,Infinity) | (5.1,34.5) | (Infinity,Infinity)
  (1e+300,Infinity) | (10,10)    | (Infinity,Infinity)
+ (Infinity,1e+300) | (5.1,34.5) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (10,10)    | (Infinity,-Infinity)
  (NaN,NaN)         | (5.1,34.5) | (NaN,NaN)
  (NaN,NaN)         | (10,10)    | (NaN,NaN)
  (10,10)           | (5.1,34.5) | (0.325588278822,-0.241724631247)
  (10,10)           | (10,10)    | (1,0)
-(18 rows)
+(20 rows)
 
 -- Overflow error
 SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0] > 1000;
@@ -501,6 +562,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -521,7 +592,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
  (10,10)           | {-1,0,3}                              |                  7 |                  7
-(90 rows)
+(100 rows)
 
 -- Distance to line segment
 SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
@@ -583,6 +654,14 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -599,7 +678,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (10,10)           | [(-10,2),(-10,3)]             |      21.1896201004 |      21.1896201004
  (10,10)           | [(0,-20),(30,-20)]            |                 30 |                 30
  (10,10)           | [(NaN,1),(NaN,90)]            |                NaN |                NaN
-(72 rows)
+(80 rows)
 
 -- Distance to box
 SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT_TBL p, BOX_TBL b;
@@ -640,6 +719,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(1,1)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |           Infinity |           Infinity
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -650,7 +734,7 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (10,10)           | (-2,2),(-8,-10)     |      14.4222051019 |      14.4222051019
  (10,10)           | (2.5,3.5),(2.5,2.5) |      9.92471662064 |      9.92471662064
  (10,10)           | (3,3),(3,3)         |      9.89949493661 |      9.89949493661
-(45 rows)
+(50 rows)
 
 -- Distance to path
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp FROM POINT_TBL p, PATH_TBL p1;
@@ -719,6 +803,15 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((10,20))                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,12),(13,14)]         |           Infinity |           Infinity
+ (Infinity,1e+300) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
  (NaN,NaN)         | ((1,2),(3,4))             |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
@@ -737,7 +830,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (10,10)           | ((10,20))                 |                 10 |                 10
  (10,10)           | [(11,12),(13,14)]         |       2.2360679775 |       2.2360679775
  (10,10)           | ((11,12),(13,14))         |       2.2360679775 |       2.2360679775
-(81 rows)
+(90 rows)
 
 -- Distance to polygon
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp FROM POINT_TBL p, POLYGON_TBL p1;
@@ -792,6 +885,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
+ (Infinity,1e+300) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
  (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
  (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
  (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
@@ -806,7 +906,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | 3.60555127546 | 3.60555127546
  (10,10)           | ((0,0))                    | 14.1421356237 | 14.1421356237
  (10,10)           | ((0,1),(0,1))              | 13.4536240471 | 13.4536240471
-(63 rows)
+(70 rows)
 
 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -882,6 +982,16 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              | 
+ (Infinity,1e+300) | {0,-1,5}                              | 
+ (Infinity,1e+300) | {1,0,5}                               | 
+ (Infinity,1e+300) | {0,3,0}                               | 
+ (Infinity,1e+300) | {1,-1,0}                              | 
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | 
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (Infinity,1e+300) | {3,NaN,5}                             | 
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
+ (Infinity,1e+300) | {0,-1,3}                              | 
+ (Infinity,1e+300) | {-1,0,3}                              | 
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
  (NaN,NaN)         | {0,3,0}                               | 
@@ -902,7 +1012,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (10,10)           | {NaN,NaN,NaN}                         | 
  (10,10)           | {0,-1,3}                              | (10,3)
  (10,10)           | {-1,0,3}                              | (3,10)
-(90 rows)
+(100 rows)
 
 -- Closest point to line segment
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
@@ -964,6 +1074,14 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
+ (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
+ (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            | (30,-20)
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            | 
  (NaN,NaN)         | [(1,2),(3,4)]                 | 
  (NaN,NaN)         | [(0,0),(6,6)]                 | 
  (NaN,NaN)         | [(10,-10),(-3,-4)]            | 
@@ -980,7 +1098,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (10,10)           | [(-10,2),(-10,3)]             | (-10,3)
  (10,10)           | [(0,-20),(30,-20)]            | (10,-20)
  (10,10)           | [(NaN,1),(NaN,90)]            | 
-(72 rows)
+(80 rows)
 
 -- Closest point to box
 SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
@@ -1021,6 +1139,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (Infinity,1e+300) | (2,2),(0,0)         | (0,2)
+ (Infinity,1e+300) | (3,3),(1,1)         | (1,3)
+ (Infinity,1e+300) | (-2,2),(-8,-10)     | (-8,2)
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
+ (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         | 
  (NaN,NaN)         | (3,3),(1,1)         | 
  (NaN,NaN)         | (-2,2),(-8,-10)     | 
@@ -1031,7 +1154,7 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (10,10)           | (-2,2),(-8,-10)     | (-2,2)
  (10,10)           | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (10,10)           | (3,3),(3,3)         | (3,3)
-(45 rows)
+(50 rows)
 
 -- On line
 SELECT p.f1, l.s FROM POINT_TBL p, LINE_TBL l WHERE p.f1 <@ l.s;
@@ -2347,6 +2470,11 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2357,7 +2485,7 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (8,12),(2,0)
             | (12.5,13.5),(12.5,12.5)
             | (13,13),(13,13)
-(45 rows)
+(50 rows)
 
 SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
    FROM BOX_TBL b, POINT_TBL p;
@@ -2398,6 +2526,11 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2408,7 +2541,7 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-12,-8),(-18,-20)
             | (-7.5,-6.5),(-7.5,-7.5)
             | (-7,-7),(-7,-7)
-(45 rows)
+(50 rows)
 
 -- Multiply with point
 SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2431,16 +2564,21 @@ SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] > 1000;
          f1          |        f1         |                  ?column?                  
 ---------------------+-------------------+--------------------------------------------
  (2,2),(0,0)         | (1e+300,Infinity) | (NaN,NaN),(-Infinity,Infinity)
+ (2,2),(0,0)         | (Infinity,1e+300) | (NaN,NaN),(Infinity,Infinity)
  (2,2),(0,0)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(1,1)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(1,1)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(1,1)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (-2,2),(-8,-10)     | (1e+300,Infinity) | (Infinity,-Infinity),(-Infinity,-Infinity)
+ (-2,2),(-8,-10)     | (Infinity,1e+300) | (-Infinity,Infinity),(-Infinity,-Infinity)
  (-2,2),(-8,-10)     | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (2.5,3.5),(2.5,2.5) | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (2.5,3.5),(2.5,2.5) | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (2.5,3.5),(2.5,2.5) | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(3,3)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(3,3)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(3,3)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
-(10 rows)
+(15 rows)
 
 -- Divide by point
 SELECT b.f1, p.f1, b.f1 / p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2470,9 +2608,10 @@ SELECT f1::box
  (-5,-12),(-5,-12)
  (1e-300,-1e-300),(1e-300,-1e-300)
  (1e+300,Infinity),(1e+300,Infinity)
+ (Infinity,1e+300),(Infinity,1e+300)
  (NaN,NaN),(NaN,NaN)
  (10,10),(10,10)
-(9 rows)
+(10 rows)
 
 SELECT bound_box(a.f1, b.f1)
     FROM BOX_TBL a, BOX_TBL b;
@@ -3102,6 +3241,15 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((1e+300,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(1e+300,Infinity),(1e+300,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((1e+300,Infinity),(1e+300,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3120,7 +3268,7 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((20,30))
  [(11,12),(13,14)]         | (10,10)           | [(21,22),(23,24)]
  ((11,12),(13,14))         | (10,10)           | ((21,22),(23,24))
-(81 rows)
+(90 rows)
 
 -- Subtract point
 SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3189,6 +3337,15 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-1e+300,-Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-1e+300,-Infinity),(-1e+300,-Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-1e+300,-Infinity),(-1e+300,-Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((-Infinity,-1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3207,7 +3364,7 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((0,10))
  [(11,12),(13,14)]         | (10,10)           | [(1,2),(3,4)]
  ((11,12),(13,14))         | (10,10)           | ((1,2),(3,4))
-(81 rows)
+(90 rows)
 
 -- Multiply with point
 SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3276,6 +3433,15 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-Infinity,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-Infinity,Infinity),(-Infinity,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-Infinity,Infinity),(-Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) | [(NaN,NaN),(Infinity,NaN),(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,Infinity))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3294,7 +3460,7 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((-100,300))
  [(11,12),(13,14)]         | (10,10)           | [(-10,230),(-10,270)]
  ((11,12),(13,14))         | (10,10)           | ((-10,230),(-10,270))
-(81 rows)
+(90 rows)
 
 -- Divide by point
 SELECT p.f1, p1.f1, p.f1 / p1.f1 FROM PATH_TBL p, POINT_TBL p1 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -3467,6 +3633,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3481,7 +3654,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)
 
 SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
    FROM POLYGON_TBL poly, POINT_TBL p;
@@ -3536,6 +3709,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3550,7 +3730,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)
 
 SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon
    FROM POLYGON_TBL;
@@ -3929,9 +4109,10 @@ SELECT '' AS six, circle(f1, 50.0)
      | <(-5,-12),50>
      | <(1e-300,-1e-300),50>
      | <(1e+300,Infinity),50>
+     | <(Infinity,1e+300),50>
      | <(NaN,NaN),50>
      | <(10,10),50>
-(9 rows)
+(10 rows)
 
 SELECT '' AS four, circle(f1)
    FROM BOX_TBL;
@@ -3993,12 +4174,19 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(100,200),10> | (-10,0)           |  218.25424421
             | <(100,200),10> | (-5,-12)          | 226.577682802
             | <(3,5),0>      | (1e+300,Infinity) |      Infinity
+            | <(3,5),0>      | (Infinity,1e+300) |      Infinity
             | <(1,2),3>      | (1e+300,Infinity) |      Infinity
             | <(5,1),3>      | (1e+300,Infinity) |      Infinity
+            | <(5,1),3>      | (Infinity,1e+300) |      Infinity
+            | <(1,2),3>      | (Infinity,1e+300) |      Infinity
             | <(1,3),5>      | (1e+300,Infinity) |      Infinity
+            | <(1,3),5>      | (Infinity,1e+300) |      Infinity
             | <(100,200),10> | (1e+300,Infinity) |      Infinity
+            | <(100,200),10> | (Infinity,1e+300) |      Infinity
             | <(1,2),100>    | (1e+300,Infinity) |      Infinity
+            | <(1,2),100>    | (Infinity,1e+300) |      Infinity
             | <(100,1),115>  | (1e+300,Infinity) |      Infinity
+            | <(100,1),115>  | (Infinity,1e+300) |      Infinity
             | <(3,5),0>      | (NaN,NaN)         |           NaN
             | <(1,2),3>      | (NaN,NaN)         |           NaN
             | <(5,1),3>      | (NaN,NaN)         |           NaN
@@ -4014,8 +4202,9 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(3,5),NaN>    | (5.1,34.5)        |           NaN
             | <(3,5),NaN>    | (10,10)           |           NaN
             | <(3,5),NaN>    | (1e+300,Infinity) |           NaN
+            | <(3,5),NaN>    | (Infinity,1e+300) |           NaN
             | <(3,5),NaN>    | (NaN,NaN)         |           NaN
-(53 rows)
+(61 rows)
 
 -- To polygon
 SELECT f1, f1::polygon FROM CIRCLE_TBL WHERE f1 >= '<(0,0),1>';
@@ -4626,6 +4815,14 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(1e+300,Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(1e+300,Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(1e+300,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4642,7 +4839,7 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(110,11),115>
  <(3,5),0>      | (10,10)           | <(13,15),0>
  <(3,5),NaN>    | (10,10)           | <(13,15),NaN>
-(72 rows)
+(80 rows)
 
 -- Subtract point
 SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4704,6 +4901,14 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-1e+300,-Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(-1e+300,-Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-1e+300,-Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(-Infinity,-1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(-Infinity,-1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(-Infinity,-1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(-Infinity,-1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(-Infinity,-1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(-Infinity,-1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4720,7 +4925,7 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(90,-9),115>
  <(3,5),0>      | (10,10)           | <(-7,-5),0>
  <(3,5),NaN>    | (10,10)           | <(-7,-5),NaN>
-(72 rows)
+(80 rows)
 
 -- Multiply with point
 SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4782,6 +4987,14 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-Infinity,Infinity),Infinity>
  <(3,5),0>      | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),NaN>
@@ -4798,7 +5011,7 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(990,1010),1626.34559673>
  <(3,5),0>      | (10,10)           | <(-20,80),0>
  <(3,5),NaN>    | (10,10)           | <(-20,80),NaN>
-(72 rows)
+(80 rows)
 
 -- Divide by point
 SELECT c.f1, p.f1, c.f1 / p.f1 FROM CIRCLE_TBL c, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 15e3b83b37..77e250fc3e 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -11,6 +11,7 @@ INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 -- bad format points
 INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
@@ -44,9 +45,10 @@ SELECT '' AS six, * FROM POINT_TBL;
      | (-5,-12)
      | (1e-300,-1e-300)
      | (1e+300,Infinity)
+     | (Infinity,1e+300)
      | (NaN,NaN)
      | (10,10)
-(9 rows)
+(10 rows)
 
 -- left of
 SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)';
@@ -115,8 +117,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)
 
 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -136,8 +139,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)
 
 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
@@ -152,8 +156,9 @@ SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
      | (10,10)           |      14.142135623731
      | (5.1,34.5)        |     34.8749193547455
      | (1e+300,Infinity) |             Infinity
+     | (Infinity,1e+300) |             Infinity
      | (NaN,NaN)         |                  NaN
-(9 rows)
+(10 rows)
 
 SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist
    FROM POINT_TBL p1, POINT_TBL p2
@@ -210,12 +215,19 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (-5,-12)          | (5.1,34.5)        |     47.5842410888311
            | (5.1,34.5)        | (-5,-12)          |     47.5842410888311
            | (-10,0)           | (1e+300,Infinity) |             Infinity
+           | (-10,0)           | (Infinity,1e+300) |             Infinity
            | (-5,-12)          | (1e+300,Infinity) |             Infinity
+           | (-5,-12)          | (Infinity,1e+300) |             Infinity
            | (-3,4)            | (1e+300,Infinity) |             Infinity
+           | (-3,4)            | (Infinity,1e+300) |             Infinity
            | (0,0)             | (1e+300,Infinity) |             Infinity
+           | (0,0)             | (Infinity,1e+300) |             Infinity
            | (1e-300,-1e-300)  | (1e+300,Infinity) |             Infinity
+           | (1e-300,-1e-300)  | (Infinity,1e+300) |             Infinity
            | (5.1,34.5)        | (1e+300,Infinity) |             Infinity
+           | (5.1,34.5)        | (Infinity,1e+300) |             Infinity
            | (10,10)           | (1e+300,Infinity) |             Infinity
+           | (10,10)           | (Infinity,1e+300) |             Infinity
            | (1e+300,Infinity) | (-10,0)           |             Infinity
            | (1e+300,Infinity) | (-5,-12)          |             Infinity
            | (1e+300,Infinity) | (-3,4)            |             Infinity
@@ -223,6 +235,15 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (1e+300,Infinity) | (1e-300,-1e-300)  |             Infinity
            | (1e+300,Infinity) | (5.1,34.5)        |             Infinity
            | (1e+300,Infinity) | (10,10)           |             Infinity
+           | (1e+300,Infinity) | (Infinity,1e+300) |             Infinity
+           | (Infinity,1e+300) | (-10,0)           |             Infinity
+           | (Infinity,1e+300) | (-5,-12)          |             Infinity
+           | (Infinity,1e+300) | (-3,4)            |             Infinity
+           | (Infinity,1e+300) | (0,0)             |             Infinity
+           | (Infinity,1e+300) | (1e-300,-1e-300)  |             Infinity
+           | (Infinity,1e+300) | (5.1,34.5)        |             Infinity
+           | (Infinity,1e+300) | (10,10)           |             Infinity
+           | (Infinity,1e+300) | (1e+300,Infinity) |             Infinity
            | (-10,0)           | (NaN,NaN)         |                  NaN
            | (-5,-12)          | (NaN,NaN)         |                  NaN
            | (-3,4)            | (NaN,NaN)         |                  NaN
@@ -232,6 +253,8 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (10,10)           | (NaN,NaN)         |                  NaN
            | (1e+300,Infinity) | (1e+300,Infinity) |                  NaN
            | (1e+300,Infinity) | (NaN,NaN)         |                  NaN
+           | (Infinity,1e+300) | (Infinity,1e+300) |                  NaN
+           | (Infinity,1e+300) | (NaN,NaN)         |                  NaN
            | (NaN,NaN)         | (-10,0)           |                  NaN
            | (NaN,NaN)         | (-5,-12)          |                  NaN
            | (NaN,NaN)         | (-3,4)            |                  NaN
@@ -240,8 +263,9 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (NaN,NaN)         | (5.1,34.5)        |                  NaN
            | (NaN,NaN)         | (10,10)           |                  NaN
            | (NaN,NaN)         | (1e+300,Infinity) |                  NaN
+           | (NaN,NaN)         | (Infinity,1e+300) |                  NaN
            | (NaN,NaN)         | (NaN,NaN)         |                  NaN
-(81 rows)
+(100 rows)
 
 SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
    FROM POINT_TBL p1, POINT_TBL p2
@@ -253,6 +277,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (0,0)             | (5.1,34.5)
         | (0,0)             | (-5,-12)
         | (0,0)             | (1e+300,Infinity)
+        | (0,0)             | (Infinity,1e+300)
         | (0,0)             | (NaN,NaN)
         | (0,0)             | (10,10)
         | (-10,0)           | (0,0)
@@ -261,6 +286,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-10,0)           | (-5,-12)
         | (-10,0)           | (1e-300,-1e-300)
         | (-10,0)           | (1e+300,Infinity)
+        | (-10,0)           | (Infinity,1e+300)
         | (-10,0)           | (NaN,NaN)
         | (-10,0)           | (10,10)
         | (-3,4)            | (0,0)
@@ -269,6 +295,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-3,4)            | (-5,-12)
         | (-3,4)            | (1e-300,-1e-300)
         | (-3,4)            | (1e+300,Infinity)
+        | (-3,4)            | (Infinity,1e+300)
         | (-3,4)            | (NaN,NaN)
         | (-3,4)            | (10,10)
         | (5.1,34.5)        | (0,0)
@@ -277,6 +304,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (5.1,34.5)        | (-5,-12)
         | (5.1,34.5)        | (1e-300,-1e-300)
         | (5.1,34.5)        | (1e+300,Infinity)
+        | (5.1,34.5)        | (Infinity,1e+300)
         | (5.1,34.5)        | (NaN,NaN)
         | (5.1,34.5)        | (10,10)
         | (-5,-12)          | (0,0)
@@ -285,6 +313,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-5,-12)          | (5.1,34.5)
         | (-5,-12)          | (1e-300,-1e-300)
         | (-5,-12)          | (1e+300,Infinity)
+        | (-5,-12)          | (Infinity,1e+300)
         | (-5,-12)          | (NaN,NaN)
         | (-5,-12)          | (10,10)
         | (1e-300,-1e-300)  | (-10,0)
@@ -292,6 +321,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e-300,-1e-300)  | (5.1,34.5)
         | (1e-300,-1e-300)  | (-5,-12)
         | (1e-300,-1e-300)  | (1e+300,Infinity)
+        | (1e-300,-1e-300)  | (Infinity,1e+300)
         | (1e-300,-1e-300)  | (NaN,NaN)
         | (1e-300,-1e-300)  | (10,10)
         | (1e+300,Infinity) | (0,0)
@@ -301,8 +331,19 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e+300,Infinity) | (-5,-12)
         | (1e+300,Infinity) | (1e-300,-1e-300)
         | (1e+300,Infinity) | (1e+300,Infinity)
+        | (1e+300,Infinity) | (Infinity,1e+300)
         | (1e+300,Infinity) | (NaN,NaN)
         | (1e+300,Infinity) | (10,10)
+        | (Infinity,1e+300) | (0,0)
+        | (Infinity,1e+300) | (-10,0)
+        | (Infinity,1e+300) | (-3,4)
+        | (Infinity,1e+300) | (5.1,34.5)
+        | (Infinity,1e+300) | (-5,-12)
+        | (Infinity,1e+300) | (1e-300,-1e-300)
+        | (Infinity,1e+300) | (1e+300,Infinity)
+        | (Infinity,1e+300) | (Infinity,1e+300)
+        | (Infinity,1e+300) | (NaN,NaN)
+        | (Infinity,1e+300) | (10,10)
         | (NaN,NaN)         | (0,0)
         | (NaN,NaN)         | (-10,0)
         | (NaN,NaN)         | (-3,4)
@@ -310,6 +351,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (NaN,NaN)         | (-5,-12)
         | (NaN,NaN)         | (1e-300,-1e-300)
         | (NaN,NaN)         | (1e+300,Infinity)
+        | (NaN,NaN)         | (Infinity,1e+300)
         | (NaN,NaN)         | (NaN,NaN)
         | (NaN,NaN)         | (10,10)
         | (10,10)           | (0,0)
@@ -319,57 +361,67 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (10,10)           | (-5,-12)
         | (10,10)           | (1e-300,-1e-300)
         | (10,10)           | (1e+300,Infinity)
+        | (10,10)           | (Infinity,1e+300)
         | (10,10)           | (NaN,NaN)
-(72 rows)
+(91 rows)
 
 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1
    ORDER BY distance, p1.f1[0], p2.f1[0];
- fifteen |      point1      |      point2       |     distance     
----------+------------------+-------------------+------------------
-         | (-3,4)           | (0,0)             |                5
-         | (-3,4)           | (1e-300,-1e-300)  |                5
-         | (-10,0)          | (-3,4)            | 8.06225774829855
-         | (-10,0)          | (0,0)             |               10
-         | (-10,0)          | (1e-300,-1e-300)  |               10
-         | (-10,0)          | (-5,-12)          |               13
-         | (-5,-12)         | (0,0)             |               13
-         | (-5,-12)         | (1e-300,-1e-300)  |               13
-         | (0,0)            | (10,10)           |  14.142135623731
-         | (1e-300,-1e-300) | (10,10)           |  14.142135623731
-         | (-3,4)           | (10,10)           | 14.3178210632764
-         | (-5,-12)         | (-3,4)            | 16.1245154965971
-         | (-10,0)          | (10,10)           | 22.3606797749979
-         | (5.1,34.5)       | (10,10)           | 24.9851956166046
-         | (-5,-12)         | (10,10)           | 26.6270539113887
-         | (-3,4)           | (5.1,34.5)        | 31.5572495632937
-         | (0,0)            | (5.1,34.5)        | 34.8749193547455
-         | (1e-300,-1e-300) | (5.1,34.5)        | 34.8749193547455
-         | (-10,0)          | (5.1,34.5)        | 37.6597928831267
-         | (-5,-12)         | (5.1,34.5)        | 47.5842410888311
-         | (-10,0)          | (1e+300,Infinity) |         Infinity
-         | (-5,-12)         | (1e+300,Infinity) |         Infinity
-         | (-3,4)           | (1e+300,Infinity) |         Infinity
-         | (0,0)            | (1e+300,Infinity) |         Infinity
-         | (1e-300,-1e-300) | (1e+300,Infinity) |         Infinity
-         | (5.1,34.5)       | (1e+300,Infinity) |         Infinity
-         | (10,10)          | (1e+300,Infinity) |         Infinity
-(27 rows)
+ fifteen |      point1       |      point2       |     distance     
+---------+-------------------+-------------------+------------------
+         | (-3,4)            | (0,0)             |                5
+         | (-3,4)            | (1e-300,-1e-300)  |                5
+         | (-10,0)           | (-3,4)            | 8.06225774829855
+         | (-10,0)           | (0,0)             |               10
+         | (-10,0)           | (1e-300,-1e-300)  |               10
+         | (-10,0)           | (-5,-12)          |               13
+         | (-5,-12)          | (0,0)             |               13
+         | (-5,-12)          | (1e-300,-1e-300)  |               13
+         | (0,0)             | (10,10)           |  14.142135623731
+         | (1e-300,-1e-300)  | (10,10)           |  14.142135623731
+         | (-3,4)            | (10,10)           | 14.3178210632764
+         | (-5,-12)          | (-3,4)            | 16.1245154965971
+         | (-10,0)           | (10,10)           | 22.3606797749979
+         | (5.1,34.5)        | (10,10)           | 24.9851956166046
+         | (-5,-12)          | (10,10)           | 26.6270539113887
+         | (-3,4)            | (5.1,34.5)        | 31.5572495632937
+         | (0,0)             | (5.1,34.5)        | 34.8749193547455
+         | (1e-300,-1e-300)  | (5.1,34.5)        | 34.8749193547455
+         | (-10,0)           | (5.1,34.5)        | 37.6597928831267
+         | (-5,-12)          | (5.1,34.5)        | 47.5842410888311
+         | (-10,0)           | (1e+300,Infinity) |         Infinity
+         | (-10,0)           | (Infinity,1e+300) |         Infinity
+         | (-5,-12)          | (1e+300,Infinity) |         Infinity
+         | (-5,-12)          | (Infinity,1e+300) |         Infinity
+         | (-3,4)            | (1e+300,Infinity) |         Infinity
+         | (-3,4)            | (Infinity,1e+300) |         Infinity
+         | (0,0)             | (1e+300,Infinity) |         Infinity
+         | (0,0)             | (Infinity,1e+300) |         Infinity
+         | (1e-300,-1e-300)  | (1e+300,Infinity) |         Infinity
+         | (1e-300,-1e-300)  | (Infinity,1e+300) |         Infinity
+         | (5.1,34.5)        | (1e+300,Infinity) |         Infinity
+         | (5.1,34.5)        | (Infinity,1e+300) |         Infinity
+         | (10,10)           | (1e+300,Infinity) |         Infinity
+         | (10,10)           | (Infinity,1e+300) |         Infinity
+         | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(35 rows)
 
 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1
    ORDER BY distance;
- three |   point1   |      point2      |     distance     
--------+------------+------------------+------------------
-       | (-3,4)     | (0,0)            |                5
-       | (-3,4)     | (1e-300,-1e-300) |                5
-       | (-10,0)    | (-5,-12)         |               13
-       | (5.1,34.5) | (10,10)          | 24.9851956166046
-(4 rows)
+ three |      point1       |      point2       |     distance     
+-------+-------------------+-------------------+------------------
+       | (-3,4)            | (0,0)             |                5
+       | (-3,4)            | (1e-300,-1e-300)  |                5
+       | (-10,0)           | (-5,-12)          |               13
+       | (5.1,34.5)        | (10,10)           | 24.9851956166046
+       | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(5 rows)
 
 -- Test that GiST indexes provide same behavior as sequential scan
 CREATE TEMP TABLE point_gist_tbl(f1 point);
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 7f8504dbd1..6a1ca12d5c 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -21,6 +21,8 @@ INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
 
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
+
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 
 -- bad format points
-- 
2.18.4

From 9d11d6781e02ab6d06db2854d1eb963b5b72f943 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Fri, 13 Nov 2020 13:31:20 +0900
Subject: [PATCH v4 2/2] fix geometric nan handling

---
 doc/src/sgml/func.sgml                     |  17 +
 src/backend/utils/adt/geo_ops.c            | 300 +++++++++++--
 src/include/utils/float.h                  |  22 +
 src/test/regress/expected/create_index.out |   2 +-
 src/test/regress/expected/geometry.out     | 463 ++++++++++-----------
 5 files changed, 511 insertions(+), 293 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7c7d177c02..9ecb0bdfcc 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10896,6 +10896,23 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
     </para>
    </caution>
 
+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
+
    <table id="functions-geometry-func-table">
     <title>Geometric Functions</title>
     <tgroup cols="1">
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..eaf4528b30 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -159,6 +159,38 @@ static char *path_encode(enum path_delim path_delim, int npts, Point *pt);
 #define LDELIM_L        '{'
 #define RDELIM_L        '}'
 
+/*
+ * Float multiplication, but "0"*Inf is calculated as 0, not NaN, only when
+ * val1 is FPzero(). val1 is assued to be one of the coefficients of a line,
+ * specifically A or B. if both is true, val2 is treaded the same way as val1.
+ */
+static inline float8
+float8_coef_mul(const float8 val1, const float8 val2, bool both)
+{
+    float8        result;
+
+    if (FPzero(val1))
+    {
+        if (isnan(val2))
+            return get_float8_nan();
+        return 0.0;
+    }
+
+    if (both && FPzero(val2))
+    {
+        if (isnan(val1))
+            return get_float8_nan();
+        return 0.0;
+    }
+
+    result = val1 * val2;
+    if (unlikely(isinf(result)) && !isinf(val1) && !isinf(val2))
+        float_overflow_error();
+    if (unlikely(result == 0.0) && val1 != 0.0 && val2 != 0.0)
+        float_underflow_error();
+
+    return result;
+}
 
 /*
  * Geometric data types are composed of points.
@@ -904,9 +936,9 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    result->high.x = float8_min_nan(box1->high.x, box2->high.x);
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+    result->high.y = float8_min_nan(box1->high.y, box2->high.y);
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,8 +1093,23 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else
+    else if (m == 0.0)
+    {
+        /* use "mx - y + yinter = 0" */
+        result->A = 0.0;
+        result->B = -1.0;
+        result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
+    }
+    else if (!isnan(m))
     {
         /* use "mx - y + yinter = 0" */
         result->A = m;
@@ -1071,7 +1118,12 @@ line_construct(LINE *result, Point *pt, float8 m)
         /* on some platforms, the preceding expression tends to produce -0 */
         if (result->C == 0.0)
             result->C = 0.0;
+
+        if (likely(!isnan(result->C)))
+            return;
     }
+
+    result->A = result->B = result->C = get_float8_nan();
 }
 
 /* line_construct_pp()
@@ -1084,6 +1136,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1104,8 +1157,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1123,14 +1180,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1141,7 +1201,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1149,7 +1209,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1195,9 +1255,19 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(line->A, -line->B);
 }
 
@@ -1209,9 +1279,19 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1224,14 +1304,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2)) /* intersecting? */
+    {
+        /* return NaN if NaN was involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1253,8 +1342,13 @@ line_interpt(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (!line_interpt_line(result, l1, l2))
+    if (!line_interpt_line(result, l1, l2) ||
+        isnan(result->x) || isnan(result->y))
+    {
+        pfree(result);
         PG_RETURN_NULL();
+    }
+
     PG_RETURN_POINT_P(result);
 }
 
@@ -1283,22 +1377,39 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
         if (FPeq(l2->A, float8_mul(l1->A, float8_div(l2->B, l1->B))))
             return false;
 
-        x = float8_div(float8_mi(float8_mul(l1->B, l2->C),
-                                 float8_mul(l2->B, l1->C)),
-                       float8_mi(float8_mul(l1->A, l2->B),
-                                 float8_mul(l2->A, l1->B)));
-        y = float8_div(-float8_pl(float8_mul(l1->A, x), l1->C), l1->B);
+        x = float8_div(float8_mi(float8_coef_mul(l1->B, l2->C, false),
+                                 float8_coef_mul(l2->B, l1->C, false)),
+                       float8_mi(float8_coef_mul(l1->A, l2->B, true),
+                                 float8_coef_mul(l2->A, l1->B, true)));
+        /*
+         * You might want to simplify this expression by using x, but that can
+         * introduce unnecessary indeterminants (inf-inf) into the calculation,
+         * which leads to a wrong result.
+         * (For example, (-1, -1, Inf) and (1, -1, 0))
+         */
+        y = float8_div(float8_mi(float8_coef_mul(l1->A, l2->C, false),
+                                 float8_coef_mul(l2->A, l1->C, false)),
+                       float8_mi(float8_coef_mul(l2->A, l1->B, true),
+                                 float8_coef_mul(l1->A, l2->B, true)));
     }
     else if (!FPzero(l2->B))
     {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
+        /*
+         * We know that l1->B is zero, which means l1 is vertical. The lines
+         * cannot be parallel and the x-coord of the cross point is -C/A of
+         * l1.
+         */
+        x = -float8_div(l1->C, l1->A);
 
-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
-                       float8_mi(float8_mul(l2->A, l1->B),
-                                 float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_coef_mul(l2->A, x, false), l2->C),
+                           l2->B);
     }
     else
         return false;
@@ -1628,8 +1739,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
-        b1.low.y = float8_min(p1->p[i].y, b1.low.y);
+        b1.low.x = float8_min_nan(p1->p[i].x, b1.low.x);
+        b1.low.y = float8_min_nan(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;
@@ -1637,8 +1748,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
-        b2.low.y = float8_min(p2->p[i].y, b2.low.y);
+        b2.low.x = float8_min_nan(p2->p[i].x, b2.low.x);
+        b2.low.y = float8_min_nan(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
         PG_RETURN_BOOL(false);
@@ -1728,6 +1839,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1980,9 +2096,17 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -1996,9 +2120,17 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return DBL_MAX;
+    }
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2414,6 +2546,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2645,6 +2782,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2674,7 +2813,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2716,6 +2856,7 @@ line_closept_point(Point *result, LINE *line, Point *point)
 {
     Point        closept;
     LINE        tmp;
+    float8        distance;
 
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
@@ -2734,7 +2875,36 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (result != NULL)
         *result = closept;
 
-    return point_dt(&closept, point);
+    distance = point_dt(&closept, point);
+
+    if (likely(!isnan(distance)))
+        return point_dt(&closept, point);
+
+    /*
+     * We may have Inf's in the two points that results in NaN wrongly. Try
+     * re-calculate the distance not using the corsspoint.
+     *
+     * | a*x0 + b*y0 + c | / sqrt(a^2 + b^2)
+     *
+     * We could avoid that calcualtion in the cases where that is apparently
+     * useless, but we don't bother checking that since the chances we get here
+     * are relatively rare.
+     */
+
+    /*
+     * But in some further special cases where A = 0 or B = 0, x and y
+     * correspondingly is completely irrelevant but that terms may yeild
+     * unwanted result. Avoid such results to be resulted by removing the
+     * ignorable terms in the expression in those cases. So use
+     * float8_coef_mul() instead of float8_mul().
+     */
+
+    return float8_div(fabs(float8_pl(
+                               float8_pl(
+                                   float8_coef_mul(line->A, point->x, false),
+                                   float8_coef_mul(line->B, point->y, false)),
+                               line->C)),
+                      HYPOT(line->A, line->B));
 }
 
 Datum
@@ -2803,6 +2973,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        anynan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2814,6 +2985,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    anynan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2823,6 +2995,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2830,6 +3003,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2837,6 +3011,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2873,6 +3053,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        anynan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2887,9 +3068,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    anynan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2901,6 +3083,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2910,6 +3093,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2917,6 +3101,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -2988,6 +3179,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3010,6 +3202,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3135,9 +3335,10 @@ close_lb(PG_FUNCTION_ARGS)
 static bool
 line_contain_point(LINE *line, Point *point)
 {
-    return FPzero(float8_pl(float8_pl(float8_mul(line->A, point->x),
-                                      float8_mul(line->B, point->y)),
-                            line->C));
+    return FPzero(float8_pl(
+                      float8_pl(float8_coef_mul(line->A, point->x, false),
+                                float8_coef_mul(line->B, point->y, false)),
+                      line->C));
 }
 
 Datum
@@ -3436,6 +3637,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3911,6 +4118,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5350,6 +5562,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5359,6 +5575,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
@@ -5517,12 +5737,12 @@ pg_hypot(float8 x, float8 y)
                 result;
 
     /* Handle INF and NaN properly */
-    if (isinf(x) || isinf(y))
+    if (unlikely(isnan(x) || isnan(y)))
+        return get_float8_nan();
+
+    if (unlikely(isinf(x) || isinf(y)))
         return get_float8_infinity();
 
-    if (isnan(x) || isnan(y))
-        return get_float8_nan();
-
     /* Else, drop any minus signs */
     x = fabs(x);
     y = fabs(y);
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 79bf8daca8..52bcf853f2 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -353,4 +353,26 @@ float8_max(const float8 val1, const float8 val2)
     return float8_gt(val1, val2) ? val1 : val2;
 }
 
+/*
+ * These two functions return NaN if either input is NaN, else the smaller
+ * of the two inputs.  This does NOT follow our usual sort rule, but it is
+ * convenient in some places.  (Note that float4_max and float8_max act this
+ * way anyway, so no similar variant is needed for them.)
+ */
+static inline float4
+float4_min_nan(const float4 val1, const float4 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
+static inline float8
+float8_min_nan(const float8 val1, const float8 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
 #endif                            /* FLOAT_H */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 76679bae8d..581bf414f2 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 81202a4c33..634e7e2dc7 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -517,7 +517,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-3,4)            | {0,3,0}                               |                  4 |                  4
  (-3,4)            | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-3,4)            | {-0.4,-1,-6}                          |      8.17059487979 |      8.17059487979
- (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690368 |      11.3851690368
+ (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690367 |      11.3851690367
  (-3,4)            | {3,NaN,5}                             |                NaN |                NaN
  (-3,4)            | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-3,4)            | {0,-1,3}                              |                  1 |                  1
@@ -537,7 +537,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-5,-12)          | {0,3,0}                               |                 12 |                 12
  (-5,-12)          | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-5,-12)          | {-0.4,-1,-6}                          |      7.42781352708 |      7.42781352708
- (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379948 |      27.3855379948
+ (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379949 |      27.3855379949
  (-5,-12)          | {3,NaN,5}                             |                NaN |                NaN
  (-5,-12)          | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-5,-12)          | {0,-1,3}                              |                 15 |                 15
@@ -553,7 +553,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e-300,-1e-300)  | {0,-1,3}                              |                  3 |                  3
  (1e-300,-1e-300)  | {-1,0,3}                              |                  3 |                  3
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
+ (1e+300,Infinity) | {1,0,5}                               |             1e+300 |             1e+300
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
  (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
@@ -561,17 +561,17 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
- (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
- (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
- (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
- (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (1e+300,Infinity) | {-1,0,3}                              |             1e+300 |             1e+300
+ (Infinity,1e+300) | {0,-1,5}                              |             1e+300 |             1e+300
+ (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
+ (Infinity,1e+300) | {0,3,0}                               |             1e+300 |             1e+300
+ (Infinity,1e+300) | {1,-1,0}                              |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
  (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |             1e+300 |             1e+300
+ (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -587,7 +587,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {0,3,0}                               |                 10 |                 10
  (10,10)           | {1,-1,0}                              |                  0 |                  0
  (10,10)           | {-0.4,-1,-6}                          |      18.5695338177 |      18.5695338177
- (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913903 |      5.38276913903
+ (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913904 |      5.38276913904
  (10,10)           | {3,NaN,5}                             |                NaN |                NaN
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
@@ -653,7 +653,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
@@ -892,13 +892,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -973,25 +973,25 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e-300,-1e-300)  | {0,-1,3}                              | (1e-300,3)
  (1e-300,-1e-300)  | {-1,0,3}                              | (3,-1e-300)
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
- (1e+300,Infinity) | {1,0,5}                               | 
+ (1e+300,Infinity) | {1,0,5}                               | (-5,Infinity)
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | (Infinity,Infinity)
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,Infinity)
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,Infinity)
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
- (1e+300,Infinity) | {-1,0,3}                              | 
- (Infinity,1e+300) | {0,-1,5}                              | 
- (Infinity,1e+300) | {1,0,5}                               | 
- (Infinity,1e+300) | {0,3,0}                               | 
- (Infinity,1e+300) | {1,-1,0}                              | 
- (Infinity,1e+300) | {-0.4,-1,-6}                          | 
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (1e+300,Infinity) | {-1,0,3}                              | (3,Infinity)
+ (Infinity,1e+300) | {0,-1,5}                              | (Infinity,5)
+ (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
+ (Infinity,1e+300) | {0,3,0}                               | (Infinity,0)
+ (Infinity,1e+300) | {1,-1,0}                              | (Infinity,Infinity)
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | (Infinity,-Infinity)
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | (Infinity,-Infinity)
  (Infinity,1e+300) | {3,NaN,5}                             | 
  (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
- (Infinity,1e+300) | {0,-1,3}                              | 
- (Infinity,1e+300) | {-1,0,3}                              | 
+ (Infinity,1e+300) | {0,-1,3}                              | (Infinity,3)
+ (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
  (NaN,NaN)         | {0,3,0}                               | 
@@ -1073,7 +1073,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
  (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
  (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1183,12 +1183,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1276,8 +1271,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1286,8 +1281,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1296,8 +1291,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1306,8 +1301,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1316,8 +1311,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1326,38 +1321,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1366,8 +1361,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1385,31 +1380,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1417,8 +1404,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1426,46 +1411,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1488,16 +1447,16 @@ SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
 
 -- Intersection point with line
 SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
-                   s                   |                   s                   |             ?column?              
----------------------------------------+---------------------------------------+-----------------------------------
+                   s                   |                   s                   |            ?column?             
+---------------------------------------+---------------------------------------+---------------------------------
  {0,-1,5}                              | {0,-1,5}                              | 
  {0,-1,5}                              | {1,0,5}                               | (-5,5)
  {0,-1,5}                              | {0,3,0}                               | 
  {0,-1,5}                              | {1,-1,0}                              | (5,5)
  {0,-1,5}                              | {-0.4,-1,-6}                          | (-27.5,5)
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} | (56250,5)
- {0,-1,5}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,5}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,5}                              | {3,NaN,5}                             | 
+ {0,-1,5}                              | {NaN,NaN,NaN}                         | 
  {0,-1,5}                              | {0,-1,3}                              | 
  {0,-1,5}                              | {-1,0,3}                              | (3,5)
  {1,0,5}                               | {0,-1,5}                              | (-5,5)
@@ -1506,8 +1465,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | 
+ {1,0,5}                               | {NaN,NaN,NaN}                         | 
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              | 
  {0,3,0}                               | {0,-1,5}                              | 
@@ -1516,8 +1475,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              | (0,0)
  {0,3,0}                               | {-0.4,-1,-6}                          | (-15,0)
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} | (83333.3333333,0)
- {0,3,0}                               | {3,NaN,5}                             | (NaN,NaN)
- {0,3,0}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,3,0}                               | {3,NaN,5}                             | 
+ {0,3,0}                               | {NaN,NaN,NaN}                         | 
  {0,3,0}                               | {0,-1,3}                              | 
  {0,3,0}                               | {-1,0,3}                              | (3,0)
  {1,-1,0}                              | {0,-1,5}                              | (5,5)
@@ -1526,8 +1485,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              | 
  {1,-1,0}                              | {-0.4,-1,-6}                          | (-4.28571428571,-4.28571428571)
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} | (15.3817756722,15.3817756722)
- {1,-1,0}                              | {3,NaN,5}                             | (NaN,NaN)
- {1,-1,0}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,-1,0}                              | {3,NaN,5}                             | 
+ {1,-1,0}                              | {NaN,NaN,NaN}                         | 
  {1,-1,0}                              | {0,-1,3}                              | (3,3)
  {1,-1,0}                              | {-1,0,3}                              | (3,3)
  {-0.4,-1,-6}                          | {0,-1,5}                              | (-27.5,5)
@@ -1536,48 +1495,48 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              | (-4.28571428571,-4.28571428571)
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} | (-53.4862244113,15.3944897645)
- {-0.4,-1,-6}                          | {3,NaN,5}                             | (NaN,NaN)
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.4,-1,-6}                          | {3,NaN,5}                             | 
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | 
  {-0.4,-1,-6}                          | {0,-1,3}                              | (-22.5,3)
  {-0.4,-1,-6}                          | {-1,0,3}                              | (3,-7.2)
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              | (56250,5)
  {-0.000184615384615,-1,15.3846153846} | {1,0,5}                               | (-5,15.3855384615)
- {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,-1.7763568394e-15)
+ {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,0)
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              | (15.3817756722,15.3817756722)
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          | (-53.4862244113,15.3944897645)
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} | 
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | (NaN,NaN)
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | 
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | 
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              | (67083.3333333,3)
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              | (3,15.3840615385)
- {3,NaN,5}                             | {0,-1,5}                              | (NaN,NaN)
- {3,NaN,5}                             | {1,0,5}                               | (NaN,NaN)
- {3,NaN,5}                             | {0,3,0}                               | (NaN,NaN)
- {3,NaN,5}                             | {1,-1,0}                              | (NaN,NaN)
- {3,NaN,5}                             | {-0.4,-1,-6}                          | (NaN,NaN)
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {3,NaN,5}                             | {3,NaN,5}                             | (NaN,NaN)
- {3,NaN,5}                             | {NaN,NaN,NaN}                         | (NaN,NaN)
- {3,NaN,5}                             | {0,-1,3}                              | (NaN,NaN)
- {3,NaN,5}                             | {-1,0,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,5}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,0,5}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,3,0}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,-1,0}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {NaN,NaN,NaN}                         | {3,NaN,5}                             | (NaN,NaN)
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-1,0,3}                              | (NaN,NaN)
+ {3,NaN,5}                             | {0,-1,5}                              | 
+ {3,NaN,5}                             | {1,0,5}                               | 
+ {3,NaN,5}                             | {0,3,0}                               | 
+ {3,NaN,5}                             | {1,-1,0}                              | 
+ {3,NaN,5}                             | {-0.4,-1,-6}                          | 
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | 
+ {3,NaN,5}                             | {3,NaN,5}                             | 
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         | 
+ {3,NaN,5}                             | {0,-1,3}                              | 
+ {3,NaN,5}                             | {-1,0,3}                              | 
+ {NaN,NaN,NaN}                         | {0,-1,5}                              | 
+ {NaN,NaN,NaN}                         | {1,0,5}                               | 
+ {NaN,NaN,NaN}                         | {0,3,0}                               | 
+ {NaN,NaN,NaN}                         | {1,-1,0}                              | 
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | 
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | 
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             | 
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | 
+ {NaN,NaN,NaN}                         | {0,-1,3}                              | 
+ {NaN,NaN,NaN}                         | {-1,0,3}                              | 
  {0,-1,3}                              | {0,-1,5}                              | 
  {0,-1,3}                              | {1,0,5}                               | (-5,3)
  {0,-1,3}                              | {0,3,0}                               | 
  {0,-1,3}                              | {1,-1,0}                              | (3,3)
  {0,-1,3}                              | {-0.4,-1,-6}                          | (-22.5,3)
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} | (67083.3333333,3)
- {0,-1,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,3}                              | {3,NaN,5}                             | 
+ {0,-1,3}                              | {NaN,NaN,NaN}                         | 
  {0,-1,3}                              | {0,-1,3}                              | 
  {0,-1,3}                              | {-1,0,3}                              | (3,3)
  {-1,0,3}                              | {0,-1,5}                              | (3,5)
@@ -1586,16 +1545,16 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | 
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | 
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              | 
 (100 rows)
 
 -- Closest point to line segment
 SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
-                   s                   |               s               |             ?column?              
----------------------------------------+-------------------------------+-----------------------------------
+                   s                   |               s               |            ?column?            
+---------------------------------------+-------------------------------+--------------------------------
  {0,-1,5}                              | [(1,2),(3,4)]                 | (3,4)
  {0,-1,5}                              | [(0,0),(6,6)]                 | (5,5)
  {0,-1,5}                              | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1615,7 +1574,7 @@ SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
  {0,3,0}                               | [(1,2),(3,4)]                 | (1,2)
  {0,3,0}                               | [(0,0),(6,6)]                 | (0,0)
  {0,3,0}                               | [(10,-10),(-3,-4)]            | (-3,-4)
- {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,-1.7763568394e-15)
+ {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,0)
  {0,3,0}                               | [(11,22),(33,44)]             | (11,22)
  {0,3,0}                               | [(-10,2),(-10,3)]             | (-10,2)
  {0,3,0}                               | [(0,-20),(30,-20)]            | 
@@ -1974,88 +1933,88 @@ SELECT l1.s, l2.s FROM LSEG_TBL l1, LSEG_TBL l2 WHERE l1.s ?-| l2.s;
 
 -- Distance to line
 SELECT l.s, l1.s, l.s <-> l1.s AS dist_sl, l1.s <-> l.s AS dist_ls FROM LSEG_TBL l, LINE_TBL l1;
-               s               |                   s                   |    dist_sl     |    dist_ls     
--------------------------------+---------------------------------------+----------------+----------------
- [(1,2),(3,4)]                 | {0,-1,5}                              |              1 |              1
- [(0,0),(6,6)]                 | {0,-1,5}                              |              0 |              0
- [(10,-10),(-3,-4)]            | {0,-1,5}                              |              9 |              9
- [(-1000000,200),(300000,-40)] | {0,-1,5}                              |              0 |              0
- [(11,22),(33,44)]             | {0,-1,5}                              |             17 |             17
- [(-10,2),(-10,3)]             | {0,-1,5}                              |              2 |              2
- [(0,-20),(30,-20)]            | {0,-1,5}                              |             25 |             25
- [(NaN,1),(NaN,90)]            | {0,-1,5}                              |            NaN |            NaN
- [(1,2),(3,4)]                 | {1,0,5}                               |              6 |              6
- [(0,0),(6,6)]                 | {1,0,5}                               |              5 |              5
- [(10,-10),(-3,-4)]            | {1,0,5}                               |              2 |              2
- [(-1000000,200),(300000,-40)] | {1,0,5}                               |              0 |              0
- [(11,22),(33,44)]             | {1,0,5}                               |             16 |             16
- [(-10,2),(-10,3)]             | {1,0,5}                               |              5 |              5
- [(0,-20),(30,-20)]            | {1,0,5}                               |              5 |              5
- [(NaN,1),(NaN,90)]            | {1,0,5}                               |            NaN |            NaN
- [(1,2),(3,4)]                 | {0,3,0}                               |              2 |              2
- [(0,0),(6,6)]                 | {0,3,0}                               |              0 |              0
- [(10,-10),(-3,-4)]            | {0,3,0}                               |              4 |              4
- [(-1000000,200),(300000,-40)] | {0,3,0}                               |              0 |              0
- [(11,22),(33,44)]             | {0,3,0}                               |             22 |             22
- [(-10,2),(-10,3)]             | {0,3,0}                               |              2 |              2
- [(0,-20),(30,-20)]            | {0,3,0}                               |             20 |             20
- [(NaN,1),(NaN,90)]            | {0,3,0}                               |            NaN |            NaN
- [(1,2),(3,4)]                 | {1,-1,0}                              | 0.707106781187 | 0.707106781187
- [(0,0),(6,6)]                 | {1,-1,0}                              |              0 |              0
- [(10,-10),(-3,-4)]            | {1,-1,0}                              | 0.707106781187 | 0.707106781187
- [(-1000000,200),(300000,-40)] | {1,-1,0}                              |              0 |              0
- [(11,22),(33,44)]             | {1,-1,0}                              |  7.77817459305 |  7.77817459305
- [(-10,2),(-10,3)]             | {1,-1,0}                              |  8.48528137424 |  8.48528137424
- [(0,-20),(30,-20)]            | {1,-1,0}                              |  14.1421356237 |  14.1421356237
- [(NaN,1),(NaN,90)]            | {1,-1,0}                              |            NaN |            NaN
- [(1,2),(3,4)]                 | {-0.4,-1,-6}                          |  7.79920420344 |  7.79920420344
- [(0,0),(6,6)]                 | {-0.4,-1,-6}                          |  5.57086014531 |  5.57086014531
- [(10,-10),(-3,-4)]            | {-0.4,-1,-6}                          |              0 |              0
- [(-1000000,200),(300000,-40)] | {-0.4,-1,-6}                          |              0 |              0
- [(11,22),(33,44)]             | {-0.4,-1,-6}                          |  30.0826447847 |  30.0826447847
- [(-10,2),(-10,3)]             | {-0.4,-1,-6}                          |  3.71390676354 |  3.71390676354
- [(0,-20),(30,-20)]            | {-0.4,-1,-6}                          |  1.85695338177 |  1.85695338177
- [(NaN,1),(NaN,90)]            | {-0.4,-1,-6}                          |            NaN |            NaN
- [(1,2),(3,4)]                 | {-0.000184615384615,-1,15.3846153846} |  11.3840613445 |  11.3840613445
- [(0,0),(6,6)]                 | {-0.000184615384615,-1,15.3846153846} |   9.3835075324 |   9.3835075324
- [(10,-10),(-3,-4)]            | {-0.000184615384615,-1,15.3846153846} |  19.3851689004 |  19.3851689004
- [(-1000000,200),(300000,-40)] | {-0.000184615384615,-1,15.3846153846} |              0 |              0
- [(11,22),(33,44)]             | {-0.000184615384615,-1,15.3846153846} |  6.61741527185 |  6.61741527185
- [(-10,2),(-10,3)]             | {-0.000184615384615,-1,15.3846153846} |  12.3864613274 |  12.3864613274
- [(0,-20),(30,-20)]            | {-0.000184615384615,-1,15.3846153846} |  35.3790763202 |  35.3790763202
- [(NaN,1),(NaN,90)]            | {-0.000184615384615,-1,15.3846153846} |            NaN |            NaN
- [(1,2),(3,4)]                 | {3,NaN,5}                             |            NaN |            NaN
- [(0,0),(6,6)]                 | {3,NaN,5}                             |            NaN |            NaN
- [(10,-10),(-3,-4)]            | {3,NaN,5}                             |            NaN |            NaN
- [(-1000000,200),(300000,-40)] | {3,NaN,5}                             |            NaN |            NaN
- [(11,22),(33,44)]             | {3,NaN,5}                             |            NaN |            NaN
- [(-10,2),(-10,3)]             | {3,NaN,5}                             |            NaN |            NaN
- [(0,-20),(30,-20)]            | {3,NaN,5}                             |            NaN |            NaN
- [(NaN,1),(NaN,90)]            | {3,NaN,5}                             |            NaN |            NaN
- [(1,2),(3,4)]                 | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(0,0),(6,6)]                 | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(10,-10),(-3,-4)]            | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(-1000000,200),(300000,-40)] | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(11,22),(33,44)]             | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(-10,2),(-10,3)]             | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(0,-20),(30,-20)]            | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(NaN,1),(NaN,90)]            | {NaN,NaN,NaN}                         |            NaN |            NaN
- [(1,2),(3,4)]                 | {0,-1,3}                              |              0 |              0
- [(0,0),(6,6)]                 | {0,-1,3}                              |              0 |              0
- [(10,-10),(-3,-4)]            | {0,-1,3}                              |              7 |              7
- [(-1000000,200),(300000,-40)] | {0,-1,3}                              |              0 |              0
- [(11,22),(33,44)]             | {0,-1,3}                              |             19 |             19
- [(-10,2),(-10,3)]             | {0,-1,3}                              |              0 |              0
- [(0,-20),(30,-20)]            | {0,-1,3}                              |             23 |             23
- [(NaN,1),(NaN,90)]            | {0,-1,3}                              |            NaN |            NaN
- [(1,2),(3,4)]                 | {-1,0,3}                              |              0 |              0
- [(0,0),(6,6)]                 | {-1,0,3}                              |              0 |              0
- [(10,-10),(-3,-4)]            | {-1,0,3}                              |              0 |              0
- [(-1000000,200),(300000,-40)] | {-1,0,3}                              |              0 |              0
- [(11,22),(33,44)]             | {-1,0,3}                              |              8 |              8
- [(-10,2),(-10,3)]             | {-1,0,3}                              |             13 |             13
- [(0,-20),(30,-20)]            | {-1,0,3}                              |              0 |              0
- [(NaN,1),(NaN,90)]            | {-1,0,3}                              |            NaN |            NaN
+               s               |                   s                   |     dist_sl      |     dist_ls      
+-------------------------------+---------------------------------------+------------------+------------------
+ [(1,2),(3,4)]                 | {0,-1,5}                              |                1 |                1
+ [(0,0),(6,6)]                 | {0,-1,5}                              |                0 |                0
+ [(10,-10),(-3,-4)]            | {0,-1,5}                              |                9 |                9
+ [(-1000000,200),(300000,-40)] | {0,-1,5}                              |                0 |                0
+ [(11,22),(33,44)]             | {0,-1,5}                              |               17 |               17
+ [(-10,2),(-10,3)]             | {0,-1,5}                              |                2 |                2
+ [(0,-20),(30,-20)]            | {0,-1,5}                              |               25 |               25
+ [(NaN,1),(NaN,90)]            | {0,-1,5}                              |              NaN |              NaN
+ [(1,2),(3,4)]                 | {1,0,5}                               |                6 |                6
+ [(0,0),(6,6)]                 | {1,0,5}                               |                5 |                5
+ [(10,-10),(-3,-4)]            | {1,0,5}                               |                2 |                2
+ [(-1000000,200),(300000,-40)] | {1,0,5}                               |                0 |                0
+ [(11,22),(33,44)]             | {1,0,5}                               |               16 |               16
+ [(-10,2),(-10,3)]             | {1,0,5}                               |                5 |                5
+ [(0,-20),(30,-20)]            | {1,0,5}                               |                5 |                5
+ [(NaN,1),(NaN,90)]            | {1,0,5}                               |              NaN |              NaN
+ [(1,2),(3,4)]                 | {0,3,0}                               |                2 |                2
+ [(0,0),(6,6)]                 | {0,3,0}                               |                0 |                0
+ [(10,-10),(-3,-4)]            | {0,3,0}                               |                4 |                4
+ [(-1000000,200),(300000,-40)] | {0,3,0}                               |                0 |                0
+ [(11,22),(33,44)]             | {0,3,0}                               |               22 |               22
+ [(-10,2),(-10,3)]             | {0,3,0}                               |                2 |                2
+ [(0,-20),(30,-20)]            | {0,3,0}                               |               20 |               20
+ [(NaN,1),(NaN,90)]            | {0,3,0}                               |              NaN |              NaN
+ [(1,2),(3,4)]                 | {1,-1,0}                              |   0.707106781187 |   0.707106781187
+ [(0,0),(6,6)]                 | {1,-1,0}                              |                0 |                0
+ [(10,-10),(-3,-4)]            | {1,-1,0}                              |   0.707106781187 |   0.707106781187
+ [(-1000000,200),(300000,-40)] | {1,-1,0}                              |                0 |                0
+ [(11,22),(33,44)]             | {1,-1,0}                              |    7.77817459305 |    7.77817459305
+ [(-10,2),(-10,3)]             | {1,-1,0}                              |    8.48528137424 |    8.48528137424
+ [(0,-20),(30,-20)]            | {1,-1,0}                              |    14.1421356237 |    14.1421356237
+ [(NaN,1),(NaN,90)]            | {1,-1,0}                              |              NaN |              NaN
+ [(1,2),(3,4)]                 | {-0.4,-1,-6}                          |    7.79920420344 |    7.79920420344
+ [(0,0),(6,6)]                 | {-0.4,-1,-6}                          |    5.57086014531 |    5.57086014531
+ [(10,-10),(-3,-4)]            | {-0.4,-1,-6}                          |                0 |                0
+ [(-1000000,200),(300000,-40)] | {-0.4,-1,-6}                          |                0 |                0
+ [(11,22),(33,44)]             | {-0.4,-1,-6}                          |    30.0826447847 |    30.0826447847
+ [(-10,2),(-10,3)]             | {-0.4,-1,-6}                          |    3.71390676354 |    3.71390676354
+ [(0,-20),(30,-20)]            | {-0.4,-1,-6}                          |    1.85695338177 |    1.85695338177
+ [(NaN,1),(NaN,90)]            | {-0.4,-1,-6}                          |              NaN |              NaN
+ [(1,2),(3,4)]                 | {-0.000184615384615,-1,15.3846153846} |    11.3840613445 |    11.3840613445
+ [(0,0),(6,6)]                 | {-0.000184615384615,-1,15.3846153846} |     9.3835075324 |     9.3835075324
+ [(10,-10),(-3,-4)]            | {-0.000184615384615,-1,15.3846153846} |    19.3851689004 |    19.3851689004
+ [(-1000000,200),(300000,-40)] | {-0.000184615384615,-1,15.3846153846} | 7.1054273576e-15 | 7.1054273576e-15
+ [(11,22),(33,44)]             | {-0.000184615384615,-1,15.3846153846} |    6.61741527185 |    6.61741527185
+ [(-10,2),(-10,3)]             | {-0.000184615384615,-1,15.3846153846} |    12.3864613274 |    12.3864613274
+ [(0,-20),(30,-20)]            | {-0.000184615384615,-1,15.3846153846} |    35.3790763202 |    35.3790763202
+ [(NaN,1),(NaN,90)]            | {-0.000184615384615,-1,15.3846153846} |              NaN |              NaN
+ [(1,2),(3,4)]                 | {3,NaN,5}                             |              NaN |              NaN
+ [(0,0),(6,6)]                 | {3,NaN,5}                             |              NaN |              NaN
+ [(10,-10),(-3,-4)]            | {3,NaN,5}                             |              NaN |              NaN
+ [(-1000000,200),(300000,-40)] | {3,NaN,5}                             |              NaN |              NaN
+ [(11,22),(33,44)]             | {3,NaN,5}                             |              NaN |              NaN
+ [(-10,2),(-10,3)]             | {3,NaN,5}                             |              NaN |              NaN
+ [(0,-20),(30,-20)]            | {3,NaN,5}                             |              NaN |              NaN
+ [(NaN,1),(NaN,90)]            | {3,NaN,5}                             |              NaN |              NaN
+ [(1,2),(3,4)]                 | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(0,0),(6,6)]                 | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(10,-10),(-3,-4)]            | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(-1000000,200),(300000,-40)] | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(11,22),(33,44)]             | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(-10,2),(-10,3)]             | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(0,-20),(30,-20)]            | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(NaN,1),(NaN,90)]            | {NaN,NaN,NaN}                         |              NaN |              NaN
+ [(1,2),(3,4)]                 | {0,-1,3}                              |                0 |                0
+ [(0,0),(6,6)]                 | {0,-1,3}                              |                0 |                0
+ [(10,-10),(-3,-4)]            | {0,-1,3}                              |                7 |                7
+ [(-1000000,200),(300000,-40)] | {0,-1,3}                              |                0 |                0
+ [(11,22),(33,44)]             | {0,-1,3}                              |               19 |               19
+ [(-10,2),(-10,3)]             | {0,-1,3}                              |                0 |                0
+ [(0,-20),(30,-20)]            | {0,-1,3}                              |               23 |               23
+ [(NaN,1),(NaN,90)]            | {0,-1,3}                              |              NaN |              NaN
+ [(1,2),(3,4)]                 | {-1,0,3}                              |                0 |                0
+ [(0,0),(6,6)]                 | {-1,0,3}                              |                0 |                0
+ [(10,-10),(-3,-4)]            | {-1,0,3}                              |                0 |                0
+ [(-1000000,200),(300000,-40)] | {-1,0,3}                              |                0 |                0
+ [(11,22),(33,44)]             | {-1,0,3}                              |                8 |                8
+ [(-10,2),(-10,3)]             | {-1,0,3}                              |               13 |               13
+ [(0,-20),(30,-20)]            | {-1,0,3}                              |                0 |                0
+ [(NaN,1),(NaN,90)]            | {-1,0,3}                              |              NaN |              NaN
 (80 rows)
 
 -- Distance to line segment
@@ -3640,13 +3599,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (Infinity,1e+300) | ((0,0))                    | f
             | (Infinity,1e+300) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3716,13 +3675,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (Infinity,1e+300) | ((0,0))                    | f
             | (Infinity,1e+300) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
-- 
2.18.4


Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
I spent some more time looking at this patch.

Some experimentation shows that the changes around bounding box
calculation (ie float8_min_nan() and its call sites) seem to be
completely pointless: removing them doesn't change any of the regression
results.  Nor does using float8_min_nan() in the other two bounding-box
calculations I'd asked about.  So I think we should just drop that set
of changes and stick with the rule that bounding box upper and lower
values are sorted as per float.h comparison rules.  This isn't that hard
to work with: if you want to know whether any NaNs are in the box, test
the upper limit (and *not* the lower limit) for isnan().  Moreover, even
if we wanted a different coding rule, we really can't have it because we
will still need to work with existing on-disk values that have bounding
boxes computed the old way.

I don't much like anything about float8_coef_mul().  In the first place,
FPzero() is an ugly, badly designed condition that we should be trying
to get rid of not add more dependencies on.  In the second place, it's
really unclear why allowing 0 times Inf to be something other than NaN
is a good idea, and it's even less clear why allowing small-but-not-zero
times Inf to be zero rather than Inf is a good idea.  In the third
place, the asymmetry between the two inputs looks more like a bug than
something we should actually want.

After some time spent staring at the specific case of line_closept_point
and its callers, I decided that the real problems there are twofold.
First, the API, or at least the callers' interpretation of this
undocumented point, is that whether the distance is undefined (NaN) is
equivalent to whether the closest point is undefined.  This is not so;
in some cases we know that the distance is infinite even though we can't
calculate a unique closest point.  Second, it's not making any attempt
to eliminate undefined cases up front.  We can do that pretty easily
by plugging the point's coordinates into the line's equation Ax+By+C
and seeing whether we get a NaN.  The attached 0002 is a subset patch
that just fixes these two issues, and I like the results it produces.

I wonder now whether the problems around line_interpt_line() and the
other intersection-ish functions wouldn't be better handled in a similar
way, by making changes to their API specs to be clearer about what
happens with NaNs and trying to eliminate ill-defined cases explicitly.
I've not tried to code that though.

Changing pg_hypot() the way you've done here is right out.  See the
comment for the function: what it is doing now is per all the relevant
standards, and your patch breaks that.  It's extremely unlikely that
doing it differently from IEEE and POSIX is a good idea.

Attached are the same old 0001 (adding the extra point_tbl entry)
and a small 0002 that fixes just line_closept_point.  I've not
tried to figure out just which of the rest of your diffs should be
dropped given that.  I did note though that the example you add
to func.sgml doesn't apply to this version of line_closept_point:

regression=# select point '(Infinity,Infinity)' <-> line '{-1,0,5}';
 ?column? 
----------
      NaN
(1 row)

regression=# select point '(Infinity,Infinity)' <-> line '{0,-1,5}';
 ?column? 
----------
      NaN
(1 row)

            regards, tom lane

diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 93a8736a3f..76679bae8d 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -157,7 +157,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count
 -------
-     3
+     4
 (1 row)

 SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
@@ -169,7 +169,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count
 -------
-     4
+     5
 (1 row)

 SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
@@ -188,10 +188,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)

-(10 rows)
+(11 rows)

 SELECT * FROM point_tbl WHERE f1 IS NULL;
  f1
@@ -202,16 +203,17 @@ SELECT * FROM point_tbl WHERE f1 IS NULL;
 SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
         f1
 -------------------
- (1e-300,-1e-300)
  (0,0)
+ (1e-300,-1e-300)
  (-3,4)
  (-10,0)
  (10,10)
  (-5,-12)
  (5.1,34.5)
  (1e+300,Infinity)
+ (Infinity,1e+300)
  (NaN,NaN)
-(9 rows)
+(10 rows)

 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
         f1
@@ -464,7 +466,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count
 -------
-     3
+     4
 (1 row)

 EXPLAIN (COSTS OFF)
@@ -494,7 +496,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count
 -------
-     4
+     5
 (1 row)

 EXPLAIN (COSTS OFF)
@@ -530,10 +532,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)

-(10 rows)
+(11 rows)

 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 IS NULL;
@@ -568,9 +571,10 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
-(9 rows)
+(10 rows)

 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..81202a4c33 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -120,6 +120,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          |                2.4
  (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
  (0,0)             | (1e+300,Infinity) |           Infinity
+ (0,0)             | (Infinity,1e+300) |                  0
  (0,0)             | (NaN,NaN)         |                NaN
  (0,0)             | (10,10)           |                  1
  (-10,0)           | (0,0)             |                  0
@@ -129,6 +130,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          |               -2.4
  (-10,0)           | (1e-300,-1e-300)  |                  0
  (-10,0)           | (1e+300,Infinity) |           Infinity
+ (-10,0)           | (Infinity,1e+300) |                  0
  (-10,0)           | (NaN,NaN)         |                NaN
  (-10,0)           | (10,10)           |                0.5
  (-3,4)            | (0,0)             |     -1.33333333333
@@ -138,6 +140,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          |                  8
  (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
  (-3,4)            | (1e+300,Infinity) |           Infinity
+ (-3,4)            | (Infinity,1e+300) |                  0
  (-3,4)            | (NaN,NaN)         |                NaN
  (-3,4)            | (10,10)           |     0.461538461538
  (5.1,34.5)        | (0,0)             |      6.76470588235
@@ -147,6 +150,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          |      4.60396039604
  (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
  (5.1,34.5)        | (1e+300,Infinity) |           Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |                  0
  (5.1,34.5)        | (NaN,NaN)         |                NaN
  (5.1,34.5)        | (10,10)           |                 -5
  (-5,-12)          | (0,0)             |                2.4
@@ -156,6 +160,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | 1.79769313486e+308
  (-5,-12)          | (1e-300,-1e-300)  |                2.4
  (-5,-12)          | (1e+300,Infinity) |           Infinity
+ (-5,-12)          | (Infinity,1e+300) |                  0
  (-5,-12)          | (NaN,NaN)         |                NaN
  (-5,-12)          | (10,10)           |      1.46666666667
  (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
@@ -165,6 +170,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          |                2.4
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
  (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
  (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
  (1e-300,-1e-300)  | (10,10)           |                  1
  (1e+300,Infinity) | (0,0)             |           Infinity
@@ -174,8 +180,19 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          |           Infinity
  (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
  (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
+ (1e+300,Infinity) | (Infinity,1e+300) |                NaN
  (1e+300,Infinity) | (NaN,NaN)         |                NaN
  (1e+300,Infinity) | (10,10)           |           Infinity
+ (Infinity,1e+300) | (0,0)             |                  0
+ (Infinity,1e+300) | (-10,0)           |                  0
+ (Infinity,1e+300) | (-3,4)            |                  0
+ (Infinity,1e+300) | (5.1,34.5)        |                  0
+ (Infinity,1e+300) | (-5,-12)          |                  0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
+ (Infinity,1e+300) | (1e+300,Infinity) |                NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |                  0
+ (Infinity,1e+300) | (NaN,NaN)         |                NaN
+ (Infinity,1e+300) | (10,10)           |                  0
  (NaN,NaN)         | (0,0)             |                NaN
  (NaN,NaN)         | (-10,0)           |                NaN
  (NaN,NaN)         | (-3,4)            |                NaN
@@ -183,6 +200,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          |                NaN
  (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
  (NaN,NaN)         | (1e+300,Infinity) |                NaN
+ (NaN,NaN)         | (Infinity,1e+300) |                NaN
  (NaN,NaN)         | (NaN,NaN)         |                NaN
  (NaN,NaN)         | (10,10)           |                NaN
  (10,10)           | (0,0)             |                  1
@@ -192,14 +210,15 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          |      1.46666666667
  (10,10)           | (1e-300,-1e-300)  |                  1
  (10,10)           | (1e+300,Infinity) |           Infinity
+ (10,10)           | (Infinity,1e+300) |                  0
  (10,10)           | (NaN,NaN)         |                NaN
  (10,10)           | (10,10)           | 1.79769313486e+308
-(81 rows)
+(100 rows)

 -- Add point
 SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |     ?column?
--------------------+-------------------+-------------------
+        f1         |        f1         |      ?column?
+-------------------+-------------------+---------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (-10,0)
  (0,0)             | (-3,4)            | (-3,4)
@@ -207,6 +226,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (-5,-12)
  (0,0)             | (1e-300,-1e-300)  | (1e-300,-1e-300)
  (0,0)             | (1e+300,Infinity) | (1e+300,Infinity)
+ (0,0)             | (Infinity,1e+300) | (Infinity,1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (10,10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -216,6 +236,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-15,-12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,-1e-300)
  (-10,0)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (-10,0)           | (Infinity,1e+300) | (Infinity,1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (0,10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -225,6 +246,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (-8,-8)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (1e+300,Infinity)
+ (-3,4)            | (Infinity,1e+300) | (Infinity,1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (7,14)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -234,6 +256,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (0.1,22.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (1e+300,Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (Infinity,1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (15.1,44.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -243,6 +266,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (-10,-24)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (1e+300,Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (Infinity,1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (5,-2)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -252,6 +276,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (-5,-12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (2e-300,-2e-300)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (1e+300,Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (Infinity,1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (10,10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -261,8 +286,19 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (2e+300,Infinity)
+ (1e+300,Infinity) | (Infinity,1e+300) | (Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (Infinity,2e+300)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -270,6 +306,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -279,14 +316,15 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (5,-2)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (10,10)           | (Infinity,1e+300) | (Infinity,1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (20,20)
-(81 rows)
+(100 rows)

 -- Subtract point
 SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |      ?column?
--------------------+-------------------+---------------------
+        f1         |        f1         |       ?column?
+-------------------+-------------------+----------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (10,0)
  (0,0)             | (-3,4)            | (3,-4)
@@ -294,6 +332,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (5,12)
  (0,0)             | (1e-300,-1e-300)  | (-1e-300,1e-300)
  (0,0)             | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (0,0)             | (Infinity,1e+300) | (-Infinity,-1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (-10,-10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -303,6 +342,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-5,12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,1e-300)
  (-10,0)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-10,0)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (-20,-10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -312,6 +352,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (2,16)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-3,4)            | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (-13,-6)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -321,6 +362,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (10.1,46.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (-Infinity,-1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (-4.9,24.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -330,6 +372,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (0,0)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (-15,-22)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -339,6 +382,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (5,12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (0,0)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (-Infinity,-1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (-10,-10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -348,8 +392,19 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (0,NaN)
+ (1e+300,Infinity) | (Infinity,1e+300) | (-Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (NaN,0)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -357,6 +412,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -366,9 +422,10 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (15,22)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (10,10)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (0,0)
-(81 rows)
+(100 rows)

 -- Multiply with point
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -388,11 +445,13 @@ SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0
  (10,10)    | (1e-300,-1e-300)  | (2e-299,0)
  (5.1,34.5) | (1e+300,Infinity) | (-Infinity,Infinity)
  (10,10)    | (1e+300,Infinity) | (-Infinity,Infinity)
+ (5.1,34.5) | (Infinity,1e+300) | (Infinity,Infinity)
+ (10,10)    | (Infinity,1e+300) | (Infinity,Infinity)
  (5.1,34.5) | (NaN,NaN)         | (NaN,NaN)
  (10,10)    | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5) | (10,10)           | (-294,396)
  (10,10)    | (10,10)           | (0,200)
-(18 rows)
+(20 rows)

 -- Underflow error
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] < 1;
@@ -415,11 +474,13 @@ SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0
  (1e-300,-1e-300)  | (10,10)    | (0,-1e-301)
  (1e+300,Infinity) | (5.1,34.5) | (Infinity,Infinity)
  (1e+300,Infinity) | (10,10)    | (Infinity,Infinity)
+ (Infinity,1e+300) | (5.1,34.5) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (10,10)    | (Infinity,-Infinity)
  (NaN,NaN)         | (5.1,34.5) | (NaN,NaN)
  (NaN,NaN)         | (10,10)    | (NaN,NaN)
  (10,10)           | (5.1,34.5) | (0.325588278822,-0.241724631247)
  (10,10)           | (10,10)    | (1,0)
-(18 rows)
+(20 rows)

 -- Overflow error
 SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0] > 1000;
@@ -501,6 +562,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -521,7 +592,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
  (10,10)           | {-1,0,3}                              |                  7 |                  7
-(90 rows)
+(100 rows)

 -- Distance to line segment
 SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
@@ -583,6 +654,14 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -599,7 +678,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (10,10)           | [(-10,2),(-10,3)]             |      21.1896201004 |      21.1896201004
  (10,10)           | [(0,-20),(30,-20)]            |                 30 |                 30
  (10,10)           | [(NaN,1),(NaN,90)]            |                NaN |                NaN
-(72 rows)
+(80 rows)

 -- Distance to box
 SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT_TBL p, BOX_TBL b;
@@ -640,6 +719,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(1,1)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |           Infinity |           Infinity
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -650,7 +734,7 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (10,10)           | (-2,2),(-8,-10)     |      14.4222051019 |      14.4222051019
  (10,10)           | (2.5,3.5),(2.5,2.5) |      9.92471662064 |      9.92471662064
  (10,10)           | (3,3),(3,3)         |      9.89949493661 |      9.89949493661
-(45 rows)
+(50 rows)

 -- Distance to path
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp FROM POINT_TBL p, PATH_TBL p1;
@@ -719,6 +803,15 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((10,20))                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,12),(13,14)]         |           Infinity |           Infinity
+ (Infinity,1e+300) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
  (NaN,NaN)         | ((1,2),(3,4))             |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
@@ -737,7 +830,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (10,10)           | ((10,20))                 |                 10 |                 10
  (10,10)           | [(11,12),(13,14)]         |       2.2360679775 |       2.2360679775
  (10,10)           | ((11,12),(13,14))         |       2.2360679775 |       2.2360679775
-(81 rows)
+(90 rows)

 -- Distance to polygon
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp FROM POINT_TBL p, POLYGON_TBL p1;
@@ -792,6 +885,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
+ (Infinity,1e+300) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
  (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
  (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
  (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
@@ -806,7 +906,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | 3.60555127546 | 3.60555127546
  (10,10)           | ((0,0))                    | 14.1421356237 | 14.1421356237
  (10,10)           | ((0,1),(0,1))              | 13.4536240471 | 13.4536240471
-(63 rows)
+(70 rows)

 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -882,6 +982,16 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              |
+ (Infinity,1e+300) | {0,-1,5}                              |
+ (Infinity,1e+300) | {1,0,5}                               |
+ (Infinity,1e+300) | {0,3,0}                               |
+ (Infinity,1e+300) | {1,-1,0}                              |
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |
+ (Infinity,1e+300) | {3,NaN,5}                             |
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |
+ (Infinity,1e+300) | {0,-1,3}                              |
+ (Infinity,1e+300) | {-1,0,3}                              |
  (NaN,NaN)         | {0,-1,5}                              |
  (NaN,NaN)         | {1,0,5}                               |
  (NaN,NaN)         | {0,3,0}                               |
@@ -902,7 +1012,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (10,10)           | {NaN,NaN,NaN}                         |
  (10,10)           | {0,-1,3}                              | (10,3)
  (10,10)           | {-1,0,3}                              | (3,10)
-(90 rows)
+(100 rows)

 -- Closest point to line segment
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
@@ -964,6 +1074,14 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
+ (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
+ (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            | (30,-20)
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |
  (NaN,NaN)         | [(1,2),(3,4)]                 |
  (NaN,NaN)         | [(0,0),(6,6)]                 |
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |
@@ -980,7 +1098,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (10,10)           | [(-10,2),(-10,3)]             | (-10,3)
  (10,10)           | [(0,-20),(30,-20)]            | (10,-20)
  (10,10)           | [(NaN,1),(NaN,90)]            |
-(72 rows)
+(80 rows)

 -- Closest point to box
 SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
@@ -1021,6 +1139,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (Infinity,1e+300) | (2,2),(0,0)         | (0,2)
+ (Infinity,1e+300) | (3,3),(1,1)         | (1,3)
+ (Infinity,1e+300) | (-2,2),(-8,-10)     | (-8,2)
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
+ (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         |
  (NaN,NaN)         | (3,3),(1,1)         |
  (NaN,NaN)         | (-2,2),(-8,-10)     |
@@ -1031,7 +1154,7 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (10,10)           | (-2,2),(-8,-10)     | (-2,2)
  (10,10)           | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (10,10)           | (3,3),(3,3)         | (3,3)
-(45 rows)
+(50 rows)

 -- On line
 SELECT p.f1, l.s FROM POINT_TBL p, LINE_TBL l WHERE p.f1 <@ l.s;
@@ -2347,6 +2470,11 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2357,7 +2485,7 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (8,12),(2,0)
             | (12.5,13.5),(12.5,12.5)
             | (13,13),(13,13)
-(45 rows)
+(50 rows)

 SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
    FROM BOX_TBL b, POINT_TBL p;
@@ -2398,6 +2526,11 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2408,7 +2541,7 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-12,-8),(-18,-20)
             | (-7.5,-6.5),(-7.5,-7.5)
             | (-7,-7),(-7,-7)
-(45 rows)
+(50 rows)

 -- Multiply with point
 SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2431,16 +2564,21 @@ SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] > 1000;
          f1          |        f1         |                  ?column?
 ---------------------+-------------------+--------------------------------------------
  (2,2),(0,0)         | (1e+300,Infinity) | (NaN,NaN),(-Infinity,Infinity)
+ (2,2),(0,0)         | (Infinity,1e+300) | (NaN,NaN),(Infinity,Infinity)
  (2,2),(0,0)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(1,1)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(1,1)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(1,1)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (-2,2),(-8,-10)     | (1e+300,Infinity) | (Infinity,-Infinity),(-Infinity,-Infinity)
+ (-2,2),(-8,-10)     | (Infinity,1e+300) | (-Infinity,Infinity),(-Infinity,-Infinity)
  (-2,2),(-8,-10)     | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (2.5,3.5),(2.5,2.5) | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (2.5,3.5),(2.5,2.5) | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (2.5,3.5),(2.5,2.5) | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(3,3)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(3,3)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(3,3)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
-(10 rows)
+(15 rows)

 -- Divide by point
 SELECT b.f1, p.f1, b.f1 / p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2470,9 +2608,10 @@ SELECT f1::box
  (-5,-12),(-5,-12)
  (1e-300,-1e-300),(1e-300,-1e-300)
  (1e+300,Infinity),(1e+300,Infinity)
+ (Infinity,1e+300),(Infinity,1e+300)
  (NaN,NaN),(NaN,NaN)
  (10,10),(10,10)
-(9 rows)
+(10 rows)

 SELECT bound_box(a.f1, b.f1)
     FROM BOX_TBL a, BOX_TBL b;
@@ -3102,6 +3241,15 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((1e+300,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(1e+300,Infinity),(1e+300,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((1e+300,Infinity),(1e+300,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3120,7 +3268,7 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((20,30))
  [(11,12),(13,14)]         | (10,10)           | [(21,22),(23,24)]
  ((11,12),(13,14))         | (10,10)           | ((21,22),(23,24))
-(81 rows)
+(90 rows)

 -- Subtract point
 SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3189,6 +3337,15 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-1e+300,-Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-1e+300,-Infinity),(-1e+300,-Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-1e+300,-Infinity),(-1e+300,-Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((-Infinity,-1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3207,7 +3364,7 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((0,10))
  [(11,12),(13,14)]         | (10,10)           | [(1,2),(3,4)]
  ((11,12),(13,14))         | (10,10)           | ((1,2),(3,4))
-(81 rows)
+(90 rows)

 -- Multiply with point
 SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3276,6 +3433,15 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-Infinity,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-Infinity,Infinity),(-Infinity,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-Infinity,Infinity),(-Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) | [(NaN,NaN),(Infinity,NaN),(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,Infinity))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3294,7 +3460,7 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((-100,300))
  [(11,12),(13,14)]         | (10,10)           | [(-10,230),(-10,270)]
  ((11,12),(13,14))         | (10,10)           | ((-10,230),(-10,270))
-(81 rows)
+(90 rows)

 -- Divide by point
 SELECT p.f1, p1.f1, p.f1 / p1.f1 FROM PATH_TBL p, POINT_TBL p1 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -3467,6 +3633,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3481,7 +3654,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)

 SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
    FROM POLYGON_TBL poly, POINT_TBL p;
@@ -3536,6 +3709,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3550,7 +3730,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)

 SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon
    FROM POLYGON_TBL;
@@ -3929,9 +4109,10 @@ SELECT '' AS six, circle(f1, 50.0)
      | <(-5,-12),50>
      | <(1e-300,-1e-300),50>
      | <(1e+300,Infinity),50>
+     | <(Infinity,1e+300),50>
      | <(NaN,NaN),50>
      | <(10,10),50>
-(9 rows)
+(10 rows)

 SELECT '' AS four, circle(f1)
    FROM BOX_TBL;
@@ -3993,12 +4174,19 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(100,200),10> | (-10,0)           |  218.25424421
             | <(100,200),10> | (-5,-12)          | 226.577682802
             | <(3,5),0>      | (1e+300,Infinity) |      Infinity
+            | <(3,5),0>      | (Infinity,1e+300) |      Infinity
             | <(1,2),3>      | (1e+300,Infinity) |      Infinity
             | <(5,1),3>      | (1e+300,Infinity) |      Infinity
+            | <(5,1),3>      | (Infinity,1e+300) |      Infinity
+            | <(1,2),3>      | (Infinity,1e+300) |      Infinity
             | <(1,3),5>      | (1e+300,Infinity) |      Infinity
+            | <(1,3),5>      | (Infinity,1e+300) |      Infinity
             | <(100,200),10> | (1e+300,Infinity) |      Infinity
+            | <(100,200),10> | (Infinity,1e+300) |      Infinity
             | <(1,2),100>    | (1e+300,Infinity) |      Infinity
+            | <(1,2),100>    | (Infinity,1e+300) |      Infinity
             | <(100,1),115>  | (1e+300,Infinity) |      Infinity
+            | <(100,1),115>  | (Infinity,1e+300) |      Infinity
             | <(3,5),0>      | (NaN,NaN)         |           NaN
             | <(1,2),3>      | (NaN,NaN)         |           NaN
             | <(5,1),3>      | (NaN,NaN)         |           NaN
@@ -4014,8 +4202,9 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(3,5),NaN>    | (5.1,34.5)        |           NaN
             | <(3,5),NaN>    | (10,10)           |           NaN
             | <(3,5),NaN>    | (1e+300,Infinity) |           NaN
+            | <(3,5),NaN>    | (Infinity,1e+300) |           NaN
             | <(3,5),NaN>    | (NaN,NaN)         |           NaN
-(53 rows)
+(61 rows)

 -- To polygon
 SELECT f1, f1::polygon FROM CIRCLE_TBL WHERE f1 >= '<(0,0),1>';
@@ -4626,6 +4815,14 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(1e+300,Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(1e+300,Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(1e+300,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4642,7 +4839,7 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(110,11),115>
  <(3,5),0>      | (10,10)           | <(13,15),0>
  <(3,5),NaN>    | (10,10)           | <(13,15),NaN>
-(72 rows)
+(80 rows)

 -- Subtract point
 SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4704,6 +4901,14 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-1e+300,-Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(-1e+300,-Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-1e+300,-Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(-Infinity,-1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(-Infinity,-1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(-Infinity,-1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(-Infinity,-1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(-Infinity,-1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(-Infinity,-1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4720,7 +4925,7 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(90,-9),115>
  <(3,5),0>      | (10,10)           | <(-7,-5),0>
  <(3,5),NaN>    | (10,10)           | <(-7,-5),NaN>
-(72 rows)
+(80 rows)

 -- Multiply with point
 SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4782,6 +4987,14 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-Infinity,Infinity),Infinity>
  <(3,5),0>      | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),NaN>
@@ -4798,7 +5011,7 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(990,1010),1626.34559673>
  <(3,5),0>      | (10,10)           | <(-20,80),0>
  <(3,5),NaN>    | (10,10)           | <(-20,80),NaN>
-(72 rows)
+(80 rows)

 -- Divide by point
 SELECT c.f1, p.f1, c.f1 / p.f1 FROM CIRCLE_TBL c, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 15e3b83b37..77e250fc3e 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -11,6 +11,7 @@ INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 -- bad format points
 INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
@@ -44,9 +45,10 @@ SELECT '' AS six, * FROM POINT_TBL;
      | (-5,-12)
      | (1e-300,-1e-300)
      | (1e+300,Infinity)
+     | (Infinity,1e+300)
      | (NaN,NaN)
      | (10,10)
-(9 rows)
+(10 rows)

 -- left of
 SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)';
@@ -115,8 +117,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)

 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -136,8 +139,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)

 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
@@ -152,8 +156,9 @@ SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
      | (10,10)           |      14.142135623731
      | (5.1,34.5)        |     34.8749193547455
      | (1e+300,Infinity) |             Infinity
+     | (Infinity,1e+300) |             Infinity
      | (NaN,NaN)         |                  NaN
-(9 rows)
+(10 rows)

 SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist
    FROM POINT_TBL p1, POINT_TBL p2
@@ -210,12 +215,19 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (-5,-12)          | (5.1,34.5)        |     47.5842410888311
            | (5.1,34.5)        | (-5,-12)          |     47.5842410888311
            | (-10,0)           | (1e+300,Infinity) |             Infinity
+           | (-10,0)           | (Infinity,1e+300) |             Infinity
            | (-5,-12)          | (1e+300,Infinity) |             Infinity
+           | (-5,-12)          | (Infinity,1e+300) |             Infinity
            | (-3,4)            | (1e+300,Infinity) |             Infinity
+           | (-3,4)            | (Infinity,1e+300) |             Infinity
            | (0,0)             | (1e+300,Infinity) |             Infinity
+           | (0,0)             | (Infinity,1e+300) |             Infinity
            | (1e-300,-1e-300)  | (1e+300,Infinity) |             Infinity
+           | (1e-300,-1e-300)  | (Infinity,1e+300) |             Infinity
            | (5.1,34.5)        | (1e+300,Infinity) |             Infinity
+           | (5.1,34.5)        | (Infinity,1e+300) |             Infinity
            | (10,10)           | (1e+300,Infinity) |             Infinity
+           | (10,10)           | (Infinity,1e+300) |             Infinity
            | (1e+300,Infinity) | (-10,0)           |             Infinity
            | (1e+300,Infinity) | (-5,-12)          |             Infinity
            | (1e+300,Infinity) | (-3,4)            |             Infinity
@@ -223,6 +235,15 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (1e+300,Infinity) | (1e-300,-1e-300)  |             Infinity
            | (1e+300,Infinity) | (5.1,34.5)        |             Infinity
            | (1e+300,Infinity) | (10,10)           |             Infinity
+           | (1e+300,Infinity) | (Infinity,1e+300) |             Infinity
+           | (Infinity,1e+300) | (-10,0)           |             Infinity
+           | (Infinity,1e+300) | (-5,-12)          |             Infinity
+           | (Infinity,1e+300) | (-3,4)            |             Infinity
+           | (Infinity,1e+300) | (0,0)             |             Infinity
+           | (Infinity,1e+300) | (1e-300,-1e-300)  |             Infinity
+           | (Infinity,1e+300) | (5.1,34.5)        |             Infinity
+           | (Infinity,1e+300) | (10,10)           |             Infinity
+           | (Infinity,1e+300) | (1e+300,Infinity) |             Infinity
            | (-10,0)           | (NaN,NaN)         |                  NaN
            | (-5,-12)          | (NaN,NaN)         |                  NaN
            | (-3,4)            | (NaN,NaN)         |                  NaN
@@ -232,6 +253,8 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (10,10)           | (NaN,NaN)         |                  NaN
            | (1e+300,Infinity) | (1e+300,Infinity) |                  NaN
            | (1e+300,Infinity) | (NaN,NaN)         |                  NaN
+           | (Infinity,1e+300) | (Infinity,1e+300) |                  NaN
+           | (Infinity,1e+300) | (NaN,NaN)         |                  NaN
            | (NaN,NaN)         | (-10,0)           |                  NaN
            | (NaN,NaN)         | (-5,-12)          |                  NaN
            | (NaN,NaN)         | (-3,4)            |                  NaN
@@ -240,8 +263,9 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (NaN,NaN)         | (5.1,34.5)        |                  NaN
            | (NaN,NaN)         | (10,10)           |                  NaN
            | (NaN,NaN)         | (1e+300,Infinity) |                  NaN
+           | (NaN,NaN)         | (Infinity,1e+300) |                  NaN
            | (NaN,NaN)         | (NaN,NaN)         |                  NaN
-(81 rows)
+(100 rows)

 SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
    FROM POINT_TBL p1, POINT_TBL p2
@@ -253,6 +277,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (0,0)             | (5.1,34.5)
         | (0,0)             | (-5,-12)
         | (0,0)             | (1e+300,Infinity)
+        | (0,0)             | (Infinity,1e+300)
         | (0,0)             | (NaN,NaN)
         | (0,0)             | (10,10)
         | (-10,0)           | (0,0)
@@ -261,6 +286,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-10,0)           | (-5,-12)
         | (-10,0)           | (1e-300,-1e-300)
         | (-10,0)           | (1e+300,Infinity)
+        | (-10,0)           | (Infinity,1e+300)
         | (-10,0)           | (NaN,NaN)
         | (-10,0)           | (10,10)
         | (-3,4)            | (0,0)
@@ -269,6 +295,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-3,4)            | (-5,-12)
         | (-3,4)            | (1e-300,-1e-300)
         | (-3,4)            | (1e+300,Infinity)
+        | (-3,4)            | (Infinity,1e+300)
         | (-3,4)            | (NaN,NaN)
         | (-3,4)            | (10,10)
         | (5.1,34.5)        | (0,0)
@@ -277,6 +304,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (5.1,34.5)        | (-5,-12)
         | (5.1,34.5)        | (1e-300,-1e-300)
         | (5.1,34.5)        | (1e+300,Infinity)
+        | (5.1,34.5)        | (Infinity,1e+300)
         | (5.1,34.5)        | (NaN,NaN)
         | (5.1,34.5)        | (10,10)
         | (-5,-12)          | (0,0)
@@ -285,6 +313,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-5,-12)          | (5.1,34.5)
         | (-5,-12)          | (1e-300,-1e-300)
         | (-5,-12)          | (1e+300,Infinity)
+        | (-5,-12)          | (Infinity,1e+300)
         | (-5,-12)          | (NaN,NaN)
         | (-5,-12)          | (10,10)
         | (1e-300,-1e-300)  | (-10,0)
@@ -292,6 +321,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e-300,-1e-300)  | (5.1,34.5)
         | (1e-300,-1e-300)  | (-5,-12)
         | (1e-300,-1e-300)  | (1e+300,Infinity)
+        | (1e-300,-1e-300)  | (Infinity,1e+300)
         | (1e-300,-1e-300)  | (NaN,NaN)
         | (1e-300,-1e-300)  | (10,10)
         | (1e+300,Infinity) | (0,0)
@@ -301,8 +331,19 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e+300,Infinity) | (-5,-12)
         | (1e+300,Infinity) | (1e-300,-1e-300)
         | (1e+300,Infinity) | (1e+300,Infinity)
+        | (1e+300,Infinity) | (Infinity,1e+300)
         | (1e+300,Infinity) | (NaN,NaN)
         | (1e+300,Infinity) | (10,10)
+        | (Infinity,1e+300) | (0,0)
+        | (Infinity,1e+300) | (-10,0)
+        | (Infinity,1e+300) | (-3,4)
+        | (Infinity,1e+300) | (5.1,34.5)
+        | (Infinity,1e+300) | (-5,-12)
+        | (Infinity,1e+300) | (1e-300,-1e-300)
+        | (Infinity,1e+300) | (1e+300,Infinity)
+        | (Infinity,1e+300) | (Infinity,1e+300)
+        | (Infinity,1e+300) | (NaN,NaN)
+        | (Infinity,1e+300) | (10,10)
         | (NaN,NaN)         | (0,0)
         | (NaN,NaN)         | (-10,0)
         | (NaN,NaN)         | (-3,4)
@@ -310,6 +351,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (NaN,NaN)         | (-5,-12)
         | (NaN,NaN)         | (1e-300,-1e-300)
         | (NaN,NaN)         | (1e+300,Infinity)
+        | (NaN,NaN)         | (Infinity,1e+300)
         | (NaN,NaN)         | (NaN,NaN)
         | (NaN,NaN)         | (10,10)
         | (10,10)           | (0,0)
@@ -319,57 +361,67 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (10,10)           | (-5,-12)
         | (10,10)           | (1e-300,-1e-300)
         | (10,10)           | (1e+300,Infinity)
+        | (10,10)           | (Infinity,1e+300)
         | (10,10)           | (NaN,NaN)
-(72 rows)
+(91 rows)

 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1
    ORDER BY distance, p1.f1[0], p2.f1[0];
- fifteen |      point1      |      point2       |     distance
----------+------------------+-------------------+------------------
-         | (-3,4)           | (0,0)             |                5
-         | (-3,4)           | (1e-300,-1e-300)  |                5
-         | (-10,0)          | (-3,4)            | 8.06225774829855
-         | (-10,0)          | (0,0)             |               10
-         | (-10,0)          | (1e-300,-1e-300)  |               10
-         | (-10,0)          | (-5,-12)          |               13
-         | (-5,-12)         | (0,0)             |               13
-         | (-5,-12)         | (1e-300,-1e-300)  |               13
-         | (0,0)            | (10,10)           |  14.142135623731
-         | (1e-300,-1e-300) | (10,10)           |  14.142135623731
-         | (-3,4)           | (10,10)           | 14.3178210632764
-         | (-5,-12)         | (-3,4)            | 16.1245154965971
-         | (-10,0)          | (10,10)           | 22.3606797749979
-         | (5.1,34.5)       | (10,10)           | 24.9851956166046
-         | (-5,-12)         | (10,10)           | 26.6270539113887
-         | (-3,4)           | (5.1,34.5)        | 31.5572495632937
-         | (0,0)            | (5.1,34.5)        | 34.8749193547455
-         | (1e-300,-1e-300) | (5.1,34.5)        | 34.8749193547455
-         | (-10,0)          | (5.1,34.5)        | 37.6597928831267
-         | (-5,-12)         | (5.1,34.5)        | 47.5842410888311
-         | (-10,0)          | (1e+300,Infinity) |         Infinity
-         | (-5,-12)         | (1e+300,Infinity) |         Infinity
-         | (-3,4)           | (1e+300,Infinity) |         Infinity
-         | (0,0)            | (1e+300,Infinity) |         Infinity
-         | (1e-300,-1e-300) | (1e+300,Infinity) |         Infinity
-         | (5.1,34.5)       | (1e+300,Infinity) |         Infinity
-         | (10,10)          | (1e+300,Infinity) |         Infinity
-(27 rows)
+ fifteen |      point1       |      point2       |     distance
+---------+-------------------+-------------------+------------------
+         | (-3,4)            | (0,0)             |                5
+         | (-3,4)            | (1e-300,-1e-300)  |                5
+         | (-10,0)           | (-3,4)            | 8.06225774829855
+         | (-10,0)           | (0,0)             |               10
+         | (-10,0)           | (1e-300,-1e-300)  |               10
+         | (-10,0)           | (-5,-12)          |               13
+         | (-5,-12)          | (0,0)             |               13
+         | (-5,-12)          | (1e-300,-1e-300)  |               13
+         | (0,0)             | (10,10)           |  14.142135623731
+         | (1e-300,-1e-300)  | (10,10)           |  14.142135623731
+         | (-3,4)            | (10,10)           | 14.3178210632764
+         | (-5,-12)          | (-3,4)            | 16.1245154965971
+         | (-10,0)           | (10,10)           | 22.3606797749979
+         | (5.1,34.5)        | (10,10)           | 24.9851956166046
+         | (-5,-12)          | (10,10)           | 26.6270539113887
+         | (-3,4)            | (5.1,34.5)        | 31.5572495632937
+         | (0,0)             | (5.1,34.5)        | 34.8749193547455
+         | (1e-300,-1e-300)  | (5.1,34.5)        | 34.8749193547455
+         | (-10,0)           | (5.1,34.5)        | 37.6597928831267
+         | (-5,-12)          | (5.1,34.5)        | 47.5842410888311
+         | (-10,0)           | (1e+300,Infinity) |         Infinity
+         | (-10,0)           | (Infinity,1e+300) |         Infinity
+         | (-5,-12)          | (1e+300,Infinity) |         Infinity
+         | (-5,-12)          | (Infinity,1e+300) |         Infinity
+         | (-3,4)            | (1e+300,Infinity) |         Infinity
+         | (-3,4)            | (Infinity,1e+300) |         Infinity
+         | (0,0)             | (1e+300,Infinity) |         Infinity
+         | (0,0)             | (Infinity,1e+300) |         Infinity
+         | (1e-300,-1e-300)  | (1e+300,Infinity) |         Infinity
+         | (1e-300,-1e-300)  | (Infinity,1e+300) |         Infinity
+         | (5.1,34.5)        | (1e+300,Infinity) |         Infinity
+         | (5.1,34.5)        | (Infinity,1e+300) |         Infinity
+         | (10,10)           | (1e+300,Infinity) |         Infinity
+         | (10,10)           | (Infinity,1e+300) |         Infinity
+         | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(35 rows)

 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1
    ORDER BY distance;
- three |   point1   |      point2      |     distance
--------+------------+------------------+------------------
-       | (-3,4)     | (0,0)            |                5
-       | (-3,4)     | (1e-300,-1e-300) |                5
-       | (-10,0)    | (-5,-12)         |               13
-       | (5.1,34.5) | (10,10)          | 24.9851956166046
-(4 rows)
+ three |      point1       |      point2       |     distance
+-------+-------------------+-------------------+------------------
+       | (-3,4)            | (0,0)             |                5
+       | (-3,4)            | (1e-300,-1e-300)  |                5
+       | (-10,0)           | (-5,-12)          |               13
+       | (5.1,34.5)        | (10,10)           | 24.9851956166046
+       | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(5 rows)

 -- Test that GiST indexes provide same behavior as sequential scan
 CREATE TEMP TABLE point_gist_tbl(f1 point);
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 7f8504dbd1..6a1ca12d5c 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -21,6 +21,8 @@ INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow

 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow

+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
+
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');

 -- bad format points
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..fc6493a0d7 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -2707,9 +2707,14 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
  *-------------------------------------------------------------------*/

 /*
- * If *result is not NULL, it is set to the intersection point of a
- * perpendicular of the line through the point.  Returns the distance
- * of those two points.
+ * Determine the closest point on the given line to the given point.
+ * If result is not NULL, *result is set to the coordinates of that point.
+ * In any case, returns the distance from the point to the line.
+ * Returns NaN for any ill-defined value.
+ *
+ * NOTE: in some cases the distance is well defined (i.e., infinity)
+ * even though the specific closest point is not.  Hence, if you care
+ * about whether the point is well-defined, check its coordinates for NaNs.
  */
 static float8
 line_closept_point(Point *result, LINE *line, Point *point)
@@ -2717,17 +2722,30 @@ line_closept_point(Point *result, LINE *line, Point *point)
     Point        closept;
     LINE        tmp;

+    /*
+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    if (unlikely(isnan(float8_pl(float8_pl(float8_mul(line->A, point->x),
+                                           float8_mul(line->B, point->y)),
+                                 line->C))))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
-     * should always find it, but that can fail in the presence of NaN
-     * coordinates, and perhaps even from simple roundoff issues.
+     * should always find it, but perhaps roundoff issues could prevent that.
      */
     line_construct(&tmp, point, line_invsl(line));
     if (!line_interpt_line(&closept, &tmp, line))
     {
         if (result != NULL)
-            *result = *point;
-
+            result->x = result->y = get_float8_nan();
         return get_float8_nan();
     }

@@ -2746,7 +2764,9 @@ close_pl(PG_FUNCTION_ARGS)

     result = (Point *) palloc(sizeof(Point));

-    if (isnan(line_closept_point(result, line, pt)))
+    (void) line_closept_point(result, line, pt);
+
+    if (unlikely(isnan(result->x) || isnan(result->y)))
         PG_RETURN_NULL();

     PG_RETURN_POINT_P(result);
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 81202a4c33..8499300b53 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -975,9 +975,9 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               |
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              |
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |
  (1e+300,Infinity) | {3,NaN,5}                             |
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)

Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
Further to this ...

I realized after looking at things some more that one of
line_closept_point's issues is really a bug in line_construct:
it fails to draw a horizontal line through a point with x = Inf,
though surely that's not particularly ill-defined.  The reason
is that somebody thought they could dispense with a special case
for m == 0, but then we end up doing

    result->C = float8_mi(pt->y, float8_mul(m, pt->x));

and if m = 0 and pt->x = Inf, we get NaN.

It also annoyed me that the code was still using DBL_MAX instead of a
true Inf to represent infinite slope.  That's sort of okay as long as
it's just a communication mechanism between line_construct and places
like line_sl, but it's not really okay, because in some places you can
get a true infinity from a slope calculation.  Thus in HEAD you get
different results from

regression=# select line(point(1,2),point(1,'inf'));
   line   
----------
 {-1,0,1}
(1 row)

regression=# select line(point(1,2),point(4,'inf'));
          line           
-------------------------
 {Infinity,-1,-Infinity}
(1 row)

which is completely silly: we ought to "round off" that infinitesimal
slope to a true vertical, rather than producing a line representation
we can't do anything with.

So I fixed that too, but then I got a weird regression test diff:
the case of
    lseg '[(-10,2),(-10,3)]' ?|| lseg '[(-10,2),(-10,3)]'
was no longer returning true.  The reason turned out to be that
lseg_parallel does

    PG_RETURN_BOOL(FPeq(lseg_sl(l1), lseg_sl(l2)));

and now lseg_sl is returning true infinities for vertical lines, and
FPeq *gets the wrong answer* when asked to compare Inf to Inf.  It
should say equal, surely, but internally it computes a NaN and ends up
with false.

So the attached 0003 patch also fixes FPeq() and friends to give
sane answers for Inf-vs-Inf comparisons.  That part seems like
a fairly fundamental bug fix, and so I feel like we ought to
go ahead and apply it before we do too much more messing with
the logic in this area.

(Note that the apparently-large results diff in 0003 is mostly
a whitespace change: the first hunk just reflects slopes coming
out as Infinity not DBL_MAX.)

I'm reposting 0001 and 0002 just to keep the cfbot happy,
they're the same as in my previous message.

            regards, tom lane

diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 93a8736a3f..76679bae8d 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -157,7 +157,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count
 -------
-     3
+     4
 (1 row)

 SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
@@ -169,7 +169,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count
 -------
-     4
+     5
 (1 row)

 SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)';
@@ -188,10 +188,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)

-(10 rows)
+(11 rows)

 SELECT * FROM point_tbl WHERE f1 IS NULL;
  f1
@@ -202,16 +203,17 @@ SELECT * FROM point_tbl WHERE f1 IS NULL;
 SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
         f1
 -------------------
- (1e-300,-1e-300)
  (0,0)
+ (1e-300,-1e-300)
  (-3,4)
  (-10,0)
  (10,10)
  (-5,-12)
  (5.1,34.5)
  (1e+300,Infinity)
+ (Infinity,1e+300)
  (NaN,NaN)
-(9 rows)
+(10 rows)

 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
         f1
@@ -464,7 +466,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)';
  count
 -------
-     3
+     4
 (1 row)

 EXPLAIN (COSTS OFF)
@@ -494,7 +496,7 @@ SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
 SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)';
  count
 -------
-     4
+     5
 (1 row)

 EXPLAIN (COSTS OFF)
@@ -530,10 +532,11 @@ SELECT * FROM point_tbl ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)

-(10 rows)
+(11 rows)

 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 IS NULL;
@@ -568,9 +571,10 @@ SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1';
  (10,10)
  (-5,-12)
  (5.1,34.5)
+ (Infinity,1e+300)
  (1e+300,Infinity)
  (NaN,NaN)
-(9 rows)
+(10 rows)

 EXPLAIN (COSTS OFF)
 SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 5b9d37030f..81202a4c33 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -120,6 +120,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          |                2.4
  (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
  (0,0)             | (1e+300,Infinity) |           Infinity
+ (0,0)             | (Infinity,1e+300) |                  0
  (0,0)             | (NaN,NaN)         |                NaN
  (0,0)             | (10,10)           |                  1
  (-10,0)           | (0,0)             |                  0
@@ -129,6 +130,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          |               -2.4
  (-10,0)           | (1e-300,-1e-300)  |                  0
  (-10,0)           | (1e+300,Infinity) |           Infinity
+ (-10,0)           | (Infinity,1e+300) |                  0
  (-10,0)           | (NaN,NaN)         |                NaN
  (-10,0)           | (10,10)           |                0.5
  (-3,4)            | (0,0)             |     -1.33333333333
@@ -138,6 +140,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          |                  8
  (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
  (-3,4)            | (1e+300,Infinity) |           Infinity
+ (-3,4)            | (Infinity,1e+300) |                  0
  (-3,4)            | (NaN,NaN)         |                NaN
  (-3,4)            | (10,10)           |     0.461538461538
  (5.1,34.5)        | (0,0)             |      6.76470588235
@@ -147,6 +150,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          |      4.60396039604
  (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
  (5.1,34.5)        | (1e+300,Infinity) |           Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |                  0
  (5.1,34.5)        | (NaN,NaN)         |                NaN
  (5.1,34.5)        | (10,10)           |                 -5
  (-5,-12)          | (0,0)             |                2.4
@@ -156,6 +160,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | 1.79769313486e+308
  (-5,-12)          | (1e-300,-1e-300)  |                2.4
  (-5,-12)          | (1e+300,Infinity) |           Infinity
+ (-5,-12)          | (Infinity,1e+300) |                  0
  (-5,-12)          | (NaN,NaN)         |                NaN
  (-5,-12)          | (10,10)           |      1.46666666667
  (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
@@ -165,6 +170,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          |                2.4
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
  (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
  (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
  (1e-300,-1e-300)  | (10,10)           |                  1
  (1e+300,Infinity) | (0,0)             |           Infinity
@@ -174,8 +180,19 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          |           Infinity
  (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
  (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
+ (1e+300,Infinity) | (Infinity,1e+300) |                NaN
  (1e+300,Infinity) | (NaN,NaN)         |                NaN
  (1e+300,Infinity) | (10,10)           |           Infinity
+ (Infinity,1e+300) | (0,0)             |                  0
+ (Infinity,1e+300) | (-10,0)           |                  0
+ (Infinity,1e+300) | (-3,4)            |                  0
+ (Infinity,1e+300) | (5.1,34.5)        |                  0
+ (Infinity,1e+300) | (-5,-12)          |                  0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
+ (Infinity,1e+300) | (1e+300,Infinity) |                NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |                  0
+ (Infinity,1e+300) | (NaN,NaN)         |                NaN
+ (Infinity,1e+300) | (10,10)           |                  0
  (NaN,NaN)         | (0,0)             |                NaN
  (NaN,NaN)         | (-10,0)           |                NaN
  (NaN,NaN)         | (-3,4)            |                NaN
@@ -183,6 +200,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          |                NaN
  (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
  (NaN,NaN)         | (1e+300,Infinity) |                NaN
+ (NaN,NaN)         | (Infinity,1e+300) |                NaN
  (NaN,NaN)         | (NaN,NaN)         |                NaN
  (NaN,NaN)         | (10,10)           |                NaN
  (10,10)           | (0,0)             |                  1
@@ -192,14 +210,15 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          |      1.46666666667
  (10,10)           | (1e-300,-1e-300)  |                  1
  (10,10)           | (1e+300,Infinity) |           Infinity
+ (10,10)           | (Infinity,1e+300) |                  0
  (10,10)           | (NaN,NaN)         |                NaN
  (10,10)           | (10,10)           | 1.79769313486e+308
-(81 rows)
+(100 rows)

 -- Add point
 SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |     ?column?
--------------------+-------------------+-------------------
+        f1         |        f1         |      ?column?
+-------------------+-------------------+---------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (-10,0)
  (0,0)             | (-3,4)            | (-3,4)
@@ -207,6 +226,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (-5,-12)
  (0,0)             | (1e-300,-1e-300)  | (1e-300,-1e-300)
  (0,0)             | (1e+300,Infinity) | (1e+300,Infinity)
+ (0,0)             | (Infinity,1e+300) | (Infinity,1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (10,10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -216,6 +236,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-15,-12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,-1e-300)
  (-10,0)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (-10,0)           | (Infinity,1e+300) | (Infinity,1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (0,10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -225,6 +246,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (-8,-8)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (1e+300,Infinity)
+ (-3,4)            | (Infinity,1e+300) | (Infinity,1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (7,14)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -234,6 +256,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (0.1,22.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (1e+300,Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (Infinity,1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (15.1,44.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -243,6 +266,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (-10,-24)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (1e+300,Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (Infinity,1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (5,-2)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -252,6 +276,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (-5,-12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (2e-300,-2e-300)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (1e+300,Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (Infinity,1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (10,10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -261,8 +286,19 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (2e+300,Infinity)
+ (1e+300,Infinity) | (Infinity,1e+300) | (Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (Infinity,2e+300)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -270,6 +306,7 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -279,14 +316,15 @@ SELECT p1.f1, p2.f1, p1.f1 + p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (5,-2)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (1e+300,Infinity)
+ (10,10)           | (Infinity,1e+300) | (Infinity,1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (20,20)
-(81 rows)
+(100 rows)

 -- Subtract point
 SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |      ?column?
--------------------+-------------------+---------------------
+        f1         |        f1         |       ?column?
+-------------------+-------------------+----------------------
  (0,0)             | (0,0)             | (0,0)
  (0,0)             | (-10,0)           | (10,0)
  (0,0)             | (-3,4)            | (3,-4)
@@ -294,6 +332,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (0,0)             | (-5,-12)          | (5,12)
  (0,0)             | (1e-300,-1e-300)  | (-1e-300,1e-300)
  (0,0)             | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (0,0)             | (Infinity,1e+300) | (-Infinity,-1e+300)
  (0,0)             | (NaN,NaN)         | (NaN,NaN)
  (0,0)             | (10,10)           | (-10,-10)
  (-10,0)           | (0,0)             | (-10,0)
@@ -303,6 +342,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-10,0)           | (-5,-12)          | (-5,12)
  (-10,0)           | (1e-300,-1e-300)  | (-10,1e-300)
  (-10,0)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-10,0)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-10,0)           | (NaN,NaN)         | (NaN,NaN)
  (-10,0)           | (10,10)           | (-20,-10)
  (-3,4)            | (0,0)             | (-3,4)
@@ -312,6 +352,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-3,4)            | (-5,-12)          | (2,16)
  (-3,4)            | (1e-300,-1e-300)  | (-3,4)
  (-3,4)            | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-3,4)            | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-3,4)            | (NaN,NaN)         | (NaN,NaN)
  (-3,4)            | (10,10)           | (-13,-6)
  (5.1,34.5)        | (0,0)             | (5.1,34.5)
@@ -321,6 +362,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (5.1,34.5)        | (-5,-12)          | (10.1,46.5)
  (5.1,34.5)        | (1e-300,-1e-300)  | (5.1,34.5)
  (5.1,34.5)        | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (5.1,34.5)        | (Infinity,1e+300) | (-Infinity,-1e+300)
  (5.1,34.5)        | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5)        | (10,10)           | (-4.9,24.5)
  (-5,-12)          | (0,0)             | (-5,-12)
@@ -330,6 +372,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (-5,-12)          | (-5,-12)          | (0,0)
  (-5,-12)          | (1e-300,-1e-300)  | (-5,-12)
  (-5,-12)          | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (-5,-12)          | (Infinity,1e+300) | (-Infinity,-1e+300)
  (-5,-12)          | (NaN,NaN)         | (NaN,NaN)
  (-5,-12)          | (10,10)           | (-15,-22)
  (1e-300,-1e-300)  | (0,0)             | (1e-300,-1e-300)
@@ -339,6 +382,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e-300,-1e-300)  | (-5,-12)          | (5,12)
  (1e-300,-1e-300)  | (1e-300,-1e-300)  | (0,0)
  (1e-300,-1e-300)  | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (1e-300,-1e-300)  | (Infinity,1e+300) | (-Infinity,-1e+300)
  (1e-300,-1e-300)  | (NaN,NaN)         | (NaN,NaN)
  (1e-300,-1e-300)  | (10,10)           | (-10,-10)
  (1e+300,Infinity) | (0,0)             | (1e+300,Infinity)
@@ -348,8 +392,19 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (1e+300,Infinity) | (-5,-12)          | (1e+300,Infinity)
  (1e+300,Infinity) | (1e-300,-1e-300)  | (1e+300,Infinity)
  (1e+300,Infinity) | (1e+300,Infinity) | (0,NaN)
+ (1e+300,Infinity) | (Infinity,1e+300) | (-Infinity,Infinity)
  (1e+300,Infinity) | (NaN,NaN)         | (NaN,NaN)
  (1e+300,Infinity) | (10,10)           | (1e+300,Infinity)
+ (Infinity,1e+300) | (0,0)             | (Infinity,1e+300)
+ (Infinity,1e+300) | (-10,0)           | (Infinity,1e+300)
+ (Infinity,1e+300) | (-3,4)            | (Infinity,1e+300)
+ (Infinity,1e+300) | (5.1,34.5)        | (Infinity,1e+300)
+ (Infinity,1e+300) | (-5,-12)          | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e-300,-1e-300)  | (Infinity,1e+300)
+ (Infinity,1e+300) | (1e+300,Infinity) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (Infinity,1e+300) | (NaN,0)
+ (Infinity,1e+300) | (NaN,NaN)         | (NaN,NaN)
+ (Infinity,1e+300) | (10,10)           | (Infinity,1e+300)
  (NaN,NaN)         | (0,0)             | (NaN,NaN)
  (NaN,NaN)         | (-10,0)           | (NaN,NaN)
  (NaN,NaN)         | (-3,4)            | (NaN,NaN)
@@ -357,6 +412,7 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (NaN,NaN)         | (-5,-12)          | (NaN,NaN)
  (NaN,NaN)         | (1e-300,-1e-300)  | (NaN,NaN)
  (NaN,NaN)         | (1e+300,Infinity) | (NaN,NaN)
+ (NaN,NaN)         | (Infinity,1e+300) | (NaN,NaN)
  (NaN,NaN)         | (NaN,NaN)         | (NaN,NaN)
  (NaN,NaN)         | (10,10)           | (NaN,NaN)
  (10,10)           | (0,0)             | (10,10)
@@ -366,9 +422,10 @@ SELECT p1.f1, p2.f1, p1.f1 - p2.f1 FROM POINT_TBL p1, POINT_TBL p2;
  (10,10)           | (-5,-12)          | (15,22)
  (10,10)           | (1e-300,-1e-300)  | (10,10)
  (10,10)           | (1e+300,Infinity) | (-1e+300,-Infinity)
+ (10,10)           | (Infinity,1e+300) | (-Infinity,-1e+300)
  (10,10)           | (NaN,NaN)         | (NaN,NaN)
  (10,10)           | (10,10)           | (0,0)
-(81 rows)
+(100 rows)

 -- Multiply with point
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -388,11 +445,13 @@ SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0
  (10,10)    | (1e-300,-1e-300)  | (2e-299,0)
  (5.1,34.5) | (1e+300,Infinity) | (-Infinity,Infinity)
  (10,10)    | (1e+300,Infinity) | (-Infinity,Infinity)
+ (5.1,34.5) | (Infinity,1e+300) | (Infinity,Infinity)
+ (10,10)    | (Infinity,1e+300) | (Infinity,Infinity)
  (5.1,34.5) | (NaN,NaN)         | (NaN,NaN)
  (10,10)    | (NaN,NaN)         | (NaN,NaN)
  (5.1,34.5) | (10,10)           | (-294,396)
  (10,10)    | (10,10)           | (0,200)
-(18 rows)
+(20 rows)

 -- Underflow error
 SELECT p1.f1, p2.f1, p1.f1 * p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p1.f1[0] < 1;
@@ -415,11 +474,13 @@ SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0
  (1e-300,-1e-300)  | (10,10)    | (0,-1e-301)
  (1e+300,Infinity) | (5.1,34.5) | (Infinity,Infinity)
  (1e+300,Infinity) | (10,10)    | (Infinity,Infinity)
+ (Infinity,1e+300) | (5.1,34.5) | (Infinity,-Infinity)
+ (Infinity,1e+300) | (10,10)    | (Infinity,-Infinity)
  (NaN,NaN)         | (5.1,34.5) | (NaN,NaN)
  (NaN,NaN)         | (10,10)    | (NaN,NaN)
  (10,10)           | (5.1,34.5) | (0.325588278822,-0.241724631247)
  (10,10)           | (10,10)    | (1,0)
-(18 rows)
+(20 rows)

 -- Overflow error
 SELECT p1.f1, p2.f1, p1.f1 / p2.f1 FROM POINT_TBL p1, POINT_TBL p2 WHERE p2.f1[0] > 1000;
@@ -501,6 +562,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -521,7 +592,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
  (10,10)           | {-1,0,3}                              |                  7 |                  7
-(90 rows)
+(100 rows)

 -- Distance to line segment
 SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TBL p, LSEG_TBL l;
@@ -583,6 +654,14 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,22),(33,44)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (NaN,NaN)         | [(1,2),(3,4)]                 |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(6,6)]                 |                NaN |                NaN
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |                NaN |                NaN
@@ -599,7 +678,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (10,10)           | [(-10,2),(-10,3)]             |      21.1896201004 |      21.1896201004
  (10,10)           | [(0,-20),(30,-20)]            |                 30 |                 30
  (10,10)           | [(NaN,1),(NaN,90)]            |                NaN |                NaN
-(72 rows)
+(80 rows)

 -- Distance to box
 SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT_TBL p, BOX_TBL b;
@@ -640,6 +719,11 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (1e+300,Infinity) | (-2,2),(-8,-10)     |           Infinity |           Infinity
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
  (1e+300,Infinity) | (3,3),(3,3)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (2,2),(0,0)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(1,1)         |           Infinity |           Infinity
+ (Infinity,1e+300) | (-2,2),(-8,-10)     |           Infinity |           Infinity
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) |           Infinity |           Infinity
+ (Infinity,1e+300) | (3,3),(3,3)         |           Infinity |           Infinity
  (NaN,NaN)         | (2,2),(0,0)         |                NaN |                NaN
  (NaN,NaN)         | (3,3),(1,1)         |                NaN |                NaN
  (NaN,NaN)         | (-2,2),(-8,-10)     |                NaN |                NaN
@@ -650,7 +734,7 @@ SELECT p.f1, b.f1, p.f1 <-> b.f1 AS dist_pb, b.f1 <-> p.f1 AS dist_bp FROM POINT
  (10,10)           | (-2,2),(-8,-10)     |      14.4222051019 |      14.4222051019
  (10,10)           | (2.5,3.5),(2.5,2.5) |      9.92471662064 |      9.92471662064
  (10,10)           | (3,3),(3,3)         |      9.89949493661 |      9.89949493661
-(45 rows)
+(50 rows)

 -- Distance to path
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp FROM POINT_TBL p, PATH_TBL p1;
@@ -719,6 +803,15 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (1e+300,Infinity) | ((10,20))                 |           Infinity |           Infinity
  (1e+300,Infinity) | [(11,12),(13,14)]         |           Infinity |           Infinity
  (1e+300,Infinity) | ((11,12),(13,14))         |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(0,0),(3,0),(4,5),(1,6)] |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((1,2),(3,4))             |           Infinity |           Infinity
+ (Infinity,1e+300) | [(1,2),(3,4)]             |           Infinity |           Infinity
+ (Infinity,1e+300) | ((10,20))                 |           Infinity |           Infinity
+ (Infinity,1e+300) | [(11,12),(13,14)]         |           Infinity |           Infinity
+ (Infinity,1e+300) | ((11,12),(13,14))         |           Infinity |           Infinity
  (NaN,NaN)         | [(1,2),(3,4)]             |                NaN |                NaN
  (NaN,NaN)         | ((1,2),(3,4))             |                NaN |                NaN
  (NaN,NaN)         | [(0,0),(3,0),(4,5),(1,6)] |                NaN |                NaN
@@ -737,7 +830,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppath, p1.f1 <-> p.f1 AS dist_pathp F
  (10,10)           | ((10,20))                 |                 10 |                 10
  (10,10)           | [(11,12),(13,14)]         |       2.2360679775 |       2.2360679775
  (10,10)           | ((11,12),(13,14))         |       2.2360679775 |       2.2360679775
-(81 rows)
+(90 rows)

 -- Distance to polygon
 SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp FROM POINT_TBL p, POLYGON_TBL p1;
@@ -792,6 +885,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,0))                    |      Infinity |      Infinity
  (1e+300,Infinity) | ((0,1),(0,1))              |      Infinity |      Infinity
+ (Infinity,1e+300) | ((2,0),(2,4),(0,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((3,1),(3,3),(1,0))        |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  |      Infinity |      Infinity
+ (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
+ (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
  (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
  (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
  (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
@@ -806,7 +906,7 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | 3.60555127546 | 3.60555127546
  (10,10)           | ((0,0))                    | 14.1421356237 | 14.1421356237
  (10,10)           | ((0,1),(0,1))              | 13.4536240471 | 13.4536240471
-(63 rows)
+(70 rows)

 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -882,6 +982,16 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              |
+ (Infinity,1e+300) | {0,-1,5}                              |
+ (Infinity,1e+300) | {1,0,5}                               |
+ (Infinity,1e+300) | {0,3,0}                               |
+ (Infinity,1e+300) | {1,-1,0}                              |
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |
+ (Infinity,1e+300) | {3,NaN,5}                             |
+ (Infinity,1e+300) | {NaN,NaN,NaN}                         |
+ (Infinity,1e+300) | {0,-1,3}                              |
+ (Infinity,1e+300) | {-1,0,3}                              |
  (NaN,NaN)         | {0,-1,5}                              |
  (NaN,NaN)         | {1,0,5}                               |
  (NaN,NaN)         | {0,3,0}                               |
@@ -902,7 +1012,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (10,10)           | {NaN,NaN,NaN}                         |
  (10,10)           | {0,-1,3}                              | (10,3)
  (10,10)           | {-1,0,3}                              | (3,10)
-(90 rows)
+(100 rows)

 -- Closest point to line segment
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
@@ -964,6 +1074,14 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
  (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
+ (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
+ (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
+ (Infinity,1e+300) | [(-1000000,200),(300000,-40)] | (300000,-40)
+ (Infinity,1e+300) | [(11,22),(33,44)]             | (33,44)
+ (Infinity,1e+300) | [(-10,2),(-10,3)]             | (-10,3)
+ (Infinity,1e+300) | [(0,-20),(30,-20)]            | (30,-20)
+ (Infinity,1e+300) | [(NaN,1),(NaN,90)]            |
  (NaN,NaN)         | [(1,2),(3,4)]                 |
  (NaN,NaN)         | [(0,0),(6,6)]                 |
  (NaN,NaN)         | [(10,-10),(-3,-4)]            |
@@ -980,7 +1098,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (10,10)           | [(-10,2),(-10,3)]             | (-10,3)
  (10,10)           | [(0,-20),(30,-20)]            | (10,-20)
  (10,10)           | [(NaN,1),(NaN,90)]            |
-(72 rows)
+(80 rows)

 -- Closest point to box
 SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
@@ -1021,6 +1139,11 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (1e+300,Infinity) | (-2,2),(-8,-10)     | (-8,2)
  (1e+300,Infinity) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (1e+300,Infinity) | (3,3),(3,3)         | (3,3)
+ (Infinity,1e+300) | (2,2),(0,0)         | (0,2)
+ (Infinity,1e+300) | (3,3),(1,1)         | (1,3)
+ (Infinity,1e+300) | (-2,2),(-8,-10)     | (-8,2)
+ (Infinity,1e+300) | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
+ (Infinity,1e+300) | (3,3),(3,3)         | (3,3)
  (NaN,NaN)         | (2,2),(0,0)         |
  (NaN,NaN)         | (3,3),(1,1)         |
  (NaN,NaN)         | (-2,2),(-8,-10)     |
@@ -1031,7 +1154,7 @@ SELECT p.f1, b.f1, p.f1 ## b.f1 FROM POINT_TBL p, BOX_TBL b;
  (10,10)           | (-2,2),(-8,-10)     | (-2,2)
  (10,10)           | (2.5,3.5),(2.5,2.5) | (2.5,3.5)
  (10,10)           | (3,3),(3,3)         | (3,3)
-(45 rows)
+(50 rows)

 -- On line
 SELECT p.f1, l.s FROM POINT_TBL p, LINE_TBL l WHERE p.f1 <@ l.s;
@@ -2347,6 +2470,11 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
             | (1e+300,Infinity),(1e+300,Infinity)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
+            | (Infinity,1e+300),(Infinity,1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2357,7 +2485,7 @@ SELECT '' AS twentyfour, b.f1 + p.f1 AS translation
             | (8,12),(2,0)
             | (12.5,13.5),(12.5,12.5)
             | (13,13),(13,13)
-(45 rows)
+(50 rows)

 SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
    FROM BOX_TBL b, POINT_TBL p;
@@ -2398,6 +2526,11 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
             | (-1e+300,-Infinity),(-1e+300,-Infinity)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
+            | (-Infinity,-1e+300),(-Infinity,-1e+300)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
             | (NaN,NaN),(NaN,NaN)
@@ -2408,7 +2541,7 @@ SELECT '' AS twentyfour, b.f1 - p.f1 AS translation
             | (-12,-8),(-18,-20)
             | (-7.5,-6.5),(-7.5,-7.5)
             | (-7,-7),(-7,-7)
-(45 rows)
+(50 rows)

 -- Multiply with point
 SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2431,16 +2564,21 @@ SELECT b.f1, p.f1, b.f1 * p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] > 1000;
          f1          |        f1         |                  ?column?
 ---------------------+-------------------+--------------------------------------------
  (2,2),(0,0)         | (1e+300,Infinity) | (NaN,NaN),(-Infinity,Infinity)
+ (2,2),(0,0)         | (Infinity,1e+300) | (NaN,NaN),(Infinity,Infinity)
  (2,2),(0,0)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(1,1)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(1,1)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(1,1)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (-2,2),(-8,-10)     | (1e+300,Infinity) | (Infinity,-Infinity),(-Infinity,-Infinity)
+ (-2,2),(-8,-10)     | (Infinity,1e+300) | (-Infinity,Infinity),(-Infinity,-Infinity)
  (-2,2),(-8,-10)     | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (2.5,3.5),(2.5,2.5) | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (2.5,3.5),(2.5,2.5) | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (2.5,3.5),(2.5,2.5) | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
  (3,3),(3,3)         | (1e+300,Infinity) | (-Infinity,Infinity),(-Infinity,Infinity)
+ (3,3),(3,3)         | (Infinity,1e+300) | (Infinity,Infinity),(Infinity,Infinity)
  (3,3),(3,3)         | (NaN,NaN)         | (NaN,NaN),(NaN,NaN)
-(10 rows)
+(15 rows)

 -- Divide by point
 SELECT b.f1, p.f1, b.f1 / p.f1 FROM BOX_TBL b, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
@@ -2470,9 +2608,10 @@ SELECT f1::box
  (-5,-12),(-5,-12)
  (1e-300,-1e-300),(1e-300,-1e-300)
  (1e+300,Infinity),(1e+300,Infinity)
+ (Infinity,1e+300),(Infinity,1e+300)
  (NaN,NaN),(NaN,NaN)
  (10,10),(10,10)
-(9 rows)
+(10 rows)

 SELECT bound_box(a.f1, b.f1)
     FROM BOX_TBL a, BOX_TBL b;
@@ -3102,6 +3241,15 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((1e+300,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(1e+300,Infinity),(1e+300,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((1e+300,Infinity),(1e+300,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300),(Infinity,1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,1e+300),(Infinity,1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,1e+300),(Infinity,1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3120,7 +3268,7 @@ SELECT p.f1, p1.f1, p.f1 + p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((20,30))
  [(11,12),(13,14)]         | (10,10)           | [(21,22),(23,24)]
  ((11,12),(13,14))         | (10,10)           | ((21,22),(23,24))
-(81 rows)
+(90 rows)

 -- Subtract point
 SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3189,6 +3337,15 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-1e+300,-Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-1e+300,-Infinity),(-1e+300,-Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-1e+300,-Infinity),(-1e+300,-Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) |
[(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((10,20))                 | (Infinity,1e+300) | ((-Infinity,-1e+300))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(-Infinity,-1e+300),(-Infinity,-1e+300)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((-Infinity,-1e+300),(-Infinity,-1e+300))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3207,7 +3364,7 @@ SELECT p.f1, p1.f1, p.f1 - p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((0,10))
  [(11,12),(13,14)]         | (10,10)           | [(1,2),(3,4)]
  ((11,12),(13,14))         | (10,10)           | ((1,2),(3,4))
-(81 rows)
+(90 rows)

 -- Multiply with point
 SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
@@ -3276,6 +3433,15 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (1e+300,Infinity) | ((-Infinity,Infinity))
  [(11,12),(13,14)]         | (1e+300,Infinity) | [(-Infinity,Infinity),(-Infinity,Infinity)]
  ((11,12),(13,14))         | (1e+300,Infinity) | ((-Infinity,Infinity),(-Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(0,0),(3,0),(4,5),(1,6)] | (Infinity,1e+300) | [(NaN,NaN),(Infinity,NaN),(Infinity,Infinity),(Infinity,Infinity)]
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ ((1,2),(3,4))             | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
+ [(1,2),(3,4)]             | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((10,20))                 | (Infinity,1e+300) | ((Infinity,Infinity))
+ [(11,12),(13,14)]         | (Infinity,1e+300) | [(Infinity,Infinity),(Infinity,Infinity)]
+ ((11,12),(13,14))         | (Infinity,1e+300) | ((Infinity,Infinity),(Infinity,Infinity))
  [(1,2),(3,4)]             | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN)]
  ((1,2),(3,4))             | (NaN,NaN)         | ((NaN,NaN),(NaN,NaN))
  [(0,0),(3,0),(4,5),(1,6)] | (NaN,NaN)         | [(NaN,NaN),(NaN,NaN),(NaN,NaN),(NaN,NaN)]
@@ -3294,7 +3460,7 @@ SELECT p.f1, p1.f1, p.f1 * p1.f1 FROM PATH_TBL p, POINT_TBL p1;
  ((10,20))                 | (10,10)           | ((-100,300))
  [(11,12),(13,14)]         | (10,10)           | [(-10,230),(-10,270)]
  ((11,12),(13,14))         | (10,10)           | ((-10,230),(-10,270))
-(81 rows)
+(90 rows)

 -- Divide by point
 SELECT p.f1, p1.f1, p.f1 / p1.f1 FROM PATH_TBL p, POINT_TBL p1 WHERE p1.f1[0] BETWEEN 1 AND 1000;
@@ -3467,6 +3633,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3481,7 +3654,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)

 SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
    FROM POLYGON_TBL poly, POINT_TBL p;
@@ -3536,6 +3709,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (1e+300,Infinity) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (1e+300,Infinity) | ((0,0))                    | f
             | (1e+300,Infinity) | ((0,1),(0,1))              | f
+            | (Infinity,1e+300) | ((2,0),(2,4),(0,0))        | f
+            | (Infinity,1e+300) | ((3,1),(3,3),(1,0))        | f
+            | (Infinity,1e+300) | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (Infinity,1e+300) | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (Infinity,1e+300) | ((0,0))                    | f
+            | (Infinity,1e+300) | ((0,1),(0,1))              | f
             | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
             | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
             | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
@@ -3550,7 +3730,7 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (10,10)           | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (10,10)           | ((0,0))                    | f
             | (10,10)           | ((0,1),(0,1))              | f
-(63 rows)
+(70 rows)

 SELECT '' AS four, npoints(f1) AS npoints, f1 AS polygon
    FROM POLYGON_TBL;
@@ -3929,9 +4109,10 @@ SELECT '' AS six, circle(f1, 50.0)
      | <(-5,-12),50>
      | <(1e-300,-1e-300),50>
      | <(1e+300,Infinity),50>
+     | <(Infinity,1e+300),50>
      | <(NaN,NaN),50>
      | <(10,10),50>
-(9 rows)
+(10 rows)

 SELECT '' AS four, circle(f1)
    FROM BOX_TBL;
@@ -3993,12 +4174,19 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(100,200),10> | (-10,0)           |  218.25424421
             | <(100,200),10> | (-5,-12)          | 226.577682802
             | <(3,5),0>      | (1e+300,Infinity) |      Infinity
+            | <(3,5),0>      | (Infinity,1e+300) |      Infinity
             | <(1,2),3>      | (1e+300,Infinity) |      Infinity
             | <(5,1),3>      | (1e+300,Infinity) |      Infinity
+            | <(5,1),3>      | (Infinity,1e+300) |      Infinity
+            | <(1,2),3>      | (Infinity,1e+300) |      Infinity
             | <(1,3),5>      | (1e+300,Infinity) |      Infinity
+            | <(1,3),5>      | (Infinity,1e+300) |      Infinity
             | <(100,200),10> | (1e+300,Infinity) |      Infinity
+            | <(100,200),10> | (Infinity,1e+300) |      Infinity
             | <(1,2),100>    | (1e+300,Infinity) |      Infinity
+            | <(1,2),100>    | (Infinity,1e+300) |      Infinity
             | <(100,1),115>  | (1e+300,Infinity) |      Infinity
+            | <(100,1),115>  | (Infinity,1e+300) |      Infinity
             | <(3,5),0>      | (NaN,NaN)         |           NaN
             | <(1,2),3>      | (NaN,NaN)         |           NaN
             | <(5,1),3>      | (NaN,NaN)         |           NaN
@@ -4014,8 +4202,9 @@ SELECT '' AS twentyfour, c1.f1 AS circle, p1.f1 AS point, (p1.f1 <-> c1.f1) AS d
             | <(3,5),NaN>    | (5.1,34.5)        |           NaN
             | <(3,5),NaN>    | (10,10)           |           NaN
             | <(3,5),NaN>    | (1e+300,Infinity) |           NaN
+            | <(3,5),NaN>    | (Infinity,1e+300) |           NaN
             | <(3,5),NaN>    | (NaN,NaN)         |           NaN
-(53 rows)
+(61 rows)

 -- To polygon
 SELECT f1, f1::polygon FROM CIRCLE_TBL WHERE f1 >= '<(0,0),1>';
@@ -4626,6 +4815,14 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(1e+300,Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(1e+300,Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(1e+300,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4642,7 +4839,7 @@ SELECT c.f1, p.f1, c.f1 + p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(110,11),115>
  <(3,5),0>      | (10,10)           | <(13,15),0>
  <(3,5),NaN>    | (10,10)           | <(13,15),NaN>
-(72 rows)
+(80 rows)

 -- Subtract point
 SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4704,6 +4901,14 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-1e+300,-Infinity),115>
  <(3,5),0>      | (1e+300,Infinity) | <(-1e+300,-Infinity),0>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-1e+300,-Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(1,2),100>    | (Infinity,1e+300) | <(-Infinity,-1e+300),100>
+ <(1,3),5>      | (Infinity,1e+300) | <(-Infinity,-1e+300),5>
+ <(1,2),3>      | (Infinity,1e+300) | <(-Infinity,-1e+300),3>
+ <(100,200),10> | (Infinity,1e+300) | <(-Infinity,-1e+300),10>
+ <(100,1),115>  | (Infinity,1e+300) | <(-Infinity,-1e+300),115>
+ <(3,5),0>      | (Infinity,1e+300) | <(-Infinity,-1e+300),0>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(-Infinity,-1e+300),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),3>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),100>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),5>
@@ -4720,7 +4925,7 @@ SELECT c.f1, p.f1, c.f1 - p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(90,-9),115>
  <(3,5),0>      | (10,10)           | <(-7,-5),0>
  <(3,5),NaN>    | (10,10)           | <(-7,-5),NaN>
-(72 rows)
+(80 rows)

 -- Multiply with point
 SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
@@ -4782,6 +4987,14 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (1e+300,Infinity) | <(-Infinity,Infinity),Infinity>
  <(3,5),0>      | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
  <(3,5),NaN>    | (1e+300,Infinity) | <(-Infinity,Infinity),NaN>
+ <(5,1),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),100>    | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,3),5>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(1,2),3>      | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,200),10> | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(100,1),115>  | (Infinity,1e+300) | <(Infinity,Infinity),Infinity>
+ <(3,5),0>      | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
+ <(3,5),NaN>    | (Infinity,1e+300) | <(Infinity,Infinity),NaN>
  <(5,1),3>      | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,2),100>    | (NaN,NaN)         | <(NaN,NaN),NaN>
  <(1,3),5>      | (NaN,NaN)         | <(NaN,NaN),NaN>
@@ -4798,7 +5011,7 @@ SELECT c.f1, p.f1, c.f1 * p.f1 FROM CIRCLE_TBL c, POINT_TBL p;
  <(100,1),115>  | (10,10)           | <(990,1010),1626.34559673>
  <(3,5),0>      | (10,10)           | <(-20,80),0>
  <(3,5),NaN>    | (10,10)           | <(-20,80),NaN>
-(72 rows)
+(80 rows)

 -- Divide by point
 SELECT c.f1, p.f1, c.f1 / p.f1 FROM CIRCLE_TBL c, POINT_TBL p WHERE p.f1[0] BETWEEN 1 AND 1000;
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 15e3b83b37..77e250fc3e 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -11,6 +11,7 @@ INSERT INTO POINT_TBL(f1) VALUES ('(5.1, 34.5)');
 INSERT INTO POINT_TBL(f1) VALUES ('(-5.0,-12.0)');
 INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow
 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow
+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');
 -- bad format points
 INSERT INTO POINT_TBL(f1) VALUES ('asdfasdf');
@@ -44,9 +45,10 @@ SELECT '' AS six, * FROM POINT_TBL;
      | (-5,-12)
      | (1e-300,-1e-300)
      | (1e+300,Infinity)
+     | (Infinity,1e+300)
      | (NaN,NaN)
      | (10,10)
-(9 rows)
+(10 rows)

 -- left of
 SELECT '' AS three, p.* FROM POINT_TBL p WHERE p.f1 << '(0.0, 0.0)';
@@ -115,8 +117,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)

 SELECT '' AS two, p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -136,8 +139,9 @@ SELECT '' AS three, p.* FROM POINT_TBL p
        | (-5,-12)
        | (1e-300,-1e-300)
        | (1e+300,Infinity)
+       | (Infinity,1e+300)
        | (NaN,NaN)
-(6 rows)
+(7 rows)

 SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
@@ -152,8 +156,9 @@ SELECT '' AS six, p.f1, p.f1 <-> point '(0,0)' AS dist
      | (10,10)           |      14.142135623731
      | (5.1,34.5)        |     34.8749193547455
      | (1e+300,Infinity) |             Infinity
+     | (Infinity,1e+300) |             Infinity
      | (NaN,NaN)         |                  NaN
-(9 rows)
+(10 rows)

 SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dist
    FROM POINT_TBL p1, POINT_TBL p2
@@ -210,12 +215,19 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (-5,-12)          | (5.1,34.5)        |     47.5842410888311
            | (5.1,34.5)        | (-5,-12)          |     47.5842410888311
            | (-10,0)           | (1e+300,Infinity) |             Infinity
+           | (-10,0)           | (Infinity,1e+300) |             Infinity
            | (-5,-12)          | (1e+300,Infinity) |             Infinity
+           | (-5,-12)          | (Infinity,1e+300) |             Infinity
            | (-3,4)            | (1e+300,Infinity) |             Infinity
+           | (-3,4)            | (Infinity,1e+300) |             Infinity
            | (0,0)             | (1e+300,Infinity) |             Infinity
+           | (0,0)             | (Infinity,1e+300) |             Infinity
            | (1e-300,-1e-300)  | (1e+300,Infinity) |             Infinity
+           | (1e-300,-1e-300)  | (Infinity,1e+300) |             Infinity
            | (5.1,34.5)        | (1e+300,Infinity) |             Infinity
+           | (5.1,34.5)        | (Infinity,1e+300) |             Infinity
            | (10,10)           | (1e+300,Infinity) |             Infinity
+           | (10,10)           | (Infinity,1e+300) |             Infinity
            | (1e+300,Infinity) | (-10,0)           |             Infinity
            | (1e+300,Infinity) | (-5,-12)          |             Infinity
            | (1e+300,Infinity) | (-3,4)            |             Infinity
@@ -223,6 +235,15 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (1e+300,Infinity) | (1e-300,-1e-300)  |             Infinity
            | (1e+300,Infinity) | (5.1,34.5)        |             Infinity
            | (1e+300,Infinity) | (10,10)           |             Infinity
+           | (1e+300,Infinity) | (Infinity,1e+300) |             Infinity
+           | (Infinity,1e+300) | (-10,0)           |             Infinity
+           | (Infinity,1e+300) | (-5,-12)          |             Infinity
+           | (Infinity,1e+300) | (-3,4)            |             Infinity
+           | (Infinity,1e+300) | (0,0)             |             Infinity
+           | (Infinity,1e+300) | (1e-300,-1e-300)  |             Infinity
+           | (Infinity,1e+300) | (5.1,34.5)        |             Infinity
+           | (Infinity,1e+300) | (10,10)           |             Infinity
+           | (Infinity,1e+300) | (1e+300,Infinity) |             Infinity
            | (-10,0)           | (NaN,NaN)         |                  NaN
            | (-5,-12)          | (NaN,NaN)         |                  NaN
            | (-3,4)            | (NaN,NaN)         |                  NaN
@@ -232,6 +253,8 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (10,10)           | (NaN,NaN)         |                  NaN
            | (1e+300,Infinity) | (1e+300,Infinity) |                  NaN
            | (1e+300,Infinity) | (NaN,NaN)         |                  NaN
+           | (Infinity,1e+300) | (Infinity,1e+300) |                  NaN
+           | (Infinity,1e+300) | (NaN,NaN)         |                  NaN
            | (NaN,NaN)         | (-10,0)           |                  NaN
            | (NaN,NaN)         | (-5,-12)          |                  NaN
            | (NaN,NaN)         | (-3,4)            |                  NaN
@@ -240,8 +263,9 @@ SELECT '' AS thirtysix, p1.f1 AS point1, p2.f1 AS point2, p1.f1 <-> p2.f1 AS dis
            | (NaN,NaN)         | (5.1,34.5)        |                  NaN
            | (NaN,NaN)         | (10,10)           |                  NaN
            | (NaN,NaN)         | (1e+300,Infinity) |                  NaN
+           | (NaN,NaN)         | (Infinity,1e+300) |                  NaN
            | (NaN,NaN)         | (NaN,NaN)         |                  NaN
-(81 rows)
+(100 rows)

 SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
    FROM POINT_TBL p1, POINT_TBL p2
@@ -253,6 +277,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (0,0)             | (5.1,34.5)
         | (0,0)             | (-5,-12)
         | (0,0)             | (1e+300,Infinity)
+        | (0,0)             | (Infinity,1e+300)
         | (0,0)             | (NaN,NaN)
         | (0,0)             | (10,10)
         | (-10,0)           | (0,0)
@@ -261,6 +286,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-10,0)           | (-5,-12)
         | (-10,0)           | (1e-300,-1e-300)
         | (-10,0)           | (1e+300,Infinity)
+        | (-10,0)           | (Infinity,1e+300)
         | (-10,0)           | (NaN,NaN)
         | (-10,0)           | (10,10)
         | (-3,4)            | (0,0)
@@ -269,6 +295,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-3,4)            | (-5,-12)
         | (-3,4)            | (1e-300,-1e-300)
         | (-3,4)            | (1e+300,Infinity)
+        | (-3,4)            | (Infinity,1e+300)
         | (-3,4)            | (NaN,NaN)
         | (-3,4)            | (10,10)
         | (5.1,34.5)        | (0,0)
@@ -277,6 +304,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (5.1,34.5)        | (-5,-12)
         | (5.1,34.5)        | (1e-300,-1e-300)
         | (5.1,34.5)        | (1e+300,Infinity)
+        | (5.1,34.5)        | (Infinity,1e+300)
         | (5.1,34.5)        | (NaN,NaN)
         | (5.1,34.5)        | (10,10)
         | (-5,-12)          | (0,0)
@@ -285,6 +313,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (-5,-12)          | (5.1,34.5)
         | (-5,-12)          | (1e-300,-1e-300)
         | (-5,-12)          | (1e+300,Infinity)
+        | (-5,-12)          | (Infinity,1e+300)
         | (-5,-12)          | (NaN,NaN)
         | (-5,-12)          | (10,10)
         | (1e-300,-1e-300)  | (-10,0)
@@ -292,6 +321,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e-300,-1e-300)  | (5.1,34.5)
         | (1e-300,-1e-300)  | (-5,-12)
         | (1e-300,-1e-300)  | (1e+300,Infinity)
+        | (1e-300,-1e-300)  | (Infinity,1e+300)
         | (1e-300,-1e-300)  | (NaN,NaN)
         | (1e-300,-1e-300)  | (10,10)
         | (1e+300,Infinity) | (0,0)
@@ -301,8 +331,19 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (1e+300,Infinity) | (-5,-12)
         | (1e+300,Infinity) | (1e-300,-1e-300)
         | (1e+300,Infinity) | (1e+300,Infinity)
+        | (1e+300,Infinity) | (Infinity,1e+300)
         | (1e+300,Infinity) | (NaN,NaN)
         | (1e+300,Infinity) | (10,10)
+        | (Infinity,1e+300) | (0,0)
+        | (Infinity,1e+300) | (-10,0)
+        | (Infinity,1e+300) | (-3,4)
+        | (Infinity,1e+300) | (5.1,34.5)
+        | (Infinity,1e+300) | (-5,-12)
+        | (Infinity,1e+300) | (1e-300,-1e-300)
+        | (Infinity,1e+300) | (1e+300,Infinity)
+        | (Infinity,1e+300) | (Infinity,1e+300)
+        | (Infinity,1e+300) | (NaN,NaN)
+        | (Infinity,1e+300) | (10,10)
         | (NaN,NaN)         | (0,0)
         | (NaN,NaN)         | (-10,0)
         | (NaN,NaN)         | (-3,4)
@@ -310,6 +351,7 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (NaN,NaN)         | (-5,-12)
         | (NaN,NaN)         | (1e-300,-1e-300)
         | (NaN,NaN)         | (1e+300,Infinity)
+        | (NaN,NaN)         | (Infinity,1e+300)
         | (NaN,NaN)         | (NaN,NaN)
         | (NaN,NaN)         | (10,10)
         | (10,10)           | (0,0)
@@ -319,57 +361,67 @@ SELECT '' AS thirty, p1.f1 AS point1, p2.f1 AS point2
         | (10,10)           | (-5,-12)
         | (10,10)           | (1e-300,-1e-300)
         | (10,10)           | (1e+300,Infinity)
+        | (10,10)           | (Infinity,1e+300)
         | (10,10)           | (NaN,NaN)
-(72 rows)
+(91 rows)

 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS fifteen, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1
    ORDER BY distance, p1.f1[0], p2.f1[0];
- fifteen |      point1      |      point2       |     distance
----------+------------------+-------------------+------------------
-         | (-3,4)           | (0,0)             |                5
-         | (-3,4)           | (1e-300,-1e-300)  |                5
-         | (-10,0)          | (-3,4)            | 8.06225774829855
-         | (-10,0)          | (0,0)             |               10
-         | (-10,0)          | (1e-300,-1e-300)  |               10
-         | (-10,0)          | (-5,-12)          |               13
-         | (-5,-12)         | (0,0)             |               13
-         | (-5,-12)         | (1e-300,-1e-300)  |               13
-         | (0,0)            | (10,10)           |  14.142135623731
-         | (1e-300,-1e-300) | (10,10)           |  14.142135623731
-         | (-3,4)           | (10,10)           | 14.3178210632764
-         | (-5,-12)         | (-3,4)            | 16.1245154965971
-         | (-10,0)          | (10,10)           | 22.3606797749979
-         | (5.1,34.5)       | (10,10)           | 24.9851956166046
-         | (-5,-12)         | (10,10)           | 26.6270539113887
-         | (-3,4)           | (5.1,34.5)        | 31.5572495632937
-         | (0,0)            | (5.1,34.5)        | 34.8749193547455
-         | (1e-300,-1e-300) | (5.1,34.5)        | 34.8749193547455
-         | (-10,0)          | (5.1,34.5)        | 37.6597928831267
-         | (-5,-12)         | (5.1,34.5)        | 47.5842410888311
-         | (-10,0)          | (1e+300,Infinity) |         Infinity
-         | (-5,-12)         | (1e+300,Infinity) |         Infinity
-         | (-3,4)           | (1e+300,Infinity) |         Infinity
-         | (0,0)            | (1e+300,Infinity) |         Infinity
-         | (1e-300,-1e-300) | (1e+300,Infinity) |         Infinity
-         | (5.1,34.5)       | (1e+300,Infinity) |         Infinity
-         | (10,10)          | (1e+300,Infinity) |         Infinity
-(27 rows)
+ fifteen |      point1       |      point2       |     distance
+---------+-------------------+-------------------+------------------
+         | (-3,4)            | (0,0)             |                5
+         | (-3,4)            | (1e-300,-1e-300)  |                5
+         | (-10,0)           | (-3,4)            | 8.06225774829855
+         | (-10,0)           | (0,0)             |               10
+         | (-10,0)           | (1e-300,-1e-300)  |               10
+         | (-10,0)           | (-5,-12)          |               13
+         | (-5,-12)          | (0,0)             |               13
+         | (-5,-12)          | (1e-300,-1e-300)  |               13
+         | (0,0)             | (10,10)           |  14.142135623731
+         | (1e-300,-1e-300)  | (10,10)           |  14.142135623731
+         | (-3,4)            | (10,10)           | 14.3178210632764
+         | (-5,-12)          | (-3,4)            | 16.1245154965971
+         | (-10,0)           | (10,10)           | 22.3606797749979
+         | (5.1,34.5)        | (10,10)           | 24.9851956166046
+         | (-5,-12)          | (10,10)           | 26.6270539113887
+         | (-3,4)            | (5.1,34.5)        | 31.5572495632937
+         | (0,0)             | (5.1,34.5)        | 34.8749193547455
+         | (1e-300,-1e-300)  | (5.1,34.5)        | 34.8749193547455
+         | (-10,0)           | (5.1,34.5)        | 37.6597928831267
+         | (-5,-12)          | (5.1,34.5)        | 47.5842410888311
+         | (-10,0)           | (1e+300,Infinity) |         Infinity
+         | (-10,0)           | (Infinity,1e+300) |         Infinity
+         | (-5,-12)          | (1e+300,Infinity) |         Infinity
+         | (-5,-12)          | (Infinity,1e+300) |         Infinity
+         | (-3,4)            | (1e+300,Infinity) |         Infinity
+         | (-3,4)            | (Infinity,1e+300) |         Infinity
+         | (0,0)             | (1e+300,Infinity) |         Infinity
+         | (0,0)             | (Infinity,1e+300) |         Infinity
+         | (1e-300,-1e-300)  | (1e+300,Infinity) |         Infinity
+         | (1e-300,-1e-300)  | (Infinity,1e+300) |         Infinity
+         | (5.1,34.5)        | (1e+300,Infinity) |         Infinity
+         | (5.1,34.5)        | (Infinity,1e+300) |         Infinity
+         | (10,10)           | (1e+300,Infinity) |         Infinity
+         | (10,10)           | (Infinity,1e+300) |         Infinity
+         | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(35 rows)

 -- put distance result into output to allow sorting with GEQ optimizer - tgl 97/05/10
 SELECT '' AS three, p1.f1 AS point1, p2.f1 AS point2, (p1.f1 <-> p2.f1) AS distance
    FROM POINT_TBL p1, POINT_TBL p2
    WHERE (p1.f1 <-> p2.f1) > 3 and p1.f1 << p2.f1 and p1.f1 >^ p2.f1
    ORDER BY distance;
- three |   point1   |      point2      |     distance
--------+------------+------------------+------------------
-       | (-3,4)     | (0,0)            |                5
-       | (-3,4)     | (1e-300,-1e-300) |                5
-       | (-10,0)    | (-5,-12)         |               13
-       | (5.1,34.5) | (10,10)          | 24.9851956166046
-(4 rows)
+ three |      point1       |      point2       |     distance
+-------+-------------------+-------------------+------------------
+       | (-3,4)            | (0,0)             |                5
+       | (-3,4)            | (1e-300,-1e-300)  |                5
+       | (-10,0)           | (-5,-12)          |               13
+       | (5.1,34.5)        | (10,10)           | 24.9851956166046
+       | (1e+300,Infinity) | (Infinity,1e+300) |         Infinity
+(5 rows)

 -- Test that GiST indexes provide same behavior as sequential scan
 CREATE TEMP TABLE point_gist_tbl(f1 point);
diff --git a/src/test/regress/sql/point.sql b/src/test/regress/sql/point.sql
index 7f8504dbd1..6a1ca12d5c 100644
--- a/src/test/regress/sql/point.sql
+++ b/src/test/regress/sql/point.sql
@@ -21,6 +21,8 @@ INSERT INTO POINT_TBL(f1) VALUES ('(1e-300,-1e-300)');    -- To underflow

 INSERT INTO POINT_TBL(f1) VALUES ('(1e+300,Inf)');        -- To overflow

+INSERT INTO POINT_TBL(f1) VALUES ('(Inf,1e+300)');        -- Transposed
+
 INSERT INTO POINT_TBL(f1) VALUES (' ( Nan , NaN ) ');

 -- bad format points
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index a7db783958..fc6493a0d7 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -2707,9 +2707,14 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
  *-------------------------------------------------------------------*/

 /*
- * If *result is not NULL, it is set to the intersection point of a
- * perpendicular of the line through the point.  Returns the distance
- * of those two points.
+ * Determine the closest point on the given line to the given point.
+ * If result is not NULL, *result is set to the coordinates of that point.
+ * In any case, returns the distance from the point to the line.
+ * Returns NaN for any ill-defined value.
+ *
+ * NOTE: in some cases the distance is well defined (i.e., infinity)
+ * even though the specific closest point is not.  Hence, if you care
+ * about whether the point is well-defined, check its coordinates for NaNs.
  */
 static float8
 line_closept_point(Point *result, LINE *line, Point *point)
@@ -2717,17 +2722,30 @@ line_closept_point(Point *result, LINE *line, Point *point)
     Point        closept;
     LINE        tmp;

+    /*
+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    if (unlikely(isnan(float8_pl(float8_pl(float8_mul(line->A, point->x),
+                                           float8_mul(line->B, point->y)),
+                                 line->C))))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
-     * should always find it, but that can fail in the presence of NaN
-     * coordinates, and perhaps even from simple roundoff issues.
+     * should always find it, but perhaps roundoff issues could prevent that.
      */
     line_construct(&tmp, point, line_invsl(line));
     if (!line_interpt_line(&closept, &tmp, line))
     {
         if (result != NULL)
-            *result = *point;
-
+            result->x = result->y = get_float8_nan();
         return get_float8_nan();
     }

@@ -2746,7 +2764,9 @@ close_pl(PG_FUNCTION_ARGS)

     result = (Point *) palloc(sizeof(Point));

-    if (isnan(line_closept_point(result, line, pt)))
+    (void) line_closept_point(result, line, pt);
+
+    if (unlikely(isnan(result->x) || isnan(result->y)))
         PG_RETURN_NULL();

     PG_RETURN_POINT_P(result);
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 81202a4c33..8499300b53 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -975,9 +975,9 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               |
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              |
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |
  (1e+300,Infinity) | {3,NaN,5}                             |
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index fc6493a0d7..a358296c98 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -1055,13 +1055,20 @@ line_send(PG_FUNCTION_ARGS)
 static inline void
 line_construct(LINE *result, Point *pt, float8 m)
 {
-    if (m == DBL_MAX)
+    if (isinf(m))
     {
         /* vertical - use "x = C" */
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
     }
+    else if (m == 0)
+    {
+        /* horizontal - use "y = C" */
+        result->A = 0.0;
+        result->B = -1.0;
+        result->C = pt->y;
+    }
     else
     {
         /* use "mx - y + yinter = 0" */
@@ -1197,7 +1204,7 @@ line_sl(LINE *line)
     if (FPzero(line->A))
         return 0.0;
     if (FPzero(line->B))
-        return DBL_MAX;
+        return get_float8_infinity();
     return float8_div(line->A, -line->B);
 }

@@ -1209,7 +1216,7 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
-        return DBL_MAX;
+        return get_float8_infinity();
     if (FPzero(line->B))
         return 0.0;
     return float8_div(line->B, line->A);
@@ -1974,13 +1981,13 @@ point_slope(PG_FUNCTION_ARGS)
 /*
  * Return slope of two points
  *
- * Note that this function returns DBL_MAX when the points are the same.
+ * Note that this function returns Inf when the points are the same.
  */
 static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
-        return DBL_MAX;
+        return get_float8_infinity();
     if (FPeq(pt1->y, pt2->y))
         return 0.0;
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
@@ -1998,7 +2005,7 @@ point_invsl(Point *pt1, Point *pt2)
     if (FPeq(pt1->x, pt2->x))
         return 0.0;
     if (FPeq(pt1->y, pt2->y))
-        return DBL_MAX;
+        return get_float8_infinity();
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }

diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index d4617558f1..6d19033f4e 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -20,23 +20,57 @@

 #include "fmgr.h"

+#include <math.h>
+
 /*--------------------------------------------------------------------
  * Useful floating point utilities and constants.
  *-------------------------------------------------------------------
  *
- * XXX: They are not NaN-aware.
+ * XXX: These are not NaN-aware.  They have, however, been made to give
+ * sane answers for infinity inputs (where it's important to avoid
+ * computing Inf minus Inf).
  */

 #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)
+
+static inline bool
+FPeq(double A, double B)
+{
+    return A == B || fabs(A - B) <= EPSILON;
+}
+
+static inline bool
+FPne(double A, double B)
+{
+    return A != B && fabs(A - B) > EPSILON;
+}
+
+static inline bool
+FPlt(double A, double B)
+{
+    return A != B && B - A > EPSILON;
+}
+
+static inline bool
+FPle(double A, double B)
+{
+    return A == B || A - B <= EPSILON;
+}
+
+static inline bool
+FPgt(double A, double B)
+{
+    return A != B && A - B > EPSILON;
+}
+
+static inline bool
+FPge(double A, double B)
+{
+    return A == B || B - A <= EPSILON;
+}
 #else
 #define FPzero(A)                ((A) == 0)
 #define FPeq(A,B)                ((A) == (B))
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 8499300b53..3233dae21b 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -111,108 +111,108 @@ SELECT '' AS one, p1.f1

 -- Slope
 SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
-        f1         |        f1         |       slope
--------------------+-------------------+--------------------
- (0,0)             | (0,0)             | 1.79769313486e+308
- (0,0)             | (-10,0)           |                  0
- (0,0)             | (-3,4)            |     -1.33333333333
- (0,0)             | (5.1,34.5)        |      6.76470588235
- (0,0)             | (-5,-12)          |                2.4
- (0,0)             | (1e-300,-1e-300)  | 1.79769313486e+308
- (0,0)             | (1e+300,Infinity) |           Infinity
- (0,0)             | (Infinity,1e+300) |                  0
- (0,0)             | (NaN,NaN)         |                NaN
- (0,0)             | (10,10)           |                  1
- (-10,0)           | (0,0)             |                  0
- (-10,0)           | (-10,0)           | 1.79769313486e+308
- (-10,0)           | (-3,4)            |     0.571428571429
- (-10,0)           | (5.1,34.5)        |      2.28476821192
- (-10,0)           | (-5,-12)          |               -2.4
- (-10,0)           | (1e-300,-1e-300)  |                  0
- (-10,0)           | (1e+300,Infinity) |           Infinity
- (-10,0)           | (Infinity,1e+300) |                  0
- (-10,0)           | (NaN,NaN)         |                NaN
- (-10,0)           | (10,10)           |                0.5
- (-3,4)            | (0,0)             |     -1.33333333333
- (-3,4)            | (-10,0)           |     0.571428571429
- (-3,4)            | (-3,4)            | 1.79769313486e+308
- (-3,4)            | (5.1,34.5)        |      3.76543209877
- (-3,4)            | (-5,-12)          |                  8
- (-3,4)            | (1e-300,-1e-300)  |     -1.33333333333
- (-3,4)            | (1e+300,Infinity) |           Infinity
- (-3,4)            | (Infinity,1e+300) |                  0
- (-3,4)            | (NaN,NaN)         |                NaN
- (-3,4)            | (10,10)           |     0.461538461538
- (5.1,34.5)        | (0,0)             |      6.76470588235
- (5.1,34.5)        | (-10,0)           |      2.28476821192
- (5.1,34.5)        | (-3,4)            |      3.76543209877
- (5.1,34.5)        | (5.1,34.5)        | 1.79769313486e+308
- (5.1,34.5)        | (-5,-12)          |      4.60396039604
- (5.1,34.5)        | (1e-300,-1e-300)  |      6.76470588235
- (5.1,34.5)        | (1e+300,Infinity) |           Infinity
- (5.1,34.5)        | (Infinity,1e+300) |                  0
- (5.1,34.5)        | (NaN,NaN)         |                NaN
- (5.1,34.5)        | (10,10)           |                 -5
- (-5,-12)          | (0,0)             |                2.4
- (-5,-12)          | (-10,0)           |               -2.4
- (-5,-12)          | (-3,4)            |                  8
- (-5,-12)          | (5.1,34.5)        |      4.60396039604
- (-5,-12)          | (-5,-12)          | 1.79769313486e+308
- (-5,-12)          | (1e-300,-1e-300)  |                2.4
- (-5,-12)          | (1e+300,Infinity) |           Infinity
- (-5,-12)          | (Infinity,1e+300) |                  0
- (-5,-12)          | (NaN,NaN)         |                NaN
- (-5,-12)          | (10,10)           |      1.46666666667
- (1e-300,-1e-300)  | (0,0)             | 1.79769313486e+308
- (1e-300,-1e-300)  | (-10,0)           |                  0
- (1e-300,-1e-300)  | (-3,4)            |     -1.33333333333
- (1e-300,-1e-300)  | (5.1,34.5)        |      6.76470588235
- (1e-300,-1e-300)  | (-5,-12)          |                2.4
- (1e-300,-1e-300)  | (1e-300,-1e-300)  | 1.79769313486e+308
- (1e-300,-1e-300)  | (1e+300,Infinity) |           Infinity
- (1e-300,-1e-300)  | (Infinity,1e+300) |                  0
- (1e-300,-1e-300)  | (NaN,NaN)         |                NaN
- (1e-300,-1e-300)  | (10,10)           |                  1
- (1e+300,Infinity) | (0,0)             |           Infinity
- (1e+300,Infinity) | (-10,0)           |           Infinity
- (1e+300,Infinity) | (-3,4)            |           Infinity
- (1e+300,Infinity) | (5.1,34.5)        |           Infinity
- (1e+300,Infinity) | (-5,-12)          |           Infinity
- (1e+300,Infinity) | (1e-300,-1e-300)  |           Infinity
- (1e+300,Infinity) | (1e+300,Infinity) | 1.79769313486e+308
- (1e+300,Infinity) | (Infinity,1e+300) |                NaN
- (1e+300,Infinity) | (NaN,NaN)         |                NaN
- (1e+300,Infinity) | (10,10)           |           Infinity
- (Infinity,1e+300) | (0,0)             |                  0
- (Infinity,1e+300) | (-10,0)           |                  0
- (Infinity,1e+300) | (-3,4)            |                  0
- (Infinity,1e+300) | (5.1,34.5)        |                  0
- (Infinity,1e+300) | (-5,-12)          |                  0
- (Infinity,1e+300) | (1e-300,-1e-300)  |                  0
- (Infinity,1e+300) | (1e+300,Infinity) |                NaN
- (Infinity,1e+300) | (Infinity,1e+300) |                  0
- (Infinity,1e+300) | (NaN,NaN)         |                NaN
- (Infinity,1e+300) | (10,10)           |                  0
- (NaN,NaN)         | (0,0)             |                NaN
- (NaN,NaN)         | (-10,0)           |                NaN
- (NaN,NaN)         | (-3,4)            |                NaN
- (NaN,NaN)         | (5.1,34.5)        |                NaN
- (NaN,NaN)         | (-5,-12)          |                NaN
- (NaN,NaN)         | (1e-300,-1e-300)  |                NaN
- (NaN,NaN)         | (1e+300,Infinity) |                NaN
- (NaN,NaN)         | (Infinity,1e+300) |                NaN
- (NaN,NaN)         | (NaN,NaN)         |                NaN
- (NaN,NaN)         | (10,10)           |                NaN
- (10,10)           | (0,0)             |                  1
- (10,10)           | (-10,0)           |                0.5
- (10,10)           | (-3,4)            |     0.461538461538
- (10,10)           | (5.1,34.5)        |                 -5
- (10,10)           | (-5,-12)          |      1.46666666667
- (10,10)           | (1e-300,-1e-300)  |                  1
- (10,10)           | (1e+300,Infinity) |           Infinity
- (10,10)           | (Infinity,1e+300) |                  0
- (10,10)           | (NaN,NaN)         |                NaN
- (10,10)           | (10,10)           | 1.79769313486e+308
+        f1         |        f1         |     slope
+-------------------+-------------------+----------------
+ (0,0)             | (0,0)             |       Infinity
+ (0,0)             | (-10,0)           |              0
+ (0,0)             | (-3,4)            | -1.33333333333
+ (0,0)             | (5.1,34.5)        |  6.76470588235
+ (0,0)             | (-5,-12)          |            2.4
+ (0,0)             | (1e-300,-1e-300)  |       Infinity
+ (0,0)             | (1e+300,Infinity) |       Infinity
+ (0,0)             | (Infinity,1e+300) |              0
+ (0,0)             | (NaN,NaN)         |            NaN
+ (0,0)             | (10,10)           |              1
+ (-10,0)           | (0,0)             |              0
+ (-10,0)           | (-10,0)           |       Infinity
+ (-10,0)           | (-3,4)            | 0.571428571429
+ (-10,0)           | (5.1,34.5)        |  2.28476821192
+ (-10,0)           | (-5,-12)          |           -2.4
+ (-10,0)           | (1e-300,-1e-300)  |              0
+ (-10,0)           | (1e+300,Infinity) |       Infinity
+ (-10,0)           | (Infinity,1e+300) |              0
+ (-10,0)           | (NaN,NaN)         |            NaN
+ (-10,0)           | (10,10)           |            0.5
+ (-3,4)            | (0,0)             | -1.33333333333
+ (-3,4)            | (-10,0)           | 0.571428571429
+ (-3,4)            | (-3,4)            |       Infinity
+ (-3,4)            | (5.1,34.5)        |  3.76543209877
+ (-3,4)            | (-5,-12)          |              8
+ (-3,4)            | (1e-300,-1e-300)  | -1.33333333333
+ (-3,4)            | (1e+300,Infinity) |       Infinity
+ (-3,4)            | (Infinity,1e+300) |              0
+ (-3,4)            | (NaN,NaN)         |            NaN
+ (-3,4)            | (10,10)           | 0.461538461538
+ (5.1,34.5)        | (0,0)             |  6.76470588235
+ (5.1,34.5)        | (-10,0)           |  2.28476821192
+ (5.1,34.5)        | (-3,4)            |  3.76543209877
+ (5.1,34.5)        | (5.1,34.5)        |       Infinity
+ (5.1,34.5)        | (-5,-12)          |  4.60396039604
+ (5.1,34.5)        | (1e-300,-1e-300)  |  6.76470588235
+ (5.1,34.5)        | (1e+300,Infinity) |       Infinity
+ (5.1,34.5)        | (Infinity,1e+300) |              0
+ (5.1,34.5)        | (NaN,NaN)         |            NaN
+ (5.1,34.5)        | (10,10)           |             -5
+ (-5,-12)          | (0,0)             |            2.4
+ (-5,-12)          | (-10,0)           |           -2.4
+ (-5,-12)          | (-3,4)            |              8
+ (-5,-12)          | (5.1,34.5)        |  4.60396039604
+ (-5,-12)          | (-5,-12)          |       Infinity
+ (-5,-12)          | (1e-300,-1e-300)  |            2.4
+ (-5,-12)          | (1e+300,Infinity) |       Infinity
+ (-5,-12)          | (Infinity,1e+300) |              0
+ (-5,-12)          | (NaN,NaN)         |            NaN
+ (-5,-12)          | (10,10)           |  1.46666666667
+ (1e-300,-1e-300)  | (0,0)             |       Infinity
+ (1e-300,-1e-300)  | (-10,0)           |              0
+ (1e-300,-1e-300)  | (-3,4)            | -1.33333333333
+ (1e-300,-1e-300)  | (5.1,34.5)        |  6.76470588235
+ (1e-300,-1e-300)  | (-5,-12)          |            2.4
+ (1e-300,-1e-300)  | (1e-300,-1e-300)  |       Infinity
+ (1e-300,-1e-300)  | (1e+300,Infinity) |       Infinity
+ (1e-300,-1e-300)  | (Infinity,1e+300) |              0
+ (1e-300,-1e-300)  | (NaN,NaN)         |            NaN
+ (1e-300,-1e-300)  | (10,10)           |              1
+ (1e+300,Infinity) | (0,0)             |       Infinity
+ (1e+300,Infinity) | (-10,0)           |       Infinity
+ (1e+300,Infinity) | (-3,4)            |       Infinity
+ (1e+300,Infinity) | (5.1,34.5)        |       Infinity
+ (1e+300,Infinity) | (-5,-12)          |       Infinity
+ (1e+300,Infinity) | (1e-300,-1e-300)  |       Infinity
+ (1e+300,Infinity) | (1e+300,Infinity) |       Infinity
+ (1e+300,Infinity) | (Infinity,1e+300) |            NaN
+ (1e+300,Infinity) | (NaN,NaN)         |            NaN
+ (1e+300,Infinity) | (10,10)           |       Infinity
+ (Infinity,1e+300) | (0,0)             |              0
+ (Infinity,1e+300) | (-10,0)           |              0
+ (Infinity,1e+300) | (-3,4)            |              0
+ (Infinity,1e+300) | (5.1,34.5)        |              0
+ (Infinity,1e+300) | (-5,-12)          |              0
+ (Infinity,1e+300) | (1e-300,-1e-300)  |              0
+ (Infinity,1e+300) | (1e+300,Infinity) |            NaN
+ (Infinity,1e+300) | (Infinity,1e+300) |       Infinity
+ (Infinity,1e+300) | (NaN,NaN)         |            NaN
+ (Infinity,1e+300) | (10,10)           |              0
+ (NaN,NaN)         | (0,0)             |            NaN
+ (NaN,NaN)         | (-10,0)           |            NaN
+ (NaN,NaN)         | (-3,4)            |            NaN
+ (NaN,NaN)         | (5.1,34.5)        |            NaN
+ (NaN,NaN)         | (-5,-12)          |            NaN
+ (NaN,NaN)         | (1e-300,-1e-300)  |            NaN
+ (NaN,NaN)         | (1e+300,Infinity) |            NaN
+ (NaN,NaN)         | (Infinity,1e+300) |            NaN
+ (NaN,NaN)         | (NaN,NaN)         |            NaN
+ (NaN,NaN)         | (10,10)           |            NaN
+ (10,10)           | (0,0)             |              1
+ (10,10)           | (-10,0)           |            0.5
+ (10,10)           | (-3,4)            | 0.461538461538
+ (10,10)           | (5.1,34.5)        |             -5
+ (10,10)           | (-5,-12)          |  1.46666666667
+ (10,10)           | (1e-300,-1e-300)  |              1
+ (10,10)           | (1e+300,Infinity) |       Infinity
+ (10,10)           | (Infinity,1e+300) |              0
+ (10,10)           | (NaN,NaN)         |            NaN
+ (10,10)           | (10,10)           |       Infinity
 (100 rows)

 -- Add point
@@ -563,7 +563,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
  (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
- (Infinity,1e+300) | {1,0,5}                               |                NaN |                NaN
+ (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
  (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
  (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
  (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
@@ -571,7 +571,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {-1,0,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
  (NaN,NaN)         | {0,3,0}                               |                NaN |                NaN
@@ -983,7 +983,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
  (1e+300,Infinity) | {-1,0,3}                              |
  (Infinity,1e+300) | {0,-1,5}                              |
- (Infinity,1e+300) | {1,0,5}                               |
+ (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
  (Infinity,1e+300) | {0,3,0}                               |
  (Infinity,1e+300) | {1,-1,0}                              |
  (Infinity,1e+300) | {-0.4,-1,-6}                          |
@@ -991,7 +991,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (Infinity,1e+300) | {3,NaN,5}                             |
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |
  (Infinity,1e+300) | {0,-1,3}                              |
- (Infinity,1e+300) | {-1,0,3}                              |
+ (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              |
  (NaN,NaN)         | {1,0,5}                               |
  (NaN,NaN)         | {0,3,0}                               |

Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
I went ahead and pushed 0001 and 0003 (the latter in two parts), since
they didn't seem particularly controversial to me.  Just to keep the
cfbot from whining, here's a rebased version of 0002.

            regards, tom lane

diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index c1dc511a1a..d9f577bd8b 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -2719,9 +2719,14 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
  *-------------------------------------------------------------------*/

 /*
- * If *result is not NULL, it is set to the intersection point of a
- * perpendicular of the line through the point.  Returns the distance
- * of those two points.
+ * Determine the closest point on the given line to the given point.
+ * If result is not NULL, *result is set to the coordinates of that point.
+ * In any case, returns the distance from the point to the line.
+ * Returns NaN for any ill-defined value.
+ *
+ * NOTE: in some cases the distance is well defined (i.e., infinity)
+ * even though the specific closest point is not.  Hence, if you care
+ * about whether the point is well-defined, check its coordinates for NaNs.
  */
 static float8
 line_closept_point(Point *result, LINE *line, Point *point)
@@ -2729,17 +2734,30 @@ line_closept_point(Point *result, LINE *line, Point *point)
     Point        closept;
     LINE        tmp;

+    /*
+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    if (unlikely(isnan(float8_pl(float8_pl(float8_mul(line->A, point->x),
+                                           float8_mul(line->B, point->y)),
+                                 line->C))))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
-     * should always find it, but that can fail in the presence of NaN
-     * coordinates, and perhaps even from simple roundoff issues.
+     * should always find it, but perhaps roundoff issues could prevent that.
      */
     line_construct(&tmp, point, line_invsl(line));
     if (!line_interpt_line(&closept, &tmp, line))
     {
         if (result != NULL)
-            *result = *point;
-
+            result->x = result->y = get_float8_nan();
         return get_float8_nan();
     }

@@ -2758,7 +2776,9 @@ close_pl(PG_FUNCTION_ARGS)

     result = (Point *) palloc(sizeof(Point));

-    if (isnan(line_closept_point(result, line, pt)))
+    (void) line_closept_point(result, line, pt);
+
+    if (unlikely(isnan(result->x) || isnan(result->y)))
         PG_RETURN_NULL();

     PG_RETURN_POINT_P(result);
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index c4f853ae9f..6210075bc1 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -1070,9 +1070,9 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
  (1e+300,Infinity) | {1,0,5}                               |
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              |
+ (1e+300,Infinity) | {-0.4,-1,-6}                          |
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} |
  (1e+300,Infinity) | {3,NaN,5}                             |
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)

Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Sat, 21 Nov 2020 17:33:53 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> I went ahead and pushed 0001 and 0003 (the latter in two parts), since
> they didn't seem particularly controversial to me.  Just to keep the
> cfbot from whining, here's a rebased version of 0002.

I didn't noticed that inf == inf sould be true (in IEEE754).

# (inf - inf == 0) => false but (inf == inf + 0) == false is somewhat
# uneasy but, yes, it's the standare we are basing on.

So, I agree that the changes of line_construct() and line_(inv)sl()
looks good to me.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Fri, 20 Nov 2020 15:57:46 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> I spent some more time looking at this patch.
> 
> Some experimentation shows that the changes around bounding box
> calculation (ie float8_min_nan() and its call sites) seem to be
> completely pointless: removing them doesn't change any of the regression
> results.  Nor does using float8_min_nan() in the other two bounding-box
> calculations I'd asked about.  So I think we should just drop that set
> of changes and stick with the rule that bounding box upper and lower
> values are sorted as per float.h comparison rules.  This isn't that hard
> to work with: if you want to know whether any NaNs are in the box, test
> the upper limit (and *not* the lower limit) for isnan().  Moreover, even
> if we wanted a different coding rule, we really can't have it because we
> will still need to work with existing on-disk values that have bounding
> boxes computed the old way.

Actually that changes the result since that code gives a shortcut of
checking NaNs in the object coordinates. I don't think that the it is
pointless to avoid full calculations that are performed only to find
NaNs are involved, if bounding box check is meaningful.

> I don't much like anything about float8_coef_mul().  In the first place,
> FPzero() is an ugly, badly designed condition that we should be trying
> to get rid of not add more dependencies on.  In the second place, it's
> really unclear why allowing 0 times Inf to be something other than NaN
> is a good idea, and it's even less clear why allowing small-but-not-zero
> times Inf to be zero rather than Inf is a good idea.  In the third
> place, the asymmetry between the two inputs looks more like a bug than
> something we should actually want.

I have the same feeling on the function, but I concluded that
coefficients and coordinates should be regarded as different things in
the practical standpoint.

For example, consider Ax + By + C == 0, if B is 0.0, we can remove the
second term from the equation, regardless of the value of y, of course
even if it were inf. that is, The function imitates that kind of
removals.

> After some time spent staring at the specific case of line_closept_point
> and its callers, I decided that the real problems there are twofold.
> First, the API, or at least the callers' interpretation of this
> undocumented point, is that whether the distance is undefined (NaN) is
> equivalent to whether the closest point is undefined.  This is not so;
> in some cases we know that the distance is infinite even though we can't
> calculate a unique closest point.  Second, it's not making any attempt
> to eliminate undefined cases up front.  We can do that pretty easily
> by plugging the point's coordinates into the line's equation Ax+By+C
> and seeing whether we get a NaN.  The attached 0002 is a subset patch
> that just fixes these two issues, and I like the results it produces.

Actually the code reacts to some "problem" cases in a "wrong" way:

+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    if (unlikely(isnan(float8_pl(float8_pl(float8_mul(line->A, point->x),
+                                           float8_mul(line->B, point->y)),
+                                 line->C))))

| postgres=# select point(1e+300, 'Infinity') <-> line('{1,0,5}');
|  ?column? 
| ----------
|       NaN

Aren't our guts telling that is 1e+300?  You might be thinking to put
some special case handling into that path (as mentioned below?), but
otherwise it yeildsa "wrong" result.  The reason for the expectation
is that we assume that "completely vertical" lines have a constant x
value regardless of the y coordinate.  That is the reason for the
float8_coef_mul() function.

> I wonder now whether the problems around line_interpt_line() and the
> other intersection-ish functions wouldn't be better handled in a similar
> way, by making changes to their API specs to be clearer about what
> happens with NaNs and trying to eliminate ill-defined cases explicitly.
> I've not tried to code that though.

One of the "ill-defined" cases is the zero-coefficient issue.  The
asymmetric multiply function "fixes" it, at least.  Of course it could
be open-coded instead of being as a function that looks as if having
some general interpretation.

> Changing pg_hypot() the way you've done here is right out.  See the
> comment for the function: what it is doing now is per all the relevant
> standards, and your patch breaks that.  It's extremely unlikely that
> doing it differently from IEEE and POSIX is a good idea.

Mmm. Ok, I agree to that.

> Attached are the same old 0001 (adding the extra point_tbl entry)
> and a small 0002 that fixes just line_closept_point.  I've not
> tried to figure out just which of the rest of your diffs should be
> dropped given that.  I did note though that the example you add
> to func.sgml doesn't apply to this version of line_closept_point:
> 
> regression=# select point '(Infinity,Infinity)' <-> line '{-1,0,5}';
>  ?column? 
> ----------
>       NaN
> (1 row)
> 
> regression=# select point '(Infinity,Infinity)' <-> line '{0,-1,5}';
>  ?column? 
> ----------
>       NaN
> (1 row)

They root on the same "zero-coefficient issue" with my example shown
above.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes:
> At Fri, 20 Nov 2020 15:57:46 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
>> I don't much like anything about float8_coef_mul().

> I have the same feeling on the function, but I concluded that
> coefficients and coordinates should be regarded as different things in
> the practical standpoint.

> For example, consider Ax + By + C == 0, if B is 0.0, we can remove the
> second term from the equation, regardless of the value of y, of course
> even if it were inf. that is, The function imitates that kind of
> removals.

Meh --- I can see where you're going with that, but I don't much like it.
I fear that it's as likely to introduce weird behaviors as remove any.

The core of the issue in

> | postgres=# select point(1e+300, 'Infinity') <-> line('{1,0,5}');
> |  ?column? 
> | ----------
> |       NaN

is that we generate the line y = Inf:

(gdb) p tmp
$1 = {A = 0, B = -1, C = inf}

and then try to find the intersection with {1,0,5} (x = -5), but that
calculation involves 0 * Inf so we get NaNs.  It seems reasonable that
the intersection should be (-5,Inf), but I don't think we should try
to force the normal calculation to produce that.  I think we'd be
better off to explicitly special-case vertical and/or horizontal lines
in line_interpt_line.

Actually though ... even if we successfully got that intersection
point, we'd still end up with a NaN distance between (1e300,Inf) and
(-5,Inf), on account of Inf - Inf being NaN.  I think this is correct
and we'd be ill-advised to try to force it to be something else.
Although we pretend that two Infs are equal for purposes such as
sorting, they aren't really, so we should not assume that their
difference is zero.

So that line of thought prompts me to tread *very* carefully when
trying to dodge NaN results.  We need to be certain that we
introduce only logically-defensible special cases.  Something like
float8_coef_mul() seems much more likely to lead us into errors
than away from them.

            regards, tom lane



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
(My mailer seems to have recovered from unresponsiveness.)

At Tue, 24 Nov 2020 12:29:41 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> Kyotaro Horiguchi <horikyota.ntt@gmail.com> writes:
> > At Fri, 20 Nov 2020 15:57:46 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> >> I don't much like anything about float8_coef_mul().
> 
> > I have the same feeling on the function, but I concluded that
> > coefficients and coordinates should be regarded as different things in
> > the practical standpoint.
> 
> > For example, consider Ax + By + C == 0, if B is 0.0, we can remove the
> > second term from the equation, regardless of the value of y, of course
> > even if it were inf. that is, The function imitates that kind of
> > removals.
> 
> Meh --- I can see where you're going with that, but I don't much like it.
> I fear that it's as likely to introduce weird behaviors as remove any.
>
> The core of the issue in
> 
> > | postgres=# select point(1e+300, 'Infinity') <-> line('{1,0,5}');
> > |  ?column? 
> > | ----------
> > |       NaN
> 
> is that we generate the line y = Inf:
> 
> (gdb) p tmp
> $1 = {A = 0, B = -1, C = inf}
> 
> and then try to find the intersection with {1,0,5} (x = -5), but that
> calculation involves 0 * Inf so we get NaNs.  It seems reasonable that
> the intersection should be (-5,Inf), but I don't think we should try
> to force the normal calculation to produce that.  I think we'd be
> better off to explicitly special-case vertical and/or horizontal lines
> in line_interpt_line.

I don't object to have explicit special case for vertical lines since
it is clear than embedding such a function in the formula, but it
seems equivalent to what the function is doing, that is, treating inf
* 0.0 as 0.0 in some special cases.

# And after rethinking, the FPzero() used in the function is wrong
# since the macro (function) is expected to be applied to coordinates,
# not to coefficients.

> Actually though ... even if we successfully got that intersection
> point, we'd still end up with a NaN distance between (1e300,Inf) and
> (-5,Inf), on account of Inf - Inf being NaN.  I think this is correct
> and we'd be ill-advised to try to force it to be something else.
> Although we pretend that two Infs are equal for purposes such as
> sorting, they aren't really, so we should not assume that their
> difference is zero.

The definition "inf == inf" comes from some practical reasons
uncertain to me, and actually inf - inf yields NaN in IEEE
754. However, aren't we going to assume a line on which B is exactly
0.0 as a completely vertical line?  Thus things are slightiy different
from the IEEE's definition.  The "Inf" as the y-coord of the
perpendicular foot is actually "the same y-coord with the point".  So
what we should do on our definition for the calculation is:

perp-foot (line {1,0,5}, point(1e300, Inf)) => point(-5, <y of the point>)
distance (point(1e300, Inf), point(-5, <y of the point>)) => 1e300 (+5)

This is what the code below is doing:

+    return float8_div(fabs(float8_pl(
+                               float8_pl(
+                                   float8_coef_mul(line->A, point->x, false),
+                                   float8_coef_mul(line->B, point->y, false)),
+                               line->C)),
+                      HYPOT(line->A, line->B));

> So that line of thought prompts me to tread *very* carefully when
> trying to dodge NaN results.  We need to be certain that we
> introduce only logically-defensible special cases.  Something like
> float8_coef_mul() seems much more likely to lead us into errors
> than away from them.

Agreed on that point.  I'm going to rewirte the patch in that
direction.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Wed, 25 Nov 2020 11:39:39 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in 
> > So that line of thought prompts me to tread *very* carefully when
> > trying to dodge NaN results.  We need to be certain that we
> > introduce only logically-defensible special cases.  Something like
> > float8_coef_mul() seems much more likely to lead us into errors
> > than away from them.
> 
> Agreed on that point.  I'm going to rewirte the patch in that
> direction.

Removed the function float8_coef_mul().


I noticed that the check you proposed to add to line_closept_point
doesn't work for the following case:

select line('{1,-1,0}') <-> point(1e300, 'Infinity');

Ax + By + C = 1 * 1e300 + -1 * Inf + 0 = -Inf is not NaN so we go on
the following steps.

derive the perpendicular line: => line(-1, -1, Inf}
derive the cross point       : => point(Inf, Inf)
calculate the distance       : => NaN  (which should be Infinity)

So I left the check whether distance is NaN in this version. In the previous version the check is done before directly
calculatingthe distance, but since we already have the result of Ax+Bx+C so I decided not to use point_dt() in this
 
version.

Although I wrote that it should be wrong that applying FPzero() to
coefficients, there are some places already doing that so I followed
those predecessors.


Reverted the change of pg_hypot().


While checking the regression results, I noticed that the follwoing
calculation, which seems wrong.

select line('{3,NaN,5}') = line('{3,NaN,5}');
 ?column? 
----------
 t

But after looking point_eq(), I decided to let the behavior alone
since I'm not sure the reason for the behavior of the functions. At
least the comment for point_eq() says that is the delibarate
behvior. box_same, poly_same base on the point_eq_point so they behave
the same way.


By the way, '=' doesn't compare the shape but compares the area.
However, what is the area of a line?  That should be always 0 even if
we considered it. And it is also strange that we don't have
corresponding comparison ('<' and so) operators.  It seems to me as if
a mistake of '~='.  If it is correct, I should revert the change of
line_eq() along with fixing operator assignment.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From 4f8f8605afcd97571bc891bff17b63c963e27fb5 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Fri, 13 Nov 2020 13:31:20 +0900
Subject: [PATCH v7] fix geometric nan handling

---
 doc/src/sgml/func.sgml                     |  17 ++
 src/backend/utils/adt/geo_ops.c            | 337 ++++++++++++++++++---
 src/include/utils/float.h                  |  22 ++
 src/test/regress/expected/create_index.out |   2 +-
 src/test/regress/expected/geometry.out     | 331 +++++++++-----------
 5 files changed, 485 insertions(+), 224 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 507bc1a668..dc9fe52174 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10859,6 +10859,23 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
     </para>
    </note>
 
+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
+
    <table id="functions-geometry-func-table">
     <title>Geometric Functions</title>
     <tgroup cols="1">
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index c1dc511a1a..e74bf3031e 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,9 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    result->high.x = float8_min_nan(box1->high.x, box2->high.x);
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+    result->high.y = float8_min_nan(box1->high.y, box2->high.y);
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,15 +1061,23 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else if (m == 0)
+    else if (m == 0.0)
     {
         /* horizontal - use "y = C" */
         result->A = 0.0;
         result->B = -1.0;
         result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else
+    else if (!isnan(m))
     {
         /* use "mx - y + yinter = 0" */
         result->A = m;
@@ -1078,7 +1086,12 @@ line_construct(LINE *result, Point *pt, float8 m)
         /* on some platforms, the preceding expression tends to produce -0 */
         if (result->C == 0.0)
             result->C = 0.0;
+
+        if (likely(!isnan(result->C)))
+            return;
     }
+
+    result->A = result->B = result->C = get_float8_nan();
 }
 
 /* line_construct_pp()
@@ -1091,6 +1104,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1111,8 +1125,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1130,14 +1148,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1148,7 +1169,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1156,7 +1177,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1206,9 +1227,20 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     return float8_div(line->A, -line->B);
 }
 
@@ -1220,9 +1252,20 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1235,14 +1278,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2)) /* intersecting? */
+    {
+        /* return NaN if NaN is involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1264,8 +1316,13 @@ line_interpt(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (!line_interpt_line(result, l1, l2))
+    if (!line_interpt_line(result, l1, l2) ||
+        isnan(result->x) || isnan(result->y))
+    {
+        pfree(result);
         PG_RETURN_NULL();
+    }
+
     PG_RETURN_POINT_P(result);
 }
 
@@ -1291,6 +1348,7 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
 
     if (!FPzero(l1->B))
     {
+        /* l1 is not virtucal */
         if (FPeq(l2->A, float8_mul(l1->A, float8_div(l2->B, l1->B))))
             return false;
 
@@ -1298,18 +1356,34 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
                                  float8_mul(l2->B, l1->C)),
                        float8_mi(float8_mul(l1->A, l2->B),
                                  float8_mul(l2->A, l1->B)));
-        y = float8_div(-float8_pl(float8_mul(l1->A, x), l1->C), l1->B);
-    }
-    else if (!FPzero(l2->B))
-    {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
-
-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
+        /*
+         * You might want to simplify this expression by using x, but that can
+         * introduce unnecessary indeterminants (inf-inf) into the calculation,
+         * which leads to a wrong result.
+         * (For example, (-1, -1, Inf) and (1, -1, 0))
+         */
+        y = float8_div(float8_mi(float8_mul(l1->A, l2->C),
+                                 float8_mul(l2->A, l1->C)),
                        float8_mi(float8_mul(l2->A, l1->B),
                                  float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+    }
+    else if (!FPzero(l2->B))
+    {
+        /* l2 is not virtical */
+        /*
+         * We know that l1 is vertical here. The lines cannot be parallel and
+         * the x-coord of the cross point is -C/A of l1.
+         */
+        x = -float8_div(l1->C, l1->A);
+
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
     }
     else
         return false;
@@ -1639,8 +1713,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
-        b1.low.y = float8_min(p1->p[i].y, b1.low.y);
+        b1.low.x = float8_min_nan(p1->p[i].x, b1.low.x);
+        b1.low.y = float8_min_nan(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;
@@ -1648,8 +1722,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
-        b2.low.y = float8_min(p2->p[i].y, b2.low.y);
+        b2.low.x = float8_min_nan(p2->p[i].x, b2.low.x);
+        b2.low.y = float8_min_nan(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
         PG_RETURN_BOOL(false);
@@ -1739,6 +1813,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1992,9 +2071,19 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
+
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -2008,9 +2097,19 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
+
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2426,6 +2525,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2657,6 +2761,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2686,7 +2792,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2728,6 +2835,78 @@ line_closept_point(Point *result, LINE *line, Point *point)
 {
     Point        closept;
     LINE        tmp;
+    float8        val;
+
+    /*
+     * Treat specially the cases where A = 0 and B = 0, which we regard the
+     * line is perfectly horizontal and vertical correspondingly, not applying
+     * the normal formula involving the behavior of inf*0 =NaN defined by
+     * IEEE754.
+     */
+    if (FPzero(line->A))
+    {
+        float8 y;
+
+        /* the line is horizontal */
+        Assert(!FPzero(line->B));
+
+        y = -line->C / line->B;
+
+        /* Avoid -0 */
+        if (y == 0.0)
+            y = 0.0;
+
+        if (result != NULL)
+        {
+            result->x = point->x;
+            result->y = y;
+        }
+
+        if (unlikely(isnan(point->x)))
+            return get_float8_nan();
+
+        return fabs(point->y - y);
+    }
+    else if (FPzero(line->B))
+    {
+        float x;
+
+        /* the line is virtical */
+        Assert(!FPzero(line->A));
+
+        x = -line->C / line->A;
+
+        /* Avoid -0 */
+        if (x == 0)
+            x = 0;
+
+        if (result != NULL)
+        {
+            result->x = x;
+            result->y = point->y;
+        }
+
+        if (unlikely(isnan(point->y)))
+            return get_float8_nan();
+
+        return fabs(point->x - x);
+    }
+
+    /*
+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    val = float8_pl(float8_pl(float8_mul(line->A, point->x),
+                              float8_mul(line->B, point->y)),
+                    line->C);
+    if (unlikely(isnan(val)))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
 
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
@@ -2738,7 +2917,7 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (!line_interpt_line(&closept, &tmp, line))
     {
         if (result != NULL)
-            *result = *point;
+            result->x = result->y = get_float8_nan();
 
         return get_float8_nan();
     }
@@ -2746,7 +2925,17 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (result != NULL)
         *result = closept;
 
-    return point_dt(&closept, point);
+    /*
+     * If the closest point contains Inf's, the closest point may lose
+     * arithmetic relationship with the point which lets point_dt wrongly give
+     * NaN. To avoid that kind of failure, we calculate the distance using the
+     * following formula instead of using the closest point.
+     *
+     * | A*x + B*y + C | / sqrt(A^2 + B^2)
+     *
+     * The dividend have been already calculated so just divide it.
+     */
+    return float8_div(fabs(val), HYPOT(line->A, line->B));
 }
 
 Datum
@@ -2758,7 +2947,9 @@ close_pl(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (isnan(line_closept_point(result, line, pt)))
+    (void) line_closept_point(result, line, pt);
+
+    if (unlikely(isnan(result->x) || isnan(result->y)))
         PG_RETURN_NULL();
 
     PG_RETURN_POINT_P(result);
@@ -2815,6 +3006,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        anynan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2826,6 +3018,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    anynan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2835,6 +3028,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2842,6 +3036,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2849,6 +3044,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2885,6 +3086,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        anynan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2899,9 +3101,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    anynan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2913,6 +3116,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2922,6 +3126,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2929,6 +3134,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -3000,6 +3212,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3022,6 +3235,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3147,9 +3368,32 @@ close_lb(PG_FUNCTION_ARGS)
 static bool
 line_contain_point(LINE *line, Point *point)
 {
-    return FPzero(float8_pl(float8_pl(float8_mul(line->A, point->x),
-                                      float8_mul(line->B, point->y)),
-                            line->C));
+    /*
+     * Treat specially way the cases where A = 0 and B = 0, which we regard the
+     * line is perfectly horizontal and vertical correspondingly to avoid the
+     * normal formula based on the IEEE754's definitions yields unwanted NaNs.
+     */
+    if (line->A == 0.0)
+    {
+        /* the line is horizontal */
+        Assert(line->B != 0.0);
+
+        /* inf == inf here */
+        return FPeq(point->y, -line->C / line->B);
+    }
+    else if (line->B == 0.0)
+    {
+        /* the line is vertical */
+        Assert(line->A != 0.0);
+
+        /* inf == inf here */
+        return FPeq(point->x, -line->C / line->A);
+    }
+
+    return FPzero(float8_pl(
+                      float8_pl(float8_mul(line->A, point->x),
+                                float8_mul(line->B, point->y)),
+                      line->C));
 }
 
 Datum
@@ -3448,6 +3692,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3923,6 +4173,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5362,6 +5617,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5371,6 +5630,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 79bf8daca8..52bcf853f2 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -353,4 +353,26 @@ float8_max(const float8 val1, const float8 val2)
     return float8_gt(val1, val2) ? val1 : val2;
 }
 
+/*
+ * These two functions return NaN if either input is NaN, else the smaller
+ * of the two inputs.  This does NOT follow our usual sort rule, but it is
+ * convenient in some places.  (Note that float4_max and float8_max act this
+ * way anyway, so no similar variant is needed for them.)
+ */
+static inline float4
+float4_min_nan(const float4 val1, const float4 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
+static inline float8
+float8_min_nan(const float8 val1, const float8 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
 #endif                            /* FLOAT_H */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index 18bb92b810..363c784513 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index c4f853ae9f..e0aa2a67cb 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -517,7 +517,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-3,4)            | {0,3,0}                               |                  4 |                  4
  (-3,4)            | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-3,4)            | {-0.4,-1,-6}                          |      8.17059487979 |      8.17059487979
- (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690368 |      11.3851690368
+ (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690367 |      11.3851690367
  (-3,4)            | {3,NaN,5}                             |                NaN |                NaN
  (-3,4)            | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-3,4)            | {0,-1,3}                              |                  1 |                  1
@@ -537,7 +537,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-5,-12)          | {0,3,0}                               |                 12 |                 12
  (-5,-12)          | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-5,-12)          | {-0.4,-1,-6}                          |      7.42781352708 |      7.42781352708
- (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379948 |      27.3855379948
+ (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379949 |      27.3855379949
  (-5,-12)          | {3,NaN,5}                             |                NaN |                NaN
  (-5,-12)          | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-5,-12)          | {0,-1,3}                              |                 15 |                 15
@@ -553,7 +553,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e-300,-1e-300)  | {0,-1,3}                              |                  3 |                  3
  (1e-300,-1e-300)  | {-1,0,3}                              |                  3 |                  3
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
+ (1e+300,Infinity) | {1,0,5}                               |             1e+300 |             1e+300
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
  (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
@@ -561,16 +561,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-1,0,3}                              |             1e+300 |             1e+300
+ (Infinity,1e+300) | {0,-1,5}                              |             1e+300 |             1e+300
  (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
- (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
- (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
- (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |             1e+300 |             1e+300
+ (Infinity,1e+300) | {1,-1,0}                              |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
  (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |             1e+300 |             1e+300
  (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
@@ -587,7 +587,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {0,3,0}                               |                 10 |                 10
  (10,10)           | {1,-1,0}                              |                  0 |                  0
  (10,10)           | {-0.4,-1,-6}                          |      18.5695338177 |      18.5695338177
- (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913903 |      5.38276913903
+ (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913904 |      5.38276913904
  (10,10)           | {3,NaN,5}                             |                NaN |                NaN
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
@@ -653,7 +653,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
@@ -892,13 +892,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -919,7 +919,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (0,0)             | (-5,-12)          | {2.4,-1,0}
  (0,0)             | (1e+300,Infinity) | {-1,0,0}
  (0,0)             | (Infinity,1e+300) | {0,-1,0}
- (0,0)             | (NaN,NaN)         | {NaN,-1,NaN}
+ (0,0)             | (NaN,NaN)         | {NaN,NaN,NaN}
  (0,0)             | (10,10)           | {1,-1,0}
  (-10,0)           | (0,0)             | {0,-1,0}
  (-10,0)           | (-3,4)            | {0.571428571429,-1,5.71428571429}
@@ -928,7 +928,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-10,0)           | (1e-300,-1e-300)  | {0,-1,0}
  (-10,0)           | (1e+300,Infinity) | {-1,0,-10}
  (-10,0)           | (Infinity,1e+300) | {0,-1,0}
- (-10,0)           | (NaN,NaN)         | {NaN,-1,NaN}
+ (-10,0)           | (NaN,NaN)         | {NaN,NaN,NaN}
  (-10,0)           | (10,10)           | {0.5,-1,5}
  (-3,4)            | (0,0)             | {-1.33333333333,-1,0}
  (-3,4)            | (-10,0)           | {0.571428571429,-1,5.71428571429}
@@ -937,7 +937,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-3,4)            | (1e-300,-1e-300)  | {-1.33333333333,-1,0}
  (-3,4)            | (1e+300,Infinity) | {-1,0,-3}
  (-3,4)            | (Infinity,1e+300) | {0,-1,4}
- (-3,4)            | (NaN,NaN)         | {NaN,-1,NaN}
+ (-3,4)            | (NaN,NaN)         | {NaN,NaN,NaN}
  (-3,4)            | (10,10)           | {0.461538461538,-1,5.38461538462}
  (5.1,34.5)        | (0,0)             | {6.76470588235,-1,0}
  (5.1,34.5)        | (-10,0)           | {2.28476821192,-1,22.8476821192}
@@ -946,7 +946,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (5.1,34.5)        | (1e-300,-1e-300)  | {6.76470588235,-1,0}
  (5.1,34.5)        | (1e+300,Infinity) | {-1,0,5.1}
  (5.1,34.5)        | (Infinity,1e+300) | {0,-1,34.5}
- (5.1,34.5)        | (NaN,NaN)         | {NaN,-1,NaN}
+ (5.1,34.5)        | (NaN,NaN)         | {NaN,NaN,NaN}
  (5.1,34.5)        | (10,10)           | {-5,-1,60}
  (-5,-12)          | (0,0)             | {2.4,-1,0}
  (-5,-12)          | (-10,0)           | {-2.4,-1,-24}
@@ -955,7 +955,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-5,-12)          | (1e-300,-1e-300)  | {2.4,-1,0}
  (-5,-12)          | (1e+300,Infinity) | {-1,0,-5}
  (-5,-12)          | (Infinity,1e+300) | {0,-1,-12}
- (-5,-12)          | (NaN,NaN)         | {NaN,-1,NaN}
+ (-5,-12)          | (NaN,NaN)         | {NaN,NaN,NaN}
  (-5,-12)          | (10,10)           | {1.46666666667,-1,-4.66666666667}
  (1e-300,-1e-300)  | (-10,0)           | {0,-1,-1e-300}
  (1e-300,-1e-300)  | (-3,4)            | {-1.33333333333,-1,3.33333333333e-301}
@@ -963,7 +963,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e-300,-1e-300)  | (-5,-12)          | {2.4,-1,-3.4e-300}
  (1e-300,-1e-300)  | (1e+300,Infinity) | {-1,0,1e-300}
  (1e-300,-1e-300)  | (Infinity,1e+300) | {0,-1,-1e-300}
- (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,-1,NaN}
+ (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e-300,-1e-300)  | (10,10)           | {1,-1,-2e-300}
  (1e+300,Infinity) | (0,0)             | {-1,0,1e+300}
  (1e+300,Infinity) | (-10,0)           | {-1,0,1e+300}
@@ -971,8 +971,8 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e+300,Infinity) | (5.1,34.5)        | {-1,0,1e+300}
  (1e+300,Infinity) | (-5,-12)          | {-1,0,1e+300}
  (1e+300,Infinity) | (1e-300,-1e-300)  | {-1,0,1e+300}
- (1e+300,Infinity) | (Infinity,1e+300) | {NaN,-1,NaN}
- (1e+300,Infinity) | (NaN,NaN)         | {NaN,-1,NaN}
+ (1e+300,Infinity) | (Infinity,1e+300) | {NaN,NaN,NaN}
+ (1e+300,Infinity) | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e+300,Infinity) | (10,10)           | {-1,0,1e+300}
  (Infinity,1e+300) | (0,0)             | {0,-1,1e+300}
  (Infinity,1e+300) | (-10,0)           | {0,-1,1e+300}
@@ -980,18 +980,18 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (Infinity,1e+300) | (5.1,34.5)        | {0,-1,1e+300}
  (Infinity,1e+300) | (-5,-12)          | {0,-1,1e+300}
  (Infinity,1e+300) | (1e-300,-1e-300)  | {0,-1,1e+300}
- (Infinity,1e+300) | (1e+300,Infinity) | {NaN,-1,NaN}
- (Infinity,1e+300) | (NaN,NaN)         | {NaN,-1,NaN}
+ (Infinity,1e+300) | (1e+300,Infinity) | {NaN,NaN,NaN}
+ (Infinity,1e+300) | (NaN,NaN)         | {NaN,NaN,NaN}
  (Infinity,1e+300) | (10,10)           | {0,-1,1e+300}
- (NaN,NaN)         | (0,0)             | {NaN,-1,NaN}
- (NaN,NaN)         | (-10,0)           | {NaN,-1,NaN}
- (NaN,NaN)         | (-3,4)            | {NaN,-1,NaN}
- (NaN,NaN)         | (5.1,34.5)        | {NaN,-1,NaN}
- (NaN,NaN)         | (-5,-12)          | {NaN,-1,NaN}
- (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,-1,NaN}
- (NaN,NaN)         | (1e+300,Infinity) | {NaN,-1,NaN}
- (NaN,NaN)         | (Infinity,1e+300) | {NaN,-1,NaN}
- (NaN,NaN)         | (10,10)           | {NaN,-1,NaN}
+ (NaN,NaN)         | (0,0)             | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-10,0)           | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-3,4)            | {NaN,NaN,NaN}
+ (NaN,NaN)         | (5.1,34.5)        | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-5,-12)          | {NaN,NaN,NaN}
+ (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,NaN,NaN}
+ (NaN,NaN)         | (1e+300,Infinity) | {NaN,NaN,NaN}
+ (NaN,NaN)         | (Infinity,1e+300) | {NaN,NaN,NaN}
+ (NaN,NaN)         | (10,10)           | {NaN,NaN,NaN}
  (10,10)           | (0,0)             | {1,-1,0}
  (10,10)           | (-10,0)           | {0.5,-1,5}
  (10,10)           | (-3,4)            | {0.461538461538,-1,5.38461538462}
@@ -1000,7 +1000,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (10,10)           | (1e-300,-1e-300)  | {1,-1,0}
  (10,10)           | (1e+300,Infinity) | {-1,0,10}
  (10,10)           | (Infinity,1e+300) | {0,-1,10}
- (10,10)           | (NaN,NaN)         | {NaN,-1,NaN}
+ (10,10)           | (NaN,NaN)         | {NaN,NaN,NaN}
 (88 rows)
 
 -- Closest point to line
@@ -1068,24 +1068,24 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e-300,-1e-300)  | {0,-1,3}                              | (1e-300,3)
  (1e-300,-1e-300)  | {-1,0,3}                              | (3,-1e-300)
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
- (1e+300,Infinity) | {1,0,5}                               | 
+ (1e+300,Infinity) | {1,0,5}                               | (-5,Infinity)
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | (Infinity,Infinity)
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,Infinity)
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,Infinity)
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
- (1e+300,Infinity) | {-1,0,3}                              | 
- (Infinity,1e+300) | {0,-1,5}                              | 
+ (1e+300,Infinity) | {-1,0,3}                              | (3,Infinity)
+ (Infinity,1e+300) | {0,-1,5}                              | (Infinity,5)
  (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
- (Infinity,1e+300) | {0,3,0}                               | 
- (Infinity,1e+300) | {1,-1,0}                              | 
- (Infinity,1e+300) | {-0.4,-1,-6}                          | 
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (Infinity,1e+300) | {0,3,0}                               | (Infinity,0)
+ (Infinity,1e+300) | {1,-1,0}                              | (Infinity,Infinity)
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | (Infinity,-Infinity)
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | (Infinity,-Infinity)
  (Infinity,1e+300) | {3,NaN,5}                             | 
  (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
- (Infinity,1e+300) | {0,-1,3}                              | 
+ (Infinity,1e+300) | {0,-1,3}                              | (Infinity,3)
  (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
@@ -1168,7 +1168,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
  (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
  (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1278,12 +1278,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1371,8 +1366,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1381,8 +1376,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1391,8 +1386,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1401,8 +1396,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1411,8 +1406,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1421,38 +1416,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1461,8 +1456,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1480,31 +1475,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1512,8 +1499,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1521,46 +1506,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1583,16 +1542,16 @@ SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
 
 -- Intersection point with line
 SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
-                   s                   |                   s                   |             ?column?              
----------------------------------------+---------------------------------------+-----------------------------------
+                   s                   |                   s                   |            ?column?             
+---------------------------------------+---------------------------------------+---------------------------------
  {0,-1,5}                              | {0,-1,5}                              | 
  {0,-1,5}                              | {1,0,5}                               | (-5,5)
  {0,-1,5}                              | {0,3,0}                               | 
  {0,-1,5}                              | {1,-1,0}                              | (5,5)
  {0,-1,5}                              | {-0.4,-1,-6}                          | (-27.5,5)
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} | (56250,5)
- {0,-1,5}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,5}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,5}                              | {3,NaN,5}                             | 
+ {0,-1,5}                              | {NaN,NaN,NaN}                         | 
  {0,-1,5}                              | {0,-1,3}                              | 
  {0,-1,5}                              | {-1,0,3}                              | (3,5)
  {1,0,5}                               | {0,-1,5}                              | (-5,5)
@@ -1601,8 +1560,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | 
+ {1,0,5}                               | {NaN,NaN,NaN}                         | 
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              | 
  {0,3,0}                               | {0,-1,5}                              | 
@@ -1611,8 +1570,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              | (0,0)
  {0,3,0}                               | {-0.4,-1,-6}                          | (-15,0)
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} | (83333.3333333,0)
- {0,3,0}                               | {3,NaN,5}                             | (NaN,NaN)
- {0,3,0}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,3,0}                               | {3,NaN,5}                             | 
+ {0,3,0}                               | {NaN,NaN,NaN}                         | 
  {0,3,0}                               | {0,-1,3}                              | 
  {0,3,0}                               | {-1,0,3}                              | (3,0)
  {1,-1,0}                              | {0,-1,5}                              | (5,5)
@@ -1621,8 +1580,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              | 
  {1,-1,0}                              | {-0.4,-1,-6}                          | (-4.28571428571,-4.28571428571)
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} | (15.3817756722,15.3817756722)
- {1,-1,0}                              | {3,NaN,5}                             | (NaN,NaN)
- {1,-1,0}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,-1,0}                              | {3,NaN,5}                             | 
+ {1,-1,0}                              | {NaN,NaN,NaN}                         | 
  {1,-1,0}                              | {0,-1,3}                              | (3,3)
  {1,-1,0}                              | {-1,0,3}                              | (3,3)
  {-0.4,-1,-6}                          | {0,-1,5}                              | (-27.5,5)
@@ -1631,48 +1590,48 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              | (-4.28571428571,-4.28571428571)
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          | 
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} | (-53.4862244113,15.3944897645)
- {-0.4,-1,-6}                          | {3,NaN,5}                             | (NaN,NaN)
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.4,-1,-6}                          | {3,NaN,5}                             | 
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | 
  {-0.4,-1,-6}                          | {0,-1,3}                              | (-22.5,3)
  {-0.4,-1,-6}                          | {-1,0,3}                              | (3,-7.2)
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              | (56250,5)
  {-0.000184615384615,-1,15.3846153846} | {1,0,5}                               | (-5,15.3855384615)
- {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,-1.7763568394e-15)
+ {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,0)
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              | (15.3817756722,15.3817756722)
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          | (-53.4862244113,15.3944897645)
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} | 
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | (NaN,NaN)
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | 
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | 
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              | (67083.3333333,3)
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              | (3,15.3840615385)
- {3,NaN,5}                             | {0,-1,5}                              | (NaN,NaN)
- {3,NaN,5}                             | {1,0,5}                               | (NaN,NaN)
- {3,NaN,5}                             | {0,3,0}                               | (NaN,NaN)
- {3,NaN,5}                             | {1,-1,0}                              | (NaN,NaN)
- {3,NaN,5}                             | {-0.4,-1,-6}                          | (NaN,NaN)
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {3,NaN,5}                             | {3,NaN,5}                             | (NaN,NaN)
- {3,NaN,5}                             | {NaN,NaN,NaN}                         | (NaN,NaN)
- {3,NaN,5}                             | {0,-1,3}                              | (NaN,NaN)
- {3,NaN,5}                             | {-1,0,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,5}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,0,5}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,3,0}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,-1,0}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {NaN,NaN,NaN}                         | {3,NaN,5}                             | (NaN,NaN)
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-1,0,3}                              | (NaN,NaN)
+ {3,NaN,5}                             | {0,-1,5}                              | 
+ {3,NaN,5}                             | {1,0,5}                               | 
+ {3,NaN,5}                             | {0,3,0}                               | 
+ {3,NaN,5}                             | {1,-1,0}                              | 
+ {3,NaN,5}                             | {-0.4,-1,-6}                          | 
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | 
+ {3,NaN,5}                             | {3,NaN,5}                             | 
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         | 
+ {3,NaN,5}                             | {0,-1,3}                              | 
+ {3,NaN,5}                             | {-1,0,3}                              | 
+ {NaN,NaN,NaN}                         | {0,-1,5}                              | 
+ {NaN,NaN,NaN}                         | {1,0,5}                               | 
+ {NaN,NaN,NaN}                         | {0,3,0}                               | 
+ {NaN,NaN,NaN}                         | {1,-1,0}                              | 
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | 
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | 
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             | 
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | 
+ {NaN,NaN,NaN}                         | {0,-1,3}                              | 
+ {NaN,NaN,NaN}                         | {-1,0,3}                              | 
  {0,-1,3}                              | {0,-1,5}                              | 
  {0,-1,3}                              | {1,0,5}                               | (-5,3)
  {0,-1,3}                              | {0,3,0}                               | 
  {0,-1,3}                              | {1,-1,0}                              | (3,3)
  {0,-1,3}                              | {-0.4,-1,-6}                          | (-22.5,3)
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} | (67083.3333333,3)
- {0,-1,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,3}                              | {3,NaN,5}                             | 
+ {0,-1,3}                              | {NaN,NaN,NaN}                         | 
  {0,-1,3}                              | {0,-1,3}                              | 
  {0,-1,3}                              | {-1,0,3}                              | (3,3)
  {-1,0,3}                              | {0,-1,5}                              | (3,5)
@@ -1681,16 +1640,16 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | 
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | 
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              | 
 (100 rows)
 
 -- Closest point to line segment
 SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
-                   s                   |               s               |             ?column?              
----------------------------------------+-------------------------------+-----------------------------------
+                   s                   |               s               |            ?column?            
+---------------------------------------+-------------------------------+--------------------------------
  {0,-1,5}                              | [(1,2),(3,4)]                 | (3,4)
  {0,-1,5}                              | [(0,0),(6,6)]                 | (5,5)
  {0,-1,5}                              | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1710,7 +1669,7 @@ SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
  {0,3,0}                               | [(1,2),(3,4)]                 | (1,2)
  {0,3,0}                               | [(0,0),(6,6)]                 | (0,0)
  {0,3,0}                               | [(10,-10),(-3,-4)]            | (-3,-4)
- {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,-1.7763568394e-15)
+ {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,0)
  {0,3,0}                               | [(11,22),(33,44)]             | (11,22)
  {0,3,0}                               | [(-10,2),(-10,3)]             | (-10,2)
  {0,3,0}                               | [(0,-20),(30,-20)]            | 
@@ -3735,13 +3694,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, poly.f1 @> p.f1 AS contains
             | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (Infinity,1e+300) | ((0,0))                    | f
             | (Infinity,1e+300) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3811,13 +3770,13 @@ SELECT '' AS twentyfour, p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
             | (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
             | (Infinity,1e+300) | ((0,0))                    | f
             | (Infinity,1e+300) | ((0,1),(0,1))              | f
-            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
-            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
-            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
-            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
-            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
-            | (NaN,NaN)         | ((0,0))                    | t
-            | (NaN,NaN)         | ((0,1),(0,1))              | t
+            | (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+            | (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+            | (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+            | (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+            | (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+            | (NaN,NaN)         | ((0,0))                    | f
+            | (NaN,NaN)         | ((0,1),(0,1))              | f
             | (10,10)           | ((2,0),(2,4),(0,0))        | f
             | (10,10)           | ((3,1),(3,3),(1,0))        | f
             | (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
-- 
2.18.4


Re: Strange behavior with polygon and NaN

From
Anastasia Lubennikova
Date:
On 25.11.2020 11:14, Kyotaro Horiguchi wrote:
> At Wed, 25 Nov 2020 11:39:39 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in
>>> So that line of thought prompts me to tread *very* carefully when
>>> trying to dodge NaN results.  We need to be certain that we
>>> introduce only logically-defensible special cases.  Something like
>>> float8_coef_mul() seems much more likely to lead us into errors
>>> than away from them.
>> Agreed on that point.  I'm going to rewirte the patch in that
>> direction.
> Removed the function float8_coef_mul().
>
>
> I noticed that the check you proposed to add to line_closept_point
> doesn't work for the following case:
>
> select line('{1,-1,0}') <-> point(1e300, 'Infinity');
>
> Ax + By + C = 1 * 1e300 + -1 * Inf + 0 = -Inf is not NaN so we go on
> the following steps.
>
> derive the perpendicular line: => line(-1, -1, Inf}
> derive the cross point       : => point(Inf, Inf)
> calculate the distance       : => NaN  (which should be Infinity)
>
> So I left the check whether distance is NaN in this version. In the previous version the check is done before
directlycalculating the distance, but since we already have the result of Ax+Bx+C so I decided not to use point_dt() in
this
> version.
>
> Although I wrote that it should be wrong that applying FPzero() to
> coefficients, there are some places already doing that so I followed
> those predecessors.
>
>
> Reverted the change of pg_hypot().
>
>
> While checking the regression results, I noticed that the follwoing
> calculation, which seems wrong.
>
> select line('{3,NaN,5}') = line('{3,NaN,5}');
>   ?column?
> ----------
>   t
>
> But after looking point_eq(), I decided to let the behavior alone
> since I'm not sure the reason for the behavior of the functions. At
> least the comment for point_eq() says that is the delibarate
> behvior. box_same, poly_same base on the point_eq_point so they behave
> the same way.
>
>
> By the way, '=' doesn't compare the shape but compares the area.
> However, what is the area of a line?  That should be always 0 even if
> we considered it. And it is also strange that we don't have
> corresponding comparison ('<' and so) operators.  It seems to me as if
> a mistake of '~='.  If it is correct, I should revert the change of
> line_eq() along with fixing operator assignment.
>
> regards.
>

Status update for a commitfest entry.

The commitfest is closed now and this entry is "Waiting on author".
As far as I see, part of the fixes is already committed. Is there 
anything left to work on or this patch needs review/ ready for committer 
now?

-- 
Anastasia Lubennikova
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company




Re: Strange behavior with polygon and NaN

From
Tom Lane
Date:
Anastasia Lubennikova <a.lubennikova@postgrespro.ru> writes:
> The commitfest is closed now and this entry is "Waiting on author".
> As far as I see, part of the fixes is already committed. Is there 
> anything left to work on or this patch needs review/ ready for committer 
> now?

I think it should be "needs review" now.

            regards, tom lane



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Tue, 01 Dec 2020 10:03:42 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote in 
> I think it should be "needs review" now.

Conflicted with some commit(s) uncertain to me. Rebased.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From 26d9edeccf3f3111a7e0ff049aa6e3ba3746dce9 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Fri, 13 Nov 2020 13:31:20 +0900
Subject: [PATCH v8] fix geometric nan handling

---
 doc/src/sgml/func.sgml                     |  17 ++
 src/backend/utils/adt/geo_ops.c            | 337 ++++++++++++++++++---
 src/include/utils/float.h                  |  22 ++
 src/test/regress/expected/create_index.out |   2 +-
 src/test/regress/expected/geometry.out     | 331 +++++++++-----------
 5 files changed, 485 insertions(+), 224 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index d5cd705eeb..2f7f3c633c 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -10855,6 +10855,23 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
     </para>
    </note>
 
+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
+
    <table id="functions-geometry-func-table">
     <title>Geometric Functions</title>
     <tgroup cols="1">
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index c1dc511a1a..e74bf3031e 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,9 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    result->high.x = float8_min_nan(box1->high.x, box2->high.x);
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+    result->high.y = float8_min_nan(box1->high.y, box2->high.y);
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,15 +1061,23 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else if (m == 0)
+    else if (m == 0.0)
     {
         /* horizontal - use "y = C" */
         result->A = 0.0;
         result->B = -1.0;
         result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else
+    else if (!isnan(m))
     {
         /* use "mx - y + yinter = 0" */
         result->A = m;
@@ -1078,7 +1086,12 @@ line_construct(LINE *result, Point *pt, float8 m)
         /* on some platforms, the preceding expression tends to produce -0 */
         if (result->C == 0.0)
             result->C = 0.0;
+
+        if (likely(!isnan(result->C)))
+            return;
     }
+
+    result->A = result->B = result->C = get_float8_nan();
 }
 
 /* line_construct_pp()
@@ -1091,6 +1104,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1111,8 +1125,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1130,14 +1148,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1148,7 +1169,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1156,7 +1177,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1206,9 +1227,20 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     return float8_div(line->A, -line->B);
 }
 
@@ -1220,9 +1252,20 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1235,14 +1278,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2)) /* intersecting? */
+    {
+        /* return NaN if NaN is involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1264,8 +1316,13 @@ line_interpt(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (!line_interpt_line(result, l1, l2))
+    if (!line_interpt_line(result, l1, l2) ||
+        isnan(result->x) || isnan(result->y))
+    {
+        pfree(result);
         PG_RETURN_NULL();
+    }
+
     PG_RETURN_POINT_P(result);
 }
 
@@ -1291,6 +1348,7 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
 
     if (!FPzero(l1->B))
     {
+        /* l1 is not virtucal */
         if (FPeq(l2->A, float8_mul(l1->A, float8_div(l2->B, l1->B))))
             return false;
 
@@ -1298,18 +1356,34 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
                                  float8_mul(l2->B, l1->C)),
                        float8_mi(float8_mul(l1->A, l2->B),
                                  float8_mul(l2->A, l1->B)));
-        y = float8_div(-float8_pl(float8_mul(l1->A, x), l1->C), l1->B);
-    }
-    else if (!FPzero(l2->B))
-    {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
-
-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
+        /*
+         * You might want to simplify this expression by using x, but that can
+         * introduce unnecessary indeterminants (inf-inf) into the calculation,
+         * which leads to a wrong result.
+         * (For example, (-1, -1, Inf) and (1, -1, 0))
+         */
+        y = float8_div(float8_mi(float8_mul(l1->A, l2->C),
+                                 float8_mul(l2->A, l1->C)),
                        float8_mi(float8_mul(l2->A, l1->B),
                                  float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+    }
+    else if (!FPzero(l2->B))
+    {
+        /* l2 is not virtical */
+        /*
+         * We know that l1 is vertical here. The lines cannot be parallel and
+         * the x-coord of the cross point is -C/A of l1.
+         */
+        x = -float8_div(l1->C, l1->A);
+
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
     }
     else
         return false;
@@ -1639,8 +1713,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
-        b1.low.y = float8_min(p1->p[i].y, b1.low.y);
+        b1.low.x = float8_min_nan(p1->p[i].x, b1.low.x);
+        b1.low.y = float8_min_nan(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;
@@ -1648,8 +1722,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
-        b2.low.y = float8_min(p2->p[i].y, b2.low.y);
+        b2.low.x = float8_min_nan(p2->p[i].x, b2.low.x);
+        b2.low.y = float8_min_nan(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
         PG_RETURN_BOOL(false);
@@ -1739,6 +1813,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1992,9 +2071,19 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
+
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -2008,9 +2097,19 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
+
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2426,6 +2525,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2657,6 +2761,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2686,7 +2792,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2728,6 +2835,78 @@ line_closept_point(Point *result, LINE *line, Point *point)
 {
     Point        closept;
     LINE        tmp;
+    float8        val;
+
+    /*
+     * Treat specially the cases where A = 0 and B = 0, which we regard the
+     * line is perfectly horizontal and vertical correspondingly, not applying
+     * the normal formula involving the behavior of inf*0 =NaN defined by
+     * IEEE754.
+     */
+    if (FPzero(line->A))
+    {
+        float8 y;
+
+        /* the line is horizontal */
+        Assert(!FPzero(line->B));
+
+        y = -line->C / line->B;
+
+        /* Avoid -0 */
+        if (y == 0.0)
+            y = 0.0;
+
+        if (result != NULL)
+        {
+            result->x = point->x;
+            result->y = y;
+        }
+
+        if (unlikely(isnan(point->x)))
+            return get_float8_nan();
+
+        return fabs(point->y - y);
+    }
+    else if (FPzero(line->B))
+    {
+        float x;
+
+        /* the line is virtical */
+        Assert(!FPzero(line->A));
+
+        x = -line->C / line->A;
+
+        /* Avoid -0 */
+        if (x == 0)
+            x = 0;
+
+        if (result != NULL)
+        {
+            result->x = x;
+            result->y = point->y;
+        }
+
+        if (unlikely(isnan(point->y)))
+            return get_float8_nan();
+
+        return fabs(point->x - x);
+    }
+
+    /*
+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    val = float8_pl(float8_pl(float8_mul(line->A, point->x),
+                              float8_mul(line->B, point->y)),
+                    line->C);
+    if (unlikely(isnan(val)))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
 
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
@@ -2738,7 +2917,7 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (!line_interpt_line(&closept, &tmp, line))
     {
         if (result != NULL)
-            *result = *point;
+            result->x = result->y = get_float8_nan();
 
         return get_float8_nan();
     }
@@ -2746,7 +2925,17 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (result != NULL)
         *result = closept;
 
-    return point_dt(&closept, point);
+    /*
+     * If the closest point contains Inf's, the closest point may lose
+     * arithmetic relationship with the point which lets point_dt wrongly give
+     * NaN. To avoid that kind of failure, we calculate the distance using the
+     * following formula instead of using the closest point.
+     *
+     * | A*x + B*y + C | / sqrt(A^2 + B^2)
+     *
+     * The dividend have been already calculated so just divide it.
+     */
+    return float8_div(fabs(val), HYPOT(line->A, line->B));
 }
 
 Datum
@@ -2758,7 +2947,9 @@ close_pl(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (isnan(line_closept_point(result, line, pt)))
+    (void) line_closept_point(result, line, pt);
+
+    if (unlikely(isnan(result->x) || isnan(result->y)))
         PG_RETURN_NULL();
 
     PG_RETURN_POINT_P(result);
@@ -2815,6 +3006,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        anynan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2826,6 +3018,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    anynan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2835,6 +3028,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2842,6 +3036,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2849,6 +3044,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2885,6 +3086,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        anynan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2899,9 +3101,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    anynan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2913,6 +3116,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2922,6 +3126,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2929,6 +3134,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -3000,6 +3212,7 @@ close_sl(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -3022,6 +3235,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3147,9 +3368,32 @@ close_lb(PG_FUNCTION_ARGS)
 static bool
 line_contain_point(LINE *line, Point *point)
 {
-    return FPzero(float8_pl(float8_pl(float8_mul(line->A, point->x),
-                                      float8_mul(line->B, point->y)),
-                            line->C));
+    /*
+     * Treat specially way the cases where A = 0 and B = 0, which we regard the
+     * line is perfectly horizontal and vertical correspondingly to avoid the
+     * normal formula based on the IEEE754's definitions yields unwanted NaNs.
+     */
+    if (line->A == 0.0)
+    {
+        /* the line is horizontal */
+        Assert(line->B != 0.0);
+
+        /* inf == inf here */
+        return FPeq(point->y, -line->C / line->B);
+    }
+    else if (line->B == 0.0)
+    {
+        /* the line is vertical */
+        Assert(line->A != 0.0);
+
+        /* inf == inf here */
+        return FPeq(point->x, -line->C / line->A);
+    }
+
+    return FPzero(float8_pl(
+                      float8_pl(float8_mul(line->A, point->x),
+                                float8_mul(line->B, point->y)),
+                      line->C));
 }
 
 Datum
@@ -3448,6 +3692,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3923,6 +4173,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5362,6 +5617,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5371,6 +5630,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 79bf8daca8..52bcf853f2 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -353,4 +353,26 @@ float8_max(const float8 val1, const float8 val2)
     return float8_gt(val1, val2) ? val1 : val2;
 }
 
+/*
+ * These two functions return NaN if either input is NaN, else the smaller
+ * of the two inputs.  This does NOT follow our usual sort rule, but it is
+ * convenient in some places.  (Note that float4_max and float8_max act this
+ * way anyway, so no similar variant is needed for them.)
+ */
+static inline float4
+float4_min_nan(const float4 val1, const float4 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
+static inline float8
+float8_min_nan(const float8 val1, const float8 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
 #endif                            /* FLOAT_H */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index fc6afab58a..3605186c44 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 84f7eabb66..1ae14c4d4b 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -517,7 +517,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-3,4)            | {0,3,0}                               |                  4 |                  4
  (-3,4)            | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-3,4)            | {-0.4,-1,-6}                          |      8.17059487979 |      8.17059487979
- (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690368 |      11.3851690368
+ (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690367 |      11.3851690367
  (-3,4)            | {3,NaN,5}                             |                NaN |                NaN
  (-3,4)            | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-3,4)            | {0,-1,3}                              |                  1 |                  1
@@ -537,7 +537,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-5,-12)          | {0,3,0}                               |                 12 |                 12
  (-5,-12)          | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-5,-12)          | {-0.4,-1,-6}                          |      7.42781352708 |      7.42781352708
- (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379948 |      27.3855379948
+ (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379949 |      27.3855379949
  (-5,-12)          | {3,NaN,5}                             |                NaN |                NaN
  (-5,-12)          | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-5,-12)          | {0,-1,3}                              |                 15 |                 15
@@ -553,7 +553,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e-300,-1e-300)  | {0,-1,3}                              |                  3 |                  3
  (1e-300,-1e-300)  | {-1,0,3}                              |                  3 |                  3
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
+ (1e+300,Infinity) | {1,0,5}                               |             1e+300 |             1e+300
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
  (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
@@ -561,16 +561,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-1,0,3}                              |             1e+300 |             1e+300
+ (Infinity,1e+300) | {0,-1,5}                              |             1e+300 |             1e+300
  (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
- (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
- (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
- (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |             1e+300 |             1e+300
+ (Infinity,1e+300) | {1,-1,0}                              |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
  (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |             1e+300 |             1e+300
  (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
@@ -587,7 +587,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {0,3,0}                               |                 10 |                 10
  (10,10)           | {1,-1,0}                              |                  0 |                  0
  (10,10)           | {-0.4,-1,-6}                          |      18.5695338177 |      18.5695338177
- (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913903 |      5.38276913903
+ (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913904 |      5.38276913904
  (10,10)           | {3,NaN,5}                             |                NaN |                NaN
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
@@ -653,7 +653,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
@@ -892,13 +892,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -919,7 +919,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (0,0)             | (-5,-12)          | {2.4,-1,0}
  (0,0)             | (1e+300,Infinity) | {-1,0,0}
  (0,0)             | (Infinity,1e+300) | {0,-1,0}
- (0,0)             | (NaN,NaN)         | {NaN,-1,NaN}
+ (0,0)             | (NaN,NaN)         | {NaN,NaN,NaN}
  (0,0)             | (10,10)           | {1,-1,0}
  (-10,0)           | (0,0)             | {0,-1,0}
  (-10,0)           | (-3,4)            | {0.571428571429,-1,5.71428571429}
@@ -928,7 +928,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-10,0)           | (1e-300,-1e-300)  | {0,-1,0}
  (-10,0)           | (1e+300,Infinity) | {-1,0,-10}
  (-10,0)           | (Infinity,1e+300) | {0,-1,0}
- (-10,0)           | (NaN,NaN)         | {NaN,-1,NaN}
+ (-10,0)           | (NaN,NaN)         | {NaN,NaN,NaN}
  (-10,0)           | (10,10)           | {0.5,-1,5}
  (-3,4)            | (0,0)             | {-1.33333333333,-1,0}
  (-3,4)            | (-10,0)           | {0.571428571429,-1,5.71428571429}
@@ -937,7 +937,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-3,4)            | (1e-300,-1e-300)  | {-1.33333333333,-1,0}
  (-3,4)            | (1e+300,Infinity) | {-1,0,-3}
  (-3,4)            | (Infinity,1e+300) | {0,-1,4}
- (-3,4)            | (NaN,NaN)         | {NaN,-1,NaN}
+ (-3,4)            | (NaN,NaN)         | {NaN,NaN,NaN}
  (-3,4)            | (10,10)           | {0.461538461538,-1,5.38461538462}
  (5.1,34.5)        | (0,0)             | {6.76470588235,-1,0}
  (5.1,34.5)        | (-10,0)           | {2.28476821192,-1,22.8476821192}
@@ -946,7 +946,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (5.1,34.5)        | (1e-300,-1e-300)  | {6.76470588235,-1,0}
  (5.1,34.5)        | (1e+300,Infinity) | {-1,0,5.1}
  (5.1,34.5)        | (Infinity,1e+300) | {0,-1,34.5}
- (5.1,34.5)        | (NaN,NaN)         | {NaN,-1,NaN}
+ (5.1,34.5)        | (NaN,NaN)         | {NaN,NaN,NaN}
  (5.1,34.5)        | (10,10)           | {-5,-1,60}
  (-5,-12)          | (0,0)             | {2.4,-1,0}
  (-5,-12)          | (-10,0)           | {-2.4,-1,-24}
@@ -955,7 +955,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-5,-12)          | (1e-300,-1e-300)  | {2.4,-1,0}
  (-5,-12)          | (1e+300,Infinity) | {-1,0,-5}
  (-5,-12)          | (Infinity,1e+300) | {0,-1,-12}
- (-5,-12)          | (NaN,NaN)         | {NaN,-1,NaN}
+ (-5,-12)          | (NaN,NaN)         | {NaN,NaN,NaN}
  (-5,-12)          | (10,10)           | {1.46666666667,-1,-4.66666666667}
  (1e-300,-1e-300)  | (-10,0)           | {0,-1,-1e-300}
  (1e-300,-1e-300)  | (-3,4)            | {-1.33333333333,-1,3.33333333333e-301}
@@ -963,7 +963,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e-300,-1e-300)  | (-5,-12)          | {2.4,-1,-3.4e-300}
  (1e-300,-1e-300)  | (1e+300,Infinity) | {-1,0,1e-300}
  (1e-300,-1e-300)  | (Infinity,1e+300) | {0,-1,-1e-300}
- (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,-1,NaN}
+ (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e-300,-1e-300)  | (10,10)           | {1,-1,-2e-300}
  (1e+300,Infinity) | (0,0)             | {-1,0,1e+300}
  (1e+300,Infinity) | (-10,0)           | {-1,0,1e+300}
@@ -971,8 +971,8 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e+300,Infinity) | (5.1,34.5)        | {-1,0,1e+300}
  (1e+300,Infinity) | (-5,-12)          | {-1,0,1e+300}
  (1e+300,Infinity) | (1e-300,-1e-300)  | {-1,0,1e+300}
- (1e+300,Infinity) | (Infinity,1e+300) | {NaN,-1,NaN}
- (1e+300,Infinity) | (NaN,NaN)         | {NaN,-1,NaN}
+ (1e+300,Infinity) | (Infinity,1e+300) | {NaN,NaN,NaN}
+ (1e+300,Infinity) | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e+300,Infinity) | (10,10)           | {-1,0,1e+300}
  (Infinity,1e+300) | (0,0)             | {0,-1,1e+300}
  (Infinity,1e+300) | (-10,0)           | {0,-1,1e+300}
@@ -980,18 +980,18 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (Infinity,1e+300) | (5.1,34.5)        | {0,-1,1e+300}
  (Infinity,1e+300) | (-5,-12)          | {0,-1,1e+300}
  (Infinity,1e+300) | (1e-300,-1e-300)  | {0,-1,1e+300}
- (Infinity,1e+300) | (1e+300,Infinity) | {NaN,-1,NaN}
- (Infinity,1e+300) | (NaN,NaN)         | {NaN,-1,NaN}
+ (Infinity,1e+300) | (1e+300,Infinity) | {NaN,NaN,NaN}
+ (Infinity,1e+300) | (NaN,NaN)         | {NaN,NaN,NaN}
  (Infinity,1e+300) | (10,10)           | {0,-1,1e+300}
- (NaN,NaN)         | (0,0)             | {NaN,-1,NaN}
- (NaN,NaN)         | (-10,0)           | {NaN,-1,NaN}
- (NaN,NaN)         | (-3,4)            | {NaN,-1,NaN}
- (NaN,NaN)         | (5.1,34.5)        | {NaN,-1,NaN}
- (NaN,NaN)         | (-5,-12)          | {NaN,-1,NaN}
- (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,-1,NaN}
- (NaN,NaN)         | (1e+300,Infinity) | {NaN,-1,NaN}
- (NaN,NaN)         | (Infinity,1e+300) | {NaN,-1,NaN}
- (NaN,NaN)         | (10,10)           | {NaN,-1,NaN}
+ (NaN,NaN)         | (0,0)             | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-10,0)           | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-3,4)            | {NaN,NaN,NaN}
+ (NaN,NaN)         | (5.1,34.5)        | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-5,-12)          | {NaN,NaN,NaN}
+ (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,NaN,NaN}
+ (NaN,NaN)         | (1e+300,Infinity) | {NaN,NaN,NaN}
+ (NaN,NaN)         | (Infinity,1e+300) | {NaN,NaN,NaN}
+ (NaN,NaN)         | (10,10)           | {NaN,NaN,NaN}
  (10,10)           | (0,0)             | {1,-1,0}
  (10,10)           | (-10,0)           | {0.5,-1,5}
  (10,10)           | (-3,4)            | {0.461538461538,-1,5.38461538462}
@@ -1000,7 +1000,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (10,10)           | (1e-300,-1e-300)  | {1,-1,0}
  (10,10)           | (1e+300,Infinity) | {-1,0,10}
  (10,10)           | (Infinity,1e+300) | {0,-1,10}
- (10,10)           | (NaN,NaN)         | {NaN,-1,NaN}
+ (10,10)           | (NaN,NaN)         | {NaN,NaN,NaN}
 (88 rows)
 
 -- Closest point to line
@@ -1068,24 +1068,24 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e-300,-1e-300)  | {0,-1,3}                              | (1e-300,3)
  (1e-300,-1e-300)  | {-1,0,3}                              | (3,-1e-300)
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
- (1e+300,Infinity) | {1,0,5}                               | 
+ (1e+300,Infinity) | {1,0,5}                               | (-5,Infinity)
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | (Infinity,Infinity)
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,Infinity)
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,Infinity)
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
- (1e+300,Infinity) | {-1,0,3}                              | 
- (Infinity,1e+300) | {0,-1,5}                              | 
+ (1e+300,Infinity) | {-1,0,3}                              | (3,Infinity)
+ (Infinity,1e+300) | {0,-1,5}                              | (Infinity,5)
  (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
- (Infinity,1e+300) | {0,3,0}                               | 
- (Infinity,1e+300) | {1,-1,0}                              | 
- (Infinity,1e+300) | {-0.4,-1,-6}                          | 
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (Infinity,1e+300) | {0,3,0}                               | (Infinity,0)
+ (Infinity,1e+300) | {1,-1,0}                              | (Infinity,Infinity)
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | (Infinity,-Infinity)
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | (Infinity,-Infinity)
  (Infinity,1e+300) | {3,NaN,5}                             | 
  (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
- (Infinity,1e+300) | {0,-1,3}                              | 
+ (Infinity,1e+300) | {0,-1,3}                              | (Infinity,3)
  (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
@@ -1168,7 +1168,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
  (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
  (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1278,12 +1278,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1371,8 +1366,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1381,8 +1376,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1391,8 +1386,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1401,8 +1396,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1411,8 +1406,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1421,38 +1416,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1461,8 +1456,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1480,31 +1475,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1512,8 +1499,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1521,46 +1506,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1583,16 +1542,16 @@ SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
 
 -- Intersection point with line
 SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
-                   s                   |                   s                   |             ?column?              
----------------------------------------+---------------------------------------+-----------------------------------
+                   s                   |                   s                   |            ?column?             
+---------------------------------------+---------------------------------------+---------------------------------
  {0,-1,5}                              | {0,-1,5}                              | 
  {0,-1,5}                              | {1,0,5}                               | (-5,5)
  {0,-1,5}                              | {0,3,0}                               | 
  {0,-1,5}                              | {1,-1,0}                              | (5,5)
  {0,-1,5}                              | {-0.4,-1,-6}                          | (-27.5,5)
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} | (56250,5)
- {0,-1,5}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,5}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,5}                              | {3,NaN,5}                             | 
+ {0,-1,5}                              | {NaN,NaN,NaN}                         | 
  {0,-1,5}                              | {0,-1,3}                              | 
  {0,-1,5}                              | {-1,0,3}                              | (3,5)
  {1,0,5}                               | {0,-1,5}                              | (-5,5)
@@ -1601,8 +1560,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | 
+ {1,0,5}                               | {NaN,NaN,NaN}                         | 
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              | 
  {0,3,0}                               | {0,-1,5}                              | 
@@ -1611,8 +1570,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              | (0,0)
  {0,3,0}                               | {-0.4,-1,-6}                          | (-15,0)
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} | (83333.3333333,0)
- {0,3,0}                               | {3,NaN,5}                             | (NaN,NaN)
- {0,3,0}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,3,0}                               | {3,NaN,5}                             | 
+ {0,3,0}                               | {NaN,NaN,NaN}                         | 
  {0,3,0}                               | {0,-1,3}                              | 
  {0,3,0}                               | {-1,0,3}                              | (3,0)
  {1,-1,0}                              | {0,-1,5}                              | (5,5)
@@ -1621,8 +1580,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              | 
  {1,-1,0}                              | {-0.4,-1,-6}                          | (-4.28571428571,-4.28571428571)
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} | (15.3817756722,15.3817756722)
- {1,-1,0}                              | {3,NaN,5}                             | (NaN,NaN)
- {1,-1,0}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,-1,0}                              | {3,NaN,5}                             | 
+ {1,-1,0}                              | {NaN,NaN,NaN}                         | 
  {1,-1,0}                              | {0,-1,3}                              | (3,3)
  {1,-1,0}                              | {-1,0,3}                              | (3,3)
  {-0.4,-1,-6}                          | {0,-1,5}                              | (-27.5,5)
@@ -1631,48 +1590,48 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              | (-4.28571428571,-4.28571428571)
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          | 
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} | (-53.4862244113,15.3944897645)
- {-0.4,-1,-6}                          | {3,NaN,5}                             | (NaN,NaN)
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.4,-1,-6}                          | {3,NaN,5}                             | 
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | 
  {-0.4,-1,-6}                          | {0,-1,3}                              | (-22.5,3)
  {-0.4,-1,-6}                          | {-1,0,3}                              | (3,-7.2)
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              | (56250,5)
  {-0.000184615384615,-1,15.3846153846} | {1,0,5}                               | (-5,15.3855384615)
- {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,-1.7763568394e-15)
+ {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,0)
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              | (15.3817756722,15.3817756722)
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          | (-53.4862244113,15.3944897645)
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} | 
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | (NaN,NaN)
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | 
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | 
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              | (67083.3333333,3)
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              | (3,15.3840615385)
- {3,NaN,5}                             | {0,-1,5}                              | (NaN,NaN)
- {3,NaN,5}                             | {1,0,5}                               | (NaN,NaN)
- {3,NaN,5}                             | {0,3,0}                               | (NaN,NaN)
- {3,NaN,5}                             | {1,-1,0}                              | (NaN,NaN)
- {3,NaN,5}                             | {-0.4,-1,-6}                          | (NaN,NaN)
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {3,NaN,5}                             | {3,NaN,5}                             | (NaN,NaN)
- {3,NaN,5}                             | {NaN,NaN,NaN}                         | (NaN,NaN)
- {3,NaN,5}                             | {0,-1,3}                              | (NaN,NaN)
- {3,NaN,5}                             | {-1,0,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,5}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,0,5}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,3,0}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,-1,0}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {NaN,NaN,NaN}                         | {3,NaN,5}                             | (NaN,NaN)
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-1,0,3}                              | (NaN,NaN)
+ {3,NaN,5}                             | {0,-1,5}                              | 
+ {3,NaN,5}                             | {1,0,5}                               | 
+ {3,NaN,5}                             | {0,3,0}                               | 
+ {3,NaN,5}                             | {1,-1,0}                              | 
+ {3,NaN,5}                             | {-0.4,-1,-6}                          | 
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | 
+ {3,NaN,5}                             | {3,NaN,5}                             | 
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         | 
+ {3,NaN,5}                             | {0,-1,3}                              | 
+ {3,NaN,5}                             | {-1,0,3}                              | 
+ {NaN,NaN,NaN}                         | {0,-1,5}                              | 
+ {NaN,NaN,NaN}                         | {1,0,5}                               | 
+ {NaN,NaN,NaN}                         | {0,3,0}                               | 
+ {NaN,NaN,NaN}                         | {1,-1,0}                              | 
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | 
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | 
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             | 
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | 
+ {NaN,NaN,NaN}                         | {0,-1,3}                              | 
+ {NaN,NaN,NaN}                         | {-1,0,3}                              | 
  {0,-1,3}                              | {0,-1,5}                              | 
  {0,-1,3}                              | {1,0,5}                               | (-5,3)
  {0,-1,3}                              | {0,3,0}                               | 
  {0,-1,3}                              | {1,-1,0}                              | (3,3)
  {0,-1,3}                              | {-0.4,-1,-6}                          | (-22.5,3)
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} | (67083.3333333,3)
- {0,-1,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,3}                              | {3,NaN,5}                             | 
+ {0,-1,3}                              | {NaN,NaN,NaN}                         | 
  {0,-1,3}                              | {0,-1,3}                              | 
  {0,-1,3}                              | {-1,0,3}                              | (3,3)
  {-1,0,3}                              | {0,-1,5}                              | (3,5)
@@ -1681,16 +1640,16 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | 
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | 
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              | 
 (100 rows)
 
 -- Closest point to line segment
 SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
-                   s                   |               s               |             ?column?              
----------------------------------------+-------------------------------+-----------------------------------
+                   s                   |               s               |            ?column?            
+---------------------------------------+-------------------------------+--------------------------------
  {0,-1,5}                              | [(1,2),(3,4)]                 | (3,4)
  {0,-1,5}                              | [(0,0),(6,6)]                 | (5,5)
  {0,-1,5}                              | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1710,7 +1669,7 @@ SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
  {0,3,0}                               | [(1,2),(3,4)]                 | (1,2)
  {0,3,0}                               | [(0,0),(6,6)]                 | (0,0)
  {0,3,0}                               | [(10,-10),(-3,-4)]            | (-3,-4)
- {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,-1.7763568394e-15)
+ {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,0)
  {0,3,0}                               | [(11,22),(33,44)]             | (11,22)
  {0,3,0}                               | [(-10,2),(-10,3)]             | (-10,2)
  {0,3,0}                               | [(0,-20),(30,-20)]            | 
@@ -3735,13 +3694,13 @@ SELECT p.f1, poly.f1, poly.f1 @> p.f1 AS contains
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
  (Infinity,1e+300) | ((0,0))                    | f
  (Infinity,1e+300) | ((0,1),(0,1))              | f
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
- (NaN,NaN)         | ((0,0))                    | t
- (NaN,NaN)         | ((0,1),(0,1))              | t
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+ (NaN,NaN)         | ((0,0))                    | f
+ (NaN,NaN)         | ((0,1),(0,1))              | f
  (10,10)           | ((2,0),(2,4),(0,0))        | f
  (10,10)           | ((3,1),(3,3),(1,0))        | f
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3811,13 +3770,13 @@ SELECT p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
  (Infinity,1e+300) | ((0,0))                    | f
  (Infinity,1e+300) | ((0,1),(0,1))              | f
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
- (NaN,NaN)         | ((0,0))                    | t
- (NaN,NaN)         | ((0,1),(0,1))              | t
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+ (NaN,NaN)         | ((0,0))                    | f
+ (NaN,NaN)         | ((0,1),(0,1))              | f
  (10,10)           | ((2,0),(2,4),(0,0))        | f
  (10,10)           | ((3,1),(3,3),(1,0))        | f
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
-- 
2.27.0


Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Mon, 15 Mar 2021 08:34:00 -0400, David Steele <david@pgmasters.net> wrote in 
> On 12/21/20 3:30 AM, Kyotaro Horiguchi wrote:
> > At Tue, 01 Dec 2020 10:03:42 -0500, Tom Lane <tgl@sss.pgh.pa.us> wrote
> > in
> >> I think it should be "needs review" now.
> > Conflicted with some commit(s) uncertain to me. Rebased.

When I recently re-found the working tree on this topic in my laptop,
it contained an unfinished work of tristate geometric comparisons. I
had forgotten how come I started it but I found the starting thread
[1].  I've done that work to the level it anyhow looks working.

The first patch fixes arithmetic functions to handle NaNs, which is
the first motive of this thread.  The second introduces tri-state
comparison as requested in [1].  The tri-state comparison returns
TS_NULL or SQL-NULL for comparisons involving NaNs.  GiST index is
adjusted so that it treats null as false. On the way doing this, the
bug #17334 [2] and another bug raised earlier [3] are naturally fixed.

The first patch changes/fixes the behavior of geometric arithmetics as
follows *as the result*.

==== 1-a
Distance between an valid object and an object containing NaNs was 0.

select line '{-0.4,-1,-6}' <-> line '{3,NaN,5}';  -- 0 => NaN

==== 1-b
The distance between a point and a vertical or horizontal line was NaN
for some valid cases.

select point '(1e+300,Infinity)' <-> line '{-1,0,3}';  -- NaN -> Infinity

==== 1-c
The closest point of two objects could not be solved if it contains
Infinity.

select point '(1e+300,Infinity)' ## line '{1,0,5}';   -- null -> (-5,Infinity)

(I'm not sure the fix works for all possible cases..)

==== 1-d
Containment involving NaNs was falsely true for some kind of objects.

select point '(NaN,NaN)' <@ path '((1,2),(3,4))';         -- true -> null
select point '(NaN,NaN)' <@ polygon '((2,0),(2,4),(0,0))';-- true -> null

=== 1-e
The intersection detection of two objects containing NaNs was true.

select line '{-1,0,3}' ?# line '{3,NaN,5}';  -- true -> null


The second patch as the result changes/fixes the behavior of
geometrical arithmetics as the follows.

==== 2-a
The containment detection between a valid shape and a point containing
NaN(s) was false.  This is not necessarirly wrong but it is changed
according to [1]

select point '(0.5, NaN)' <@ box '(0,0,1,1)';   -- false -> null
select point '(NaN, NaN)' <@ path '[(0,0),(1,0),(1,1),(0,1)]'; -- false -> null

==== 2-b
The equality of two lines containing NaNs can be true or false. This
is right assuming NaN == NaN. But it is changed according to the
policy that NaN makes an object invalid.

select line '{NaN, 1, NaN}' = line '{NaN, 1, NaN}'; -- true -> null
select line '{NaN, 1, NaN}' = line '{NaN, 2, NaN}'; -- false -> null

==== 2-c
The result of the following expression changed from Infinity to
NaN. The distance from the point to to the box is indeterminant.

select box '(-Infinity,500),(-Infinity,100)' <-> point '123,456';

The internal function is dist_bp().  The difference comes from the
behavior that lseg_closept_line() ignores the NaN returned from
line_closept_point() and uses the last one of the two ends of the lseg
as the result, which is (-inf, 500).  With this patch the same
function returns (NaN, NaN) which leads to null as the final result.
The previos behavior (for these particular values) may be correct at a
glance but it is wrong at the time lseg_closept_line ignores the fact
that it could not determine which end is closer.

==== 2-d

The comparison between objects involving NaNs results was false, but
it is now null.  So NaNs that were shown as a part of the following
query are now excluded.  (I'm not sure this is the desired result.)

SELECT p1.f1, p2.f1 FROM
(VALUES (point '0,0'), (point '1,1'), (point 'NaN,NaN')) p1(f1),
(VALUES (point '0,0'), (point '1,1'), (point 'NaN,NaN')) p2(f1)
WHERE p1.f1 <> p2.f1;

     f1     |    f1     
 -----------+-----------
  (0,0)     | (1,1)
- (0,0)     | (NaN,NaN)
  (1,1)     | (0,0)
- (1,1)     | (NaN,NaN)
- (NaN,NaN) | (0,0)
- (NaN,NaN) | (1,1)
(6 rows)

==== 2-e

circle_same(~=) returned true for '<(3,5),NaN>' and circle
'<(3,5),0>', which is definitely bogus.
null.

SELECT circle '<(3,5),NaN>' ~= circle '<(3,5),0>';   -- true -> null
SELECT circle '<(3,5),NaN>' ~= circle '<(3,5),NaN>'; -- true -> null


[1] https://www.postgresql.org/message-id/CAOBaU_ZvJGkAuKqfFxQxnsirpaVci_-S3F3M5M1Wzrq1kGyC%3Dg%40mail.gmail.com
[2] https://www.postgresql.org/message-id/17334-135f485c21739caa%40postgresql.org
[3] https://www.postgresql.org/message-id/CAMbWs4-C9K-8V=cAY7q0ciZmJKBMiUnp_xBGzxgKpEWPKd0bng@mail.gmail.com

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center
From 7f7dae7919d0566038df5ffcfe1d4b1437586fe9 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyoga.ntt@gmail.com>
Date: Fri, 13 Nov 2020 13:31:20 +0900
Subject: [PATCH v9 1/2] Fix NaN handling of geometric arithmetics

Geometrical arithmetic functions have not consciously handled NaNs. As
the result they made a unexpected results for NaNs in certain
cases. Correct that behavior by handling NaNs consciously.
---
 doc/src/sgml/func.sgml                     |  17 ++
 src/backend/utils/adt/geo_ops.c            | 337 ++++++++++++++++++---
 src/include/utils/float.h                  |  22 ++
 src/test/regress/expected/create_index.out |   2 +-
 src/test/regress/expected/geometry.out     | 331 +++++++++-----------
 5 files changed, 485 insertions(+), 224 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 5801299b27..9c8991449b 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -11456,6 +11456,23 @@ CREATE TYPE rainbow AS ENUM ('red', 'orange', 'yellow', 'green', 'blue', 'purple
     </para>
    </note>
 
+   <caution>
+     <para>
+       NaN and Infinity make geometric functions and operators behave
+       inconsistently. Geometric operators or functions that return a boolean
+       return false for operands that contain NaNs. Number-returning functions
+       and operators return NaN in most cases but sometimes return a valid
+       value if no NaNs are met while actual calculation.  Object-returning ones
+       yield an object that contain NaNs depending to the operation.  Likewise
+       the objects containing Infinity can make geometric operators and
+       functions behave inconsistently. For example (point
+       '(Infinity,Infinity)' <-> line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' <-> line '{0,-1,5}') is NaN. It can never
+       be a value other than these, but you should consider it uncertain how
+       geometric operators behave for objects containing Infinity.
+     </para>
+   </caution>
+
    <table id="functions-geometry-func-table">
     <title>Geometric Functions</title>
     <tgroup cols="1">
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 92dc9483b9..851c171108 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -904,9 +904,9 @@ box_intersect(PG_FUNCTION_ARGS)
 
     result = (BOX *) palloc(sizeof(BOX));
 
-    result->high.x = float8_min(box1->high.x, box2->high.x);
+    result->high.x = float8_min_nan(box1->high.x, box2->high.x);
     result->low.x = float8_max(box1->low.x, box2->low.x);
-    result->high.y = float8_min(box1->high.y, box2->high.y);
+    result->high.y = float8_min_nan(box1->high.y, box2->high.y);
     result->low.y = float8_max(box1->low.y, box2->low.y);
 
     PG_RETURN_BOX_P(result);
@@ -1061,15 +1061,23 @@ line_construct(LINE *result, Point *pt, float8 m)
         result->A = -1.0;
         result->B = 0.0;
         result->C = pt->x;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else if (m == 0)
+    else if (m == 0.0)
     {
         /* horizontal - use "y = C" */
         result->A = 0.0;
         result->B = -1.0;
         result->C = pt->y;
+
+        /* Avoid creating a valid line from an invalid point */
+        if (likely(!isnan(pt->x) && !isnan(pt->y)))
+            return;
     }
-    else
+    else if (!isnan(m))
     {
         /* use "mx - y + yinter = 0" */
         result->A = m;
@@ -1078,7 +1086,12 @@ line_construct(LINE *result, Point *pt, float8 m)
         /* on some platforms, the preceding expression tends to produce -0 */
         if (result->C == 0.0)
             result->C = 0.0;
+
+        if (likely(!isnan(result->C)))
+            return;
     }
+
+    result->A = result->B = result->C = get_float8_nan();
 }
 
 /* line_construct_pp()
@@ -1091,6 +1104,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     Point       *pt2 = PG_GETARG_POINT_P(1);
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
+    /* NaNs are considered to be equal by point_eq_point */
     if (point_eq_point(pt1, pt2))
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -1111,8 +1125,12 @@ line_intersect(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
 
-    PG_RETURN_BOOL(line_interpt_line(NULL, l1, l2));
+    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
+        PG_RETURN_BOOL(true);
+    else
+        PG_RETURN_BOOL(false);
 }
 
 Datum
@@ -1130,14 +1148,17 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
+    if (unlikely(isnan(l1->C) || isnan(l2->C)))
+        return false;
+
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
 
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
@@ -1148,7 +1169,7 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B));
+    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
 }
 
 Datum
@@ -1156,7 +1177,7 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A));
+    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
 }
 
 
@@ -1206,9 +1227,20 @@ static inline float8
 line_sl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return 0.0;
+    }
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     return float8_div(line->A, -line->B);
 }
 
@@ -1220,9 +1252,20 @@ static inline float8
 line_invsl(LINE *line)
 {
     if (FPzero(line->A))
+    {
+        /* C is likely to be NaN than B */
+        if (unlikely(isnan(line->C) || isnan(line->B)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     if (FPzero(line->B))
+    {
+        /* C is likely to be NaN than A */
+        if (unlikely(isnan(line->C) || isnan(line->A)))
+            return get_float8_nan();
         return 0.0;
+    }
     return float8_div(line->B, line->A);
 }
 
@@ -1235,14 +1278,23 @@ line_distance(PG_FUNCTION_ARGS)
 {
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
+    Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(NULL, l1, l2))    /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2)) /* intersecting? */
+    {
+        /* return NaN if NaN is involved */
+        if (isnan(xp.x) || isnan(xp.y))
+            PG_RETURN_FLOAT8(get_float8_nan());
+
         PG_RETURN_FLOAT8(0.0);
+    }
 
-    if (!FPzero(l1->A) && !isnan(l1->A) && !FPzero(l2->A) && !isnan(l2->A))
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l2->A) || isnan(l2->B)))
+        ratio = get_float8_nan();
+    else if (!FPzero(l1->A) && !FPzero(l2->A))
         ratio = float8_div(l1->A, l2->A);
-    else if (!FPzero(l1->B) && !isnan(l1->B) && !FPzero(l2->B) && !isnan(l2->B))
+    else if (!FPzero(l1->B) && !FPzero(l2->B))
         ratio = float8_div(l1->B, l2->B);
     else
         ratio = 1.0;
@@ -1264,8 +1316,13 @@ line_interpt(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (!line_interpt_line(result, l1, l2))
+    if (!line_interpt_line(result, l1, l2) ||
+        isnan(result->x) || isnan(result->y))
+    {
+        pfree(result);
         PG_RETURN_NULL();
+    }
+
     PG_RETURN_POINT_P(result);
 }
 
@@ -1291,6 +1348,7 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
 
     if (!FPzero(l1->B))
     {
+        /* l1 is not virtucal */
         if (FPeq(l2->A, float8_mul(l1->A, float8_div(l2->B, l1->B))))
             return false;
 
@@ -1298,18 +1356,34 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
                                  float8_mul(l2->B, l1->C)),
                        float8_mi(float8_mul(l1->A, l2->B),
                                  float8_mul(l2->A, l1->B)));
-        y = float8_div(-float8_pl(float8_mul(l1->A, x), l1->C), l1->B);
-    }
-    else if (!FPzero(l2->B))
-    {
-        if (FPeq(l1->A, float8_mul(l2->A, float8_div(l1->B, l2->B))))
-            return false;
-
-        x = float8_div(float8_mi(float8_mul(l2->B, l1->C),
-                                 float8_mul(l1->B, l2->C)),
+        /*
+         * You might want to simplify this expression by using x, but that can
+         * introduce unnecessary indeterminants (inf-inf) into the calculation,
+         * which leads to a wrong result.
+         * (For example, (-1, -1, Inf) and (1, -1, 0))
+         */
+        y = float8_div(float8_mi(float8_mul(l1->A, l2->C),
+                                 float8_mul(l2->A, l1->C)),
                        float8_mi(float8_mul(l2->A, l1->B),
                                  float8_mul(l1->A, l2->B)));
-        y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+    }
+    else if (!FPzero(l2->B))
+    {
+        /* l2 is not virtical */
+        /*
+         * We know that l1 is vertical here. The lines cannot be parallel and
+         * the x-coord of the cross point is -C/A of l1.
+         */
+        x = -float8_div(l1->C, l1->A);
+
+        /*
+         * When l2->A is zero, y is determined independently from x even if it
+         * is Inf.
+         */
+        if (FPzero(l2->A))
+            y = -float8_div(l2->C, l2->B);
+        else
+            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
     }
     else
         return false;
@@ -1639,8 +1713,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b1.high.x = float8_max(p1->p[i].x, b1.high.x);
         b1.high.y = float8_max(p1->p[i].y, b1.high.y);
-        b1.low.x = float8_min(p1->p[i].x, b1.low.x);
-        b1.low.y = float8_min(p1->p[i].y, b1.low.y);
+        b1.low.x = float8_min_nan(p1->p[i].x, b1.low.x);
+        b1.low.y = float8_min_nan(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;
@@ -1648,8 +1722,8 @@ path_inter(PG_FUNCTION_ARGS)
     {
         b2.high.x = float8_max(p2->p[i].x, b2.high.x);
         b2.high.y = float8_max(p2->p[i].y, b2.high.y);
-        b2.low.x = float8_min(p2->p[i].x, b2.low.x);
-        b2.low.y = float8_min(p2->p[i].y, b2.low.y);
+        b2.low.x = float8_min_nan(p2->p[i].x, b2.low.x);
+        b2.low.y = float8_min_nan(p2->p[i].y, b2.low.y);
     }
     if (!box_ov(&b1, &b2))
         PG_RETURN_BOOL(false);
@@ -1739,6 +1813,11 @@ path_distance(PG_FUNCTION_ARGS)
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
 
             tmp = lseg_closept_lseg(NULL, &seg1, &seg2);
+
+            /* return NULL immediately if NaN is involved */
+            if (isnan(tmp))
+                PG_RETURN_NULL();
+
             if (!have_min || float8_lt(tmp, min))
             {
                 min = tmp;
@@ -1992,9 +2071,19 @@ static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return 0.0;
+    }
+
     return float8_div(float8_mi(pt1->y, pt2->y), float8_mi(pt1->x, pt2->x));
 }
 
@@ -2008,9 +2097,19 @@ static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
     if (FPeq(pt1->x, pt2->x))
+    {
+        if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
+            return get_float8_nan();
         return 0.0;
+    }
+
     if (FPeq(pt1->y, pt2->y))
+    {
+        if (unlikely(isnan(pt1->x) || isnan(pt2->x)))
+            return get_float8_nan();
         return get_float8_infinity();
+    }
+
     return float8_div(float8_mi(pt1->x, pt2->x), float8_mi(pt2->y, pt1->y));
 }
 
@@ -2426,6 +2525,11 @@ dist_ppath_internal(Point *pt, PATH *path)
 
         statlseg_construct(&lseg, &path->p[iprev], &path->p[i]);
         tmp = lseg_closept_point(NULL, &lseg, pt);
+
+        /* return NaN if NaN is involved */
+        if (unlikely(isnan(tmp)))
+            return tmp;
+
         if (!have_min || float8_lt(tmp, result))
         {
             result = tmp;
@@ -2619,6 +2723,8 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
         d = lseg_closept_point(NULL, &seg, pt);
         if (float8_lt(d, result))
             result = d;
+        else if (unlikely(isnan(d)))
+            return get_float8_nan();
     }
 
     return result;
@@ -2648,7 +2754,8 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line))
+    if (!line_interpt_line(&interpt, &tmp, line) ||
+        unlikely(isnan(interpt.x) || isnan(interpt.y)))
         return false;
 
     /*
@@ -2690,6 +2797,78 @@ line_closept_point(Point *result, LINE *line, Point *point)
 {
     Point        closept;
     LINE        tmp;
+    float8        val;
+
+    /*
+     * Treat specially the cases where A = 0 and B = 0, which we regard the
+     * line is perfectly horizontal and vertical correspondingly, not applying
+     * the normal formula involving the behavior of inf*0 =NaN defined by
+     * IEEE754.
+     */
+    if (FPzero(line->A))
+    {
+        float8 y;
+
+        /* the line is horizontal */
+        Assert(!FPzero(line->B));
+
+        y = -line->C / line->B;
+
+        /* Avoid -0 */
+        if (y == 0.0)
+            y = 0.0;
+
+        if (result != NULL)
+        {
+            result->x = point->x;
+            result->y = y;
+        }
+
+        if (unlikely(isnan(point->x)))
+            return get_float8_nan();
+
+        return fabs(point->y - y);
+    }
+    else if (FPzero(line->B))
+    {
+        float x;
+
+        /* the line is virtical */
+        Assert(!FPzero(line->A));
+
+        x = -line->C / line->A;
+
+        /* Avoid -0 */
+        if (x == 0)
+            x = 0;
+
+        if (result != NULL)
+        {
+            result->x = x;
+            result->y = point->y;
+        }
+
+        if (unlikely(isnan(point->y)))
+            return get_float8_nan();
+
+        return fabs(point->x - x);
+    }
+
+    /*
+     * If it is unclear whether the point is on the line or not, then the
+     * results are ill-defined.  This eliminates cases where any of the given
+     * coordinates are NaN, as well as cases where infinite coordinates give
+     * rise to Inf - Inf, 0 * Inf, etc.
+     */
+    val = float8_pl(float8_pl(float8_mul(line->A, point->x),
+                              float8_mul(line->B, point->y)),
+                    line->C);
+    if (unlikely(isnan(val)))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
 
     /*
      * We drop a perpendicular to find the intersection point.  Ordinarily we
@@ -2700,7 +2879,7 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (!line_interpt_line(&closept, &tmp, line))
     {
         if (result != NULL)
-            *result = *point;
+            result->x = result->y = get_float8_nan();
 
         return get_float8_nan();
     }
@@ -2708,7 +2887,17 @@ line_closept_point(Point *result, LINE *line, Point *point)
     if (result != NULL)
         *result = closept;
 
-    return point_dt(&closept, point);
+    /*
+     * If the closest point contains Inf's, the closest point may lose
+     * arithmetic relationship with the point which lets point_dt wrongly give
+     * NaN. To avoid that kind of failure, we calculate the distance using the
+     * following formula instead of using the closest point.
+     *
+     * | A*x + B*y + C | / sqrt(A^2 + B^2)
+     *
+     * The dividend have been already calculated so just divide it.
+     */
+    return float8_div(fabs(val), HYPOT(line->A, line->B));
 }
 
 Datum
@@ -2720,7 +2909,9 @@ close_pl(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (isnan(line_closept_point(result, line, pt)))
+    (void) line_closept_point(result, line, pt);
+
+    if (unlikely(isnan(result->x) || isnan(result->y)))
         PG_RETURN_NULL();
 
     PG_RETURN_POINT_P(result);
@@ -2777,6 +2968,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     Point        point;
     float8        dist,
                 d;
+    bool        anynan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
     if (lseg_interpt_lseg(result, on_lseg, to_lseg))
@@ -2788,6 +2980,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
      */
     dist = lseg_closept_point(result, on_lseg, &to_lseg->p[0]);
     d = lseg_closept_point(&point, on_lseg, &to_lseg->p[1]);
+    anynan |= (isnan(dist) || isnan(d));
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2797,6 +2990,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
 
     /* The closest point can still be one of the endpoints, so we test them. */
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[0]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2804,6 +2998,7 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[0];
     }
     d = lseg_closept_point(NULL, to_lseg, &on_lseg->p[1]);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2811,6 +3006,12 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
             *result = on_lseg->p[1];
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
     return dist;
 }
 
@@ -2847,6 +3048,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     Point        point,
                 closept;
     LSEG        lseg;
+    bool        anynan = false;
 
     if (box_contain_point(box, pt))
     {
@@ -2861,9 +3063,10 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->high.y;
     statlseg_construct(&lseg, &box->low, &point);
     dist = lseg_closept_point(result, &lseg, pt);
-
+    anynan |= isnan(dist);
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2875,6 +3078,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     point.y = box->low.y;
     statlseg_construct(&lseg, &box->low, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2884,6 +3088,7 @@ box_closept_point(Point *result, BOX *box, Point *pt)
 
     statlseg_construct(&lseg, &box->high, &point);
     d = lseg_closept_point(&closept, &lseg, pt);
+    anynan |= isnan(d);
     if (float8_lt(d, dist))
     {
         dist = d;
@@ -2891,6 +3096,13 @@ box_closept_point(Point *result, BOX *box, Point *pt)
             *result = closept;
     }
 
+    if (unlikely(anynan))
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+        return get_float8_nan();
+    }
+
     return dist;
 }
 
@@ -2920,6 +3132,7 @@ close_pb(PG_FUNCTION_ARGS)
  * even because of simple roundoff issues, there may not be a single closest
  * point.  We are likely to set the result to the second endpoint in these
  * cases.
+ * Returns Nan and stores {NaN,NaN} to result if NaN is involved,
  */
 static float8
 lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
@@ -2942,6 +3155,14 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
     }
     else
     {
+        /* return NaN if any of the two is NaN */
+        if (unlikely(isnan(dist1) || isnan(dist2)))
+        {
+            if (result != NULL)
+                result->x = result->y = get_float8_nan();
+            return get_float8_nan();
+        }
+
         if (result != NULL)
             *result = lseg->p[1];
 
@@ -3051,9 +3272,32 @@ close_sb(PG_FUNCTION_ARGS)
 static bool
 line_contain_point(LINE *line, Point *point)
 {
-    return FPzero(float8_pl(float8_pl(float8_mul(line->A, point->x),
-                                      float8_mul(line->B, point->y)),
-                            line->C));
+    /*
+     * Treat specially way the cases where A = 0 and B = 0, which we regard the
+     * line is perfectly horizontal and vertical correspondingly to avoid the
+     * normal formula based on the IEEE754's definitions yields unwanted NaNs.
+     */
+    if (line->A == 0.0)
+    {
+        /* the line is horizontal */
+        Assert(line->B != 0.0);
+
+        /* inf == inf here */
+        return FPeq(point->y, -line->C / line->B);
+    }
+    else if (line->B == 0.0)
+    {
+        /* the line is vertical */
+        Assert(line->A != 0.0);
+
+        /* inf == inf here */
+        return FPeq(point->x, -line->C / line->A);
+    }
+
+    return FPzero(float8_pl(
+                      float8_pl(float8_mul(line->A, point->x),
+                                float8_mul(line->B, point->y)),
+                      line->C));
 }
 
 Datum
@@ -3352,6 +3596,12 @@ make_bound_box(POLYGON *poly)
     y2 = y1 = poly->p[0].y;
     for (i = 1; i < poly->npts; i++)
     {
+        /* if NaN found, make an invalid boundbox */
+        if (unlikely(isnan(poly->p[i].x) || isnan(poly->p[i].y)))
+        {
+            x1 = x2 = y1 = y2 = get_float8_nan();
+            break;
+        }
         if (float8_lt(poly->p[i].x, x1))
             x1 = poly->p[i].x;
         if (float8_gt(poly->p[i].x, x2))
@@ -3837,6 +4087,11 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
+    /* Fast path. Check against boundbox. Also checks NaNs. */
+    if (!box_contain_point(&poly->boundbox, a) ||
+        !box_contain_point(&poly->boundbox, b))
+        return false;
+
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
@@ -5309,6 +5564,10 @@ point_inside(Point *p, int npts, Point *plist)
     x0 = float8_mi(plist[0].x, p->x);
     y0 = float8_mi(plist[0].y, p->y);
 
+    /* NaN makes the point cannot be inside the polygon */
+    if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
+        return 0;
+
     prev_x = x0;
     prev_y = y0;
     /* loop over polygon points and aggregate total_cross */
@@ -5318,6 +5577,10 @@ point_inside(Point *p, int npts, Point *plist)
         x = float8_mi(plist[i].x, p->x);
         y = float8_mi(plist[i].y, p->y);
 
+        /* NaN makes the point cannot be inside the polygon */
+        if (unlikely(isnan(x) || isnan(y)))
+            return 0;
+
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
             return 2;
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index fcf7bd581b..4ab3f9d8ef 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -353,4 +353,26 @@ float8_max(const float8 val1, const float8 val2)
     return float8_gt(val1, val2) ? val1 : val2;
 }
 
+/*
+ * These two functions return NaN if either input is NaN, else the smaller
+ * of the two inputs.  This does NOT follow our usual sort rule, but it is
+ * convenient in some places.  (Note that float4_max and float8_max act this
+ * way anyway, so no similar variant is needed for them.)
+ */
+static inline float4
+float4_min_nan(const float4 val1, const float4 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
+static inline float8
+float8_min_nan(const float8 val1, const float8 val2)
+{
+    return (isnan(val1) ? val1 :
+            (isnan(val2) ? val2 :
+             (val1 < val2 ? val1 : val2)));
+}
+
 #endif                            /* FLOAT_H */
diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out
index daf75dd5c4..5e77e0937d 100644
--- a/src/test/regress/expected/create_index.out
+++ b/src/test/regress/expected/create_index.out
@@ -139,7 +139,7 @@ SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1;
 SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)';
  count 
 -------
-     5
+     4
 (1 row)
 
 SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>';
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index d91d829f0f..77ff1b3d7b 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -517,7 +517,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-3,4)            | {0,3,0}                               |                  4 |                  4
  (-3,4)            | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-3,4)            | {-0.4,-1,-6}                          |      8.17059487979 |      8.17059487979
- (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690368 |      11.3851690368
+ (-3,4)            | {-0.000184615384615,-1,15.3846153846} |      11.3851690367 |      11.3851690367
  (-3,4)            | {3,NaN,5}                             |                NaN |                NaN
  (-3,4)            | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-3,4)            | {0,-1,3}                              |                  1 |                  1
@@ -537,7 +537,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (-5,-12)          | {0,3,0}                               |                 12 |                 12
  (-5,-12)          | {1,-1,0}                              |      4.94974746831 |      4.94974746831
  (-5,-12)          | {-0.4,-1,-6}                          |      7.42781352708 |      7.42781352708
- (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379948 |      27.3855379948
+ (-5,-12)          | {-0.000184615384615,-1,15.3846153846} |      27.3855379949 |      27.3855379949
  (-5,-12)          | {3,NaN,5}                             |                NaN |                NaN
  (-5,-12)          | {NaN,NaN,NaN}                         |                NaN |                NaN
  (-5,-12)          | {0,-1,3}                              |                 15 |                 15
@@ -553,7 +553,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e-300,-1e-300)  | {0,-1,3}                              |                  3 |                  3
  (1e-300,-1e-300)  | {-1,0,3}                              |                  3 |                  3
  (1e+300,Infinity) | {0,-1,5}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {1,0,5}                               |                NaN |                NaN
+ (1e+300,Infinity) | {1,0,5}                               |             1e+300 |             1e+300
  (1e+300,Infinity) | {0,3,0}                               |           Infinity |           Infinity
  (1e+300,Infinity) | {1,-1,0}                              |           Infinity |           Infinity
  (1e+300,Infinity) | {-0.4,-1,-6}                          |           Infinity |           Infinity
@@ -561,16 +561,16 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (1e+300,Infinity) | {3,NaN,5}                             |                NaN |                NaN
  (1e+300,Infinity) | {NaN,NaN,NaN}                         |                NaN |                NaN
  (1e+300,Infinity) | {0,-1,3}                              |           Infinity |           Infinity
- (1e+300,Infinity) | {-1,0,3}                              |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,5}                              |                NaN |                NaN
+ (1e+300,Infinity) | {-1,0,3}                              |             1e+300 |             1e+300
+ (Infinity,1e+300) | {0,-1,5}                              |             1e+300 |             1e+300
  (Infinity,1e+300) | {1,0,5}                               |           Infinity |           Infinity
- (Infinity,1e+300) | {0,3,0}                               |                NaN |                NaN
- (Infinity,1e+300) | {1,-1,0}                              |                NaN |                NaN
- (Infinity,1e+300) | {-0.4,-1,-6}                          |                NaN |                NaN
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |                NaN |                NaN
+ (Infinity,1e+300) | {0,3,0}                               |             1e+300 |             1e+300
+ (Infinity,1e+300) | {1,-1,0}                              |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.4,-1,-6}                          |           Infinity |           Infinity
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} |           Infinity |           Infinity
  (Infinity,1e+300) | {3,NaN,5}                             |                NaN |                NaN
  (Infinity,1e+300) | {NaN,NaN,NaN}                         |                NaN |                NaN
- (Infinity,1e+300) | {0,-1,3}                              |                NaN |                NaN
+ (Infinity,1e+300) | {0,-1,3}                              |             1e+300 |             1e+300
  (Infinity,1e+300) | {-1,0,3}                              |           Infinity |           Infinity
  (NaN,NaN)         | {0,-1,5}                              |                NaN |                NaN
  (NaN,NaN)         | {1,0,5}                               |                NaN |                NaN
@@ -587,7 +587,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_pl, l.s <-> p.f1 AS dist_lp FROM POINT_TB
  (10,10)           | {0,3,0}                               |                 10 |                 10
  (10,10)           | {1,-1,0}                              |                  0 |                  0
  (10,10)           | {-0.4,-1,-6}                          |      18.5695338177 |      18.5695338177
- (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913903 |      5.38276913903
+ (10,10)           | {-0.000184615384615,-1,15.3846153846} |      5.38276913904 |      5.38276913904
  (10,10)           | {3,NaN,5}                             |                NaN |                NaN
  (10,10)           | {NaN,NaN,NaN}                         |                NaN |                NaN
  (10,10)           | {0,-1,3}                              |                  7 |                  7
@@ -653,7 +653,7 @@ SELECT p.f1, l.s, p.f1 <-> l.s AS dist_ps, l.s <-> p.f1 AS dist_sp FROM POINT_TB
  (1e+300,Infinity) | [(11,22),(33,44)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(-10,2),(-10,3)]             |           Infinity |           Infinity
  (1e+300,Infinity) | [(0,-20),(30,-20)]            |           Infinity |           Infinity
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |           Infinity |           Infinity
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            |                NaN |                NaN
  (Infinity,1e+300) | [(1,2),(3,4)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(0,0),(6,6)]                 |           Infinity |           Infinity
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            |           Infinity |           Infinity
@@ -892,13 +892,13 @@ SELECT p.f1, p1.f1, p.f1 <-> p1.f1 AS dist_ppoly, p1.f1 <-> p.f1 AS dist_polyp F
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,0))                    |      Infinity |      Infinity
  (Infinity,1e+300) | ((0,1),(0,1))              |      Infinity |      Infinity
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        |             0 |             0
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        |             0 |             0
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |             0 |             0
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |             0 |             0
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |             0 |             0
- (NaN,NaN)         | ((0,0))                    |             0 |             0
- (NaN,NaN)         | ((0,1),(0,1))              |             0 |             0
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  |           NaN |           NaN
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  |           NaN |           NaN
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) |           NaN |           NaN
+ (NaN,NaN)         | ((0,0))                    |           NaN |           NaN
+ (NaN,NaN)         | ((0,1),(0,1))              |           NaN |           NaN
  (10,10)           | ((2,0),(2,4),(0,0))        |            10 |            10
  (10,10)           | ((3,1),(3,3),(1,0))        | 9.89949493661 | 9.89949493661
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | 3.60555127546 | 3.60555127546
@@ -919,7 +919,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (0,0)             | (-5,-12)          | {2.4,-1,0}
  (0,0)             | (1e+300,Infinity) | {-1,0,0}
  (0,0)             | (Infinity,1e+300) | {0,-1,0}
- (0,0)             | (NaN,NaN)         | {NaN,-1,NaN}
+ (0,0)             | (NaN,NaN)         | {NaN,NaN,NaN}
  (0,0)             | (10,10)           | {1,-1,0}
  (-10,0)           | (0,0)             | {0,-1,0}
  (-10,0)           | (-3,4)            | {0.571428571429,-1,5.71428571429}
@@ -928,7 +928,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-10,0)           | (1e-300,-1e-300)  | {0,-1,0}
  (-10,0)           | (1e+300,Infinity) | {-1,0,-10}
  (-10,0)           | (Infinity,1e+300) | {0,-1,0}
- (-10,0)           | (NaN,NaN)         | {NaN,-1,NaN}
+ (-10,0)           | (NaN,NaN)         | {NaN,NaN,NaN}
  (-10,0)           | (10,10)           | {0.5,-1,5}
  (-3,4)            | (0,0)             | {-1.33333333333,-1,0}
  (-3,4)            | (-10,0)           | {0.571428571429,-1,5.71428571429}
@@ -937,7 +937,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-3,4)            | (1e-300,-1e-300)  | {-1.33333333333,-1,0}
  (-3,4)            | (1e+300,Infinity) | {-1,0,-3}
  (-3,4)            | (Infinity,1e+300) | {0,-1,4}
- (-3,4)            | (NaN,NaN)         | {NaN,-1,NaN}
+ (-3,4)            | (NaN,NaN)         | {NaN,NaN,NaN}
  (-3,4)            | (10,10)           | {0.461538461538,-1,5.38461538462}
  (5.1,34.5)        | (0,0)             | {6.76470588235,-1,0}
  (5.1,34.5)        | (-10,0)           | {2.28476821192,-1,22.8476821192}
@@ -946,7 +946,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (5.1,34.5)        | (1e-300,-1e-300)  | {6.76470588235,-1,0}
  (5.1,34.5)        | (1e+300,Infinity) | {-1,0,5.1}
  (5.1,34.5)        | (Infinity,1e+300) | {0,-1,34.5}
- (5.1,34.5)        | (NaN,NaN)         | {NaN,-1,NaN}
+ (5.1,34.5)        | (NaN,NaN)         | {NaN,NaN,NaN}
  (5.1,34.5)        | (10,10)           | {-5,-1,60}
  (-5,-12)          | (0,0)             | {2.4,-1,0}
  (-5,-12)          | (-10,0)           | {-2.4,-1,-24}
@@ -955,7 +955,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-5,-12)          | (1e-300,-1e-300)  | {2.4,-1,0}
  (-5,-12)          | (1e+300,Infinity) | {-1,0,-5}
  (-5,-12)          | (Infinity,1e+300) | {0,-1,-12}
- (-5,-12)          | (NaN,NaN)         | {NaN,-1,NaN}
+ (-5,-12)          | (NaN,NaN)         | {NaN,NaN,NaN}
  (-5,-12)          | (10,10)           | {1.46666666667,-1,-4.66666666667}
  (1e-300,-1e-300)  | (-10,0)           | {0,-1,-1e-300}
  (1e-300,-1e-300)  | (-3,4)            | {-1.33333333333,-1,3.33333333333e-301}
@@ -963,7 +963,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e-300,-1e-300)  | (-5,-12)          | {2.4,-1,-3.4e-300}
  (1e-300,-1e-300)  | (1e+300,Infinity) | {-1,0,1e-300}
  (1e-300,-1e-300)  | (Infinity,1e+300) | {0,-1,-1e-300}
- (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,-1,NaN}
+ (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e-300,-1e-300)  | (10,10)           | {1,-1,-2e-300}
  (1e+300,Infinity) | (0,0)             | {-1,0,1e+300}
  (1e+300,Infinity) | (-10,0)           | {-1,0,1e+300}
@@ -971,8 +971,8 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e+300,Infinity) | (5.1,34.5)        | {-1,0,1e+300}
  (1e+300,Infinity) | (-5,-12)          | {-1,0,1e+300}
  (1e+300,Infinity) | (1e-300,-1e-300)  | {-1,0,1e+300}
- (1e+300,Infinity) | (Infinity,1e+300) | {NaN,-1,NaN}
- (1e+300,Infinity) | (NaN,NaN)         | {NaN,-1,NaN}
+ (1e+300,Infinity) | (Infinity,1e+300) | {NaN,NaN,NaN}
+ (1e+300,Infinity) | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e+300,Infinity) | (10,10)           | {-1,0,1e+300}
  (Infinity,1e+300) | (0,0)             | {0,-1,1e+300}
  (Infinity,1e+300) | (-10,0)           | {0,-1,1e+300}
@@ -980,18 +980,18 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (Infinity,1e+300) | (5.1,34.5)        | {0,-1,1e+300}
  (Infinity,1e+300) | (-5,-12)          | {0,-1,1e+300}
  (Infinity,1e+300) | (1e-300,-1e-300)  | {0,-1,1e+300}
- (Infinity,1e+300) | (1e+300,Infinity) | {NaN,-1,NaN}
- (Infinity,1e+300) | (NaN,NaN)         | {NaN,-1,NaN}
+ (Infinity,1e+300) | (1e+300,Infinity) | {NaN,NaN,NaN}
+ (Infinity,1e+300) | (NaN,NaN)         | {NaN,NaN,NaN}
  (Infinity,1e+300) | (10,10)           | {0,-1,1e+300}
- (NaN,NaN)         | (0,0)             | {NaN,-1,NaN}
- (NaN,NaN)         | (-10,0)           | {NaN,-1,NaN}
- (NaN,NaN)         | (-3,4)            | {NaN,-1,NaN}
- (NaN,NaN)         | (5.1,34.5)        | {NaN,-1,NaN}
- (NaN,NaN)         | (-5,-12)          | {NaN,-1,NaN}
- (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,-1,NaN}
- (NaN,NaN)         | (1e+300,Infinity) | {NaN,-1,NaN}
- (NaN,NaN)         | (Infinity,1e+300) | {NaN,-1,NaN}
- (NaN,NaN)         | (10,10)           | {NaN,-1,NaN}
+ (NaN,NaN)         | (0,0)             | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-10,0)           | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-3,4)            | {NaN,NaN,NaN}
+ (NaN,NaN)         | (5.1,34.5)        | {NaN,NaN,NaN}
+ (NaN,NaN)         | (-5,-12)          | {NaN,NaN,NaN}
+ (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,NaN,NaN}
+ (NaN,NaN)         | (1e+300,Infinity) | {NaN,NaN,NaN}
+ (NaN,NaN)         | (Infinity,1e+300) | {NaN,NaN,NaN}
+ (NaN,NaN)         | (10,10)           | {NaN,NaN,NaN}
  (10,10)           | (0,0)             | {1,-1,0}
  (10,10)           | (-10,0)           | {0.5,-1,5}
  (10,10)           | (-3,4)            | {0.461538461538,-1,5.38461538462}
@@ -1000,7 +1000,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (10,10)           | (1e-300,-1e-300)  | {1,-1,0}
  (10,10)           | (1e+300,Infinity) | {-1,0,10}
  (10,10)           | (Infinity,1e+300) | {0,-1,10}
- (10,10)           | (NaN,NaN)         | {NaN,-1,NaN}
+ (10,10)           | (NaN,NaN)         | {NaN,NaN,NaN}
 (88 rows)
 
 -- Closest point to line
@@ -1068,24 +1068,24 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
  (1e-300,-1e-300)  | {0,-1,3}                              | (1e-300,3)
  (1e-300,-1e-300)  | {-1,0,3}                              | (3,-1e-300)
  (1e+300,Infinity) | {0,-1,5}                              | (1e+300,5)
- (1e+300,Infinity) | {1,0,5}                               | 
+ (1e+300,Infinity) | {1,0,5}                               | (-5,Infinity)
  (1e+300,Infinity) | {0,3,0}                               | (1e+300,0)
- (1e+300,Infinity) | {1,-1,0}                              | (Infinity,NaN)
- (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,NaN)
- (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN)
+ (1e+300,Infinity) | {1,-1,0}                              | (Infinity,Infinity)
+ (1e+300,Infinity) | {-0.4,-1,-6}                          | (-Infinity,Infinity)
+ (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,Infinity)
  (1e+300,Infinity) | {3,NaN,5}                             | 
  (1e+300,Infinity) | {NaN,NaN,NaN}                         | 
  (1e+300,Infinity) | {0,-1,3}                              | (1e+300,3)
- (1e+300,Infinity) | {-1,0,3}                              | 
- (Infinity,1e+300) | {0,-1,5}                              | 
+ (1e+300,Infinity) | {-1,0,3}                              | (3,Infinity)
+ (Infinity,1e+300) | {0,-1,5}                              | (Infinity,5)
  (Infinity,1e+300) | {1,0,5}                               | (-5,1e+300)
- (Infinity,1e+300) | {0,3,0}                               | 
- (Infinity,1e+300) | {1,-1,0}                              | 
- (Infinity,1e+300) | {-0.4,-1,-6}                          | 
- (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | 
+ (Infinity,1e+300) | {0,3,0}                               | (Infinity,0)
+ (Infinity,1e+300) | {1,-1,0}                              | (Infinity,Infinity)
+ (Infinity,1e+300) | {-0.4,-1,-6}                          | (Infinity,-Infinity)
+ (Infinity,1e+300) | {-0.000184615384615,-1,15.3846153846} | (Infinity,-Infinity)
  (Infinity,1e+300) | {3,NaN,5}                             | 
  (Infinity,1e+300) | {NaN,NaN,NaN}                         | 
- (Infinity,1e+300) | {0,-1,3}                              | 
+ (Infinity,1e+300) | {0,-1,3}                              | (Infinity,3)
  (Infinity,1e+300) | {-1,0,3}                              | (3,1e+300)
  (NaN,NaN)         | {0,-1,5}                              | 
  (NaN,NaN)         | {1,0,5}                               | 
@@ -1168,7 +1168,7 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LSEG_TBL l;
  (1e+300,Infinity) | [(11,22),(33,44)]             | (33,44)
  (1e+300,Infinity) | [(-10,2),(-10,3)]             | (-10,3)
  (1e+300,Infinity) | [(0,-20),(30,-20)]            | (30,-20)
- (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | (NaN,90)
+ (1e+300,Infinity) | [(NaN,1),(NaN,90)]            | 
  (Infinity,1e+300) | [(1,2),(3,4)]                 | (3,4)
  (Infinity,1e+300) | [(0,0),(6,6)]                 | (6,6)
  (Infinity,1e+300) | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1278,12 +1278,7 @@ SELECT p.f1, p1.f1 FROM POINT_TBL p, PATH_TBL p1 WHERE p.f1 <@ p1.f1;
 ------------------+---------------------------
  (0,0)            | [(0,0),(3,0),(4,5),(1,6)]
  (1e-300,-1e-300) | [(0,0),(3,0),(4,5),(1,6)]
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((1,2),(3,4))
- (NaN,NaN)        | ((10,20))
- (NaN,NaN)        | ((11,12),(13,14))
-(7 rows)
+(2 rows)
 
 --
 -- Lines
@@ -1371,8 +1366,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,-1,5}                              | {1,-1,0}                              |        0
  {0,-1,5}                              | {-0.4,-1,-6}                          |        0
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,5}                              | {3,NaN,5}                             |        0
- {0,-1,5}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,5}                              | {3,NaN,5}                             |      NaN
+ {0,-1,5}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,5}                              | {0,-1,3}                              |        2
  {0,-1,5}                              | {-1,0,3}                              |        0
  {1,0,5}                               | {0,-1,5}                              |        0
@@ -1381,8 +1376,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              |        0
  {1,0,5}                               | {-0.4,-1,-6}                          |        0
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {1,0,5}                               | {3,NaN,5}                             |        0
- {1,0,5}                               | {NaN,NaN,NaN}                         |        0
+ {1,0,5}                               | {3,NaN,5}                             |      NaN
+ {1,0,5}                               | {NaN,NaN,NaN}                         |      NaN
  {1,0,5}                               | {0,-1,3}                              |        0
  {1,0,5}                               | {-1,0,3}                              |        8
  {0,3,0}                               | {0,-1,5}                              |        5
@@ -1391,8 +1386,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              |        0
  {0,3,0}                               | {-0.4,-1,-6}                          |        0
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} |        0
- {0,3,0}                               | {3,NaN,5}                             |        0
- {0,3,0}                               | {NaN,NaN,NaN}                         |        0
+ {0,3,0}                               | {3,NaN,5}                             |      NaN
+ {0,3,0}                               | {NaN,NaN,NaN}                         |      NaN
  {0,3,0}                               | {0,-1,3}                              |        3
  {0,3,0}                               | {-1,0,3}                              |        0
  {1,-1,0}                              | {0,-1,5}                              |        0
@@ -1401,8 +1396,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              |        0
  {1,-1,0}                              | {-0.4,-1,-6}                          |        0
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {1,-1,0}                              | {3,NaN,5}                             |        0
- {1,-1,0}                              | {NaN,NaN,NaN}                         |        0
+ {1,-1,0}                              | {3,NaN,5}                             |      NaN
+ {1,-1,0}                              | {NaN,NaN,NaN}                         |      NaN
  {1,-1,0}                              | {0,-1,3}                              |        0
  {1,-1,0}                              | {-1,0,3}                              |        0
  {-0.4,-1,-6}                          | {0,-1,5}                              |        0
@@ -1411,8 +1406,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              |        0
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          |        0
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.4,-1,-6}                          | {3,NaN,5}                             |        0
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |        0
+ {-0.4,-1,-6}                          | {3,NaN,5}                             |      NaN
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         |      NaN
  {-0.4,-1,-6}                          | {0,-1,3}                              |        0
  {-0.4,-1,-6}                          | {-1,0,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              |        0
@@ -1421,38 +1416,38 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          |        0
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} |        0
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |        0
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |        0
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             |      NaN
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         |      NaN
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              |        0
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              |        0
- {3,NaN,5}                             | {0,-1,5}                              |        0
- {3,NaN,5}                             | {1,0,5}                               |        0
- {3,NaN,5}                             | {0,3,0}                               |        0
- {3,NaN,5}                             | {1,-1,0}                              |        0
- {3,NaN,5}                             | {-0.4,-1,-6}                          |        0
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |        0
- {3,NaN,5}                             | {3,NaN,5}                             |        0
- {3,NaN,5}                             | {NaN,NaN,NaN}                         |        0
- {3,NaN,5}                             | {0,-1,3}                              |        0
- {3,NaN,5}                             | {-1,0,3}                              |        0
- {NaN,NaN,NaN}                         | {0,-1,5}                              |        0
- {NaN,NaN,NaN}                         | {1,0,5}                               |        0
- {NaN,NaN,NaN}                         | {0,3,0}                               |        0
- {NaN,NaN,NaN}                         | {1,-1,0}                              |        0
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |        0
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |        0
- {NaN,NaN,NaN}                         | {3,NaN,5}                             |        0
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |        0
- {NaN,NaN,NaN}                         | {0,-1,3}                              |        0
- {NaN,NaN,NaN}                         | {-1,0,3}                              |        0
+ {3,NaN,5}                             | {0,-1,5}                              |      NaN
+ {3,NaN,5}                             | {1,0,5}                               |      NaN
+ {3,NaN,5}                             | {0,3,0}                               |      NaN
+ {3,NaN,5}                             | {1,-1,0}                              |      NaN
+ {3,NaN,5}                             | {-0.4,-1,-6}                          |      NaN
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {3,NaN,5}                             | {3,NaN,5}                             |      NaN
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         |      NaN
+ {3,NaN,5}                             | {0,-1,3}                              |      NaN
+ {3,NaN,5}                             | {-1,0,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,5}                              |      NaN
+ {NaN,NaN,NaN}                         | {1,0,5}                               |      NaN
+ {NaN,NaN,NaN}                         | {0,3,0}                               |      NaN
+ {NaN,NaN,NaN}                         | {1,-1,0}                              |      NaN
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          |      NaN
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} |      NaN
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             |      NaN
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         |      NaN
+ {NaN,NaN,NaN}                         | {0,-1,3}                              |      NaN
+ {NaN,NaN,NaN}                         | {-1,0,3}                              |      NaN
  {0,-1,3}                              | {0,-1,5}                              |        2
  {0,-1,3}                              | {1,0,5}                               |        0
  {0,-1,3}                              | {0,3,0}                               |        3
  {0,-1,3}                              | {1,-1,0}                              |        0
  {0,-1,3}                              | {-0.4,-1,-6}                          |        0
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {0,-1,3}                              | {3,NaN,5}                             |        0
- {0,-1,3}                              | {NaN,NaN,NaN}                         |        0
+ {0,-1,3}                              | {3,NaN,5}                             |      NaN
+ {0,-1,3}                              | {NaN,NaN,NaN}                         |      NaN
  {0,-1,3}                              | {0,-1,3}                              |        0
  {0,-1,3}                              | {-1,0,3}                              |        0
  {-1,0,3}                              | {0,-1,5}                              |        0
@@ -1461,8 +1456,8 @@ SELECT l1.s, l2.s, l1.s <-> l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              |        0
  {-1,0,3}                              | {-0.4,-1,-6}                          |        0
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} |        0
- {-1,0,3}                              | {3,NaN,5}                             |        0
- {-1,0,3}                              | {NaN,NaN,NaN}                         |        0
+ {-1,0,3}                              | {3,NaN,5}                             |      NaN
+ {-1,0,3}                              | {NaN,NaN,NaN}                         |      NaN
  {-1,0,3}                              | {0,-1,3}                              |        0
  {-1,0,3}                              | {-1,0,3}                              |        0
 (100 rows)
@@ -1475,31 +1470,23 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {0,-1,5}                              | {1,-1,0}
  {0,-1,5}                              | {-0.4,-1,-6}
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,5}                              | {3,NaN,5}
- {0,-1,5}                              | {NaN,NaN,NaN}
  {0,-1,5}                              | {-1,0,3}
  {1,0,5}                               | {0,-1,5}
  {1,0,5}                               | {0,3,0}
  {1,0,5}                               | {1,-1,0}
  {1,0,5}                               | {-0.4,-1,-6}
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846}
- {1,0,5}                               | {3,NaN,5}
- {1,0,5}                               | {NaN,NaN,NaN}
  {1,0,5}                               | {0,-1,3}
  {0,3,0}                               | {1,0,5}
  {0,3,0}                               | {1,-1,0}
  {0,3,0}                               | {-0.4,-1,-6}
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846}
- {0,3,0}                               | {3,NaN,5}
- {0,3,0}                               | {NaN,NaN,NaN}
  {0,3,0}                               | {-1,0,3}
  {1,-1,0}                              | {0,-1,5}
  {1,-1,0}                              | {1,0,5}
  {1,-1,0}                              | {0,3,0}
  {1,-1,0}                              | {-0.4,-1,-6}
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846}
- {1,-1,0}                              | {3,NaN,5}
- {1,-1,0}                              | {NaN,NaN,NaN}
  {1,-1,0}                              | {0,-1,3}
  {1,-1,0}                              | {-1,0,3}
  {-0.4,-1,-6}                          | {0,-1,5}
@@ -1507,8 +1494,6 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.4,-1,-6}                          | {0,3,0}
  {-0.4,-1,-6}                          | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846}
- {-0.4,-1,-6}                          | {3,NaN,5}
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}
  {-0.4,-1,-6}                          | {0,-1,3}
  {-0.4,-1,-6}                          | {-1,0,3}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}
@@ -1516,46 +1501,20 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?# l2.s;
  {-0.000184615384615,-1,15.3846153846} | {0,3,0}
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}
- {3,NaN,5}                             | {0,-1,5}
- {3,NaN,5}                             | {1,0,5}
- {3,NaN,5}                             | {0,3,0}
- {3,NaN,5}                             | {1,-1,0}
- {3,NaN,5}                             | {-0.4,-1,-6}
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {3,NaN,5}                             | {NaN,NaN,NaN}
- {3,NaN,5}                             | {0,-1,3}
- {3,NaN,5}                             | {-1,0,3}
- {NaN,NaN,NaN}                         | {0,-1,5}
- {NaN,NaN,NaN}                         | {1,0,5}
- {NaN,NaN,NaN}                         | {0,3,0}
- {NaN,NaN,NaN}                         | {1,-1,0}
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846}
- {NaN,NaN,NaN}                         | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
- {NaN,NaN,NaN}                         | {0,-1,3}
- {NaN,NaN,NaN}                         | {-1,0,3}
  {0,-1,3}                              | {1,0,5}
  {0,-1,3}                              | {1,-1,0}
  {0,-1,3}                              | {-0.4,-1,-6}
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846}
- {0,-1,3}                              | {3,NaN,5}
- {0,-1,3}                              | {NaN,NaN,NaN}
  {0,-1,3}                              | {-1,0,3}
  {-1,0,3}                              | {0,-1,5}
  {-1,0,3}                              | {0,3,0}
  {-1,0,3}                              | {1,-1,0}
  {-1,0,3}                              | {-0.4,-1,-6}
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846}
- {-1,0,3}                              | {3,NaN,5}
- {-1,0,3}                              | {NaN,NaN,NaN}
  {-1,0,3}                              | {0,-1,3}
-(84 rows)
+(48 rows)
 
 -- Intersect with box
 SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
@@ -1578,16 +1537,16 @@ SELECT l.s, b.f1 FROM LINE_TBL l, BOX_TBL b WHERE l.s ?# b.f1;
 
 -- Intersection point with line
 SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
-                   s                   |                   s                   |             ?column?              
----------------------------------------+---------------------------------------+-----------------------------------
+                   s                   |                   s                   |            ?column?             
+---------------------------------------+---------------------------------------+---------------------------------
  {0,-1,5}                              | {0,-1,5}                              | 
  {0,-1,5}                              | {1,0,5}                               | (-5,5)
  {0,-1,5}                              | {0,3,0}                               | 
  {0,-1,5}                              | {1,-1,0}                              | (5,5)
  {0,-1,5}                              | {-0.4,-1,-6}                          | (-27.5,5)
  {0,-1,5}                              | {-0.000184615384615,-1,15.3846153846} | (56250,5)
- {0,-1,5}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,5}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,5}                              | {3,NaN,5}                             | 
+ {0,-1,5}                              | {NaN,NaN,NaN}                         | 
  {0,-1,5}                              | {0,-1,3}                              | 
  {0,-1,5}                              | {-1,0,3}                              | (3,5)
  {1,0,5}                               | {0,-1,5}                              | (-5,5)
@@ -1596,8 +1555,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,0,5}                               | {1,-1,0}                              | (-5,-5)
  {1,0,5}                               | {-0.4,-1,-6}                          | (-5,-4)
  {1,0,5}                               | {-0.000184615384615,-1,15.3846153846} | (-5,15.3855384615)
- {1,0,5}                               | {3,NaN,5}                             | (NaN,NaN)
- {1,0,5}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,0,5}                               | {3,NaN,5}                             | 
+ {1,0,5}                               | {NaN,NaN,NaN}                         | 
  {1,0,5}                               | {0,-1,3}                              | (-5,3)
  {1,0,5}                               | {-1,0,3}                              | 
  {0,3,0}                               | {0,-1,5}                              | 
@@ -1606,8 +1565,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {0,3,0}                               | {1,-1,0}                              | (0,0)
  {0,3,0}                               | {-0.4,-1,-6}                          | (-15,0)
  {0,3,0}                               | {-0.000184615384615,-1,15.3846153846} | (83333.3333333,0)
- {0,3,0}                               | {3,NaN,5}                             | (NaN,NaN)
- {0,3,0}                               | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,3,0}                               | {3,NaN,5}                             | 
+ {0,3,0}                               | {NaN,NaN,NaN}                         | 
  {0,3,0}                               | {0,-1,3}                              | 
  {0,3,0}                               | {-1,0,3}                              | (3,0)
  {1,-1,0}                              | {0,-1,5}                              | (5,5)
@@ -1616,8 +1575,8 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {1,-1,0}                              | {1,-1,0}                              | 
  {1,-1,0}                              | {-0.4,-1,-6}                          | (-4.28571428571,-4.28571428571)
  {1,-1,0}                              | {-0.000184615384615,-1,15.3846153846} | (15.3817756722,15.3817756722)
- {1,-1,0}                              | {3,NaN,5}                             | (NaN,NaN)
- {1,-1,0}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {1,-1,0}                              | {3,NaN,5}                             | 
+ {1,-1,0}                              | {NaN,NaN,NaN}                         | 
  {1,-1,0}                              | {0,-1,3}                              | (3,3)
  {1,-1,0}                              | {-1,0,3}                              | (3,3)
  {-0.4,-1,-6}                          | {0,-1,5}                              | (-27.5,5)
@@ -1626,48 +1585,48 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-0.4,-1,-6}                          | {1,-1,0}                              | (-4.28571428571,-4.28571428571)
  {-0.4,-1,-6}                          | {-0.4,-1,-6}                          | 
  {-0.4,-1,-6}                          | {-0.000184615384615,-1,15.3846153846} | (-53.4862244113,15.3944897645)
- {-0.4,-1,-6}                          | {3,NaN,5}                             | (NaN,NaN)
- {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.4,-1,-6}                          | {3,NaN,5}                             | 
+ {-0.4,-1,-6}                          | {NaN,NaN,NaN}                         | 
  {-0.4,-1,-6}                          | {0,-1,3}                              | (-22.5,3)
  {-0.4,-1,-6}                          | {-1,0,3}                              | (3,-7.2)
  {-0.000184615384615,-1,15.3846153846} | {0,-1,5}                              | (56250,5)
  {-0.000184615384615,-1,15.3846153846} | {1,0,5}                               | (-5,15.3855384615)
- {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,-1.7763568394e-15)
+ {-0.000184615384615,-1,15.3846153846} | {0,3,0}                               | (83333.3333333,0)
  {-0.000184615384615,-1,15.3846153846} | {1,-1,0}                              | (15.3817756722,15.3817756722)
  {-0.000184615384615,-1,15.3846153846} | {-0.4,-1,-6}                          | (-53.4862244113,15.3944897645)
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846} | 
- {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | (NaN,NaN)
- {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-0.000184615384615,-1,15.3846153846} | {3,NaN,5}                             | 
+ {-0.000184615384615,-1,15.3846153846} | {NaN,NaN,NaN}                         | 
  {-0.000184615384615,-1,15.3846153846} | {0,-1,3}                              | (67083.3333333,3)
  {-0.000184615384615,-1,15.3846153846} | {-1,0,3}                              | (3,15.3840615385)
- {3,NaN,5}                             | {0,-1,5}                              | (NaN,NaN)
- {3,NaN,5}                             | {1,0,5}                               | (NaN,NaN)
- {3,NaN,5}                             | {0,3,0}                               | (NaN,NaN)
- {3,NaN,5}                             | {1,-1,0}                              | (NaN,NaN)
- {3,NaN,5}                             | {-0.4,-1,-6}                          | (NaN,NaN)
- {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {3,NaN,5}                             | {3,NaN,5}                             | (NaN,NaN)
- {3,NaN,5}                             | {NaN,NaN,NaN}                         | (NaN,NaN)
- {3,NaN,5}                             | {0,-1,3}                              | (NaN,NaN)
- {3,NaN,5}                             | {-1,0,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,5}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,0,5}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,3,0}                               | (NaN,NaN)
- {NaN,NaN,NaN}                         | {1,-1,0}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | (NaN,NaN)
- {NaN,NaN,NaN}                         | {3,NaN,5}                             | (NaN,NaN)
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | (NaN,NaN)
- {NaN,NaN,NaN}                         | {0,-1,3}                              | (NaN,NaN)
- {NaN,NaN,NaN}                         | {-1,0,3}                              | (NaN,NaN)
+ {3,NaN,5}                             | {0,-1,5}                              | 
+ {3,NaN,5}                             | {1,0,5}                               | 
+ {3,NaN,5}                             | {0,3,0}                               | 
+ {3,NaN,5}                             | {1,-1,0}                              | 
+ {3,NaN,5}                             | {-0.4,-1,-6}                          | 
+ {3,NaN,5}                             | {-0.000184615384615,-1,15.3846153846} | 
+ {3,NaN,5}                             | {3,NaN,5}                             | 
+ {3,NaN,5}                             | {NaN,NaN,NaN}                         | 
+ {3,NaN,5}                             | {0,-1,3}                              | 
+ {3,NaN,5}                             | {-1,0,3}                              | 
+ {NaN,NaN,NaN}                         | {0,-1,5}                              | 
+ {NaN,NaN,NaN}                         | {1,0,5}                               | 
+ {NaN,NaN,NaN}                         | {0,3,0}                               | 
+ {NaN,NaN,NaN}                         | {1,-1,0}                              | 
+ {NaN,NaN,NaN}                         | {-0.4,-1,-6}                          | 
+ {NaN,NaN,NaN}                         | {-0.000184615384615,-1,15.3846153846} | 
+ {NaN,NaN,NaN}                         | {3,NaN,5}                             | 
+ {NaN,NaN,NaN}                         | {NaN,NaN,NaN}                         | 
+ {NaN,NaN,NaN}                         | {0,-1,3}                              | 
+ {NaN,NaN,NaN}                         | {-1,0,3}                              | 
  {0,-1,3}                              | {0,-1,5}                              | 
  {0,-1,3}                              | {1,0,5}                               | (-5,3)
  {0,-1,3}                              | {0,3,0}                               | 
  {0,-1,3}                              | {1,-1,0}                              | (3,3)
  {0,-1,3}                              | {-0.4,-1,-6}                          | (-22.5,3)
  {0,-1,3}                              | {-0.000184615384615,-1,15.3846153846} | (67083.3333333,3)
- {0,-1,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {0,-1,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {0,-1,3}                              | {3,NaN,5}                             | 
+ {0,-1,3}                              | {NaN,NaN,NaN}                         | 
  {0,-1,3}                              | {0,-1,3}                              | 
  {0,-1,3}                              | {-1,0,3}                              | (3,3)
  {-1,0,3}                              | {0,-1,5}                              | (3,5)
@@ -1676,16 +1635,16 @@ SELECT l1.s, l2.s, l1.s # l2.s FROM LINE_TBL l1, LINE_TBL l2;
  {-1,0,3}                              | {1,-1,0}                              | (3,3)
  {-1,0,3}                              | {-0.4,-1,-6}                          | (3,-7.2)
  {-1,0,3}                              | {-0.000184615384615,-1,15.3846153846} | (3,15.3840615385)
- {-1,0,3}                              | {3,NaN,5}                             | (NaN,NaN)
- {-1,0,3}                              | {NaN,NaN,NaN}                         | (NaN,NaN)
+ {-1,0,3}                              | {3,NaN,5}                             | 
+ {-1,0,3}                              | {NaN,NaN,NaN}                         | 
  {-1,0,3}                              | {0,-1,3}                              | (3,3)
  {-1,0,3}                              | {-1,0,3}                              | 
 (100 rows)
 
 -- Closest point to line segment
 SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
-                   s                   |               s               |             ?column?              
----------------------------------------+-------------------------------+-----------------------------------
+                   s                   |               s               |            ?column?            
+---------------------------------------+-------------------------------+--------------------------------
  {0,-1,5}                              | [(1,2),(3,4)]                 | (3,4)
  {0,-1,5}                              | [(0,0),(6,6)]                 | (5,5)
  {0,-1,5}                              | [(10,-10),(-3,-4)]            | (-3,-4)
@@ -1705,7 +1664,7 @@ SELECT l.s, l1.s, l.s ## l1.s FROM LINE_TBL l, LSEG_TBL l1;
  {0,3,0}                               | [(1,2),(3,4)]                 | (1,2)
  {0,3,0}                               | [(0,0),(6,6)]                 | (0,0)
  {0,3,0}                               | [(10,-10),(-3,-4)]            | (-3,-4)
- {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,-1.7763568394e-15)
+ {0,3,0}                               | [(-1000000,200),(300000,-40)] | (83333.3333333,0)
  {0,3,0}                               | [(11,22),(33,44)]             | (11,22)
  {0,3,0}                               | [(-10,2),(-10,3)]             | (-10,2)
  {0,3,0}                               | [(0,-20),(30,-20)]            | 
@@ -3721,13 +3680,13 @@ SELECT p.f1, poly.f1, poly.f1 @> p.f1 AS contains
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
  (Infinity,1e+300) | ((0,0))                    | f
  (Infinity,1e+300) | ((0,1),(0,1))              | f
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
- (NaN,NaN)         | ((0,0))                    | t
- (NaN,NaN)         | ((0,1),(0,1))              | t
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+ (NaN,NaN)         | ((0,0))                    | f
+ (NaN,NaN)         | ((0,1),(0,1))              | f
  (10,10)           | ((2,0),(2,4),(0,0))        | f
  (10,10)           | ((3,1),(3,3),(1,0))        | f
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3797,13 +3756,13 @@ SELECT p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
  (Infinity,1e+300) | ((0,0))                    | f
  (Infinity,1e+300) | ((0,1),(0,1))              | f
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        | t
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        | t
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | t
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | t
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | t
- (NaN,NaN)         | ((0,0))                    | t
- (NaN,NaN)         | ((0,1),(0,1))              | t
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
+ (NaN,NaN)         | ((0,0))                    | f
+ (NaN,NaN)         | ((0,1),(0,1))              | f
  (10,10)           | ((2,0),(2,4),(0,0))        | f
  (10,10)           | ((3,1),(3,3),(1,0))        | f
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
-- 
2.27.0

From 400b0bd6102414ad3421ff03818d927c92dcbdb7 Mon Sep 17 00:00:00 2001
From: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Date: Thu, 8 Jul 2021 10:24:25 +0900
Subject: [PATCH v9 2/2] Make geometric comparisons tri-state

Geometric comparisons are constructively tri-state so that comparisons
with an invalid objects yields "undefined".  This patch introduces
that behavior. Geometric comparison operators return null forr invalid
objects or when the intermediate calculation yeilds NaN.  GiST is
adjusted to handle such null return from box placement operators
properly.
---
 src/backend/access/gist/gistproc.c     | 215 ++++---
 src/backend/utils/adt/geo_ops.c        | 796 ++++++++++++++++---------
 src/backend/utils/fmgr/fmgr.c          |  18 +-
 src/include/c.h                        |   7 +
 src/include/fmgr.h                     |  19 +-
 src/include/utils/float.h              | 109 ++++
 src/include/utils/geo_decls.h          | 107 ++++
 src/test/regress/expected/geometry.out |  75 +--
 src/test/regress/expected/line.out     |   3 +-
 src/test/regress/expected/point.out    |   6 +-
 src/test/regress/sql/line.sql          |   1 +
 11 files changed, 926 insertions(+), 430 deletions(-)

diff --git a/src/backend/access/gist/gistproc.c b/src/backend/access/gist/gistproc.c
index d474612b77..31a49c47da 100644
--- a/src/backend/access/gist/gistproc.c
+++ b/src/backend/access/gist/gistproc.c
@@ -873,75 +873,90 @@ static bool
 gist_box_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy)
 {
     bool        retval;
+    bool        isnull = false;
 
     switch (strategy)
     {
         case RTLeftStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_left,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_left,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverLeftStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overleft,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overleft,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverlapStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overlap,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overlap,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverRightStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overright,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overright,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTRightStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_right,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_right,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTSameStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_same,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_same,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTContainsStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_contain,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_contain,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTContainedByStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_contained,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_contained,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverBelowStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overbelow,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overbelow,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTBelowStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_below,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_below,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTAboveStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_above,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_above,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverAboveStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overabove,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overabove,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         default:
             elog(ERROR, "unrecognized strategy number: %d", strategy);
             retval = false;        /* keep compiler quiet */
             break;
     }
-    return retval;
+
+    /* consider null as false */
+    return retval && !isnull;
 }
 
 /*****************************************
@@ -958,71 +973,85 @@ static bool
 rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
 {
     bool        retval;
+    bool        isnull = false;
 
     switch (strategy)
     {
         case RTLeftStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_overright,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_overright,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTOverLeftStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_right,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_right,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTOverlapStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overlap,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overlap,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverRightStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_left,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_left,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTRightStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_overleft,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_overleft,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTSameStrategyNumber:
         case RTContainsStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_contain,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_contain,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTContainedByStrategyNumber:
-            retval = DatumGetBool(DirectFunctionCall2(box_overlap,
-                                                      PointerGetDatum(key),
-                                                      PointerGetDatum(query)));
+            retval = DatumGetBool(DirectFunctionCall2Ext(box_overlap,
+                                                         PointerGetDatum(key),
+                                                         PointerGetDatum(query),
+                                                         &isnull));
             break;
         case RTOverBelowStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_above,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_above,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTBelowStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_overabove,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_overabove,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTAboveStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_overbelow,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_overbelow,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         case RTOverAboveStrategyNumber:
-            retval = !DatumGetBool(DirectFunctionCall2(box_below,
-                                                       PointerGetDatum(key),
-                                                       PointerGetDatum(query)));
+            retval = !DatumGetBool(DirectFunctionCall2Ext(box_below,
+                                                          PointerGetDatum(key),
+                                                          PointerGetDatum(query),
+                                                          &isnull));
             break;
         default:
             elog(ERROR, "unrecognized strategy number: %d", strategy);
             retval = false;        /* keep compiler quiet */
             break;
     }
-    return retval;
+
+    /* consider null as false */
+    return retval || isnull;
 }
 
 /**************************************************
@@ -1237,22 +1266,30 @@ computeDistance(bool isLeaf, BOX *box, Point *point)
     else if (point->x <= box->high.x && point->x >= box->low.x)
     {
         /* point is over or below box */
-        Assert(box->low.y <= box->high.y);
+        Assert(box->low.y <= box->high.y
+               || isnan(box->low.y) || isnan(box->high.y));
+
         if (point->y > box->high.y)
             result = float8_mi(point->y, box->high.y);
         else if (point->y < box->low.y)
             result = float8_mi(box->low.y, point->y);
+        else if (isnan(point->y) || isnan(box->high.y) || isnan(box->low.y))
+            result = get_float8_nan();
         else
             elog(ERROR, "inconsistent point values");
     }
     else if (point->y <= box->high.y && point->y >= box->low.y)
     {
         /* point is to left or right of box */
-        Assert(box->low.x <= box->high.x);
+        Assert(box->low.x <= box->high.x
+               || isnan(box->low.y) || isnan(box->high.y));
+
         if (point->x > box->high.x)
             result = float8_mi(point->x, box->high.x);
         else if (point->x < box->low.x)
             result = float8_mi(box->low.x, point->x);
+        else if (isnan(point->x) || isnan(box->high.x) || isnan(box->low.x))
+            result = get_float8_nan();
         else
             elog(ERROR, "inconsistent point values");
     }
@@ -1406,12 +1443,18 @@ gist_point_consistent(PG_FUNCTION_ARGS)
                      * of polygon's bounding box and point
                      */
                     BOX           *box = DatumGetBoxP(entry->key);
+                    bool        isnull = false;
 
-                    Assert(box->high.x == box->low.x
-                           && box->high.y == box->low.y);
-                    result = DatumGetBool(DirectFunctionCall2(poly_contain_pt,
-                                                              PolygonPGetDatum(query),
-                                                              PointPGetDatum(&box->high)));
+                    Assert((box->high.x == box->low.x
+                            && box->high.y == box->low.y) ||
+                           (isnan(box->high.x) && isnan(box->low.x)) ||
+                           (isnan(box->high.y) && isnan(box->low.y)));
+                           
+                    result = DatumGetBool(DirectFunctionCall2Ext(poly_contain_pt,
+                                                                 PolygonPGetDatum(query),
+                                                                 PointPGetDatum(&box->high),
+                                                                 &isnull));
+                    result &= !isnull;
                     *recheck = false;
                 }
             }
@@ -1433,12 +1476,18 @@ gist_point_consistent(PG_FUNCTION_ARGS)
                      * of polygon's bounding box and point
                      */
                     BOX           *box = DatumGetBoxP(entry->key);
+                    bool        isnull = false;
+
+                    Assert((box->high.x == box->low.x
+                            && box->high.y == box->low.y) ||
+                           (isnan(box->high.x) && isnan(box->low.x)) ||
+                           (isnan(box->high.y) && isnan(box->low.y)));
+                    result = DatumGetBool(DirectFunctionCall2Ext(circle_contain_pt,
+                                                                 CirclePGetDatum(query),
+                                                                 PointPGetDatum(&box->high),
+                                                                 &isnull));
+                    result &= !isnull;
 
-                    Assert(box->high.x == box->low.x
-                           && box->high.y == box->low.y);
-                    result = DatumGetBool(DirectFunctionCall2(circle_contain_pt,
-                                                              CirclePGetDatum(query),
-                                                              PointPGetDatum(&box->high)));
                     *recheck = false;
                 }
             }
diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c
index 851c171108..59362db727 100644
--- a/src/backend/utils/adt/geo_ops.c
+++ b/src/backend/utils/adt/geo_ops.c
@@ -44,14 +44,14 @@
  *
  * Common operators are:
  * * Intersection point:
- *   bool type1_interpt_type2(Point *result, Type1 *obj1, Type2 *obj2);
+ *   tsbool type1_interpt_type2(Point *result, Type1 *obj1, Type2 *obj2);
  *        Return whether the two objects intersect. If *result is not NULL,
  *        it is set to the intersection point.
  *
  * * Containment:
- *   bool type1_contain_type2(Type1 *obj1, Type2 *obj2);
+ *   tsbool type1_contain_type2(Type1 *obj1, Type2 *obj2);
  *        Return whether obj1 contains obj2.
- *   bool type1_contain_type2(Type1 *contains_obj, Type1 *contained_obj);
+ *   tsbool type1_contain_type2(Type1 *contains_obj, Type1 *contained_obj);
  *        Return whether obj1 contains obj2 (used when types are the same)
  *
  * * Distance of closest point in or on obj1 to obj2:
@@ -61,7 +61,8 @@
  *
  * These functions may be used to implement multiple SQL-level operators.  For
  * example, determining whether two lines are parallel is done by checking
- * whether they don't intersect.
+ * whether they don't intersect. tsbool-returning functions return TS_NULL if
+ * its calculation involves NaN.
  */
 
 /*
@@ -79,7 +80,7 @@ static inline void point_add_point(Point *result, Point *pt1, Point *pt2);
 static inline void point_sub_point(Point *result, Point *pt1, Point *pt2);
 static inline void point_mul_point(Point *result, Point *pt1, Point *pt2);
 static inline void point_div_point(Point *result, Point *pt1, Point *pt2);
-static inline bool point_eq_point(Point *pt1, Point *pt2);
+static inline tsbool point_eq_point(Point *pt1, Point *pt2);
 static inline float8 point_dt(Point *pt1, Point *pt2);
 static inline float8 point_sl(Point *pt1, Point *pt2);
 static int    point_inside(Point *p, int npts, Point *plist);
@@ -88,18 +89,18 @@ static int    point_inside(Point *p, int npts, Point *plist);
 static inline void line_construct(LINE *result, Point *pt, float8 m);
 static inline float8 line_sl(LINE *line);
 static inline float8 line_invsl(LINE *line);
-static bool line_interpt_line(Point *result, LINE *l1, LINE *l2);
-static bool line_contain_point(LINE *line, Point *point);
+static tsbool line_interpt_line(Point *result, LINE *l1, LINE *l2);
+static tsbool line_contain_point(LINE *line, Point *point);
 static float8 line_closept_point(Point *result, LINE *line, Point *pt);
 
 /* Routines for line segments */
 static inline void statlseg_construct(LSEG *lseg, Point *pt1, Point *pt2);
 static inline float8 lseg_sl(LSEG *lseg);
 static inline float8 lseg_invsl(LSEG *lseg);
-static bool lseg_interpt_line(Point *result, LSEG *lseg, LINE *line);
-static bool lseg_interpt_lseg(Point *result, LSEG *l1, LSEG *l2);
+static tsbool lseg_interpt_line(Point *result, LSEG *lseg, LINE *line);
+static tsbool lseg_interpt_lseg(Point *result, LSEG *l1, LSEG *l2);
 static int    lseg_crossing(float8 x, float8 y, float8 px, float8 py);
-static bool lseg_contain_point(LSEG *lseg, Point *point);
+static tsbool lseg_contain_point(LSEG *lseg, Point *point);
 static float8 lseg_closept_point(Point *result, LSEG *lseg, Point *pt);
 static float8 lseg_closept_line(Point *result, LSEG *lseg, LINE *line);
 static float8 lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg);
@@ -107,14 +108,14 @@ static float8 lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg);
 /* Routines for boxes */
 static inline void box_construct(BOX *result, Point *pt1, Point *pt2);
 static void box_cn(Point *center, BOX *box);
-static bool box_ov(BOX *box1, BOX *box2);
+static tsbool box_ov(BOX *box1, BOX *box2);
 static float8 box_ar(BOX *box);
 static float8 box_ht(BOX *box);
 static float8 box_wd(BOX *box);
-static bool box_contain_point(BOX *box, Point *point);
-static bool box_contain_box(BOX *contains_box, BOX *contained_box);
-static bool box_contain_lseg(BOX *box, LSEG *lseg);
-static bool box_interpt_lseg(Point *result, BOX *box, LSEG *lseg);
+static tsbool box_contain_point(BOX *box, Point *point);
+static tsbool box_contain_box(BOX *contains_box, BOX *contained_box);
+static tsbool box_contain_lseg(BOX *box, LSEG *lseg);
+static tsbool box_interpt_lseg(Point *result, BOX *box, LSEG *lseg);
 static float8 box_closept_point(Point *result, BOX *box, Point *point);
 static float8 box_closept_lseg(Point *result, BOX *box, LSEG *lseg);
 
@@ -124,9 +125,9 @@ static float8 circle_ar(CIRCLE *circle);
 /* Routines for polygons */
 static void make_bound_box(POLYGON *poly);
 static void poly_to_circle(CIRCLE *result, POLYGON *poly);
-static bool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
-static bool poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly);
-static bool plist_same(int npts, Point *p1, Point *p2);
+static tsbool lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start);
+static tsbool poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly);
+static tsbool plist_same(int npts, Point *p1, Point *p2);
 static float8 dist_ppoly_internal(Point *pt, POLYGON *poly);
 
 /* Routines for encoding and decoding */
@@ -540,9 +541,13 @@ box_same(PG_FUNCTION_ARGS)
 {
     BOX           *box1 = PG_GETARG_BOX_P(0);
     BOX           *box2 = PG_GETARG_BOX_P(1);
+    tsbool        res1 = point_eq_point(&box1->high, &box2->high);
+    tsbool        res2 = point_eq_point(&box1->low, &box2->low);
 
-    PG_RETURN_BOOL(point_eq_point(&box1->high, &box2->high) &&
-                   point_eq_point(&box1->low, &box2->low));
+    if (res1 == TS_NULL || res2 == TS_NULL)
+        PG_RETURN_NULL();
+
+    PG_RETURN_BOOL(res1 && res2);
 }
 
 /*        box_overlap        -        does box1 overlap box2?
@@ -553,16 +558,16 @@ 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));
+    PG_RETURN_TSBOOL(box_ov(box1, box2));
 }
 
-static bool
+static tsbool
 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 TS_AND4(FPTle(box1->low.x, box2->high.x),
+                   FPTle(box2->low.x, box1->high.x),
+                   FPTle(box1->low.y, box2->high.y),
+                   FPTle(box2->low.y, box1->high.y));
 }
 
 /*        box_left        -        is box1 strictly left of box2?
@@ -573,7 +578,7 @@ 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_TSBOOL(FPTlt(box1->high.x, box2->low.x));
 }
 
 /*        box_overleft    -        is the right edge of box1 at or left of
@@ -588,7 +593,7 @@ 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_TSBOOL(FPTle(box1->high.x, box2->high.x));
 }
 
 /*        box_right        -        is box1 strictly right of box2?
@@ -599,7 +604,7 @@ 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_TSBOOL(FPTgt(box1->low.x, box2->high.x));
 }
 
 /*        box_overright    -        is the left edge of box1 at or right of
@@ -614,7 +619,7 @@ 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_TSBOOL(FPTge(box1->low.x, box2->low.x));
 }
 
 /*        box_below        -        is box1 strictly below box2?
@@ -625,7 +630,7 @@ 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_TSBOOL(FPTlt(box1->high.y, box2->low.y));
 }
 
 /*        box_overbelow    -        is the upper edge of box1 at or below
@@ -637,7 +642,7 @@ 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_TSBOOL(FPTle(box1->high.y, box2->high.y));
 }
 
 /*        box_above        -        is box1 strictly above box2?
@@ -648,7 +653,7 @@ 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_TSBOOL(FPTgt(box1->low.y, box2->high.y));
 }
 
 /*        box_overabove    -        is the lower edge of box1 at or above
@@ -660,7 +665,7 @@ 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_TSBOOL(FPTge(box1->low.y, box2->low.y));
 }
 
 /*        box_contained    -        is box1 contained by box2?
@@ -671,7 +676,7 @@ box_contained(PG_FUNCTION_ARGS)
     BOX           *box1 = PG_GETARG_BOX_P(0);
     BOX           *box2 = PG_GETARG_BOX_P(1);
 
-    PG_RETURN_BOOL(box_contain_box(box2, box1));
+    PG_RETURN_TSBOOL(box_contain_box(box2, box1));
 }
 
 /*        box_contain        -        does box1 contain box2?
@@ -682,19 +687,19 @@ box_contain(PG_FUNCTION_ARGS)
     BOX           *box1 = PG_GETARG_BOX_P(0);
     BOX           *box2 = PG_GETARG_BOX_P(1);
 
-    PG_RETURN_BOOL(box_contain_box(box1, box2));
+    PG_RETURN_TSBOOL(box_contain_box(box1, box2));
 }
 
 /*
  * Check whether the second box is in the first box or on its border
  */
-static bool
+static tsbool
 box_contain_box(BOX *contains_box, BOX *contained_box)
 {
-    return FPge(contains_box->high.x, contained_box->high.x) &&
-        FPle(contains_box->low.x, contained_box->low.x) &&
-        FPge(contains_box->high.y, contained_box->high.y) &&
-        FPle(contains_box->low.y, contained_box->low.y);
+    return TS_AND4(FPTge(contains_box->high.x, contained_box->high.x),
+                   FPTle(contains_box->low.x, contained_box->low.x),
+                   FPTge(contains_box->high.y, contained_box->high.y),
+                   FPTle(contains_box->low.y, contained_box->low.y));
 }
 
 
@@ -712,7 +717,7 @@ 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_TSBOOL(FPTle(box1->high.y, box2->low.y));
 }
 
 Datum
@@ -721,7 +726,7 @@ 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_TSBOOL(FPTge(box1->low.y, box2->high.y));
 }
 
 
@@ -734,7 +739,7 @@ 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_TSBOOL(FPTlt(box_ar(box1), box_ar(box2)));
 }

 Datum
@@ -743,7 +748,7 @@ 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_TSBOOL(FPTgt(box_ar(box1), box_ar(box2)));
 }
 
 Datum
@@ -752,7 +757,7 @@ 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_TSBOOL(FPTeq(box_ar(box1), box_ar(box2)));
 }
 
 Datum
@@ -761,7 +766,7 @@ 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_TSBOOL(FPTle(box_ar(box1), box_ar(box2)));
 }
 
 Datum
@@ -770,7 +775,7 @@ 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_TSBOOL(FPTge(box_ar(box1), box_ar(box2)));
 }
 
 
@@ -981,7 +986,7 @@ line_in(PG_FUNCTION_ARGS)
     else
     {
         path_decode(s, true, 2, &lseg.p[0], &isopen, NULL, "line", str);
-        if (point_eq_point(&lseg.p[0], &lseg.p[1]))
+        if (point_eq_point(&lseg.p[0], &lseg.p[1]) == TS_TRUE)
             ereport(ERROR,
                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
                      errmsg("invalid line specification: must be two distinct points")));
@@ -1105,7 +1110,7 @@ line_construct_pp(PG_FUNCTION_ARGS)
     LINE       *result = (LINE *) palloc(sizeof(LINE));
 
     /* NaNs are considered to be equal by point_eq_point */
-    if (point_eq_point(pt1, pt2))
+    if (point_eq_point(pt1, pt2) == TS_TRUE)
         ereport(ERROR,
                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                  errmsg("invalid line specification: must be two distinct points")));
@@ -1126,11 +1131,16 @@ line_intersect(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
     Point        xp;
+    tsbool        r;
 
-    if (line_interpt_line(&xp, l1, l2) && !isnan(xp.x) && !isnan(xp.y))
-        PG_RETURN_BOOL(true);
+    if ((r = line_interpt_line(&xp, l1, l2)) == TS_TRUE)
+    {
+        if (!isnan(xp.x) && !isnan(xp.y))
+            PG_RETURN_BOOL(true);
+        PG_RETURN_NULL();
+    }
     else
-        PG_RETURN_BOOL(false);
+        PG_RETURN_TSBOOL(r);
 }
 
 Datum
@@ -1139,7 +1149,7 @@ line_parallel(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
-    PG_RETURN_BOOL(!line_interpt_line(NULL, l1, l2));
+    PG_RETURN_TSBOOL(TS_NOT(line_interpt_line(NULL, l1, l2)));
 }
 
 Datum
@@ -1148,18 +1158,27 @@ line_perp(PG_FUNCTION_ARGS)
     LINE       *l1 = PG_GETARG_LINE_P(0);
     LINE       *l2 = PG_GETARG_LINE_P(1);
 
-    if (unlikely(isnan(l1->C) || isnan(l2->C)))
-        return false;
+    if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l1->C) ||
+                 isnan(l2->A) || isnan(l2->B) || isnan(l2->C)))
+        PG_RETURN_NULL();
 
+    /*
+     * Since the coefficients are all non-NaN, we don't need to use the
+     * tristate versions of FPTxx functions here.
+     */
     if (FPzero(l1->A))
-        PG_RETURN_BOOL(FPzero(l2->B) && !isnan(l1->B) && !isnan(l2->A));
+        PG_RETURN_BOOL(FPzero(l2->B));
     if (FPzero(l2->A))
-        PG_RETURN_BOOL(FPzero(l1->B) && !isnan(l2->B) && !isnan(l1->A));
+        PG_RETURN_BOOL(FPzero(l1->B));
     if (FPzero(l1->B))
-        PG_RETURN_BOOL(FPzero(l2->A) && !isnan(l1->A) && !isnan(l2->B));
+        PG_RETURN_BOOL(FPzero(l2->A));
     if (FPzero(l2->B))
-        PG_RETURN_BOOL(FPzero(l1->A) && !isnan(l2->A) && !isnan(l1->B));
+        PG_RETURN_BOOL(FPzero(l1->A));
 
+    /*
+     * We don't reach here with numbers less than EPSILON. Thus the following
+     * arithmetic cannot yield NaN.
+     */
     PG_RETURN_BOOL(FPeq(float8_div(float8_mul(l1->A, l2->A),
                                    float8_mul(l1->B, l2->B)), -1.0));
 }
@@ -1169,7 +1188,11 @@ line_vertical(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->B) && !isnan(line->A) && !isnan(line->C));
+    /* is it correct to return NULL for C = NaN? */
+    if (unlikely(isnan(line->A) || isnan(line->C)))
+        PG_RETURN_NULL();
+        
+    PG_RETURN_TSBOOL(FPTzero(line->B));
 }
 
 Datum
@@ -1177,7 +1200,11 @@ line_horizontal(PG_FUNCTION_ARGS)
 {
     LINE       *line = PG_GETARG_LINE_P(0);
 
-    PG_RETURN_BOOL(FPzero(line->A) && !isnan(line->B) && !isnan(line->C));
+    /* is it correct to return NULL for C = NaN? */
+    if (unlikely(isnan(line->B) || isnan(line->C)))
+        PG_RETURN_NULL();
+        
+    PG_RETURN_TSBOOL(FPTzero(line->A));
 }
 
 
@@ -1191,14 +1218,10 @@ line_eq(PG_FUNCTION_ARGS)
     LINE       *l2 = PG_GETARG_LINE_P(1);
     float8        ratio;
 
-    /* If any NaNs are involved, insist on exact equality */
+    /* If any NaNs are involved, the two cannot be equal */
     if (unlikely(isnan(l1->A) || isnan(l1->B) || isnan(l1->C) ||
                  isnan(l2->A) || isnan(l2->B) || isnan(l2->C)))
-    {
-        PG_RETURN_BOOL(float8_eq(l1->A, l2->A) &&
-                       float8_eq(l1->B, l2->B) &&
-                       float8_eq(l1->C, l2->C));
-    }
+        PG_RETURN_NULL();
 
     /* Otherwise, lines whose parameters are proportional are the same */
     if (!FPzero(l2->A))
@@ -1281,7 +1304,7 @@ line_distance(PG_FUNCTION_ARGS)
     Point        xp;
     float8        ratio;
 
-    if (line_interpt_line(&xp, l1, l2)) /* intersecting? */
+    if (line_interpt_line(&xp, l1, l2) == TS_TRUE) /* intersecting? */
     {
         /* return NaN if NaN is involved */
         if (isnan(xp.x) || isnan(xp.y))
@@ -1316,7 +1339,7 @@ line_interpt(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (!line_interpt_line(result, l1, l2) ||
+    if (line_interpt_line(result, l1, l2) != TS_TRUE ||
         isnan(result->x) || isnan(result->y))
     {
         pfree(result);
@@ -1340,17 +1363,19 @@ line_interpt(PG_FUNCTION_ARGS)
  * point would have NaN coordinates.  We shouldn't return false in this case
  * because that would mean the lines are parallel.
  */
-static bool
+static tsbool
 line_interpt_line(Point *result, LINE *l1, LINE *l2)
 {
     float8        x,
                 y;
+    tsbool        t;
 
-    if (!FPzero(l1->B))
+    if ((t = FPTzero(l1->B)) == TS_FALSE)
     {
         /* l1 is not virtucal */
-        if (FPeq(l2->A, float8_mul(l1->A, float8_div(l2->B, l1->B))))
-            return false;
+        t = FPTne(l2->A, float8_mul(l1->A, float8_div(l2->B, l1->B)));
+        if (t != TS_TRUE)
+            return t;
 
         x = float8_div(float8_mi(float8_mul(l1->B, l2->C),
                                  float8_mul(l2->B, l1->C)),
@@ -1367,7 +1392,7 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
                        float8_mi(float8_mul(l2->A, l1->B),
                                  float8_mul(l1->A, l2->B)));
     }
-    else if (!FPzero(l2->B))
+    else if (t == TS_TRUE && (t = FPTzero(l2->B)) == TS_FALSE)
     {
         /* l2 is not virtical */
         /*
@@ -1380,13 +1405,22 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
          * When l2->A is zero, y is determined independently from x even if it
          * is Inf.
          */
-        if (FPzero(l2->A))
-            y = -float8_div(l2->C, l2->B);
-        else
-            y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+        switch (FPTzero(l2->A))
+        {
+            case TS_TRUE:
+                y = -float8_div(l2->C, l2->B);
+                break;
+            case TS_FALSE:
+                y = float8_div(-float8_pl(float8_mul(l2->A, x), l2->C), l2->B);
+                break;
+            case TS_NULL:
+                return TS_NULL;
+        }
     }
+    else if (t != TS_NULL)
+        return TS_FALSE;
     else
-        return false;
+        return TS_NULL;
 
     /* On some platforms, the preceding expressions tend to produce -0. */
     if (x == 0.0)
@@ -1397,7 +1431,7 @@ line_interpt_line(Point *result, LINE *l1, LINE *l2)
     if (result != NULL)
         point_construct(result, x, y);
 
-    return true;
+    return TS_TRUE;
 }
 
 
@@ -1704,6 +1738,7 @@ path_inter(PG_FUNCTION_ARGS)
                 j;
     LSEG        seg1,
                 seg2;
+    tsbool        r;
 
     Assert(p1->npts > 0 && p2->npts > 0);
 
@@ -1716,6 +1751,7 @@ path_inter(PG_FUNCTION_ARGS)
         b1.low.x = float8_min_nan(p1->p[i].x, b1.low.x);
         b1.low.y = float8_min_nan(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++)
@@ -1725,8 +1761,8 @@ path_inter(PG_FUNCTION_ARGS)
         b2.low.x = float8_min_nan(p2->p[i].x, b2.low.x);
         b2.low.y = float8_min_nan(p2->p[i].y, b2.low.y);
     }
-    if (!box_ov(&b1, &b2))
-        PG_RETURN_BOOL(false);
+    if ((r = box_ov(&b1, &b2)) != TS_TRUE)
+        PG_RETURN_TSBOOL(r);
 
     /* pairwise check lseg intersections */
     for (i = 0; i < p1->npts; i++)
@@ -1745,6 +1781,7 @@ path_inter(PG_FUNCTION_ARGS)
         for (j = 0; j < p2->npts; j++)
         {
             int            jprev;
+            tsbool        t;
 
             if (j > 0)
                 jprev = j - 1;
@@ -1757,13 +1794,14 @@ path_inter(PG_FUNCTION_ARGS)
 
             statlseg_construct(&seg1, &p1->p[iprev], &p1->p[i]);
             statlseg_construct(&seg2, &p2->p[jprev], &p2->p[j]);
-            if (lseg_interpt_lseg(NULL, &seg1, &seg2))
-                PG_RETURN_BOOL(true);
+            t = lseg_interpt_lseg(NULL, &seg1, &seg2);
+            if (t != TS_FALSE)
+                PG_RETURN_TSBOOL(t);
         }
     }
 
     /* if we dropped through, no two segs intersected */
-    PG_RETURN_BOOL(false);
+    PG_RETURN_TSBOOL(TS_FALSE);
 }
 
 /* path_distance()
@@ -2004,8 +2042,12 @@ point_eq(PG_FUNCTION_ARGS)
 {
     Point       *pt1 = PG_GETARG_POINT_P(0);
     Point       *pt2 = PG_GETARG_POINT_P(1);
+    tsbool        res = point_eq_point(pt1, pt2);
 
-    PG_RETURN_BOOL(point_eq_point(pt1, pt2));
+    if (res == TS_NULL)
+        PG_RETURN_NULL();
+
+    PG_RETURN_BOOL(res);
 }
 
 Datum
@@ -2013,23 +2055,22 @@ point_ne(PG_FUNCTION_ARGS)
 {
     Point       *pt1 = PG_GETARG_POINT_P(0);
     Point       *pt2 = PG_GETARG_POINT_P(1);
+    tsbool        res = point_eq_point(pt1, pt2);
 
-    PG_RETURN_BOOL(!point_eq_point(pt1, pt2));
+    if (res == TS_NULL)
+        PG_RETURN_NULL();
+
+    PG_RETURN_BOOL(!res);
 }
 
 
 /*
  * Check whether the two points are the same
  */
-static inline bool
+static inline tsbool
 point_eq_point(Point *pt1, Point *pt2)
 {
-    /* If any NaNs are involved, insist on exact equality */
-    if (unlikely(isnan(pt1->x) || isnan(pt1->y) ||
-                 isnan(pt2->x) || isnan(pt2->y)))
-        return (float8_eq(pt1->x, pt2->x) && float8_eq(pt1->y, pt2->y));
-
-    return (FPeq(pt1->x, pt2->x) && FPeq(pt1->y, pt2->y));
+    return TS_AND2(FPTeq(pt1->x, pt2->x), FPTeq(pt1->y, pt2->y));
 }
 
 
@@ -2070,6 +2111,7 @@ point_slope(PG_FUNCTION_ARGS)
 static inline float8
 point_sl(Point *pt1, Point *pt2)
 {
+    /* NaN doesn't equal to NaN, so don't bother using a tri-state value */
     if (FPeq(pt1->x, pt2->x))
     {
         if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
@@ -2096,6 +2138,7 @@ point_sl(Point *pt1, Point *pt2)
 static inline float8
 point_invsl(Point *pt1, Point *pt2)
 {
+    /* NaN doesn't equal to NaN, so don't bother using a tri-state value */
     if (FPeq(pt1->x, pt2->x))
     {
         if (unlikely(isnan(pt1->y) || isnan(pt2->y)))
@@ -2254,7 +2297,7 @@ lseg_intersect(PG_FUNCTION_ARGS)
     LSEG       *l1 = PG_GETARG_LSEG_P(0);
     LSEG       *l2 = PG_GETARG_LSEG_P(1);
 
-    PG_RETURN_BOOL(lseg_interpt_lseg(NULL, l1, l2));
+    PG_RETURN_TSBOOL(lseg_interpt_lseg(NULL, l1, l2));
 }
 
 
@@ -2264,7 +2307,7 @@ lseg_parallel(PG_FUNCTION_ARGS)
     LSEG       *l1 = PG_GETARG_LSEG_P(0);
     LSEG       *l2 = PG_GETARG_LSEG_P(1);
 
-    PG_RETURN_BOOL(FPeq(lseg_sl(l1), lseg_sl(l2)));
+    PG_RETURN_TSBOOL(FPTeq(lseg_sl(l1), lseg_sl(l2)));
 }
 
 /*
@@ -2276,7 +2319,7 @@ lseg_perp(PG_FUNCTION_ARGS)
     LSEG       *l1 = PG_GETARG_LSEG_P(0);
     LSEG       *l2 = PG_GETARG_LSEG_P(1);
 
-    PG_RETURN_BOOL(FPeq(lseg_sl(l1), lseg_invsl(l2)));
+    PG_RETURN_TSBOOL(FPTeq(lseg_sl(l1), lseg_invsl(l2)));
 }
 
 Datum
@@ -2284,7 +2327,7 @@ 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_TSBOOL(FPTeq(lseg->p[0].x, lseg->p[1].x));
 }
 
 Datum
@@ -2292,7 +2335,7 @@ 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_TSBOOL(FPTeq(lseg->p[0].y, lseg->p[1].y));
 }
 
 
@@ -2302,8 +2345,8 @@ lseg_eq(PG_FUNCTION_ARGS)
     LSEG       *l1 = PG_GETARG_LSEG_P(0);
     LSEG       *l2 = PG_GETARG_LSEG_P(1);
 
-    PG_RETURN_BOOL(point_eq_point(&l1->p[0], &l2->p[0]) &&
-                   point_eq_point(&l1->p[1], &l2->p[1]));
+    PG_RETURN_TSBOOL(TS_AND2(point_eq_point(&l1->p[0], &l2->p[0]),
+                             point_eq_point(&l1->p[1], &l2->p[1])));
 }
 
 Datum
@@ -2312,8 +2355,9 @@ lseg_ne(PG_FUNCTION_ARGS)
     LSEG       *l1 = PG_GETARG_LSEG_P(0);
     LSEG       *l2 = PG_GETARG_LSEG_P(1);
 
-    PG_RETURN_BOOL(!point_eq_point(&l1->p[0], &l2->p[0]) ||
-                   !point_eq_point(&l1->p[1], &l2->p[1]));
+    PG_RETURN_TSBOOL(TS_OR2(
+                         TS_NOT(point_eq_point(&l1->p[0], &l2->p[0])),
+                         TS_NOT(point_eq_point(&l1->p[1], &l2->p[1]))));
 }
 
 Datum
@@ -2322,8 +2366,8 @@ 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_TSBOOL(FPTlt(point_dt(&l1->p[0], &l1->p[1]),
+                           point_dt(&l2->p[0], &l2->p[1])));
 }
 
 Datum
@@ -2332,8 +2376,8 @@ 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_TSBOOL(FPTle(point_dt(&l1->p[0], &l1->p[1]),
+                           point_dt(&l2->p[0], &l2->p[1])));
 }
 
 Datum
@@ -2342,8 +2386,8 @@ 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_TSBOOL(FPTgt(point_dt(&l1->p[0], &l1->p[1]),
+                           point_dt(&l2->p[0], &l2->p[1])));
 }
 
 Datum
@@ -2352,8 +2396,8 @@ 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_TSBOOL(FPTge(point_dt(&l1->p[0], &l1->p[1]),
+                           point_dt(&l2->p[0], &l2->p[1])));
 }
 
 
@@ -2398,27 +2442,28 @@ lseg_center(PG_FUNCTION_ARGS)
  * This function is almost perfectly symmetric, even though it doesn't look
  * like it.  See lseg_interpt_line() for the other half of it.
  */
-static bool
+static tsbool
 lseg_interpt_lseg(Point *result, LSEG *l1, LSEG *l2)
 {
     Point        interpt;
     LINE        tmp;
+    tsbool        r;
 
     line_construct(&tmp, &l2->p[0], lseg_sl(l2));
-    if (!lseg_interpt_line(&interpt, l1, &tmp))
-        return false;
+    if ((r = lseg_interpt_line(&interpt, l1, &tmp)) != TS_TRUE)
+        return r;
 
     /*
      * If the line intersection point isn't within l2, there is no valid
      * segment intersection point at all.
      */
-    if (!lseg_contain_point(l2, &interpt))
-        return false;
+    if ((r = lseg_contain_point(l2, &interpt)) != TS_TRUE)
+        return r;
 
     if (result != NULL)
         *result = interpt;
 
-    return true;
+    return TS_TRUE;
 }
 
 Datum
@@ -2430,7 +2475,7 @@ lseg_interpt(PG_FUNCTION_ARGS)
 
     result = (Point *) palloc(sizeof(Point));
 
-    if (!lseg_interpt_lseg(result, l1, l2))
+    if (lseg_interpt_lseg(result, l1, l2) != TS_TRUE)
         PG_RETURN_NULL();
     PG_RETURN_POINT_P(result);
 }
@@ -2702,8 +2747,13 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
     float8        d;
     int            i;
     LSEG        seg;
+    int            inside;
 
-    if (point_inside(pt, poly->npts, poly->p) != 0)
+    inside = point_inside(pt, poly->npts, poly->p);
+    if (inside == -1)
+        return get_float8_nan();
+
+    if (inside != 0)
         return 0.0;
 
     /* initialize distance with segment between first and last points */
@@ -2742,11 +2792,12 @@ dist_ppoly_internal(Point *pt, POLYGON *poly)
  * Return whether the line segment intersect with the line. If *result is not
  * NULL, it is set to the intersection point.
  */
-static bool
+static tsbool
 lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
 {
     Point        interpt;
     LINE        tmp;
+    tsbool        r;
 
     /*
      * First, we promote the line segment to a line, because we know how to
@@ -2754,32 +2805,40 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line)
      * intersection point, we are done.
      */
     line_construct(&tmp, &lseg->p[0], lseg_sl(lseg));
-    if (!line_interpt_line(&interpt, &tmp, line) ||
-        unlikely(isnan(interpt.x) || isnan(interpt.y)))
-        return false;
+    if ((r = line_interpt_line(&interpt, &tmp, line)) != TS_TRUE)
+        return r;
+
+    if (unlikely(isnan(interpt.x) || isnan(interpt.y)))
+        return TS_FALSE;
 
     /*
      * Then, we check whether the intersection point is actually on the line
      * segment.
      */
-    if (!lseg_contain_point(lseg, &interpt))
-        return false;
+    if ((r = lseg_contain_point(lseg, &interpt)) != TS_TRUE)
+        return r;
+
     if (result != NULL)
     {
+        tsbool    r;
+
         /*
          * If there is an intersection, then check explicitly for matching
          * endpoints since there may be rounding effects with annoying LSB
          * residue.
          */
-        if (point_eq_point(&lseg->p[0], &interpt))
+        if ((r = point_eq_point(&lseg->p[0], &interpt)) == TS_TRUE)
             *result = lseg->p[0];
-        else if (point_eq_point(&lseg->p[1], &interpt))
+        else if (r == TS_FALSE &&
+                 (r = point_eq_point(&lseg->p[1], &interpt)) == TS_TRUE)
             *result = lseg->p[1];
-        else
+        else if (r == TS_FALSE)
             *result = interpt;
+        else
+            return r;
     }
 
-    return true;
+    return TS_TRUE;
 }
 
 /*---------------------------------------------------------------------
@@ -2971,8 +3030,15 @@ lseg_closept_lseg(Point *result, LSEG *on_lseg, LSEG *to_lseg)
     bool        anynan = false;
 
     /* First, we handle the case when the line segments are intersecting. */
-    if (lseg_interpt_lseg(result, on_lseg, to_lseg))
-        return 0.0;
+    switch(lseg_interpt_lseg(result, on_lseg, to_lseg))
+    {
+        case TS_TRUE:
+            return 0.0;
+        case TS_NULL:
+            return get_float8_nan();
+        case TS_FALSE:
+            break;
+    }
 
     /*
      * Then, we find the closest points from the endpoints of the second line
@@ -3050,12 +3116,19 @@ box_closept_point(Point *result, BOX *box, Point *pt)
     LSEG        lseg;
     bool        anynan = false;
 
-    if (box_contain_point(box, pt))
+    switch(box_contain_point(box, pt))
     {
-        if (result != NULL)
-            *result = *pt;
+        case TS_TRUE:
+            if (result != NULL)
+                *result = *pt;
 
-        return 0.0;
+            return 0.0;
+
+        case TS_NULL:
+            return get_float8_nan();
+
+        case TS_FALSE:
+            break;
     }
 
     /* pairwise check lseg distances */
@@ -3139,9 +3212,17 @@ lseg_closept_line(Point *result, LSEG *lseg, LINE *line)
 {
     float8        dist1,
                 dist2;
+    tsbool        r;
 
-    if (lseg_interpt_line(result, lseg, line))
+    if ((r = lseg_interpt_line(result, lseg, line)) == TS_TRUE)
         return 0.0;
+    else if (r == TS_NULL)
+    {
+        if (result != NULL)
+            result->x = result->y = get_float8_nan();
+
+        return get_float8_nan();
+    }
 
     dist1 = line_closept_point(NULL, line, &lseg->p[0]);
     dist2 = line_closept_point(NULL, line, &lseg->p[1]);
@@ -3204,8 +3285,15 @@ box_closept_lseg(Point *result, BOX *box, LSEG *lseg)
                 closept;
     LSEG        bseg;
 
-    if (box_interpt_lseg(result, box, lseg))
-        return 0.0;
+    switch (box_interpt_lseg(result, box, lseg))
+    {
+        case TS_TRUE:
+            return 0.0;
+        case TS_NULL:
+            return get_float8_nan();
+        case TS_FALSE:
+            break;
+    }
 
     /* pairwise check lseg distances */
     point.x = box->low.x;
@@ -3269,7 +3357,7 @@ close_sb(PG_FUNCTION_ARGS)
 /*
  *        Does the point satisfy the equation?
  */
-static bool
+static tsbool
 line_contain_point(LINE *line, Point *point)
 {
     /*
@@ -3283,7 +3371,7 @@ line_contain_point(LINE *line, Point *point)
         Assert(line->B != 0.0);
 
         /* inf == inf here */
-        return FPeq(point->y, -line->C / line->B);
+        return FPTeq(point->y, -line->C / line->B);
     }
     else if (line->B == 0.0)
     {
@@ -3291,13 +3379,13 @@ line_contain_point(LINE *line, Point *point)
         Assert(line->A != 0.0);
 
         /* inf == inf here */
-        return FPeq(point->x, -line->C / line->A);
+        return FPTeq(point->x, -line->C / line->A);
     }
 
-    return FPzero(float8_pl(
-                      float8_pl(float8_mul(line->A, point->x),
-                                float8_mul(line->B, point->y)),
-                      line->C));
+    return FPTzero(float8_pl(
+                       float8_pl(float8_mul(line->A, point->x),
+                                 float8_mul(line->B, point->y)),
+                       line->C));
 }
 
 Datum
@@ -3306,7 +3394,7 @@ on_pl(PG_FUNCTION_ARGS)
     Point       *pt = PG_GETARG_POINT_P(0);
     LINE       *line = PG_GETARG_LINE_P(1);
 
-    PG_RETURN_BOOL(line_contain_point(line, pt));
+    PG_RETURN_TSBOOL(line_contain_point(line, pt));
 }
 
 
@@ -3314,12 +3402,12 @@ on_pl(PG_FUNCTION_ARGS)
  *        Determine colinearity by detecting a triangle inequality.
  * This algorithm seems to behave nicely even with lsb residues - tgl 1997-07-09
  */
-static bool
+static tsbool
 lseg_contain_point(LSEG *lseg, Point *pt)
 {
-    return FPeq(point_dt(pt, &lseg->p[0]) +
-                point_dt(pt, &lseg->p[1]),
-                point_dt(&lseg->p[0], &lseg->p[1]));
+    return FPTeq(point_dt(pt, &lseg->p[0]) +
+                 point_dt(pt, &lseg->p[1]),
+                 point_dt(&lseg->p[0], &lseg->p[1]));
 }
 
 Datum
@@ -3328,18 +3416,25 @@ on_ps(PG_FUNCTION_ARGS)
     Point       *pt = PG_GETARG_POINT_P(0);
     LSEG       *lseg = PG_GETARG_LSEG_P(1);
 
-    PG_RETURN_BOOL(lseg_contain_point(lseg, pt));
+    PG_RETURN_TSBOOL(lseg_contain_point(lseg, pt));
 }
 
 
 /*
  * Check whether the point is in the box or on its border
  */
-static bool
+static tsbool
 box_contain_point(BOX *box, Point *point)
 {
-    return box->high.x >= point->x && box->low.x <= point->x &&
-        box->high.y >= point->y && box->low.y <= point->y;
+    if (box->high.x >= point->x && box->low.x <= point->x &&
+        box->high.y >= point->y && box->low.y <= point->y)
+        return TS_TRUE;
+    else if (!isnan(box->high.x) && !isnan(box->high.y) &&
+             !isnan(box->low.x) && !isnan(box->low.y) &&
+             !isnan(point->x) && !isnan(point->y))
+        return TS_FALSE;
+
+    return TS_NULL;
 }
 
 Datum
@@ -3348,7 +3443,7 @@ on_pb(PG_FUNCTION_ARGS)
     Point       *pt = PG_GETARG_POINT_P(0);
     BOX           *box = PG_GETARG_BOX_P(1);
 
-    PG_RETURN_BOOL(box_contain_point(box, pt));
+    PG_RETURN_TSBOOL(box_contain_point(box, pt));
 }
 
 Datum
@@ -3357,7 +3452,7 @@ box_contain_pt(PG_FUNCTION_ARGS)
     BOX           *box = PG_GETARG_BOX_P(0);
     Point       *pt = PG_GETARG_POINT_P(1);
 
-    PG_RETURN_BOOL(box_contain_point(box, pt));
+    PG_RETURN_TSBOOL(box_contain_point(box, pt));
 }
 
 /* on_ppath -
@@ -3380,24 +3475,38 @@ on_ppath(PG_FUNCTION_ARGS)
                 n;
     float8        a,
                 b;
+    int            inside;
 
     /*-- OPEN --*/
     if (!path->closed)
     {
+        tsbool r;
+
         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(float8_pl(a, b), point_dt(&path->p[i], &path->p[i + 1])))
-                PG_RETURN_BOOL(true);
+            r = FPTeq(float8_pl(a, b), point_dt(&path->p[i], &path->p[i + 1]));
+            if (r != TS_FALSE)
+                PG_RETURN_TSBOOL(r);
             a = b;
         }
+        /* See the PG_RETURN_BOOL at the end of this function */
         PG_RETURN_BOOL(false);
     }
 
     /*-- CLOSED --*/
-    PG_RETURN_BOOL(point_inside(pt, path->npts, path->p) != 0);
+    inside = point_inside(pt, path->npts, path->p);
+
+    if (inside < 0)
+        PG_RETURN_NULL();
+
+    /*
+     * PG_RETURN_BOOL is compatible and faster than PG_RETURN_TSBOOL when the
+     * value is guaranteed to be in bool.
+     */
+    PG_RETURN_BOOL(inside != 0);
 }
 
 
@@ -3412,8 +3521,8 @@ on_sl(PG_FUNCTION_ARGS)
     LSEG       *lseg = PG_GETARG_LSEG_P(0);
     LINE       *line = PG_GETARG_LINE_P(1);
 
-    PG_RETURN_BOOL(line_contain_point(line, &lseg->p[0]) &&
-                   line_contain_point(line, &lseg->p[1]));
+    PG_RETURN_TSBOOL(TS_AND2(line_contain_point(line, &lseg->p[0]),
+                             line_contain_point(line, &lseg->p[1])));
 }
 
 
@@ -3422,11 +3531,11 @@ on_sl(PG_FUNCTION_ARGS)
  *
  * It is, if both of its points are in the box or on its border.
  */
-static bool
+static tsbool
 box_contain_lseg(BOX *box, LSEG *lseg)
 {
-    return box_contain_point(box, &lseg->p[0]) &&
-        box_contain_point(box, &lseg->p[1]);
+    return TS_AND2(box_contain_point(box, &lseg->p[0]),
+                   box_contain_point(box, &lseg->p[1]));
 }
 
 Datum
@@ -3435,7 +3544,7 @@ on_sb(PG_FUNCTION_ARGS)
     LSEG       *lseg = PG_GETARG_LSEG_P(0);
     BOX           *box = PG_GETARG_BOX_P(1);
 
-    PG_RETURN_BOOL(box_contain_lseg(box, lseg));
+    PG_RETURN_TSBOOL(box_contain_lseg(box, lseg));
 }
 
 /*---------------------------------------------------------------------
@@ -3449,7 +3558,7 @@ inter_sl(PG_FUNCTION_ARGS)
     LSEG       *lseg = PG_GETARG_LSEG_P(0);
     LINE       *line = PG_GETARG_LINE_P(1);
 
-    PG_RETURN_BOOL(lseg_interpt_line(NULL, lseg, line));
+    PG_RETURN_TSBOOL(lseg_interpt_line(NULL, lseg, line));
 }
 
 
@@ -3468,12 +3577,13 @@ inter_sl(PG_FUNCTION_ARGS)
  * Optimize for non-intersection by checking for box intersection first.
  * - thomas 1998-01-30
  */
-static bool
+static tsbool
 box_interpt_lseg(Point *result, BOX *box, LSEG *lseg)
 {
     BOX            lbox;
     LSEG        bseg;
     Point        point;
+    tsbool        r;
 
     lbox.low.x = float8_min(lseg->p[0].x, lseg->p[1].x);
     lbox.low.y = float8_min(lseg->p[0].y, lseg->p[1].y);
@@ -3481,8 +3591,8 @@ box_interpt_lseg(Point *result, BOX *box, LSEG *lseg)
     lbox.high.y = float8_max(lseg->p[0].y, lseg->p[1].y);
 
     /* nothing close to overlap? then not going to intersect */
-    if (!box_ov(&lbox, box))
-        return false;
+    if ((r = box_ov(&lbox, box)) != TS_TRUE)
+        return r;
 
     if (result != NULL)
     {
@@ -3491,30 +3601,30 @@ box_interpt_lseg(Point *result, BOX *box, LSEG *lseg)
     }
 
     /* an endpoint of segment is inside box? then clearly intersects */
-    if (box_contain_point(box, &lseg->p[0]) ||
-        box_contain_point(box, &lseg->p[1]))
-        return true;
+    if ((r = TS_OR2(box_contain_point(box, &lseg->p[0]),
+                    box_contain_point(box, &lseg->p[1]))) != TS_FALSE)
+        return r;
 
     /* pairwise check lseg intersections */
     point.x = box->low.x;
     point.y = box->high.y;
     statlseg_construct(&bseg, &box->low, &point);
-    if (lseg_interpt_lseg(NULL, &bseg, lseg))
-        return true;
+    if ((r = lseg_interpt_lseg(NULL, &bseg, lseg)) != TS_FALSE)
+        return r;
 
     statlseg_construct(&bseg, &box->high, &point);
-    if (lseg_interpt_lseg(NULL, &bseg, lseg))
-        return true;
+    if ((r = lseg_interpt_lseg(NULL, &bseg, lseg)) != TS_FALSE)
+        return r;
 
     point.x = box->high.x;
     point.y = box->low.y;
     statlseg_construct(&bseg, &box->low, &point);
-    if (lseg_interpt_lseg(NULL, &bseg, lseg))
-        return true;
+    if ((r = lseg_interpt_lseg(NULL, &bseg, lseg)) != TS_FALSE)
+        return r;
 
     statlseg_construct(&bseg, &box->high, &point);
-    if (lseg_interpt_lseg(NULL, &bseg, lseg))
-        return true;
+    if ((r = lseg_interpt_lseg(NULL, &bseg, lseg)) != TS_FALSE)
+        return r;
 
     /* if we dropped through, no two segs intersected */
     return false;
@@ -3526,7 +3636,7 @@ inter_sb(PG_FUNCTION_ARGS)
     LSEG       *lseg = PG_GETARG_LSEG_P(0);
     BOX           *box = PG_GETARG_BOX_P(1);
 
-    PG_RETURN_BOOL(box_interpt_lseg(NULL, box, lseg));
+    PG_RETURN_TSBOOL(box_interpt_lseg(NULL, box, lseg));
 }
 
 
@@ -3541,6 +3651,7 @@ inter_lb(PG_FUNCTION_ARGS)
     LSEG        bseg;
     Point        p1,
                 p2;
+    tsbool        r;
 
     /* pairwise check lseg intersections */
     p1.x = box->low.x;
@@ -3548,25 +3659,28 @@ inter_lb(PG_FUNCTION_ARGS)
     p2.x = box->low.x;
     p2.y = box->high.y;
     statlseg_construct(&bseg, &p1, &p2);
-    if (lseg_interpt_line(NULL, &bseg, line))
-        PG_RETURN_BOOL(true);
+    if ((r = lseg_interpt_line(NULL, &bseg, line)) != TS_FALSE)
+        PG_RETURN_TSBOOL(r);
     p1.x = box->high.x;
     p1.y = box->high.y;
     statlseg_construct(&bseg, &p1, &p2);
-    if (lseg_interpt_line(NULL, &bseg, line))
-        PG_RETURN_BOOL(true);
+    if ((r = lseg_interpt_line(NULL, &bseg, line)) != TS_FALSE)
+        PG_RETURN_TSBOOL(r);
     p2.x = box->high.x;
     p2.y = box->low.y;
     statlseg_construct(&bseg, &p1, &p2);
-    if (lseg_interpt_line(NULL, &bseg, line))
-        PG_RETURN_BOOL(true);
+    if ((r = lseg_interpt_line(NULL, &bseg, line)) != TS_FALSE)
+        PG_RETURN_TSBOOL(r);
     p1.x = box->low.x;
     p1.y = box->low.y;
     statlseg_construct(&bseg, &p1, &p2);
-    if (lseg_interpt_line(NULL, &bseg, line))
-        PG_RETURN_BOOL(true);
+    if ((r = lseg_interpt_line(NULL, &bseg, line)) != TS_FALSE)
+        PG_RETURN_TSBOOL(r);
 
-    /* if we dropped through, no intersection */
+    /*
+     * if we dropped through, no intersection "false" doesn't need
+     * PG_RETURN_TSBOOL()
+     */
     PG_RETURN_BOOL(false);
 }
 
@@ -3748,6 +3862,9 @@ poly_left(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.high.x < polyb->boundbox.low.x;
 
     /*
@@ -3771,6 +3888,9 @@ poly_overleft(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.high.x <= polyb->boundbox.high.x;
 
     /*
@@ -3794,6 +3914,9 @@ poly_right(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.low.x > polyb->boundbox.high.x;
 
     /*
@@ -3817,6 +3940,9 @@ poly_overright(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.low.x >= polyb->boundbox.low.x;
 
     /*
@@ -3840,6 +3966,9 @@ poly_below(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.high.y < polyb->boundbox.low.y;
 
     /*
@@ -3863,6 +3992,9 @@ poly_overbelow(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.high.y <= polyb->boundbox.high.y;
 
     /*
@@ -3886,6 +4018,9 @@ poly_above(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.low.y > polyb->boundbox.high.y;
 
     /*
@@ -3909,6 +4044,9 @@ poly_overabove(PG_FUNCTION_ARGS)
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
     bool        result;
 
+    if (isnan(polya->boundbox.high.x) || isnan(polyb->boundbox.high.x))
+        PG_RETURN_NULL();
+
     result = polya->boundbox.low.y >= polyb->boundbox.low.y;
 
     /*
@@ -3927,16 +4065,20 @@ poly_overabove(PG_FUNCTION_ARGS)
  * Check all points for matches in both forward and reverse
  *    direction since polygons are non-directional and are
  *    closed shapes.
+ *
+ * XXX: returns TS_FALSE when the two polygons consists of
+ * different number of points even if any of the points were
+ * NaN.  It might be thewrong defintion.
  *-------------------------------------------------------*/
 Datum
 poly_same(PG_FUNCTION_ARGS)
 {
     POLYGON    *polya = PG_GETARG_POLYGON_P(0);
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
-    bool        result;
+    tsbool        result;
 
     if (polya->npts != polyb->npts)
-        result = false;
+        result = TS_FALSE;
     else
         result = plist_same(polya->npts, polya->p, polyb->p);
 
@@ -3952,22 +4094,25 @@ poly_same(PG_FUNCTION_ARGS)
 /*-----------------------------------------------------------------
  * Determine if polygon A overlaps polygon B
  *-----------------------------------------------------------------*/
-static bool
+static tsbool
 poly_overlap_internal(POLYGON *polya, POLYGON *polyb)
 {
-    bool        result;
+    tsbool        result;
 
     Assert(polya->npts > 0 && polyb->npts > 0);
 
     /* Quick check by bounding box */
     result = box_ov(&polya->boundbox, &polyb->boundbox);
 
+    if (result == TS_NULL)
+        return TS_NULL;
+
     /*
      * 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)
+    if (result == TS_TRUE)
     {
         int            ia,
                     ib;
@@ -3976,9 +4121,9 @@ poly_overlap_internal(POLYGON *polya, POLYGON *polyb)
 
         /* Init first of polya's edge with last point */
         sa.p[0] = polya->p[polya->npts - 1];
-        result = false;
+        result = TS_FALSE;
 
-        for (ia = 0; ia < polya->npts && !result; ia++)
+        for (ia = 0; ia < polya->npts && result != TS_TRUE; ia++)
         {
             /* Second point of polya's edge is a current one */
             sa.p[1] = polya->p[ia];
@@ -3999,8 +4144,12 @@ poly_overlap_internal(POLYGON *polya, POLYGON *polyb)
             sa.p[0] = sa.p[1];
         }
 
-        if (!result)
+        if (result == TS_NULL)
+            return TS_NULL;
+
+        if (result == TS_FALSE)
         {
+            /* in the case of NaN is handled ealier */
             result = (point_inside(polya->p, polyb->npts, polyb->p) ||
                       point_inside(polyb->p, polya->npts, polya->p));
         }
@@ -4014,7 +4163,7 @@ poly_overlap(PG_FUNCTION_ARGS)
 {
     POLYGON    *polya = PG_GETARG_POLYGON_P(0);
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
-    bool        result;
+    tsbool        result;
 
     result = poly_overlap_internal(polya, polyb);
 
@@ -4024,7 +4173,7 @@ poly_overlap(PG_FUNCTION_ARGS)
     PG_FREE_IF_COPY(polya, 0);
     PG_FREE_IF_COPY(polyb, 1);
 
-    PG_RETURN_BOOL(result);
+    PG_RETURN_TSBOOL(result);
 }
 
 /*
@@ -4038,35 +4187,62 @@ poly_overlap(PG_FUNCTION_ARGS)
  *      mean that segment is in polygon!
  */
 
-static bool
+static tsbool
 touched_lseg_inside_poly(Point *a, Point *b, LSEG *s, POLYGON *poly, int start)
 {
     /* point a is on s, b is not */
     LSEG        t;
+    tsbool        r;
 
     t.p[0] = *a;
     t.p[1] = *b;
 
-    if (point_eq_point(a, s->p))
+    /*
+     * assume no parameters have NaN, so the tsbool functions shouldn't return
+     * TS_NULL.
+     */
+    Assert(!isnan(a->x) && !isnan(a->y) && !isnan(b->x) && !isnan(b->y) &&
+           !isnan(poly->boundbox.high.x));
+    if ((r = point_eq_point(a, s->p)) == TS_TRUE)
     {
-        if (lseg_contain_point(&t, s->p + 1))
-            return lseg_inside_poly(b, s->p + 1, poly, start);
+        switch(lseg_contain_point(&t, s->p + 1))
+        {
+            case TS_TRUE:
+                return lseg_inside_poly(b, s->p + 1, poly, start);
+            case TS_NULL:
+                return TS_NULL;
+            case TS_FALSE:
+                break;
+        }
     }
-    else if (point_eq_point(a, s->p + 1))
+    else if (r != TS_NULL &&
+             (r = point_eq_point(a, s->p + 1)) == TS_TRUE)
     {
-        if (lseg_contain_point(&t, s->p))
-            return lseg_inside_poly(b, s->p, poly, start);
+        switch(lseg_contain_point(&t, s->p))
+        {
+            case TS_TRUE:
+                return lseg_inside_poly(b, s->p, poly, start);
+            case TS_NULL:
+                return TS_NULL;
+            case TS_FALSE:
+                break;
+        }
     }
-    else if (lseg_contain_point(&t, s->p))
+    else if (r != TS_NULL &&
+             (r = lseg_contain_point(&t, s->p)) == TS_TRUE)
     {
         return lseg_inside_poly(b, s->p, poly, start);
     }
-    else if (lseg_contain_point(&t, s->p + 1))
+    else if (r != TS_NULL &&
+             (r = lseg_contain_point(&t, s->p + 1)) == TS_TRUE)
     {
         return lseg_inside_poly(b, s->p + 1, poly, start);
     }
 
-    return true;                /* may be not true, but that will check later */
+    if (r == TS_NULL)
+        return TS_NULL;
+
+    return TS_TRUE;            /* may be not true, but that will check later */
 }
 
 /*
@@ -4074,61 +4250,75 @@ touched_lseg_inside_poly(Point *a, Point *b, LSEG *s, POLYGON *poly, int start)
  * start is used for optimization - function checks
  * polygon's edges starting from start
  */
-static bool
+static tsbool
 lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
 {
     LSEG        s,
                 t;
     int            i;
-    bool        res = true,
-                intersection = false;
+    tsbool        res = TS_TRUE;
+    bool        intersection = false;
+    tsbool        res1;
+    tsbool        res2;
+    tsbool        maybe_contained;
 
     t.p[0] = *a;
     t.p[1] = *b;
     s.p[0] = poly->p[(start == 0) ? (poly->npts - 1) : (start - 1)];
 
     /* Fast path. Check against boundbox. Also checks NaNs. */
-    if (!box_contain_point(&poly->boundbox, a) ||
-        !box_contain_point(&poly->boundbox, b))
-        return false;
+    res1 = box_contain_point(&poly->boundbox, a);
+    res2 = box_contain_point(&poly->boundbox, b);
+
+    maybe_contained = TS_AND2(res1, res2);
+    if (maybe_contained != TS_TRUE)
+        return maybe_contained;
 
     for (i = start; i < poly->npts && res; i++)
     {
         Point        interpt;
+        tsbool        r;
 
         CHECK_FOR_INTERRUPTS();
 
         s.p[1] = poly->p[i];
 
-        if (lseg_contain_point(&s, t.p))
+        if ((r = lseg_contain_point(&s, t.p)) == TS_TRUE)
         {
-            if (lseg_contain_point(&s, t.p + 1))
-                return true;    /* t is contained by s */
+            r = lseg_contain_point(&s, t.p + 1);
+            if (r != TS_FALSE)
+                return r;        /* t is contained by s, or NaN involved */
 
             /* Y-cross */
             res = touched_lseg_inside_poly(t.p, t.p + 1, &s, poly, i + 1);
         }
-        else if (lseg_contain_point(&s, t.p + 1))
+        else if (r != TS_NULL &&
+                 (r = lseg_contain_point(&s, t.p + 1)) == TS_TRUE)
         {
             /* Y-cross */
             res = touched_lseg_inside_poly(t.p + 1, t.p, &s, poly, i + 1);
         }
-        else if (lseg_interpt_lseg(&interpt, &t, &s))
+        else if (r != TS_NULL &&
+                 (r = lseg_interpt_lseg(&interpt, &t, &s)) == TS_TRUE)
         {
             /*
              * segments are X-crossing, go to check each subsegment
              */
 
             intersection = true;
+
+            /* the calls below won't return TS_NULL */
             res = lseg_inside_poly(t.p, &interpt, poly, i + 1);
             if (res)
                 res = lseg_inside_poly(t.p + 1, &interpt, poly, i + 1);
         }
+        else if (r == TS_NULL)
+            return TS_NULL;
 
         s.p[0] = s.p[1];
     }
 
-    if (res && !intersection)
+    if (res == TS_TRUE && !intersection)
     {
         Point        p;
 
@@ -4139,7 +4329,19 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
         p.x = float8_div(float8_pl(t.p[0].x, t.p[1].x), 2.0);
         p.y = float8_div(float8_pl(t.p[0].y, t.p[1].y), 2.0);
 
-        res = point_inside(&p, poly->npts, poly->p);
+        switch (point_inside(&p, poly->npts, poly->p))
+        {
+            case 0:
+                res = TS_FALSE;
+                break;
+            case 1:
+            case 2:
+                res = TS_TRUE;
+                break;
+            case -1:
+                res = TS_NULL;
+                break;
+        }
     }
 
     return res;
@@ -4148,11 +4350,12 @@ lseg_inside_poly(Point *a, Point *b, POLYGON *poly, int start)
 /*
  * Check whether the first polygon contains the second
  */
-static bool
+static tsbool
 poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly)
 {
     int            i;
     LSEG        s;
+    tsbool        r;
 
     Assert(contains_poly->npts > 0 && contained_poly->npts > 0);
 
@@ -4160,20 +4363,22 @@ poly_contain_poly(POLYGON *contains_poly, POLYGON *contained_poly)
      * Quick check to see if contained's bounding box is contained in
      * contains' bb.
      */
-    if (!box_contain_box(&contains_poly->boundbox, &contained_poly->boundbox))
-        return false;
+    r = box_contain_box(&contains_poly->boundbox, &contained_poly->boundbox);
+    if (r != TS_TRUE)
+        return r;
 
     s.p[0] = contained_poly->p[contained_poly->npts - 1];
 
     for (i = 0; i < contained_poly->npts; i++)
     {
         s.p[1] = contained_poly->p[i];
-        if (!lseg_inside_poly(s.p, s.p + 1, contains_poly, 0))
-            return false;
+        r = lseg_inside_poly(s.p, s.p + 1, contains_poly, 0);
+        if (r != TS_TRUE)
+            return r;
         s.p[0] = s.p[1];
     }
 
-    return true;
+    return TS_TRUE;
 }
 
 Datum
@@ -4181,7 +4386,7 @@ poly_contain(PG_FUNCTION_ARGS)
 {
     POLYGON    *polya = PG_GETARG_POLYGON_P(0);
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
-    bool        result;
+    tsbool        result;
 
     result = poly_contain_poly(polya, polyb);
 
@@ -4191,7 +4396,7 @@ poly_contain(PG_FUNCTION_ARGS)
     PG_FREE_IF_COPY(polya, 0);
     PG_FREE_IF_COPY(polyb, 1);
 
-    PG_RETURN_BOOL(result);
+    PG_RETURN_TSBOOL(result);
 }
 
 
@@ -4203,7 +4408,7 @@ poly_contained(PG_FUNCTION_ARGS)
 {
     POLYGON    *polya = PG_GETARG_POLYGON_P(0);
     POLYGON    *polyb = PG_GETARG_POLYGON_P(1);
-    bool        result;
+    tsbool        result;
 
     /* Just switch the arguments and pass it off to poly_contain */
     result = poly_contain_poly(polyb, polya);
@@ -4214,7 +4419,7 @@ poly_contained(PG_FUNCTION_ARGS)
     PG_FREE_IF_COPY(polya, 0);
     PG_FREE_IF_COPY(polyb, 1);
 
-    PG_RETURN_BOOL(result);
+    PG_RETURN_TSBOOL(result);
 }
 
 
@@ -4223,8 +4428,12 @@ poly_contain_pt(PG_FUNCTION_ARGS)
 {
     POLYGON    *poly = PG_GETARG_POLYGON_P(0);
     Point       *p = PG_GETARG_POINT_P(1);
+    int            r = point_inside(p, poly->npts, poly->p);
 
-    PG_RETURN_BOOL(point_inside(p, poly->npts, poly->p) != 0);
+    if (r >= 0)
+        PG_RETURN_BOOL(r != 0);
+
+    PG_RETURN_NULL();
 }
 
 Datum
@@ -4232,8 +4441,12 @@ pt_contained_poly(PG_FUNCTION_ARGS)
 {
     Point       *p = PG_GETARG_POINT_P(0);
     POLYGON    *poly = PG_GETARG_POLYGON_P(1);
+    int            r = point_inside(p, poly->npts, poly->p);
 
-    PG_RETURN_BOOL(point_inside(p, poly->npts, poly->p) != 0);
+    if (r >= 0)
+        PG_RETURN_BOOL(r != 0);
+
+    PG_RETURN_NULL();
 }
 
 
@@ -4255,9 +4468,16 @@ poly_distance(PG_FUNCTION_ARGS)
      * path distance will not give the right answer if one poly is entirely
      * within the other.
      */
-    if (poly_overlap_internal(polya, polyb))
-        PG_RETURN_FLOAT8(0.0);
-
+    switch (poly_overlap_internal(polya, polyb))
+    {
+        case TS_TRUE:
+            PG_RETURN_FLOAT8(0.0);
+        case TS_NULL:
+            PG_RETURN_FLOAT8(get_float8_nan());
+        case TS_FALSE:
+            break;
+    }
+            
     /*
      * When they don't overlap, the distance calculation is identical to that
      * for closed paths (i.e., we needn't care about the fact that polygons
@@ -4962,9 +5182,9 @@ circle_same(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(((isnan(circle1->radius) && isnan(circle1->radius)) ||
-                    FPeq(circle1->radius, circle2->radius)) &&
-                   point_eq_point(&circle1->center, &circle2->center));
+    PG_RETURN_TSBOOL(
+        TS_AND2(FPTeq(circle1->radius, circle2->radius),
+                point_eq_point(&circle1->center, &circle2->center)));
 }
 
 /*        circle_overlap    -        does circle1 overlap circle2?
@@ -4975,8 +5195,8 @@ circle_overlap(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center),
-                        float8_pl(circle1->radius, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTle(point_dt(&circle1->center, &circle2->center),
+                           float8_pl(circle1->radius, circle2->radius)));
 }
 
 /*        circle_overleft -        is the right edge of circle1 at or left of
@@ -4988,8 +5208,8 @@ circle_overleft(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPle(float8_pl(circle1->center.x, circle1->radius),
-                        float8_pl(circle2->center.x, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTle(float8_pl(circle1->center.x, circle1->radius),
+                           float8_pl(circle2->center.x, circle2->radius)));
 }
 
 /*        circle_left        -        is circle1 strictly left of circle2?
@@ -5000,8 +5220,8 @@ circle_left(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPlt(float8_pl(circle1->center.x, circle1->radius),
-                        float8_mi(circle2->center.x, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTlt(float8_pl(circle1->center.x, circle1->radius),
+                           float8_mi(circle2->center.x, circle2->radius)));
 }
 
 /*        circle_right    -        is circle1 strictly right of circle2?
@@ -5012,8 +5232,8 @@ circle_right(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPgt(float8_mi(circle1->center.x, circle1->radius),
-                        float8_pl(circle2->center.x, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTgt(float8_mi(circle1->center.x, circle1->radius),
+                           float8_pl(circle2->center.x, circle2->radius)));
 }
 
 /*        circle_overright    -    is the left edge of circle1 at or right of
@@ -5025,8 +5245,8 @@ circle_overright(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPge(float8_mi(circle1->center.x, circle1->radius),
-                        float8_mi(circle2->center.x, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTge(float8_mi(circle1->center.x, circle1->radius),
+                           float8_mi(circle2->center.x, circle2->radius)));
 }
 
 /*        circle_contained        -        is circle1 contained by circle2?
@@ -5049,8 +5269,8 @@ circle_contain(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPle(point_dt(&circle1->center, &circle2->center),
-                        float8_mi(circle1->radius, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTle(point_dt(&circle1->center, &circle2->center),
+                           float8_mi(circle1->radius, circle2->radius)));
 }
 
 
@@ -5062,8 +5282,8 @@ circle_below(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPlt(float8_pl(circle1->center.y, circle1->radius),
-                        float8_mi(circle2->center.y, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTlt(float8_pl(circle1->center.y, circle1->radius),
+                           float8_mi(circle2->center.y, circle2->radius)));
 }
 
 /*        circle_above    -        is circle1 strictly above circle2?
@@ -5074,8 +5294,8 @@ circle_above(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPgt(float8_mi(circle1->center.y, circle1->radius),
-                        float8_pl(circle2->center.y, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTgt(float8_mi(circle1->center.y, circle1->radius),
+                           float8_pl(circle2->center.y, circle2->radius)));
 }
 
 /*        circle_overbelow -        is the upper edge of circle1 at or below
@@ -5087,8 +5307,8 @@ circle_overbelow(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPle(float8_pl(circle1->center.y, circle1->radius),
-                        float8_pl(circle2->center.y, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTle(float8_pl(circle1->center.y, circle1->radius),
+                           float8_pl(circle2->center.y, circle2->radius)));
 }
 
 /*        circle_overabove    -    is the lower edge of circle1 at or above
@@ -5100,13 +5320,15 @@ circle_overabove(PG_FUNCTION_ARGS)
     CIRCLE       *circle1 = PG_GETARG_CIRCLE_P(0);
     CIRCLE       *circle2 = PG_GETARG_CIRCLE_P(1);
 
-    PG_RETURN_BOOL(FPge(float8_mi(circle1->center.y, circle1->radius),
-                        float8_mi(circle2->center.y, circle2->radius)));
+    PG_RETURN_TSBOOL(FPTge(float8_mi(circle1->center.y, circle1->radius),
+                           float8_mi(circle2->center.y, circle2->radius)));
 }
 
 
 /*        circle_relop    -        is area(circle1) relop area(circle2), within
  *                                our accuracy constraint?
+ *
+ *  XXX; area comparison doen't consider the NaN-ness of the center location.
  */
 Datum
 circle_eq(PG_FUNCTION_ARGS)
@@ -5114,7 +5336,7 @@ 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_TSBOOL(FPTeq(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
@@ -5123,7 +5345,7 @@ 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_TSBOOL(FPTne(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
@@ -5132,7 +5354,7 @@ 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_TSBOOL(FPTlt(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
@@ -5141,7 +5363,7 @@ 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_TSBOOL(FPTgt(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
@@ -5150,7 +5372,7 @@ 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_TSBOOL(FPTle(circle_ar(circle1), circle_ar(circle2)));
 }
 
 Datum
@@ -5159,7 +5381,7 @@ 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_TSBOOL(FPTge(circle_ar(circle1), circle_ar(circle2)));
 }
 
 
@@ -5295,6 +5517,11 @@ circle_contain_pt(PG_FUNCTION_ARGS)
     float8        d;
 
     d = point_dt(&circle->center, point);
+
+    if (isnan(d) || isnan(circle->radius))
+        PG_RETURN_NULL();
+
+    /*  XXX: why don't we use FP(T)le? */
     PG_RETURN_BOOL(d <= circle->radius);
 }
 
@@ -5307,6 +5534,10 @@ pt_contained_circle(PG_FUNCTION_ARGS)
     float8        d;
 
     d = point_dt(&circle->center, point);
+    if (isnan(d) || isnan(circle->radius))
+        PG_RETURN_NULL();
+
+    /*  XXX: why don't we use FP(T)le? */
     PG_RETURN_BOOL(d <= circle->radius);
 }
 
@@ -5533,8 +5764,9 @@ poly_circle(PG_FUNCTION_ARGS)
  ***********************************************************************/
 
 /*
- *    Test to see if the point is inside the polygon, returns 1/0, or 2 if
- *    the point is on the polygon.
+ *    Test to see if the point is inside the polygon, returns 1/0, or 2 if the
+ *    point is on the polygon. -1 means undetermined, in case any operand is an
+ *    invalid object. (-1, 0 and 1 are compatible with tsbool type)
  *    Code adapted but not copied from integer-based routines in WN: A
  *    Server for the HTTP
  *    version 1.15.1, file wn/image.c
@@ -5566,7 +5798,7 @@ point_inside(Point *p, int npts, Point *plist)
 
     /* NaN makes the point cannot be inside the polygon */
     if (unlikely(isnan(x0) || isnan(y0) || isnan(p->x) || isnan(p->y)))
-        return 0;
+        return -1;
 
     prev_x = x0;
     prev_y = y0;
@@ -5579,7 +5811,7 @@ point_inside(Point *p, int npts, Point *plist)
 
         /* NaN makes the point cannot be inside the polygon */
         if (unlikely(isnan(x) || isnan(y)))
-            return 0;
+            return -1;
 
         /* compute previous to current point crossing */
         if ((cross = lseg_crossing(x, y, prev_x, prev_y)) == POINT_ON_POLYGON)
@@ -5606,6 +5838,8 @@ 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).
+ * This function doesn't check if the parameters contain NaNs, it's the
+ * responsibility of the callers.
  * Wow, that is one confusing API, but it is used above, and when summed,
  * can tell is if a point is in a polygon.
  */
@@ -5670,17 +5904,18 @@ lseg_crossing(float8 x, float8 y, float8 prev_x, float8 prev_y)
 }
 
 
-static bool
+static tsbool
 plist_same(int npts, Point *p1, Point *p2)
 {
     int            i,
                 ii,
                 j;
+    tsbool        r;
 
     /* find match for first point */
     for (i = 0; i < npts; i++)
     {
-        if (point_eq_point(&p2[i], &p1[0]))
+        if ((r = point_eq_point(&p2[i], &p1[0])) == TS_TRUE)
         {
 
             /* match found? then look forward through remaining points */
@@ -5688,26 +5923,29 @@ plist_same(int npts, Point *p1, Point *p2)
             {
                 if (j >= npts)
                     j = 0;
-                if (!point_eq_point(&p2[j], &p1[ii]))
+                if ((r = point_eq_point(&p2[j], &p1[ii])) != TS_TRUE)
                     break;
             }
             if (ii == npts)
-                return true;
+                return TS_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 (!point_eq_point(&p2[j], &p1[ii]))
+                if ((r = point_eq_point(&p2[j], &p1[ii])) != TS_TRUE)
                     break;
             }
             if (ii == npts)
-                return true;
+                return TS_TRUE;
         }
+
+        if (r == TS_NULL)
+            return TS_NULL;
     }
 
-    return false;
+    return TS_FALSE;
 }
 
 
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 3dfe6e5825..a2e6006a49 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -807,8 +807,15 @@ DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
     return result;
 }
 
+/*
+ * We make a special use of binary operator functions that expects null to be
+ * returned.  Thus only the two-operand version among these functions have
+ * additional parameter to deal with that case. This function has a translation
+ * macro DirectFunctionCall2Coll for the ordinary use.
+ */
 Datum
-DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
+DirectFunctionCall2CollExt(PGFunction func, Oid collation,
+                           Datum arg1, Datum arg2, bool *isnull)
 {
     LOCAL_FCINFO(fcinfo, 2);
     Datum        result;
@@ -822,9 +829,14 @@ DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
 
     result = (*func) (fcinfo);
 
-    /* Check for null result, since caller is clearly not expecting one */
+    /* Interpret null as false, since caller is clearly not expecting one */
     if (fcinfo->isnull)
-        elog(ERROR, "function %p returned NULL", (void *) func);
+    {
+        if (isnull)
+            *isnull = true;
+        else
+            elog(ERROR, "function %p returned NULL", (void *) func);
+    }
 
     return result;
 }
diff --git a/src/include/c.h b/src/include/c.h
index 7e591171a8..4e0a1b0077 100644
--- a/src/include/c.h
+++ b/src/include/c.h
@@ -402,6 +402,13 @@ typedef unsigned char bool;
 #endif                            /* not PG_USE_STDBOOL */
 #endif                            /* not C++ */
 
+/* tri-state boolean, false/true are compatible with bool */
+typedef enum tsbool
+{
+    TS_NULL = -1,
+    TS_FALSE = false,
+    TS_TRUE = true
+} tsbool;
 
 /* ----------------------------------------------------------------
  *                Section 3:    standard system types
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index cec663bdff..e10a5bf5fc 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -503,13 +503,16 @@ extern int no_such_variable
 
 /* These are for invocation of a specifically named function with a
  * directly-computed parameter list.  Note that neither arguments nor result
- * are allowed to be NULL.  Also, the function cannot be one that needs to
+ * are allowed to be C NULL.  Also, the function cannot be one that needs to
  * look at FmgrInfo, since there won't be any.
+ *
+ * Only the 2-operand version can call functions that may return SQL-null to
+ * deal with tristate comparison operators.
  */
 extern Datum DirectFunctionCall1Coll(PGFunction func, Oid collation,
                                      Datum arg1);
-extern Datum DirectFunctionCall2Coll(PGFunction func, Oid collation,
-                                     Datum arg1, Datum arg2);
+extern Datum DirectFunctionCall2CollExt(PGFunction func, Oid collation,
+                                        Datum arg1, Datum arg2, bool *isnull);
 extern Datum DirectFunctionCall3Coll(PGFunction func, Oid collation,
                                      Datum arg1, Datum arg2,
                                      Datum arg3);
@@ -623,6 +626,14 @@ extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
                                   Datum arg3, Datum arg4, Datum arg5,
                                   Datum arg6, Datum arg7, Datum arg8,
                                   Datum arg9);
+/*
+ * The two-operand version of these functions is able to deal with SQL-null
+ * returns. Addtional translation macros for compatibility to other versions.
+ */
+#define DirectFunctionCall2Ext(func, arg1, arg2, isnull)                \
+    DirectFunctionCall2CollExt(func, InvalidOid, arg1, arg2, isnull)
+#define DirectFunctionCall2Coll(func, coll, arg1, arg2)            \
+    DirectFunctionCall2CollExt(func, coll, arg1, arg2, NULL)
 
 /* These macros allow the collation argument to be omitted (with a default of
  * InvalidOid, ie, no collation).  They exist mostly for backwards
@@ -631,7 +642,7 @@ extern Datum OidFunctionCall9Coll(Oid functionId, Oid collation,
 #define DirectFunctionCall1(func, arg1) \
     DirectFunctionCall1Coll(func, InvalidOid, arg1)
 #define DirectFunctionCall2(func, arg1, arg2) \
-    DirectFunctionCall2Coll(func, InvalidOid, arg1, arg2)
+    DirectFunctionCall2CollExt(func, InvalidOid, arg1, arg2, NULL)
 #define DirectFunctionCall3(func, arg1, arg2, arg3) \
     DirectFunctionCall3Coll(func, InvalidOid, arg1, arg2, arg3)
 #define DirectFunctionCall4(func, arg1, arg2, arg3, arg4) \
diff --git a/src/include/utils/float.h b/src/include/utils/float.h
index 4ab3f9d8ef..a983d6d8d0 100644
--- a/src/include/utils/float.h
+++ b/src/include/utils/float.h
@@ -353,6 +353,115 @@ float8_max(const float8 val1, const float8 val2)
     return float8_gt(val1, val2) ? val1 : val2;
 }
 
+/* tri-state equivalents */
+static inline tsbool
+float4_teq(const float4 val1, const float4 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 == val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float8_teq(const float8 val1, const float8 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 == val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float4_tne(const float4 val1, const float4 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 != val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float8_tne(const float8 val1, const float8 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 != val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float4_tlt(const float4 val1, const float4 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 < val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float8_tlt(const float8 val1, const float8 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 < val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float4_tle(const float4 val1, const float4 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 <= val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float8_tle(const float8 val1, const float8 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 <= val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float4_tgt(const float4 val1, const float4 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 > val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float8_tgt(const float8 val1, const float8 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 > val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float4_tge(const float4 val1, const float4 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 >= val2;
+
+    return TS_NULL;
+}
+
+static inline tsbool
+float8_tge(const float8 val1, const float8 val2)
+{
+    if (!isnan(val1) && !isnan(val2))
+        return val1 >= val2;
+
+    return TS_NULL;
+}
+
 /*
  * These two functions return NaN if either input is NaN, else the smaller
  * of the two inputs.  This does NOT follow our usual sort rule, but it is
diff --git a/src/include/utils/geo_decls.h b/src/include/utils/geo_decls.h
index 0b87437d83..0825b1f44b 100644
--- a/src/include/utils/geo_decls.h
+++ b/src/include/utils/geo_decls.h
@@ -19,6 +19,7 @@
 #define GEO_DECLS_H
 
 #include <math.h>
+#include <limits.h>
 
 #include "fmgr.h"
 
@@ -40,6 +41,18 @@
 
 #define EPSILON                    1.0E-06
 
+/* helper function for tri-state checking */
+static inline tsbool
+FP_TSCHECK(double A, double B, bool cond)
+{
+    if (cond)
+        return TS_TRUE;
+    if (!isnan(A) && !isnan(B))
+        return TS_FALSE;
+
+    return TS_NULL;
+}
+
 #ifdef EPSILON
 #define FPzero(A)                (fabs(A) <= EPSILON)
 
@@ -88,6 +101,100 @@ FPge(double A, double B)
 #define FPge(A,B)                ((A) >= (B))
 #endif
 
+
+/* define as inline functions to avoid duplicate evaluation */
+static inline tsbool
+FPTzero(double A)
+{
+    if (fabs(A) <= EPSILON)
+        return TS_TRUE;
+    if (isnan(A))
+        return TS_NULL;
+    return TS_FALSE;
+}
+
+static inline tsbool
+FPTeq(double A, double B)
+{
+    return FP_TSCHECK(A, B, FPeq(A, B));
+}
+
+static inline tsbool
+FPTne(double A, double B)
+{
+    return FP_TSCHECK(A, B, FPne(A, B));
+}
+
+static inline tsbool
+FPTlt(double A, double B)
+{
+    return FP_TSCHECK(A, B, FPlt(A, B));
+}
+
+static inline tsbool
+FPTle(double A, double B)
+{
+    return FP_TSCHECK(A, B, FPle(A, B));
+}
+
+static inline tsbool
+FPTgt(double A, double B)
+{
+    return FP_TSCHECK(A, B, FPgt(A, B));
+}
+
+static inline tsbool
+FPTge(double A, double B)
+{
+    return FP_TSCHECK(A, B, FPge(A, B));
+}
+
+/* https://graphics.stanford.edu/~seander/bithacks.html#ZeroInWord */
+#define TS_SIGN(v) (-(int)((unsigned int)((int)v) >> (sizeof(int) * CHAR_BIT - 1)))
+
+static inline tsbool
+TS_NOT(tsbool a)
+{
+    return (!a) | TS_SIGN(a);
+}
+
+/*
+ * Returns the result of tristate-OR of two tsbools.
+ * The operations on true and false are the same to boolean.  returns TS_NULL
+ * if any of the operands is TS_NULL.
+ */
+static inline tsbool
+TS_OR2(tsbool p1, tsbool p2)
+{
+
+    return p1 | p2;        /* not a boolean operator, but a bitwise operator */
+}
+
+/*
+ * Returns the result of tristate-AND of two tsbools.
+ * The operations on true and false are the same to boolean.  returns TS_NULL
+ * if any of the operands is TS_NULL.
+ */
+static inline tsbool
+TS_AND2(tsbool p1, tsbool p2)
+{
+    return (p1 & p2) | TS_SIGN(p1 | p2);
+}
+
+static inline tsbool
+TS_AND4(tsbool p1, tsbool p2, tsbool p3, tsbool p4)
+{
+    return (p1 & p2 & p3 & p4) | TS_SIGN(p1 | p2 | p3 | p4);
+}
+
+#define PG_RETURN_TSBOOL(e)            \
+    do                                \
+    {                                \
+        if ((e) != TS_NULL)            \
+            PG_RETURN_BOOL(e);        \
+        PG_RETURN_NULL();            \
+    } while (0)
+
 #define HYPOT(A, B)                pg_hypot(A, B)
 
 /*---------------------------------------------------------------------
diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out
index 77ff1b3d7b..5e5969c820 100644
--- a/src/test/regress/expected/geometry.out
+++ b/src/test/regress/expected/geometry.out
@@ -919,7 +919,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (0,0)             | (-5,-12)          | {2.4,-1,0}
  (0,0)             | (1e+300,Infinity) | {-1,0,0}
  (0,0)             | (Infinity,1e+300) | {0,-1,0}
- (0,0)             | (NaN,NaN)         | {NaN,NaN,NaN}
  (0,0)             | (10,10)           | {1,-1,0}
  (-10,0)           | (0,0)             | {0,-1,0}
  (-10,0)           | (-3,4)            | {0.571428571429,-1,5.71428571429}
@@ -928,7 +927,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-10,0)           | (1e-300,-1e-300)  | {0,-1,0}
  (-10,0)           | (1e+300,Infinity) | {-1,0,-10}
  (-10,0)           | (Infinity,1e+300) | {0,-1,0}
- (-10,0)           | (NaN,NaN)         | {NaN,NaN,NaN}
  (-10,0)           | (10,10)           | {0.5,-1,5}
  (-3,4)            | (0,0)             | {-1.33333333333,-1,0}
  (-3,4)            | (-10,0)           | {0.571428571429,-1,5.71428571429}
@@ -937,7 +935,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-3,4)            | (1e-300,-1e-300)  | {-1.33333333333,-1,0}
  (-3,4)            | (1e+300,Infinity) | {-1,0,-3}
  (-3,4)            | (Infinity,1e+300) | {0,-1,4}
- (-3,4)            | (NaN,NaN)         | {NaN,NaN,NaN}
  (-3,4)            | (10,10)           | {0.461538461538,-1,5.38461538462}
  (5.1,34.5)        | (0,0)             | {6.76470588235,-1,0}
  (5.1,34.5)        | (-10,0)           | {2.28476821192,-1,22.8476821192}
@@ -946,7 +943,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (5.1,34.5)        | (1e-300,-1e-300)  | {6.76470588235,-1,0}
  (5.1,34.5)        | (1e+300,Infinity) | {-1,0,5.1}
  (5.1,34.5)        | (Infinity,1e+300) | {0,-1,34.5}
- (5.1,34.5)        | (NaN,NaN)         | {NaN,NaN,NaN}
  (5.1,34.5)        | (10,10)           | {-5,-1,60}
  (-5,-12)          | (0,0)             | {2.4,-1,0}
  (-5,-12)          | (-10,0)           | {-2.4,-1,-24}
@@ -955,7 +951,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (-5,-12)          | (1e-300,-1e-300)  | {2.4,-1,0}
  (-5,-12)          | (1e+300,Infinity) | {-1,0,-5}
  (-5,-12)          | (Infinity,1e+300) | {0,-1,-12}
- (-5,-12)          | (NaN,NaN)         | {NaN,NaN,NaN}
  (-5,-12)          | (10,10)           | {1.46666666667,-1,-4.66666666667}
  (1e-300,-1e-300)  | (-10,0)           | {0,-1,-1e-300}
  (1e-300,-1e-300)  | (-3,4)            | {-1.33333333333,-1,3.33333333333e-301}
@@ -963,7 +958,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e-300,-1e-300)  | (-5,-12)          | {2.4,-1,-3.4e-300}
  (1e-300,-1e-300)  | (1e+300,Infinity) | {-1,0,1e-300}
  (1e-300,-1e-300)  | (Infinity,1e+300) | {0,-1,-1e-300}
- (1e-300,-1e-300)  | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e-300,-1e-300)  | (10,10)           | {1,-1,-2e-300}
  (1e+300,Infinity) | (0,0)             | {-1,0,1e+300}
  (1e+300,Infinity) | (-10,0)           | {-1,0,1e+300}
@@ -972,7 +966,6 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (1e+300,Infinity) | (-5,-12)          | {-1,0,1e+300}
  (1e+300,Infinity) | (1e-300,-1e-300)  | {-1,0,1e+300}
  (1e+300,Infinity) | (Infinity,1e+300) | {NaN,NaN,NaN}
- (1e+300,Infinity) | (NaN,NaN)         | {NaN,NaN,NaN}
  (1e+300,Infinity) | (10,10)           | {-1,0,1e+300}
  (Infinity,1e+300) | (0,0)             | {0,-1,1e+300}
  (Infinity,1e+300) | (-10,0)           | {0,-1,1e+300}
@@ -981,17 +974,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (Infinity,1e+300) | (-5,-12)          | {0,-1,1e+300}
  (Infinity,1e+300) | (1e-300,-1e-300)  | {0,-1,1e+300}
  (Infinity,1e+300) | (1e+300,Infinity) | {NaN,NaN,NaN}
- (Infinity,1e+300) | (NaN,NaN)         | {NaN,NaN,NaN}
  (Infinity,1e+300) | (10,10)           | {0,-1,1e+300}
- (NaN,NaN)         | (0,0)             | {NaN,NaN,NaN}
- (NaN,NaN)         | (-10,0)           | {NaN,NaN,NaN}
- (NaN,NaN)         | (-3,4)            | {NaN,NaN,NaN}
- (NaN,NaN)         | (5.1,34.5)        | {NaN,NaN,NaN}
- (NaN,NaN)         | (-5,-12)          | {NaN,NaN,NaN}
- (NaN,NaN)         | (1e-300,-1e-300)  | {NaN,NaN,NaN}
- (NaN,NaN)         | (1e+300,Infinity) | {NaN,NaN,NaN}
- (NaN,NaN)         | (Infinity,1e+300) | {NaN,NaN,NaN}
- (NaN,NaN)         | (10,10)           | {NaN,NaN,NaN}
  (10,10)           | (0,0)             | {1,-1,0}
  (10,10)           | (-10,0)           | {0.5,-1,5}
  (10,10)           | (-3,4)            | {0.461538461538,-1,5.38461538462}
@@ -1000,8 +983,7 @@ SELECT p1.f1, p2.f1, line(p1.f1, p2.f1)
  (10,10)           | (1e-300,-1e-300)  | {1,-1,0}
  (10,10)           | (1e+300,Infinity) | {-1,0,10}
  (10,10)           | (Infinity,1e+300) | {0,-1,10}
- (10,10)           | (NaN,NaN)         | {NaN,NaN,NaN}
-(88 rows)
+(70 rows)
 
 -- Closest point to line
 SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l;
@@ -1310,11 +1292,9 @@ SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s = l2.s;
  {1,-1,0}                              | {1,-1,0}
  {-0.4,-1,-6}                          | {-0.4,-1,-6}
  {-0.000184615384615,-1,15.3846153846} | {-0.000184615384615,-1,15.3846153846}
- {3,NaN,5}                             | {3,NaN,5}
- {NaN,NaN,NaN}                         | {NaN,NaN,NaN}
  {0,-1,3}                              | {0,-1,3}
  {-1,0,3}                              | {-1,0,3}
-(10 rows)
+(8 rows)
 
 -- Parallel to line
 SELECT l1.s, l2.s FROM LINE_TBL l1, LINE_TBL l2 WHERE l1.s ?|| l2.s;
@@ -1865,8 +1845,7 @@ SELECT l1.s, l2.s FROM LSEG_TBL l1, LSEG_TBL l2 WHERE l1.s = l2.s;
  [(11,22),(33,44)]             | [(11,22),(33,44)]
  [(-10,2),(-10,3)]             | [(-10,2),(-10,3)]
  [(0,-20),(30,-20)]            | [(0,-20),(30,-20)]
- [(NaN,1),(NaN,90)]            | [(NaN,1),(NaN,90)]
-(8 rows)
+(7 rows)
 
 -- Has points greater than or equal to line segment
 SELECT l1.s, l2.s FROM LSEG_TBL l1, LSEG_TBL l2 WHERE l1.s >= l2.s;
@@ -1939,57 +1918,43 @@ SELECT l1.s, l2.s FROM LSEG_TBL l1, LSEG_TBL l2 WHERE l1.s != l2.s;
  [(1,2),(3,4)]                 | [(11,22),(33,44)]
  [(1,2),(3,4)]                 | [(-10,2),(-10,3)]
  [(1,2),(3,4)]                 | [(0,-20),(30,-20)]
- [(1,2),(3,4)]                 | [(NaN,1),(NaN,90)]
  [(0,0),(6,6)]                 | [(1,2),(3,4)]
  [(0,0),(6,6)]                 | [(10,-10),(-3,-4)]
  [(0,0),(6,6)]                 | [(-1000000,200),(300000,-40)]
  [(0,0),(6,6)]                 | [(11,22),(33,44)]
  [(0,0),(6,6)]                 | [(-10,2),(-10,3)]
  [(0,0),(6,6)]                 | [(0,-20),(30,-20)]
- [(0,0),(6,6)]                 | [(NaN,1),(NaN,90)]
  [(10,-10),(-3,-4)]            | [(1,2),(3,4)]
  [(10,-10),(-3,-4)]            | [(0,0),(6,6)]
  [(10,-10),(-3,-4)]            | [(-1000000,200),(300000,-40)]
  [(10,-10),(-3,-4)]            | [(11,22),(33,44)]
  [(10,-10),(-3,-4)]            | [(-10,2),(-10,3)]
  [(10,-10),(-3,-4)]            | [(0,-20),(30,-20)]
- [(10,-10),(-3,-4)]            | [(NaN,1),(NaN,90)]
  [(-1000000,200),(300000,-40)] | [(1,2),(3,4)]
  [(-1000000,200),(300000,-40)] | [(0,0),(6,6)]
  [(-1000000,200),(300000,-40)] | [(10,-10),(-3,-4)]
  [(-1000000,200),(300000,-40)] | [(11,22),(33,44)]
  [(-1000000,200),(300000,-40)] | [(-10,2),(-10,3)]
  [(-1000000,200),(300000,-40)] | [(0,-20),(30,-20)]
- [(-1000000,200),(300000,-40)] | [(NaN,1),(NaN,90)]
  [(11,22),(33,44)]             | [(1,2),(3,4)]
  [(11,22),(33,44)]             | [(0,0),(6,6)]
  [(11,22),(33,44)]             | [(10,-10),(-3,-4)]
  [(11,22),(33,44)]             | [(-1000000,200),(300000,-40)]
  [(11,22),(33,44)]             | [(-10,2),(-10,3)]
  [(11,22),(33,44)]             | [(0,-20),(30,-20)]
- [(11,22),(33,44)]             | [(NaN,1),(NaN,90)]
  [(-10,2),(-10,3)]             | [(1,2),(3,4)]
  [(-10,2),(-10,3)]             | [(0,0),(6,6)]
  [(-10,2),(-10,3)]             | [(10,-10),(-3,-4)]
  [(-10,2),(-10,3)]             | [(-1000000,200),(300000,-40)]
  [(-10,2),(-10,3)]             | [(11,22),(33,44)]
  [(-10,2),(-10,3)]             | [(0,-20),(30,-20)]
- [(-10,2),(-10,3)]             | [(NaN,1),(NaN,90)]
  [(0,-20),(30,-20)]            | [(1,2),(3,4)]
  [(0,-20),(30,-20)]            | [(0,0),(6,6)]
  [(0,-20),(30,-20)]            | [(10,-10),(-3,-4)]
  [(0,-20),(30,-20)]            | [(-1000000,200),(300000,-40)]
  [(0,-20),(30,-20)]            | [(11,22),(33,44)]
  [(0,-20),(30,-20)]            | [(-10,2),(-10,3)]
- [(0,-20),(30,-20)]            | [(NaN,1),(NaN,90)]
- [(NaN,1),(NaN,90)]            | [(1,2),(3,4)]
- [(NaN,1),(NaN,90)]            | [(0,0),(6,6)]
- [(NaN,1),(NaN,90)]            | [(10,-10),(-3,-4)]
- [(NaN,1),(NaN,90)]            | [(-1000000,200),(300000,-40)]
- [(NaN,1),(NaN,90)]            | [(11,22),(33,44)]
- [(NaN,1),(NaN,90)]            | [(-10,2),(-10,3)]
- [(NaN,1),(NaN,90)]            | [(0,-20),(30,-20)]
-(56 rows)
+(42 rows)
 
 -- Parallel with line segment
 SELECT l1.s, l2.s FROM LSEG_TBL l1, LSEG_TBL l2 WHERE l1.s ?|| l2.s;
@@ -3680,13 +3645,13 @@ SELECT p.f1, poly.f1, poly.f1 @> p.f1 AS contains
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
  (Infinity,1e+300) | ((0,0))                    | f
  (Infinity,1e+300) | ((0,1),(0,1))              | f
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
- (NaN,NaN)         | ((0,0))                    | f
- (NaN,NaN)         | ((0,1),(0,1))              | f
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        | 
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        | 
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | 
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | 
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | 
+ (NaN,NaN)         | ((0,0))                    | 
+ (NaN,NaN)         | ((0,1),(0,1))              | 
  (10,10)           | ((2,0),(2,4),(0,0))        | f
  (10,10)           | ((3,1),(3,3),(1,0))        | f
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -3756,13 +3721,13 @@ SELECT p.f1, poly.f1, p.f1 <@ poly.f1 AS contained
  (Infinity,1e+300) | ((1,2),(7,8),(5,6),(3,-4)) | f
  (Infinity,1e+300) | ((0,0))                    | f
  (Infinity,1e+300) | ((0,1),(0,1))              | f
- (NaN,NaN)         | ((2,0),(2,4),(0,0))        | f
- (NaN,NaN)         | ((3,1),(3,3),(1,0))        | f
- (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | f
- (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | f
- (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | f
- (NaN,NaN)         | ((0,0))                    | f
- (NaN,NaN)         | ((0,1),(0,1))              | f
+ (NaN,NaN)         | ((2,0),(2,4),(0,0))        | 
+ (NaN,NaN)         | ((3,1),(3,3),(1,0))        | 
+ (NaN,NaN)         | ((1,2),(3,4),(5,6),(7,8))  | 
+ (NaN,NaN)         | ((7,8),(5,6),(3,4),(1,2))  | 
+ (NaN,NaN)         | ((1,2),(7,8),(5,6),(3,-4)) | 
+ (NaN,NaN)         | ((0,0))                    | 
+ (NaN,NaN)         | ((0,1),(0,1))              | 
  (10,10)           | ((2,0),(2,4),(0,0))        | f
  (10,10)           | ((3,1),(3,3),(1,0))        | f
  (10,10)           | ((1,2),(3,4),(5,6),(7,8))  | f
@@ -4339,9 +4304,7 @@ SELECT c1.f1, c2.f1 FROM CIRCLE_TBL c1, CIRCLE_TBL c2 WHERE c1.f1 ~= c2.f1;
  <(100,200),10> | <(100,200),10>
  <(100,1),115>  | <(100,1),115>
  <(3,5),0>      | <(3,5),0>
- <(3,5),NaN>    | <(3,5),0>
- <(3,5),NaN>    | <(3,5),NaN>
-(9 rows)
+(7 rows)
 
 -- Overlap with circle
 SELECT c1.f1, c2.f1 FROM CIRCLE_TBL c1, CIRCLE_TBL c2 WHERE c1.f1 && c2.f1;
diff --git a/src/test/regress/expected/line.out b/src/test/regress/expected/line.out
index fe106589c6..175fb3ab45 100644
--- a/src/test/regress/expected/line.out
+++ b/src/test/regress/expected/line.out
@@ -78,10 +78,11 @@ select * from LINE_TBL;
  {-1,0,3}
 (10 rows)
 
+-- Both of them return null
 select '{nan, 1, nan}'::line = '{nan, 1, nan}'::line as true,
        '{nan, 1, nan}'::line = '{nan, 2, nan}'::line as false;
  true | false 
 ------+-------
- t    | f
+      | 
 (1 row)
 
diff --git a/src/test/regress/expected/point.out b/src/test/regress/expected/point.out
index 1dc535d1b3..7afcf07241 100644
--- a/src/test/regress/expected/point.out
+++ b/src/test/regress/expected/point.out
@@ -118,8 +118,7 @@ SELECT p.* FROM POINT_TBL p
  (1e-300,-1e-300)
  (1e+300,Infinity)
  (Infinity,1e+300)
- (NaN,NaN)
-(7 rows)
+(6 rows)
 
 SELECT p.* FROM POINT_TBL p
    WHERE p.f1 <@ path '[(0,0),(-10,0),(-10,10)]';
@@ -140,8 +139,7 @@ SELECT p.* FROM POINT_TBL p
  (1e-300,-1e-300)
  (1e+300,Infinity)
  (Infinity,1e+300)
- (NaN,NaN)
-(7 rows)
+(6 rows)
 
 SELECT p.f1, p.f1 <-> point '(0,0)' AS dist
    FROM POINT_TBL p
diff --git a/src/test/regress/sql/line.sql b/src/test/regress/sql/line.sql
index f589ffecc8..56afd3cc63 100644
--- a/src/test/regress/sql/line.sql
+++ b/src/test/regress/sql/line.sql
@@ -38,5 +38,6 @@ INSERT INTO LINE_TBL VALUES (line(point '(1,0)', point '(1,0)'));
 
 select * from LINE_TBL;
 
+-- Both of them return null
 select '{nan, 1, nan}'::line = '{nan, 1, nan}'::line as true,
        '{nan, 1, nan}'::line = '{nan, 2, nan}'::line as false;
-- 
2.27.0


Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Wed, 15 Dec 2021 16:20:55 +0900 (JST), Kyotaro Horiguchi <horikyota.ntt@gmail.com> wrote in 
> adjusted so that it treats null as false. On the way doing this, the
> bug #17334 [2] and another bug raised earlier [3] are naturally fixed.

That being said, even if this patch were committed to the master
branch, we won't apply the whole patch set for backbranches.

I guess applying the computeDistance part in the patch works.

# But I found that the part contains a bugX(

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center



Re: Strange behavior with polygon and NaN

From
Jacob Champion
Date:
As discussed in [1], we're taking this opportunity to return some
patchsets that don't appear to be getting enough reviewer interest.

This is not a rejection, since we don't necessarily think there's
anything unacceptable about the entry, but it differs from a standard
"Returned with Feedback" in that there's probably not much actionable
feedback at all. Rather than code changes, what this patch needs is more
community interest. You might

- ask people for help with your approach,
- see if there are similar patches that your code could supplement,
- get interested parties to agree to review your patch in a CF, or
- possibly present the functionality in a way that's easier to review
  overall.

(Doing these things is no guarantee that there will be interest, but
it's hopefully better than endlessly rebasing a patchset that is not
receiving any feedback from the community.)

Once you think you've built up some community support and the patchset
is ready for review, you (or any interested party) can resurrect the
patch entry by visiting

    https://commitfest.postgresql.org/38/2710/

and changing the status to "Needs Review", and then changing the
status again to "Move to next CF". (Don't forget the second step;
hopefully we will have streamlined this in the near future!)

Thanks,
--Jacob

[1]
https://postgr.es/m/flat/0ab66589-2f71-69b3-2002-49e821740b0d%40timescale.com



Re: Strange behavior with polygon and NaN

From
Kyotaro Horiguchi
Date:
At Mon, 1 Aug 2022 13:29:09 -0700, Jacob Champion <jchampion@timescale.com> wrote in 
> As discussed in [1], we're taking this opportunity to return some
> patchsets that don't appear to be getting enough reviewer interest.

Oh, sorry. I missed that thread. Thank you for kindly noticing that.

> This is not a rejection, since we don't necessarily think there's
> anything unacceptable about the entry, but it differs from a standard
> "Returned with Feedback" in that there's probably not much actionable
> feedback at all. Rather than code changes, what this patch needs is more
> community interest. You might
> 
> - ask people for help with your approach,
> - see if there are similar patches that your code could supplement,
> - get interested parties to agree to review your patch in a CF, or
> - possibly present the functionality in a way that's easier to review
>   overall.
> 
> (Doing these things is no guarantee that there will be interest, but
> it's hopefully better than endlessly rebasing a patchset that is not
> receiving any feedback from the community.)
> 
> Once you think you've built up some community support and the patchset
> is ready for review, you (or any interested party) can resurrect the
> patch entry by visiting
> 
>     https://commitfest.postgresql.org/38/2710/
> 
> and changing the status to "Needs Review", and then changing the
> status again to "Move to next CF". (Don't forget the second step;
> hopefully we will have streamlined this in the near future!)

Thanks. I don't insist on this patch unless some other people are
interested in.

regards.

-- 
Kyotaro Horiguchi
NTT Open Source Software Center