pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Tom Lane <tgl@sss.pgh.pa.us>
To: Kyotaro Horiguchi <horikyota.ntt@gmail.com>
Cc: gkokolatos@pm.me
Cc: pgsql-hackers@lists.postgresql.org
Subject: Re: Strange behavior with polygon and NaN
Date: Sat, 21 Nov 2020 17:33:53 -0500
Message-ID: <1757392.1605998033@sss.pgh.pa.us> (raw)
In-Reply-To: <1495502.1605911206@sss.pgh.pa.us>
References: <2200966.1605036608@sss.pgh.pa.us>
	<20201113.153558.1784247402374030454.horikyota.ntt@gmail.com>
	<289049.1605284781@sss.pgh.pa.us>
	<20201116.151636.571392156451834232.horikyota.ntt@gmail.com>
	<1456736.1605905866@sss.pgh.pa.us>
	<1495502.1605911206@sss.pgh.pa.us>

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

			regards, tom lane

Attachments:

v7-0002-fix-line_closept_point.patch (text/x-diff, 3.6K) download diff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.c index c1dc511a1a..d9f577bd8b 100644 --- a/src/backend/utils/adt/geo_ops.c +++ b/src/backend/utils/adt/geo_ops.c @@ -2719,9 +2719,14 @@ lseg_interpt_line(Point *result, LSEG *lseg, LINE *line) *-------------------------------------------------------------------*/ /* - * If *result is not NULL, it is set to the intersection point of a - * perpendicular of the line through the point. Returns the distance - * of those two points. + * Determine the closest point on the given line to the given point. + * If result is not NULL, *result is set to the coordinates of that point. + * In any case, returns the distance from the point to the line. + * Returns NaN for any ill-defined value. + * + * NOTE: in some cases the distance is well defined (i.e., infinity) + * even though the specific closest point is not. Hence, if you care + * about whether the point is well-defined, check its coordinates for NaNs. */ static float8 line_closept_point(Point *result, LINE *line, Point *point) @@ -2729,17 +2734,30 @@ line_closept_point(Point *result, LINE *line, Point *point) Point closept; LINE tmp; + /* + * If it is unclear whether the point is on the line or not, then the + * results are ill-defined. This eliminates cases where any of the given + * coordinates are NaN, as well as cases where infinite coordinates give + * rise to Inf - Inf, 0 * Inf, etc. + */ + if (unlikely(isnan(float8_pl(float8_pl(float8_mul(line->A, point->x), + float8_mul(line->B, point->y)), + line->C)))) + { + if (result != NULL) + result->x = result->y = get_float8_nan(); + return get_float8_nan(); + } + /* * We drop a perpendicular to find the intersection point. Ordinarily we - * should always find it, but that can fail in the presence of NaN - * coordinates, and perhaps even from simple roundoff issues. + * should always find it, but perhaps roundoff issues could prevent that. */ line_construct(&tmp, point, line_invsl(line)); if (!line_interpt_line(&closept, &tmp, line)) { if (result != NULL) - *result = *point; - + result->x = result->y = get_float8_nan(); return get_float8_nan(); } @@ -2758,7 +2776,9 @@ close_pl(PG_FUNCTION_ARGS) result = (Point *) palloc(sizeof(Point)); - if (isnan(line_closept_point(result, line, pt))) + (void) line_closept_point(result, line, pt); + + if (unlikely(isnan(result->x) || isnan(result->y))) PG_RETURN_NULL(); PG_RETURN_POINT_P(result); diff --git a/src/test/regress/expected/geometry.out b/src/test/regress/expected/geometry.out index c4f853ae9f..6210075bc1 100644 --- a/src/test/regress/expected/geometry.out +++ b/src/test/regress/expected/geometry.out @@ -1070,9 +1070,9 @@ SELECT p.f1, l.s, p.f1 ## l.s FROM POINT_TBL p, LINE_TBL l; (1e+300,Infinity) | {0,-1,5} | (1e+300,5) (1e+300,Infinity) | {1,0,5} | (1e+300,Infinity) | {0,3,0} | (1e+300,0) - (1e+300,Infinity) | {1,-1,0} | (Infinity,NaN) - (1e+300,Infinity) | {-0.4,-1,-6} | (-Infinity,NaN) - (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (-Infinity,NaN) + (1e+300,Infinity) | {1,-1,0} | + (1e+300,Infinity) | {-0.4,-1,-6} | + (1e+300,Infinity) | {-0.000184615384615,-1,15.3846153846} | (1e+300,Infinity) | {3,NaN,5} | (1e+300,Infinity) | {NaN,NaN,NaN} | (1e+300,Infinity) | {0,-1,3} | (1e+300,3)

view thread (30+ messages)  latest in thread

Message-ID: <1757392.1605998033@sss.pgh.pa.us>
Permalink:  ../1757392.1605998033@sss.pgh.pa.us/
Also on:    postgresql.org/message-id/1757392.1605998033@sss.pgh.pa.us

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: tgl@sss.pgh.pa.us, horikyota.ntt@gmail.com, gkokolatos@pm.me, pgsql-hackers@lists.postgresql.org
  Subject: Re: Strange behavior with polygon and NaN
  In-Reply-To: <1757392.1605998033@sss.pgh.pa.us>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox