Strange behavior with polygon and NaN

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
7 messages Options
Reply | Threaded
Open this post in threaded view
|

Strange behavior with polygon and NaN

Jesse Zhang
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


Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with polygon and NaN

Bruce Momjian

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  <[hidden email]>        https://momjian.us
  EnterpriseDB                             https://enterprisedb.com

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



Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with polygon and NaN

Kyotaro Horiguchi-4
At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian <[hidden email]> 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;
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with polygon and NaN

Tom Lane-2
Kyotaro Horiguchi <[hidden email]> writes:
> At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian <[hidden email]> 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


Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with polygon and NaN

Kyotaro Horiguchi-4
At Wed, 26 Aug 2020 08:18:49 -0400, Tom Lane <[hidden email]> wrote in

> Kyotaro Horiguchi <[hidden email]> writes:
> > At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian <[hidden email]> 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 <[hidden email]>
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

Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with polygon and NaN

gkokolatos





‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
On Thursday, 27 August 2020 14:24, Kyotaro Horiguchi <[hidden email]> wrote:

> At Wed, 26 Aug 2020 08:18:49 -0400, Tom Lane [hidden email] wrote in
>
> > Kyotaro Horiguchi [hidden email] writes:
> >
> > > At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian [hidden email] 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 exceptions below.

>
>     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 wrong on 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
>


v1-0001-Fix-NaN-handling-of-some-geometric-operators-and-.patch (60K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: Strange behavior with polygon and NaN

Kyotaro Horiguchi-4
Hello, Georgios.

At Mon, 07 Sep 2020 12:46:50 +0000, [hidden email] wrote in

> ‐‐‐‐‐‐‐ Original Message ‐‐‐‐‐‐‐
> On Thursday, 27 August 2020 14:24, Kyotaro Horiguchi <[hidden email]> wrote:
>
> > At Wed, 26 Aug 2020 08:18:49 -0400, Tom Lane [hidden email] wrote in
> >
> > > Kyotaro Horiguchi [hidden email] writes:
> > >
> > > > At Tue, 25 Aug 2020 19:03:50 -0400, Bruce Momjian [hidden email] 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 exceptions below.
>
> >
> >     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 wrong on 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 <[hidden email]>
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)' &lt;-&gt; line '{-1,0,5}') is Infinity but (point
+       '(Infinity,Infinity)' &lt;-&gt; 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