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) downloaddiff --git a/src/backend/utils/adt/geo_ops.c b/src/backend/utils/adt/geo_ops.cindex 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.outindex 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)
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