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

Commitc4c3400

Browse files
committed
Use the built-in float datatypes to implement geometric types
This patch makes the geometric operators and functions use the exportedfunction of the float4/float8 datatypes. The main reason of doing so isto check for underflow and overflow, and to handle NaNs consciously.The float datatypes consider NaNs values to be equal and greater thanall non-NaN values. This change considers NaNs equal only for equalityoperators. The placement operators, contains, overlaps, left/right ofetc. continue to return false when NaNs are involved. We don't needto worry about them being considered greater than any-NaN because therearen't any basic comparison operators like less/greater than for thegeometric datatypes.The changes may be summarised as:* Check for underflow, overflow and division by zero* Consider NaN values to be equal* Return NULL when the distance is NaN for all closest point operators* Favour not-NaN over NaN where it makes senseThe patch also replaces all occurrences of "double" as "float8". Theyare the same, but were used inconsistently in the same file.Author: Emre HasegeliReviewed-by: Kyotaro Horiguchi, Tomas VondraDiscussion:https://www.postgresql.org/message-id/CAE2gYzxF7-5djV6-cEvqQu-fNsnt%3DEqbOURx7ZDg%2BVv6ZMTWbg%40mail.gmail.com
1 parenta082aed commitc4c3400

File tree

4 files changed

+343
-305
lines changed

4 files changed

+343
-305
lines changed

‎src/backend/access/gist/gistproc.c

Lines changed: 48 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ rt_box_union(BOX *n, const BOX *a, const BOX *b)
5555
* Size of a BOX for penalty-calculation purposes.
5656
* The result can be +Infinity, but not NaN.
5757
*/
58-
staticdouble
58+
staticfloat8
5959
size_box(constBOX*box)
6060
{
6161
/*
@@ -76,20 +76,21 @@ size_box(const BOX *box)
7676
*/
7777
if (isnan(box->high.x)||isnan(box->high.y))
7878
returnget_float8_infinity();
79-
return (box->high.x-box->low.x)* (box->high.y-box->low.y);
79+
returnfloat8_mul(float8_mi(box->high.x,box->low.x),
80+
float8_mi(box->high.y,box->low.y));
8081
}
8182

8283
/*
8384
* Return amount by which the union of the two boxes is larger than
8485
* the original BOX's area. The result can be +Infinity, but not NaN.
8586
*/
86-
staticdouble
87+
staticfloat8
8788
box_penalty(constBOX*original,constBOX*new)
8889
{
8990
BOXunionbox;
9091

9192
rt_box_union(&unionbox,original,new);
92-
returnsize_box(&unionbox)-size_box(original);
93+
returnfloat8_mi(size_box(&unionbox),size_box(original));
9394
}
9495

9596
/*
@@ -263,7 +264,7 @@ typedef struct
263264
/* Index of entry in the initial array */
264265
intindex;
265266
/* Delta between penalties of entry insertion into different groups */
266-
doubledelta;
267+
float8delta;
267268
}CommonEntry;
268269

269270
/*
@@ -279,13 +280,13 @@ typedef struct
279280

280281
boolfirst;/* true if no split was selected yet */
281282

282-
doubleleftUpper;/* upper bound of left interval */
283-
doublerightLower;/* lower bound of right interval */
283+
float8leftUpper;/* upper bound of left interval */
284+
float8rightLower;/* lower bound of right interval */
284285

285286
float4ratio;
286287
float4overlap;
287288
intdim;/* axis of this split */
288-
doublerange;/* width of general MBR projection to the
289+
float8range;/* width of general MBR projection to the
289290
* selected axis */
290291
}ConsiderSplitContext;
291292

@@ -294,7 +295,7 @@ typedef struct
294295
*/
295296
typedefstruct
296297
{
297-
doublelower,
298+
float8lower,
298299
upper;
299300
}SplitInterval;
300301

@@ -304,7 +305,7 @@ typedef struct
304305
staticint
305306
interval_cmp_lower(constvoid*i1,constvoid*i2)
306307
{
307-
doublelower1= ((constSplitInterval*)i1)->lower,
308+
float8lower1= ((constSplitInterval*)i1)->lower,
308309
lower2= ((constSplitInterval*)i2)->lower;
309310

310311
returnfloat8_cmp_internal(lower1,lower2);
@@ -316,7 +317,7 @@ interval_cmp_lower(const void *i1, const void *i2)
316317
staticint
317318
interval_cmp_upper(constvoid*i1,constvoid*i2)
318319
{
319-
doubleupper1= ((constSplitInterval*)i1)->upper,
320+
float8upper1= ((constSplitInterval*)i1)->upper,
320321
upper2= ((constSplitInterval*)i2)->upper;
321322

322323
returnfloat8_cmp_internal(upper1,upper2);
@@ -339,14 +340,14 @@ non_negative(float val)
339340
*/
340341
staticinlinevoid
341342
g_box_consider_split(ConsiderSplitContext*context,intdimNum,
342-
doublerightLower,intminLeftCount,
343-
doubleleftUpper,intmaxLeftCount)
343+
float8rightLower,intminLeftCount,
344+
float8leftUpper,intmaxLeftCount)
344345
{
345346
intleftCount,
346347
rightCount;
347348
float4ratio,
348349
overlap;
349-
doublerange;
350+
float8range;
350351

351352
/*
352353
* Calculate entries distribution ratio assuming most uniform distribution
@@ -369,8 +370,7 @@ g_box_consider_split(ConsiderSplitContext *context, int dimNum,
369370
* Ratio of split - quotient between size of lesser group and total
370371
* entries count.
371372
*/
372-
ratio= ((float4)Min(leftCount,rightCount)) /
373-
((float4)context->entriesCount);
373+
ratio=float4_div(Min(leftCount,rightCount),context->entriesCount);
374374

375375
if (ratio>LIMIT_RATIO)
376376
{
@@ -384,11 +384,13 @@ g_box_consider_split(ConsiderSplitContext *context, int dimNum,
384384
* or less range with same overlap.
385385
*/
386386
if (dimNum==0)
387-
range=context->boundingBox.high.x-context->boundingBox.low.x;
387+
range=float8_mi(context->boundingBox.high.x,
388+
context->boundingBox.low.x);
388389
else
389-
range=context->boundingBox.high.y-context->boundingBox.low.y;
390+
range=float8_mi(context->boundingBox.high.y,
391+
context->boundingBox.low.y);
390392

391-
overlap=(leftUpper-rightLower) /range;
393+
overlap=float8_div(float8_mi(leftUpper,rightLower),range);
392394

393395
/* If there is no previous selection, select this */
394396
if (context->first)
@@ -444,20 +446,14 @@ g_box_consider_split(ConsiderSplitContext *context, int dimNum,
444446

445447
/*
446448
* Compare common entries by their deltas.
447-
* (We assume the deltas can't be NaN.)
448449
*/
449450
staticint
450451
common_entry_cmp(constvoid*i1,constvoid*i2)
451452
{
452-
doubledelta1= ((constCommonEntry*)i1)->delta,
453+
float8delta1= ((constCommonEntry*)i1)->delta,
453454
delta2= ((constCommonEntry*)i2)->delta;
454455

455-
if (delta1<delta2)
456-
return-1;
457-
elseif (delta1>delta2)
458-
return1;
459-
else
460-
return0;
456+
returnfloat8_cmp_internal(delta1,delta2);
461457
}
462458

463459
/*
@@ -531,7 +527,7 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
531527
context.first= true;/* nothing selected yet */
532528
for (dim=0;dim<2;dim++)
533529
{
534-
doubleleftUpper,
530+
float8leftUpper,
535531
rightLower;
536532
inti1,
537533
i2;
@@ -728,7 +724,7 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
728724
*/
729725
for (i=FirstOffsetNumber;i <=maxoff;i=OffsetNumberNext(i))
730726
{
731-
doublelower,
727+
float8lower,
732728
upper;
733729

734730
/*
@@ -783,7 +779,7 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
783779
* Calculate minimum number of entries that must be placed in both
784780
* groups, to reach LIMIT_RATIO.
785781
*/
786-
intm=ceil(LIMIT_RATIO*(double)nentries);
782+
intm=ceil(LIMIT_RATIO*nentries);
787783

788784
/*
789785
* Calculate delta between penalties of join "common entries" to
@@ -792,8 +788,8 @@ gist_box_picksplit(PG_FUNCTION_ARGS)
792788
for (i=0;i<commonEntriesCount;i++)
793789
{
794790
box=DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);
795-
commonEntries[i].delta=Abs(box_penalty(leftBox,box)-
796-
box_penalty(rightBox,box));
791+
commonEntries[i].delta=Abs(float8_mi(box_penalty(leftBox,box),
792+
box_penalty(rightBox,box)));
797793
}
798794

799795
/*
@@ -1107,10 +1103,10 @@ gist_circle_compress(PG_FUNCTION_ARGS)
11071103
BOX*r;
11081104

11091105
r= (BOX*)palloc(sizeof(BOX));
1110-
r->high.x=in->center.x+in->radius;
1111-
r->low.x=in->center.x-in->radius;
1112-
r->high.y=in->center.y+in->radius;
1113-
r->low.y=in->center.y-in->radius;
1106+
r->high.x=float8_pl(in->center.x,in->radius);
1107+
r->low.x=float8_mi(in->center.x,in->radius);
1108+
r->high.y=float8_pl(in->center.y,in->radius);
1109+
r->low.y=float8_mi(in->center.y,in->radius);
11141110

11151111
retval= (GISTENTRY*)palloc(sizeof(GISTENTRY));
11161112
gistentryinit(*retval,PointerGetDatum(r),
@@ -1148,10 +1144,10 @@ gist_circle_consistent(PG_FUNCTION_ARGS)
11481144
* rtree_internal_consistent even at leaf nodes. (This works in part
11491145
* because the index entries are bounding boxes not circles.)
11501146
*/
1151-
bbox.high.x=query->center.x+query->radius;
1152-
bbox.low.x=query->center.x-query->radius;
1153-
bbox.high.y=query->center.y+query->radius;
1154-
bbox.low.y=query->center.y-query->radius;
1147+
bbox.high.x=float8_pl(query->center.x,query->radius);
1148+
bbox.low.x=float8_mi(query->center.x,query->radius);
1149+
bbox.high.y=float8_pl(query->center.y,query->radius);
1150+
bbox.low.y=float8_mi(query->center.y,query->radius);
11551151

11561152
result=rtree_internal_consistent(DatumGetBoxP(entry->key),
11571153
&bbox,strategy);
@@ -1216,10 +1212,10 @@ gist_point_fetch(PG_FUNCTION_ARGS)
12161212
DatumGetFloat8(DirectFunctionCall2(point_distance, \
12171213
PointPGetDatum(p1), PointPGetDatum(p2)))
12181214

1219-
staticdouble
1215+
staticfloat8
12201216
computeDistance(boolisLeaf,BOX*box,Point*point)
12211217
{
1222-
doubleresult=0.0;
1218+
float8result=0.0;
12231219

12241220
if (isLeaf)
12251221
{
@@ -1237,9 +1233,9 @@ computeDistance(bool isLeaf, BOX *box, Point *point)
12371233
/* point is over or below box */
12381234
Assert(box->low.y <=box->high.y);
12391235
if (point->y>box->high.y)
1240-
result=point->y-box->high.y;
1236+
result=float8_mi(point->y,box->high.y);
12411237
elseif (point->y<box->low.y)
1242-
result=box->low.y-point->y;
1238+
result=float8_mi(box->low.y,point->y);
12431239
else
12441240
elog(ERROR,"inconsistent point values");
12451241
}
@@ -1248,17 +1244,17 @@ computeDistance(bool isLeaf, BOX *box, Point *point)
12481244
/* point is to left or right of box */
12491245
Assert(box->low.x <=box->high.x);
12501246
if (point->x>box->high.x)
1251-
result=point->x-box->high.x;
1247+
result=float8_mi(point->x,box->high.x);
12521248
elseif (point->x<box->low.x)
1253-
result=box->low.x-point->x;
1249+
result=float8_mi(box->low.x,point->x);
12541250
else
12551251
elog(ERROR,"inconsistent point values");
12561252
}
12571253
else
12581254
{
12591255
/* closest point will be a vertex */
12601256
Pointp;
1261-
doublesubresult;
1257+
float8subresult;
12621258

12631259
result=point_point_distance(point,&box->low);
12641260

@@ -1449,7 +1445,7 @@ gist_point_distance(PG_FUNCTION_ARGS)
14491445
{
14501446
GISTENTRY*entry= (GISTENTRY*)PG_GETARG_POINTER(0);
14511447
StrategyNumberstrategy= (StrategyNumber)PG_GETARG_UINT16(2);
1452-
doubledistance;
1448+
float8distance;
14531449
StrategyNumberstrategyGroup=strategy /GeoStrategyNumberOffset;
14541450

14551451
switch (strategyGroup)
@@ -1478,11 +1474,11 @@ gist_point_distance(PG_FUNCTION_ARGS)
14781474
* This is a lower bound estimate of distance from point to indexed geometric
14791475
* type.
14801476
*/
1481-
staticdouble
1477+
staticfloat8
14821478
gist_bbox_distance(GISTENTRY*entry,Datumquery,
14831479
StrategyNumberstrategy,bool*recheck)
14841480
{
1485-
doubledistance;
1481+
float8distance;
14861482
StrategyNumberstrategyGroup=strategy /GeoStrategyNumberOffset;
14871483

14881484
/* Bounding box distance is always inexact. */
@@ -1512,7 +1508,7 @@ gist_circle_distance(PG_FUNCTION_ARGS)
15121508

15131509
/* Oid subtype = PG_GETARG_OID(3); */
15141510
bool*recheck= (bool*)PG_GETARG_POINTER(4);
1515-
doubledistance;
1511+
float8distance;
15161512

15171513
distance=gist_bbox_distance(entry,query,strategy,recheck);
15181514

@@ -1528,7 +1524,7 @@ gist_poly_distance(PG_FUNCTION_ARGS)
15281524

15291525
/* Oid subtype = PG_GETARG_OID(3); */
15301526
bool*recheck= (bool*)PG_GETARG_POINTER(4);
1531-
doubledistance;
1527+
float8distance;
15321528

15331529
distance=gist_bbox_distance(entry,query,strategy,recheck);
15341530

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp