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