Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit8597a48

Browse files
committed
Fix FPeq() and friends to get the right answers for infinities.
"FPeq(infinity, infinity)" returned false, on account of getting NaNwhen it subtracts the two inputs. Fix that by adding a separatecheck for exact equality.FPle() and FPge() similarly got the wrong answer for two like-signedinfinities. In those cases, we can just rearrange the comparisonsto avoid potentially subtracting infinities.While the sibling functions FPne() etc accidentally gave the rightanswers even with the internal NaN results, it seems best to makesimilar adjustments to them to avoid depending on this.FPeq() has to be converted to an inline function to avoid doubleevaluations of its arguments, and I did the same for the othersjust for consistency.In passing, make the handling of NaN cases in line_eq() andpoint_eq_point() simpler and easier to reason about, and perhapsfaster.This results in just one visible regression test change: slope()now gives DBL_MAX for two inputs of (inf,1e300), which is consistentwith what it does for (1e300,inf), so that seems like a bug fix.Discussion:https://postgr.es/m/CAGf+fX70rWFOk5cd00uMfa__0yP+vtQg5ck7c2Onb-Yczp0URA@mail.gmail.com
1 parenta45272b commit8597a48

File tree

3 files changed

+72
-26
lines changed

3 files changed

+72
-26
lines changed

‎src/backend/utils/adt/geo_ops.c

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,9 +1155,6 @@ line_horizontal(PG_FUNCTION_ARGS)
11551155

11561156
/*
11571157
* Check whether the two lines are the same
1158-
*
1159-
* We consider NaNs values to be equal to each other to let those lines
1160-
* to be found.
11611158
*/
11621159
Datum
11631160
line_eq(PG_FUNCTION_ARGS)
@@ -1166,21 +1163,28 @@ line_eq(PG_FUNCTION_ARGS)
11661163
LINE*l2=PG_GETARG_LINE_P(1);
11671164
float8ratio;
11681165

1169-
if (!FPzero(l2->A)&& !isnan(l2->A))
1166+
/* If any NaNs are involved, insist on exact equality */
1167+
if (unlikely(isnan(l1->A)||isnan(l1->B)||isnan(l1->C)||
1168+
isnan(l2->A)||isnan(l2->B)||isnan(l2->C)))
1169+
{
1170+
PG_RETURN_BOOL(float8_eq(l1->A,l2->A)&&
1171+
float8_eq(l1->B,l2->B)&&
1172+
float8_eq(l1->C,l2->C));
1173+
}
1174+
1175+
/* Otherwise, lines whose parameters are proportional are the same */
1176+
if (!FPzero(l2->A))
11701177
ratio=float8_div(l1->A,l2->A);
1171-
elseif (!FPzero(l2->B)&& !isnan(l2->B))
1178+
elseif (!FPzero(l2->B))
11721179
ratio=float8_div(l1->B,l2->B);
1173-
elseif (!FPzero(l2->C)&& !isnan(l2->C))
1180+
elseif (!FPzero(l2->C))
11741181
ratio=float8_div(l1->C,l2->C);
11751182
else
11761183
ratio=1.0;
11771184

1178-
PG_RETURN_BOOL((FPeq(l1->A,float8_mul(ratio,l2->A))&&
1179-
FPeq(l1->B,float8_mul(ratio,l2->B))&&
1180-
FPeq(l1->C,float8_mul(ratio,l2->C)))||
1181-
(float8_eq(l1->A,l2->A)&&
1182-
float8_eq(l1->B,l2->B)&&
1183-
float8_eq(l1->C,l2->C)));
1185+
PG_RETURN_BOOL(FPeq(l1->A,float8_mul(ratio,l2->A))&&
1186+
FPeq(l1->B,float8_mul(ratio,l2->B))&&
1187+
FPeq(l1->C,float8_mul(ratio,l2->C)));
11841188
}
11851189

11861190

@@ -1930,15 +1934,16 @@ point_ne(PG_FUNCTION_ARGS)
19301934

19311935
/*
19321936
* Check whether the two points are the same
1933-
*
1934-
* We consider NaNs coordinates to be equal to each other to let those points
1935-
* to be found.
19361937
*/
19371938
staticinlinebool
19381939
point_eq_point(Point*pt1,Point*pt2)
19391940
{
1940-
return ((FPeq(pt1->x,pt2->x)&&FPeq(pt1->y,pt2->y))||
1941-
(float8_eq(pt1->x,pt2->x)&&float8_eq(pt1->y,pt2->y)));
1941+
/* If any NaNs are involved, insist on exact equality */
1942+
if (unlikely(isnan(pt1->x)||isnan(pt1->y)||
1943+
isnan(pt2->x)||isnan(pt2->y)))
1944+
return (float8_eq(pt1->x,pt2->x)&&float8_eq(pt1->y,pt2->y));
1945+
1946+
return (FPeq(pt1->x,pt2->x)&&FPeq(pt1->y,pt2->y));
19421947
}
19431948

19441949

‎src/include/utils/geo_decls.h

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,66 @@
1818
#ifndefGEO_DECLS_H
1919
#defineGEO_DECLS_H
2020

21+
#include<math.h>
22+
2123
#include"fmgr.h"
2224

2325
/*--------------------------------------------------------------------
2426
* Useful floating point utilities and constants.
25-
*-------------------------------------------------------------------
27+
*--------------------------------------------------------------------
28+
*
29+
* "Fuzzy" floating-point comparisons: values within EPSILON of each other
30+
* are considered equal. Beware of normal reasoning about the behavior of
31+
* these comparisons, since for example FPeq does not behave transitively.
2632
*
27-
* XXX: They are not NaN-aware.
33+
* Note that these functions are not NaN-aware and will give FALSE for
34+
* any case involving NaN inputs.
35+
*
36+
* Also note that these will give sane answers for infinite inputs,
37+
* where it's important to avoid computing Inf minus Inf; we do so
38+
* by eliminating equality cases before subtracting.
2839
*/
2940

3041
#defineEPSILON1.0E-06
3142

3243
#ifdefEPSILON
3344
#defineFPzero(A)(fabs(A) <= EPSILON)
34-
#defineFPeq(A,B)(fabs((A) - (B)) <= EPSILON)
35-
#defineFPne(A,B)(fabs((A) - (B)) > EPSILON)
36-
#defineFPlt(A,B)((B) - (A) > EPSILON)
37-
#defineFPle(A,B)((A) - (B) <= EPSILON)
38-
#defineFPgt(A,B)((A) - (B) > EPSILON)
39-
#defineFPge(A,B)((B) - (A) <= EPSILON)
45+
46+
staticinlinebool
47+
FPeq(doubleA,doubleB)
48+
{
49+
returnA==B||fabs(A-B) <=EPSILON;
50+
}
51+
52+
staticinlinebool
53+
FPne(doubleA,doubleB)
54+
{
55+
returnA!=B&&fabs(A-B)>EPSILON;
56+
}
57+
58+
staticinlinebool
59+
FPlt(doubleA,doubleB)
60+
{
61+
returnA+EPSILON<B;
62+
}
63+
64+
staticinlinebool
65+
FPle(doubleA,doubleB)
66+
{
67+
returnA <=B+EPSILON;
68+
}
69+
70+
staticinlinebool
71+
FPgt(doubleA,doubleB)
72+
{
73+
returnA>B+EPSILON;
74+
}
75+
76+
staticinlinebool
77+
FPge(doubleA,doubleB)
78+
{
79+
returnA+EPSILON >=B;
80+
}
4081
#else
4182
#defineFPzero(A)((A) == 0)
4283
#defineFPeq(A,B)((A) == (B))

‎src/test/regress/expected/geometry.out

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ SELECT p1.f1, p2.f1, slope(p1.f1, p2.f1) FROM POINT_TBL p1, POINT_TBL p2;
190190
(Infinity,1e+300) | (-5,-12) | 0
191191
(Infinity,1e+300) | (1e-300,-1e-300) | 0
192192
(Infinity,1e+300) | (1e+300,Infinity) | NaN
193-
(Infinity,1e+300) | (Infinity,1e+300) | 0
193+
(Infinity,1e+300) | (Infinity,1e+300) |1.79769313486e+308
194194
(Infinity,1e+300) | (NaN,NaN) | NaN
195195
(Infinity,1e+300) | (10,10) | 0
196196
(NaN,NaN) | (0,0) | NaN

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp