PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
gistproc.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/gist.h"
#include "access/stratnum.h"
#include "utils/float.h"
#include "utils/fmgrprotos.h"
#include "utils/geo_decls.h"
#include "utils/sortsupport.h"
Include dependency graph for gistproc.c:

Go to the source code of this file.

Data Structures

struct  CommonEntry
 
struct  ConsiderSplitContext
 
struct  SplitInterval
 

Macros

#define LIMIT_RATIO   0.3
 
#define PLACE_LEFT(box, off)
 
#define PLACE_RIGHT(box, off)
 
#define point_point_distance(p1, p2)
 
#define GeoStrategyNumberOffset   20
 
#define PointStrategyNumberGroup   0
 
#define BoxStrategyNumberGroup   1
 
#define PolygonStrategyNumberGroup   2
 
#define CircleStrategyNumberGroup   3
 

Functions

static bool gist_box_leaf_consistent (BOX *key, BOX *query, StrategyNumber strategy)
 
static bool rtree_internal_consistent (BOX *key, BOX *query, StrategyNumber strategy)
 
static uint64 point_zorder_internal (float4 x, float4 y)
 
static uint64 part_bits32_by2 (uint32 x)
 
static uint32 ieee_float32_to_uint32 (float f)
 
static int gist_bbox_zorder_cmp (Datum a, Datum b, SortSupport ssup)
 
static Datum gist_bbox_zorder_abbrev_convert (Datum original, SortSupport ssup)
 
static bool gist_bbox_zorder_abbrev_abort (int memtupcount, SortSupport ssup)
 
static void rt_box_union (BOX *n, const BOX *a, const BOX *b)
 
static float8 size_box (const BOX *box)
 
static float8 box_penalty (const BOX *original, const BOX *new)
 
Datum gist_box_consistent (PG_FUNCTION_ARGS)
 
static void adjustBox (BOX *b, const BOX *addon)
 
Datum gist_box_union (PG_FUNCTION_ARGS)
 
Datum gist_box_penalty (PG_FUNCTION_ARGS)
 
static void fallbackSplit (GistEntryVector *entryvec, GIST_SPLITVEC *v)
 
static int interval_cmp_lower (const void *i1, const void *i2)
 
static int interval_cmp_upper (const void *i1, const void *i2)
 
static float non_negative (float val)
 
static void g_box_consider_split (ConsiderSplitContext *context, int dimNum, float8 rightLower, int minLeftCount, float8 leftUpper, int maxLeftCount)
 
static int common_entry_cmp (const void *i1, const void *i2)
 
Datum gist_box_picksplit (PG_FUNCTION_ARGS)
 
Datum gist_box_same (PG_FUNCTION_ARGS)
 
Datum gist_poly_compress (PG_FUNCTION_ARGS)
 
Datum gist_poly_consistent (PG_FUNCTION_ARGS)
 
Datum gist_circle_compress (PG_FUNCTION_ARGS)
 
Datum gist_circle_consistent (PG_FUNCTION_ARGS)
 
Datum gist_point_compress (PG_FUNCTION_ARGS)
 
Datum gist_point_fetch (PG_FUNCTION_ARGS)
 
static float8 computeDistance (bool isLeaf, BOX *box, Point *point)
 
static bool gist_point_consistent_internal (StrategyNumber strategy, bool isLeaf, BOX *key, Point *query)
 
Datum gist_point_consistent (PG_FUNCTION_ARGS)
 
Datum gist_point_distance (PG_FUNCTION_ARGS)
 
static float8 gist_bbox_distance (GISTENTRY *entry, Datum query, StrategyNumber strategy)
 
Datum gist_box_distance (PG_FUNCTION_ARGS)
 
Datum gist_circle_distance (PG_FUNCTION_ARGS)
 
Datum gist_poly_distance (PG_FUNCTION_ARGS)
 
Datum gist_point_sortsupport (PG_FUNCTION_ARGS)
 

Macro Definition Documentation

◆ BoxStrategyNumberGroup

#define BoxStrategyNumberGroup   1

Definition at line 1332 of file gistproc.c.

◆ CircleStrategyNumberGroup

#define CircleStrategyNumberGroup   3

Definition at line 1334 of file gistproc.c.

◆ GeoStrategyNumberOffset

#define GeoStrategyNumberOffset   20

Definition at line 1330 of file gistproc.c.

◆ LIMIT_RATIO

#define LIMIT_RATIO   0.3

Definition at line 44 of file gistproc.c.

◆ PLACE_LEFT

#define PLACE_LEFT (   box,
  off 
)
Value:
do { \
if (v->spl_nleft > 0) \
adjustBox(leftBox, box); \
else \
*leftBox = *(box); \
v->spl_left[v->spl_nleft++] = off; \
} while(0)

◆ PLACE_RIGHT

#define PLACE_RIGHT (   box,
  off 
)
Value:
do { \
if (v->spl_nright > 0) \
adjustBox(rightBox, box); \
else \
*rightBox = *(box); \
v->spl_right[v->spl_nright++] = off; \
} while(0)

◆ point_point_distance

#define point_point_distance (   p1,
  p2 
)
Value:
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
static Datum PointPGetDatum(const Point *X)
Definition: geo_decls.h:181
Datum point_distance(PG_FUNCTION_ARGS)
Definition: geo_ops.c:1993
static float8 DatumGetFloat8(Datum X)
Definition: postgres.h:499

Definition at line 1216 of file gistproc.c.

◆ PointStrategyNumberGroup

#define PointStrategyNumberGroup   0

Definition at line 1331 of file gistproc.c.

◆ PolygonStrategyNumberGroup

#define PolygonStrategyNumberGroup   2

Definition at line 1333 of file gistproc.c.

Function Documentation

◆ adjustBox()

static void adjustBox ( BOX b,
const BOX addon 
)
static

Definition at line 146 of file gistproc.c.

147{
148 if (float8_lt(b->high.x, addon->high.x))
149 b->high.x = addon->high.x;
150 if (float8_gt(b->low.x, addon->low.x))
151 b->low.x = addon->low.x;
152 if (float8_lt(b->high.y, addon->high.y))
153 b->high.y = addon->high.y;
154 if (float8_gt(b->low.y, addon->low.y))
155 b->low.y = addon->low.y;
156}
static bool float8_lt(const float8 val1, const float8 val2)
Definition: float.h:292
static bool float8_gt(const float8 val1, const float8 val2)
Definition: float.h:316
int b
Definition: isn.c:69
Point low
Definition: geo_decls.h:143
Point high
Definition: geo_decls.h:142
float8 y
Definition: geo_decls.h:99
float8 x
Definition: geo_decls.h:98

References b, float8_gt(), float8_lt(), BOX::high, BOX::low, Point::x, and Point::y.

Referenced by fallbackSplit(), gist_box_picksplit(), and gist_box_union().

◆ box_penalty()

static float8 box_penalty ( const BOX original,
const BOX new 
)
static

Definition at line 97 of file gistproc.c.

98{
99 BOX unionbox;
100
101 rt_box_union(&unionbox, original, new);
102 return float8_mi(size_box(&unionbox), size_box(original));
103}
static float8 float8_mi(const float8 val1, const float8 val2)
Definition: float.h:182
static void rt_box_union(BOX *n, const BOX *a, const BOX *b)
Definition: gistproc.c:55
static float8 size_box(const BOX *box)
Definition: gistproc.c:68
Definition: geo_decls.h:141

References float8_mi(), rt_box_union(), and size_box().

Referenced by gist_box_penalty(), and gist_box_picksplit().

◆ common_entry_cmp()

static int common_entry_cmp ( const void *  i1,
const void *  i2 
)
static

Definition at line 460 of file gistproc.c.

461{
462 float8 delta1 = ((const CommonEntry *) i1)->delta,
463 delta2 = ((const CommonEntry *) i2)->delta;
464
465 return float8_cmp_internal(delta1, delta2);
466}
double float8
Definition: c.h:587
int float8_cmp_internal(float8 a, float8 b)
Definition: float.c:910

References float8_cmp_internal().

Referenced by gist_box_picksplit().

◆ computeDistance()

static float8 computeDistance ( bool  isLeaf,
BOX box,
Point point 
)
static

Definition at line 1221 of file gistproc.c.

1222{
1223 float8 result = 0.0;
1224
1225 if (isLeaf)
1226 {
1227 /* simple point to point distance */
1228 result = point_point_distance(point, &box->low);
1229 }
1230 else if (point->x <= box->high.x && point->x >= box->low.x &&
1231 point->y <= box->high.y && point->y >= box->low.y)
1232 {
1233 /* point inside the box */
1234 result = 0.0;
1235 }
1236 else if (point->x <= box->high.x && point->x >= box->low.x)
1237 {
1238 /* point is over or below box */
1239 Assert(box->low.y <= box->high.y);
1240 if (point->y > box->high.y)
1241 result = float8_mi(point->y, box->high.y);
1242 else if (point->y < box->low.y)
1243 result = float8_mi(box->low.y, point->y);
1244 else
1245 elog(ERROR, "inconsistent point values");
1246 }
1247 else if (point->y <= box->high.y && point->y >= box->low.y)
1248 {
1249 /* point is to left or right of box */
1250 Assert(box->low.x <= box->high.x);
1251 if (point->x > box->high.x)
1252 result = float8_mi(point->x, box->high.x);
1253 else if (point->x < box->low.x)
1254 result = float8_mi(box->low.x, point->x);
1255 else
1256 elog(ERROR, "inconsistent point values");
1257 }
1258 else
1259 {
1260 /* closest point will be a vertex */
1261 Point p;
1262 float8 subresult;
1263
1264 result = point_point_distance(point, &box->low);
1265
1266 subresult = point_point_distance(point, &box->high);
1267 if (result > subresult)
1268 result = subresult;
1269
1270 p.x = box->low.x;
1271 p.y = box->high.y;
1272 subresult = point_point_distance(point, &p);
1273 if (result > subresult)
1274 result = subresult;
1275
1276 p.x = box->high.x;
1277 p.y = box->low.y;
1278 subresult = point_point_distance(point, &p);
1279 if (result > subresult)
1280 result = subresult;
1281 }
1282
1283 return result;
1284}
#define Assert(condition)
Definition: c.h:815
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define point_point_distance(p1, p2)
Definition: gistproc.c:1216

References Assert, elog, ERROR, float8_mi(), BOX::high, BOX::low, point_point_distance, Point::x, and Point::y.

Referenced by gist_bbox_distance(), and gist_point_distance().

◆ fallbackSplit()

static void fallbackSplit ( GistEntryVector entryvec,
GIST_SPLITVEC v 
)
static

Definition at line 216 of file gistproc.c.

217{
219 maxoff;
220 BOX *unionL = NULL,
221 *unionR = NULL;
222 int nbytes;
223
224 maxoff = entryvec->n - 1;
225
226 nbytes = (maxoff + 2) * sizeof(OffsetNumber);
227 v->spl_left = (OffsetNumber *) palloc(nbytes);
228 v->spl_right = (OffsetNumber *) palloc(nbytes);
229 v->spl_nleft = v->spl_nright = 0;
230
231 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
232 {
233 BOX *cur = DatumGetBoxP(entryvec->vector[i].key);
234
235 if (i <= (maxoff - FirstOffsetNumber + 1) / 2)
236 {
237 v->spl_left[v->spl_nleft] = i;
238 if (unionL == NULL)
239 {
240 unionL = (BOX *) palloc(sizeof(BOX));
241 *unionL = *cur;
242 }
243 else
244 adjustBox(unionL, cur);
245
246 v->spl_nleft++;
247 }
248 else
249 {
250 v->spl_right[v->spl_nright] = i;
251 if (unionR == NULL)
252 {
253 unionR = (BOX *) palloc(sizeof(BOX));
254 *unionR = *cur;
255 }
256 else
257 adjustBox(unionR, cur);
258
259 v->spl_nright++;
260 }
261 }
262
263 v->spl_ldatum = BoxPGetDatum(unionL);
264 v->spl_rdatum = BoxPGetDatum(unionR);
265}
struct cursor * cur
Definition: ecpg.c:29
static BOX * DatumGetBoxP(Datum X)
Definition: geo_decls.h:234
static Datum BoxPGetDatum(const BOX *X)
Definition: geo_decls.h:239
static void adjustBox(BOX *b, const BOX *addon)
Definition: gistproc.c:146
int i
Definition: isn.c:72
void * palloc(Size size)
Definition: mcxt.c:1317
#define OffsetNumberNext(offsetNumber)
Definition: off.h:52
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
Datum key
Definition: gist.h:161
int spl_nleft
Definition: gist.h:144
OffsetNumber * spl_right
Definition: gist.h:148
Datum spl_ldatum
Definition: gist.h:145
Datum spl_rdatum
Definition: gist.h:150
int spl_nright
Definition: gist.h:149
OffsetNumber * spl_left
Definition: gist.h:143
GISTENTRY vector[FLEXIBLE_ARRAY_MEMBER]
Definition: gist.h:237
int32 n
Definition: gist.h:236

References adjustBox(), BoxPGetDatum(), cur, DatumGetBoxP(), FirstOffsetNumber, i, GISTENTRY::key, GistEntryVector::n, OffsetNumberNext, palloc(), GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, and GistEntryVector::vector.

Referenced by gist_box_picksplit().

◆ g_box_consider_split()

static void g_box_consider_split ( ConsiderSplitContext context,
int  dimNum,
float8  rightLower,
int  minLeftCount,
float8  leftUpper,
int  maxLeftCount 
)
inlinestatic

Definition at line 351 of file gistproc.c.

354{
355 int leftCount,
356 rightCount;
357 float4 ratio,
358 overlap;
360
361 /*
362 * Calculate entries distribution ratio assuming most uniform distribution
363 * of common entries.
364 */
365 if (minLeftCount >= (context->entriesCount + 1) / 2)
366 {
367 leftCount = minLeftCount;
368 }
369 else
370 {
371 if (maxLeftCount <= context->entriesCount / 2)
372 leftCount = maxLeftCount;
373 else
374 leftCount = context->entriesCount / 2;
375 }
376 rightCount = context->entriesCount - leftCount;
377
378 /*
379 * Ratio of split - quotient between size of lesser group and total
380 * entries count.
381 */
382 ratio = float4_div(Min(leftCount, rightCount), context->entriesCount);
383
384 if (ratio > LIMIT_RATIO)
385 {
386 bool selectthis = false;
387
388 /*
389 * The ratio is acceptable, so compare current split with previously
390 * selected one. Between splits of one dimension we search for minimal
391 * overlap (allowing negative values) and minimal ration (between same
392 * overlaps. We switch dimension if find less overlap (non-negative)
393 * or less range with same overlap.
394 */
395 if (dimNum == 0)
396 range = float8_mi(context->boundingBox.high.x,
397 context->boundingBox.low.x);
398 else
399 range = float8_mi(context->boundingBox.high.y,
400 context->boundingBox.low.y);
401
402 overlap = float8_div(float8_mi(leftUpper, rightLower), range);
403
404 /* If there is no previous selection, select this */
405 if (context->first)
406 selectthis = true;
407 else if (context->dim == dimNum)
408 {
409 /*
410 * Within the same dimension, choose the new split if it has a
411 * smaller overlap, or same overlap but better ratio.
412 */
413 if (overlap < context->overlap ||
414 (overlap == context->overlap && ratio > context->ratio))
415 selectthis = true;
416 }
417 else
418 {
419 /*
420 * Across dimensions, choose the new split if it has a smaller
421 * *non-negative* overlap, or same *non-negative* overlap but
422 * bigger range. This condition differs from the one described in
423 * the article. On the datasets where leaf MBRs don't overlap
424 * themselves, non-overlapping splits (i.e. splits which have zero
425 * *non-negative* overlap) are frequently possible. In this case
426 * splits tends to be along one dimension, because most distant
427 * non-overlapping splits (i.e. having lowest negative overlap)
428 * appears to be in the same dimension as in the previous split.
429 * Therefore MBRs appear to be very prolonged along another
430 * dimension, which leads to bad search performance. Using range
431 * as the second split criteria makes MBRs more quadratic. Using
432 * *non-negative* overlap instead of overlap as the first split
433 * criteria gives to range criteria a chance to matter, because
434 * non-overlapping splits are equivalent in this criteria.
435 */
436 if (non_negative(overlap) < non_negative(context->overlap) ||
437 (range > context->range &&
438 non_negative(overlap) <= non_negative(context->overlap)))
439 selectthis = true;
440 }
441
442 if (selectthis)
443 {
444 /* save information about selected split */
445 context->first = false;
446 context->ratio = ratio;
447 context->range = range;
448 context->overlap = overlap;
449 context->rightLower = rightLower;
450 context->leftUpper = leftUpper;
451 context->dim = dimNum;
452 }
453 }
454}
#define Min(x, y)
Definition: c.h:961
float float4
Definition: c.h:586
static float4 float4_div(const float4 val1, const float4 val2)
Definition: float.h:222
static float8 float8_div(const float8 val1, const float8 val2)
Definition: float.h:238
#define LIMIT_RATIO
Definition: gistproc.c:44
static float non_negative(float val)
Definition: gistproc.c:339
static struct cvec * range(struct vars *v, chr a, chr b, int cases)
Definition: regc_locale.c:412

References ConsiderSplitContext::boundingBox, ConsiderSplitContext::dim, ConsiderSplitContext::entriesCount, ConsiderSplitContext::first, float4_div(), float8_div(), float8_mi(), BOX::high, ConsiderSplitContext::leftUpper, LIMIT_RATIO, BOX::low, Min, non_negative(), ConsiderSplitContext::overlap, ConsiderSplitContext::range, range(), ConsiderSplitContext::ratio, ConsiderSplitContext::rightLower, Point::x, and Point::y.

Referenced by gist_box_picksplit().

◆ gist_bbox_distance()

static float8 gist_bbox_distance ( GISTENTRY entry,
Datum  query,
StrategyNumber  strategy 
)
static

Definition at line 1479 of file gistproc.c.

1480{
1481 float8 distance;
1482 StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1483
1484 switch (strategyGroup)
1485 {
1487 distance = computeDistance(false,
1488 DatumGetBoxP(entry->key),
1489 DatumGetPointP(query));
1490 break;
1491 default:
1492 elog(ERROR, "unrecognized strategy number: %d", strategy);
1493 distance = 0.0; /* keep compiler quiet */
1494 }
1495
1496 return distance;
1497}
static Point * DatumGetPointP(Datum X)
Definition: geo_decls.h:176
#define GeoStrategyNumberOffset
Definition: gistproc.c:1330
#define PointStrategyNumberGroup
Definition: gistproc.c:1331
static float8 computeDistance(bool isLeaf, BOX *box, Point *point)
Definition: gistproc.c:1221
uint16 StrategyNumber
Definition: stratnum.h:22

References computeDistance(), DatumGetBoxP(), DatumGetPointP(), elog, ERROR, GeoStrategyNumberOffset, GISTENTRY::key, and PointStrategyNumberGroup.

Referenced by gist_box_distance(), gist_circle_distance(), and gist_poly_distance().

◆ gist_bbox_zorder_abbrev_abort()

static bool gist_bbox_zorder_abbrev_abort ( int  memtupcount,
SortSupport  ssup 
)
static

Definition at line 1736 of file gistproc.c.

1737{
1738 return false;
1739}

Referenced by gist_point_sortsupport().

◆ gist_bbox_zorder_abbrev_convert()

static Datum gist_bbox_zorder_abbrev_convert ( Datum  original,
SortSupport  ssup 
)
static

Definition at line 1714 of file gistproc.c.

1715{
1716 Point *p = &(DatumGetBoxP(original)->low);
1717 uint64 z;
1718
1719 z = point_zorder_internal(p->x, p->y);
1720
1721#if SIZEOF_DATUM == 8
1722 return (Datum) z;
1723#else
1724 return (Datum) (z >> 32);
1725#endif
1726}
uint64_t uint64
Definition: c.h:489
static uint64 point_zorder_internal(float4 x, float4 y)
Definition: gistproc.c:1575
uintptr_t Datum
Definition: postgres.h:69

References DatumGetBoxP(), BOX::low, point_zorder_internal(), Point::x, and Point::y.

Referenced by gist_point_sortsupport().

◆ gist_bbox_zorder_cmp()

static int gist_bbox_zorder_cmp ( Datum  a,
Datum  b,
SortSupport  ssup 
)
static

Definition at line 1681 of file gistproc.c.

1682{
1683 Point *p1 = &(DatumGetBoxP(a)->low);
1684 Point *p2 = &(DatumGetBoxP(b)->low);
1685 uint64 z1;
1686 uint64 z2;
1687
1688 /*
1689 * Do a quick check for equality first. It's not clear if this is worth it
1690 * in general, but certainly is when used as tie-breaker with abbreviated
1691 * keys,
1692 */
1693 if (p1->x == p2->x && p1->y == p2->y)
1694 return 0;
1695
1696 z1 = point_zorder_internal(p1->x, p1->y);
1697 z2 = point_zorder_internal(p2->x, p2->y);
1698 if (z1 > z2)
1699 return 1;
1700 else if (z1 < z2)
1701 return -1;
1702 else
1703 return 0;
1704}
int a
Definition: isn.c:68

References a, b, DatumGetBoxP(), BOX::low, p2, point_zorder_internal(), Point::x, and Point::y.

Referenced by gist_point_sortsupport().

◆ gist_box_consistent()

Datum gist_box_consistent ( PG_FUNCTION_ARGS  )

Definition at line 113 of file gistproc.c.

114{
115 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
116 BOX *query = PG_GETARG_BOX_P(1);
118
119 /* Oid subtype = PG_GETARG_OID(3); */
120 bool *recheck = (bool *) PG_GETARG_POINTER(4);
121
122 /* All cases served by this function are exact */
123 *recheck = false;
124
125 if (DatumGetBoxP(entry->key) == NULL || query == NULL)
126 PG_RETURN_BOOL(false);
127
128 /*
129 * if entry is not leaf, use rtree_internal_consistent, else use
130 * gist_box_leaf_consistent
131 */
132 if (GIST_LEAF(entry))
134 query,
135 strategy));
136 else
138 query,
139 strategy));
140}
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_GETARG_UINT16(n)
Definition: fmgr.h:272
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
#define PG_GETARG_BOX_P(n)
Definition: geo_decls.h:243
#define GIST_LEAF(entry)
Definition: gist.h:171
static bool rtree_internal_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:957
static bool gist_box_leaf_consistent(BOX *key, BOX *query, StrategyNumber strategy)
Definition: gistproc.c:872

References DatumGetBoxP(), gist_box_leaf_consistent(), GIST_LEAF, GISTENTRY::key, PG_GETARG_BOX_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, and rtree_internal_consistent().

◆ gist_box_distance()

Datum gist_box_distance ( PG_FUNCTION_ARGS  )

Definition at line 1500 of file gistproc.c.

1501{
1502 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1503 Datum query = PG_GETARG_DATUM(1);
1505
1506 /* Oid subtype = PG_GETARG_OID(3); */
1507 /* bool *recheck = (bool *) PG_GETARG_POINTER(4); */
1508 float8 distance;
1509
1510 distance = gist_bbox_distance(entry, query, strategy);
1511
1512 PG_RETURN_FLOAT8(distance);
1513}
#define PG_RETURN_FLOAT8(x)
Definition: fmgr.h:367
#define PG_GETARG_DATUM(n)
Definition: fmgr.h:268
static float8 gist_bbox_distance(GISTENTRY *entry, Datum query, StrategyNumber strategy)
Definition: gistproc.c:1479

References gist_bbox_distance(), PG_GETARG_DATUM, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_FLOAT8.

◆ gist_box_leaf_consistent()

static bool gist_box_leaf_consistent ( BOX key,
BOX query,
StrategyNumber  strategy 
)
static

Definition at line 872 of file gistproc.c.

873{
874 bool retval;
875
876 switch (strategy)
877 {
881 PointerGetDatum(query)));
882 break;
886 PointerGetDatum(query)));
887 break;
891 PointerGetDatum(query)));
892 break;
896 PointerGetDatum(query)));
897 break;
901 PointerGetDatum(query)));
902 break;
906 PointerGetDatum(query)));
907 break;
911 PointerGetDatum(query)));
912 break;
916 PointerGetDatum(query)));
917 break;
921 PointerGetDatum(query)));
922 break;
926 PointerGetDatum(query)));
927 break;
931 PointerGetDatum(query)));
932 break;
936 PointerGetDatum(query)));
937 break;
938 default:
939 elog(ERROR, "unrecognized strategy number: %d", strategy);
940 retval = false; /* keep compiler quiet */
941 break;
942 }
943 return retval;
944}
Datum box_left(PG_FUNCTION_ARGS)
Definition: geo_ops.c:583
Datum box_right(PG_FUNCTION_ARGS)
Definition: geo_ops.c:609
Datum box_same(PG_FUNCTION_ARGS)
Definition: geo_ops.c:551
Datum box_below(PG_FUNCTION_ARGS)
Definition: geo_ops.c:635
Datum box_overright(PG_FUNCTION_ARGS)
Definition: geo_ops.c:624
Datum box_overabove(PG_FUNCTION_ARGS)
Definition: geo_ops.c:670
Datum box_overlap(PG_FUNCTION_ARGS)
Definition: geo_ops.c:563
Datum box_contain(PG_FUNCTION_ARGS)
Definition: geo_ops.c:692
Datum box_overbelow(PG_FUNCTION_ARGS)
Definition: geo_ops.c:647
Datum box_contained(PG_FUNCTION_ARGS)
Definition: geo_ops.c:681
Datum box_overleft(PG_FUNCTION_ARGS)
Definition: geo_ops.c:598
Datum box_above(PG_FUNCTION_ARGS)
Definition: geo_ops.c:658
static bool DatumGetBool(Datum X)
Definition: postgres.h:95
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
#define RTOverlapStrategyNumber
Definition: stratnum.h:53
#define RTLeftStrategyNumber
Definition: stratnum.h:51
#define RTOverRightStrategyNumber
Definition: stratnum.h:54
#define RTRightStrategyNumber
Definition: stratnum.h:55
#define RTSameStrategyNumber
Definition: stratnum.h:56
#define RTOverAboveStrategyNumber
Definition: stratnum.h:62
#define RTContainsStrategyNumber
Definition: stratnum.h:57
#define RTOverBelowStrategyNumber
Definition: stratnum.h:59
#define RTBelowStrategyNumber
Definition: stratnum.h:60
#define RTAboveStrategyNumber
Definition: stratnum.h:61
#define RTOverLeftStrategyNumber
Definition: stratnum.h:52
#define RTContainedByStrategyNumber
Definition: stratnum.h:58

References box_above(), box_below(), box_contain(), box_contained(), box_left(), box_overabove(), box_overbelow(), box_overlap(), box_overleft(), box_overright(), box_right(), box_same(), DatumGetBool(), DirectFunctionCall2, elog, ERROR, sort-test::key, PointerGetDatum(), RTAboveStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTContainsStrategyNumber, RTLeftStrategyNumber, RTOverAboveStrategyNumber, RTOverBelowStrategyNumber, RTOverlapStrategyNumber, RTOverLeftStrategyNumber, RTOverRightStrategyNumber, RTRightStrategyNumber, and RTSameStrategyNumber.

Referenced by gist_box_consistent().

◆ gist_box_penalty()

Datum gist_box_penalty ( PG_FUNCTION_ARGS  )

Definition at line 199 of file gistproc.c.

200{
201 GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
202 GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
203 float *result = (float *) PG_GETARG_POINTER(2);
204 BOX *origbox = DatumGetBoxP(origentry->key);
205 BOX *newbox = DatumGetBoxP(newentry->key);
206
207 *result = (float) box_penalty(origbox, newbox);
208 PG_RETURN_POINTER(result);
209}
#define PG_RETURN_POINTER(x)
Definition: fmgr.h:361
static float8 box_penalty(const BOX *original, const BOX *new)
Definition: gistproc.c:97

References box_penalty(), DatumGetBoxP(), GISTENTRY::key, PG_GETARG_POINTER, and PG_RETURN_POINTER.

◆ gist_box_picksplit()

Datum gist_box_picksplit ( PG_FUNCTION_ARGS  )

Definition at line 495 of file gistproc.c.

496{
500 maxoff;
501 ConsiderSplitContext context;
502 BOX *box,
503 *leftBox,
504 *rightBox;
505 int dim,
506 commonEntriesCount;
507 SplitInterval *intervalsLower,
508 *intervalsUpper;
509 CommonEntry *commonEntries;
510 int nentries;
511
512 memset(&context, 0, sizeof(ConsiderSplitContext));
513
514 maxoff = entryvec->n - 1;
515 nentries = context.entriesCount = maxoff - FirstOffsetNumber + 1;
516
517 /* Allocate arrays for intervals along axes */
518 intervalsLower = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
519 intervalsUpper = (SplitInterval *) palloc(nentries * sizeof(SplitInterval));
520
521 /*
522 * Calculate the overall minimum bounding box over all the entries.
523 */
524 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
525 {
526 box = DatumGetBoxP(entryvec->vector[i].key);
527 if (i == FirstOffsetNumber)
528 context.boundingBox = *box;
529 else
530 adjustBox(&context.boundingBox, box);
531 }
532
533 /*
534 * Iterate over axes for optimal split searching.
535 */
536 context.first = true; /* nothing selected yet */
537 for (dim = 0; dim < 2; dim++)
538 {
539 float8 leftUpper,
540 rightLower;
541 int i1,
542 i2;
543
544 /* Project each entry as an interval on the selected axis. */
545 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
546 {
547 box = DatumGetBoxP(entryvec->vector[i].key);
548 if (dim == 0)
549 {
550 intervalsLower[i - FirstOffsetNumber].lower = box->low.x;
551 intervalsLower[i - FirstOffsetNumber].upper = box->high.x;
552 }
553 else
554 {
555 intervalsLower[i - FirstOffsetNumber].lower = box->low.y;
556 intervalsLower[i - FirstOffsetNumber].upper = box->high.y;
557 }
558 }
559
560 /*
561 * Make two arrays of intervals: one sorted by lower bound and another
562 * sorted by upper bound.
563 */
564 memcpy(intervalsUpper, intervalsLower,
565 sizeof(SplitInterval) * nentries);
566 qsort(intervalsLower, nentries, sizeof(SplitInterval),
568 qsort(intervalsUpper, nentries, sizeof(SplitInterval),
570
571 /*----
572 * The goal is to form a left and right interval, so that every entry
573 * interval is contained by either left or right interval (or both).
574 *
575 * For example, with the intervals (0,1), (1,3), (2,3), (2,4):
576 *
577 * 0 1 2 3 4
578 * +-+
579 * +---+
580 * +-+
581 * +---+
582 *
583 * The left and right intervals are of the form (0,a) and (b,4).
584 * We first consider splits where b is the lower bound of an entry.
585 * We iterate through all entries, and for each b, calculate the
586 * smallest possible a. Then we consider splits where a is the
587 * upper bound of an entry, and for each a, calculate the greatest
588 * possible b.
589 *
590 * In the above example, the first loop would consider splits:
591 * b=0: (0,1)-(0,4)
592 * b=1: (0,1)-(1,4)
593 * b=2: (0,3)-(2,4)
594 *
595 * And the second loop:
596 * a=1: (0,1)-(1,4)
597 * a=3: (0,3)-(2,4)
598 * a=4: (0,4)-(2,4)
599 */
600
601 /*
602 * Iterate over lower bound of right group, finding smallest possible
603 * upper bound of left group.
604 */
605 i1 = 0;
606 i2 = 0;
607 rightLower = intervalsLower[i1].lower;
608 leftUpper = intervalsUpper[i2].lower;
609 while (true)
610 {
611 /*
612 * Find next lower bound of right group.
613 */
614 while (i1 < nentries &&
615 float8_eq(rightLower, intervalsLower[i1].lower))
616 {
617 if (float8_lt(leftUpper, intervalsLower[i1].upper))
618 leftUpper = intervalsLower[i1].upper;
619 i1++;
620 }
621 if (i1 >= nentries)
622 break;
623 rightLower = intervalsLower[i1].lower;
624
625 /*
626 * Find count of intervals which anyway should be placed to the
627 * left group.
628 */
629 while (i2 < nentries &&
630 float8_le(intervalsUpper[i2].upper, leftUpper))
631 i2++;
632
633 /*
634 * Consider found split.
635 */
636 g_box_consider_split(&context, dim, rightLower, i1, leftUpper, i2);
637 }
638
639 /*
640 * Iterate over upper bound of left group finding greatest possible
641 * lower bound of right group.
642 */
643 i1 = nentries - 1;
644 i2 = nentries - 1;
645 rightLower = intervalsLower[i1].upper;
646 leftUpper = intervalsUpper[i2].upper;
647 while (true)
648 {
649 /*
650 * Find next upper bound of left group.
651 */
652 while (i2 >= 0 && float8_eq(leftUpper, intervalsUpper[i2].upper))
653 {
654 if (float8_gt(rightLower, intervalsUpper[i2].lower))
655 rightLower = intervalsUpper[i2].lower;
656 i2--;
657 }
658 if (i2 < 0)
659 break;
660 leftUpper = intervalsUpper[i2].upper;
661
662 /*
663 * Find count of intervals which anyway should be placed to the
664 * right group.
665 */
666 while (i1 >= 0 && float8_ge(intervalsLower[i1].lower, rightLower))
667 i1--;
668
669 /*
670 * Consider found split.
671 */
672 g_box_consider_split(&context, dim,
673 rightLower, i1 + 1, leftUpper, i2 + 1);
674 }
675 }
676
677 /*
678 * If we failed to find any acceptable splits, use trivial split.
679 */
680 if (context.first)
681 {
682 fallbackSplit(entryvec, v);
684 }
685
686 /*
687 * Ok, we have now selected the split across one axis.
688 *
689 * While considering the splits, we already determined that there will be
690 * enough entries in both groups to reach the desired ratio, but we did
691 * not memorize which entries go to which group. So determine that now.
692 */
693
694 /* Allocate vectors for results */
695 v->spl_left = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
696 v->spl_right = (OffsetNumber *) palloc(nentries * sizeof(OffsetNumber));
697 v->spl_nleft = 0;
698 v->spl_nright = 0;
699
700 /* Allocate bounding boxes of left and right groups */
701 leftBox = palloc0(sizeof(BOX));
702 rightBox = palloc0(sizeof(BOX));
703
704 /*
705 * Allocate an array for "common entries" - entries which can be placed to
706 * either group without affecting overlap along selected axis.
707 */
708 commonEntriesCount = 0;
709 commonEntries = (CommonEntry *) palloc(nentries * sizeof(CommonEntry));
710
711 /* Helper macros to place an entry in the left or right group */
712#define PLACE_LEFT(box, off) \
713 do { \
714 if (v->spl_nleft > 0) \
715 adjustBox(leftBox, box); \
716 else \
717 *leftBox = *(box); \
718 v->spl_left[v->spl_nleft++] = off; \
719 } while(0)
720
721#define PLACE_RIGHT(box, off) \
722 do { \
723 if (v->spl_nright > 0) \
724 adjustBox(rightBox, box); \
725 else \
726 *rightBox = *(box); \
727 v->spl_right[v->spl_nright++] = off; \
728 } while(0)
729
730 /*
731 * Distribute entries which can be distributed unambiguously, and collect
732 * common entries.
733 */
734 for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
735 {
737 upper;
738
739 /*
740 * Get upper and lower bounds along selected axis.
741 */
742 box = DatumGetBoxP(entryvec->vector[i].key);
743 if (context.dim == 0)
744 {
745 lower = box->low.x;
746 upper = box->high.x;
747 }
748 else
749 {
750 lower = box->low.y;
751 upper = box->high.y;
752 }
753
754 if (float8_le(upper, context.leftUpper))
755 {
756 /* Fits to the left group */
757 if (float8_ge(lower, context.rightLower))
758 {
759 /* Fits also to the right group, so "common entry" */
760 commonEntries[commonEntriesCount++].index = i;
761 }
762 else
763 {
764 /* Doesn't fit to the right group, so join to the left group */
765 PLACE_LEFT(box, i);
766 }
767 }
768 else
769 {
770 /*
771 * Each entry should fit on either left or right group. Since this
772 * entry didn't fit on the left group, it better fit in the right
773 * group.
774 */
775 Assert(float8_ge(lower, context.rightLower));
776
777 /* Doesn't fit to the left group, so join to the right group */
778 PLACE_RIGHT(box, i);
779 }
780 }
781
782 /*
783 * Distribute "common entries", if any.
784 */
785 if (commonEntriesCount > 0)
786 {
787 /*
788 * Calculate minimum number of entries that must be placed in both
789 * groups, to reach LIMIT_RATIO.
790 */
791 int m = ceil(LIMIT_RATIO * nentries);
792
793 /*
794 * Calculate delta between penalties of join "common entries" to
795 * different groups.
796 */
797 for (i = 0; i < commonEntriesCount; i++)
798 {
799 box = DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);
800 commonEntries[i].delta = fabs(float8_mi(box_penalty(leftBox, box),
801 box_penalty(rightBox, box)));
802 }
803
804 /*
805 * Sort "common entries" by calculated deltas in order to distribute
806 * the most ambiguous entries first.
807 */
808 qsort(commonEntries, commonEntriesCount, sizeof(CommonEntry), common_entry_cmp);
809
810 /*
811 * Distribute "common entries" between groups.
812 */
813 for (i = 0; i < commonEntriesCount; i++)
814 {
815 box = DatumGetBoxP(entryvec->vector[commonEntries[i].index].key);
816
817 /*
818 * Check if we have to place this entry in either group to achieve
819 * LIMIT_RATIO.
820 */
821 if (v->spl_nleft + (commonEntriesCount - i) <= m)
822 PLACE_LEFT(box, commonEntries[i].index);
823 else if (v->spl_nright + (commonEntriesCount - i) <= m)
824 PLACE_RIGHT(box, commonEntries[i].index);
825 else
826 {
827 /* Otherwise select the group by minimal penalty */
828 if (box_penalty(leftBox, box) < box_penalty(rightBox, box))
829 PLACE_LEFT(box, commonEntries[i].index);
830 else
831 PLACE_RIGHT(box, commonEntries[i].index);
832 }
833 }
834 }
835
836 v->spl_ldatum = PointerGetDatum(leftBox);
837 v->spl_rdatum = PointerGetDatum(rightBox);
839}
static bool float8_ge(const float8 val1, const float8 val2)
Definition: float.h:328
static bool float8_le(const float8 val1, const float8 val2)
Definition: float.h:304
static bool float8_eq(const float8 val1, const float8 val2)
Definition: float.h:268
static void fallbackSplit(GistEntryVector *entryvec, GIST_SPLITVEC *v)
Definition: gistproc.c:216
static int interval_cmp_upper(const void *i1, const void *i2)
Definition: gistproc.c:327
#define PLACE_RIGHT(box, off)
static void g_box_consider_split(ConsiderSplitContext *context, int dimNum, float8 rightLower, int minLeftCount, float8 leftUpper, int maxLeftCount)
Definition: gistproc.c:351
static int interval_cmp_lower(const void *i1, const void *i2)
Definition: gistproc.c:315
static int common_entry_cmp(const void *i1, const void *i2)
Definition: gistproc.c:460
#define PLACE_LEFT(box, off)
void * palloc0(Size size)
Definition: mcxt.c:1347
Datum lower(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:49
Datum upper(PG_FUNCTION_ARGS)
Definition: oracle_compat.c:80
#define qsort(a, b, c, d)
Definition: port.h:474
float8 delta
Definition: gistproc.c:276
float8 upper
Definition: gistproc.c:308
float8 lower
Definition: gistproc.c:307
Definition: type.h:96

References adjustBox(), Assert, ConsiderSplitContext::boundingBox, box_penalty(), common_entry_cmp(), DatumGetBoxP(), CommonEntry::delta, ConsiderSplitContext::dim, ConsiderSplitContext::entriesCount, fallbackSplit(), ConsiderSplitContext::first, FirstOffsetNumber, float8_eq(), float8_ge(), float8_gt(), float8_le(), float8_lt(), float8_mi(), g_box_consider_split(), BOX::high, i, CommonEntry::index, interval_cmp_lower(), interval_cmp_upper(), GISTENTRY::key, ConsiderSplitContext::leftUpper, LIMIT_RATIO, BOX::low, SplitInterval::lower, lower(), GistEntryVector::n, OffsetNumberNext, palloc(), palloc0(), PG_GETARG_POINTER, PG_RETURN_POINTER, PLACE_LEFT, PLACE_RIGHT, PointerGetDatum(), qsort, ConsiderSplitContext::rightLower, GIST_SPLITVEC::spl_ldatum, GIST_SPLITVEC::spl_left, GIST_SPLITVEC::spl_nleft, GIST_SPLITVEC::spl_nright, GIST_SPLITVEC::spl_rdatum, GIST_SPLITVEC::spl_right, SplitInterval::upper, upper(), GistEntryVector::vector, Point::x, and Point::y.

◆ gist_box_same()

Datum gist_box_same ( PG_FUNCTION_ARGS  )

Definition at line 852 of file gistproc.c.

853{
854 BOX *b1 = PG_GETARG_BOX_P(0);
855 BOX *b2 = PG_GETARG_BOX_P(1);
856 bool *result = (bool *) PG_GETARG_POINTER(2);
857
858 if (b1 && b2)
859 *result = (float8_eq(b1->low.x, b2->low.x) &&
860 float8_eq(b1->low.y, b2->low.y) &&
861 float8_eq(b1->high.x, b2->high.x) &&
862 float8_eq(b1->high.y, b2->high.y));
863 else
864 *result = (b1 == NULL && b2 == NULL);
865 PG_RETURN_POINTER(result);
866}

References float8_eq(), BOX::high, BOX::low, PG_GETARG_BOX_P, PG_GETARG_POINTER, PG_RETURN_POINTER, Point::x, and Point::y.

◆ gist_box_union()

Datum gist_box_union ( PG_FUNCTION_ARGS  )

Definition at line 164 of file gistproc.c.

165{
167 int *sizep = (int *) PG_GETARG_POINTER(1);
168 int numranges,
169 i;
170 BOX *cur,
171 *pageunion;
172
173 numranges = entryvec->n;
174 pageunion = (BOX *) palloc(sizeof(BOX));
175 cur = DatumGetBoxP(entryvec->vector[0].key);
176 memcpy(pageunion, cur, sizeof(BOX));
177
178 for (i = 1; i < numranges; i++)
179 {
180 cur = DatumGetBoxP(entryvec->vector[i].key);
181 adjustBox(pageunion, cur);
182 }
183 *sizep = sizeof(BOX);
184
185 PG_RETURN_POINTER(pageunion);
186}

References adjustBox(), cur, DatumGetBoxP(), i, GISTENTRY::key, GistEntryVector::n, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, and GistEntryVector::vector.

◆ gist_circle_compress()

Datum gist_circle_compress ( PG_FUNCTION_ARGS  )

Definition at line 1100 of file gistproc.c.

1101{
1102 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1103 GISTENTRY *retval;
1104
1105 if (entry->leafkey)
1106 {
1107 CIRCLE *in = DatumGetCircleP(entry->key);
1108 BOX *r;
1109
1110 r = (BOX *) palloc(sizeof(BOX));
1111 r->high.x = float8_pl(in->center.x, in->radius);
1112 r->low.x = float8_mi(in->center.x, in->radius);
1113 r->high.y = float8_pl(in->center.y, in->radius);
1114 r->low.y = float8_mi(in->center.y, in->radius);
1115
1116 retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1117 gistentryinit(*retval, PointerGetDatum(r),
1118 entry->rel, entry->page,
1119 entry->offset, false);
1120 }
1121 else
1122 retval = entry;
1123 PG_RETURN_POINTER(retval);
1124}
static float8 float8_pl(const float8 val1, const float8 val2)
Definition: float.h:158
static CIRCLE * DatumGetCircleP(Datum X)
Definition: geo_decls.h:266
#define gistentryinit(e, k, r, pg, o, l)
Definition: gist.h:245
float8 radius
Definition: geo_decls.h:165
Point center
Definition: geo_decls.h:164
OffsetNumber offset
Definition: gist.h:164
Page page
Definition: gist.h:163
Relation rel
Definition: gist.h:162
bool leafkey
Definition: gist.h:165

References CIRCLE::center, DatumGetCircleP(), float8_mi(), float8_pl(), gistentryinit, BOX::high, GISTENTRY::key, GISTENTRY::leafkey, BOX::low, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum(), CIRCLE::radius, GISTENTRY::rel, Point::x, and Point::y.

◆ gist_circle_consistent()

Datum gist_circle_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1130 of file gistproc.c.

1131{
1132 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1133 CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1135
1136 /* Oid subtype = PG_GETARG_OID(3); */
1137 bool *recheck = (bool *) PG_GETARG_POINTER(4);
1138 BOX bbox;
1139 bool result;
1140
1141 /* All cases served by this function are inexact */
1142 *recheck = true;
1143
1144 if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1145 PG_RETURN_BOOL(false);
1146
1147 /*
1148 * Since the operators require recheck anyway, we can just use
1149 * rtree_internal_consistent even at leaf nodes. (This works in part
1150 * because the index entries are bounding boxes not circles.)
1151 */
1152 bbox.high.x = float8_pl(query->center.x, query->radius);
1153 bbox.low.x = float8_mi(query->center.x, query->radius);
1154 bbox.high.y = float8_pl(query->center.y, query->radius);
1155 bbox.low.y = float8_mi(query->center.y, query->radius);
1156
1158 &bbox, strategy);
1159
1160 PG_RETURN_BOOL(result);
1161}
#define PG_GETARG_CIRCLE_P(n)
Definition: geo_decls.h:275

References CIRCLE::center, DatumGetBoxP(), float8_mi(), float8_pl(), BOX::high, GISTENTRY::key, BOX::low, PG_GETARG_CIRCLE_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_BOOL, CIRCLE::radius, rtree_internal_consistent(), Point::x, and Point::y.

Referenced by gist_point_consistent().

◆ gist_circle_distance()

Datum gist_circle_distance ( PG_FUNCTION_ARGS  )

Definition at line 1526 of file gistproc.c.

1527{
1528 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1529 Datum query = PG_GETARG_DATUM(1);
1531
1532 /* Oid subtype = PG_GETARG_OID(3); */
1533 bool *recheck = (bool *) PG_GETARG_POINTER(4);
1534 float8 distance;
1535
1536 distance = gist_bbox_distance(entry, query, strategy);
1537 *recheck = true;
1538
1539 PG_RETURN_FLOAT8(distance);
1540}

References gist_bbox_distance(), PG_GETARG_DATUM, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_FLOAT8.

◆ gist_point_compress()

Datum gist_point_compress ( PG_FUNCTION_ARGS  )

Definition at line 1168 of file gistproc.c.

1169{
1170 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1171
1172 if (entry->leafkey) /* Point, actually */
1173 {
1174 BOX *box = palloc(sizeof(BOX));
1175 Point *point = DatumGetPointP(entry->key);
1176 GISTENTRY *retval = palloc(sizeof(GISTENTRY));
1177
1178 box->high = box->low = *point;
1179
1180 gistentryinit(*retval, BoxPGetDatum(box),
1181 entry->rel, entry->page, entry->offset, false);
1182
1183 PG_RETURN_POINTER(retval);
1184 }
1185
1186 PG_RETURN_POINTER(entry);
1187}

References BoxPGetDatum(), DatumGetPointP(), gistentryinit, BOX::high, GISTENTRY::key, GISTENTRY::leafkey, BOX::low, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, and GISTENTRY::rel.

◆ gist_point_consistent()

Datum gist_point_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1337 of file gistproc.c.

1338{
1339 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1341 bool *recheck = (bool *) PG_GETARG_POINTER(4);
1342 bool result;
1343 StrategyNumber strategyGroup;
1344
1345 /*
1346 * We have to remap these strategy numbers to get this klugy
1347 * classification logic to work.
1348 */
1349 if (strategy == RTOldBelowStrategyNumber)
1350 strategy = RTBelowStrategyNumber;
1351 else if (strategy == RTOldAboveStrategyNumber)
1352 strategy = RTAboveStrategyNumber;
1353
1354 strategyGroup = strategy / GeoStrategyNumberOffset;
1355 switch (strategyGroup)
1356 {
1359 GIST_LEAF(entry),
1360 DatumGetBoxP(entry->key),
1362 *recheck = false;
1363 break;
1365 {
1366 /*
1367 * The only operator in this group is point <@ box (on_pb), so
1368 * we needn't examine strategy again.
1369 *
1370 * For historical reasons, on_pb uses exact rather than fuzzy
1371 * comparisons. We could use box_overlap when at an internal
1372 * page, but that would lead to possibly visiting child pages
1373 * uselessly, because box_overlap uses fuzzy comparisons.
1374 * Instead we write a non-fuzzy overlap test. The same code
1375 * will also serve for leaf-page tests, since leaf keys have
1376 * high == low.
1377 */
1378 BOX *query,
1379 *key;
1380
1381 query = PG_GETARG_BOX_P(1);
1382 key = DatumGetBoxP(entry->key);
1383
1384 result = (key->high.x >= query->low.x &&
1385 key->low.x <= query->high.x &&
1386 key->high.y >= query->low.y &&
1387 key->low.y <= query->high.y);
1388 *recheck = false;
1389 }
1390 break;
1392 {
1393 POLYGON *query = PG_GETARG_POLYGON_P(1);
1394
1396 PointerGetDatum(entry),
1397 PolygonPGetDatum(query),
1399 0, PointerGetDatum(recheck)));
1400
1401 if (GIST_LEAF(entry) && result)
1402 {
1403 /*
1404 * We are on leaf page and quick check shows overlapping
1405 * of polygon's bounding box and point
1406 */
1407 BOX *box = DatumGetBoxP(entry->key);
1408
1409 Assert(box->high.x == box->low.x
1410 && box->high.y == box->low.y);
1412 PolygonPGetDatum(query),
1413 PointPGetDatum(&box->high)));
1414 *recheck = false;
1415 }
1416 }
1417 break;
1419 {
1420 CIRCLE *query = PG_GETARG_CIRCLE_P(1);
1421
1423 PointerGetDatum(entry),
1424 CirclePGetDatum(query),
1426 0, PointerGetDatum(recheck)));
1427
1428 if (GIST_LEAF(entry) && result)
1429 {
1430 /*
1431 * We are on leaf page and quick check shows overlapping
1432 * of polygon's bounding box and point
1433 */
1434 BOX *box = DatumGetBoxP(entry->key);
1435
1436 Assert(box->high.x == box->low.x
1437 && box->high.y == box->low.y);
1439 CirclePGetDatum(query),
1440 PointPGetDatum(&box->high)));
1441 *recheck = false;
1442 }
1443 }
1444 break;
1445 default:
1446 elog(ERROR, "unrecognized strategy number: %d", strategy);
1447 result = false; /* keep compiler quiet */
1448 break;
1449 }
1450
1451 PG_RETURN_BOOL(result);
1452}
#define DirectFunctionCall5(func, arg1, arg2, arg3, arg4, arg5)
Definition: fmgr.h:649
#define PG_GETARG_POINT_P(n)
Definition: geo_decls.h:185
static Datum PolygonPGetDatum(const POLYGON *X)
Definition: geo_decls.h:257
#define PG_GETARG_POLYGON_P(n)
Definition: geo_decls.h:261
static Datum CirclePGetDatum(const CIRCLE *X)
Definition: geo_decls.h:271
Datum poly_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:4008
Datum circle_contain_pt(PG_FUNCTION_ARGS)
Definition: geo_ops.c:5082
#define BoxStrategyNumberGroup
Definition: gistproc.c:1332
#define CircleStrategyNumberGroup
Definition: gistproc.c:1334
Datum gist_circle_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1130
#define PolygonStrategyNumberGroup
Definition: gistproc.c:1333
Datum gist_poly_consistent(PG_FUNCTION_ARGS)
Definition: gistproc.c:1062
static bool gist_point_consistent_internal(StrategyNumber strategy, bool isLeaf, BOX *key, Point *query)
Definition: gistproc.c:1287
static Datum Int16GetDatum(int16 X)
Definition: postgres.h:177
#define RTOldBelowStrategyNumber
Definition: stratnum.h:79
#define RTOldAboveStrategyNumber
Definition: stratnum.h:80

References Assert, BoxStrategyNumberGroup, circle_contain_pt(), CirclePGetDatum(), CircleStrategyNumberGroup, DatumGetBool(), DatumGetBoxP(), DirectFunctionCall2, DirectFunctionCall5, elog, ERROR, GeoStrategyNumberOffset, gist_circle_consistent(), GIST_LEAF, gist_point_consistent_internal(), gist_poly_consistent(), BOX::high, Int16GetDatum(), GISTENTRY::key, sort-test::key, BOX::low, PG_GETARG_BOX_P, PG_GETARG_CIRCLE_P, PG_GETARG_POINT_P, PG_GETARG_POINTER, PG_GETARG_POLYGON_P, PG_GETARG_UINT16, PG_RETURN_BOOL, PointerGetDatum(), PointPGetDatum(), PointStrategyNumberGroup, poly_contain_pt(), PolygonPGetDatum(), PolygonStrategyNumberGroup, RTAboveStrategyNumber, RTBelowStrategyNumber, RTOldAboveStrategyNumber, RTOldBelowStrategyNumber, RTOverlapStrategyNumber, Point::x, and Point::y.

◆ gist_point_consistent_internal()

static bool gist_point_consistent_internal ( StrategyNumber  strategy,
bool  isLeaf,
BOX key,
Point query 
)
static

Definition at line 1287 of file gistproc.c.

1289{
1290 bool result = false;
1291
1292 switch (strategy)
1293 {
1295 result = FPlt(key->low.x, query->x);
1296 break;
1298 result = FPgt(key->high.x, query->x);
1299 break;
1301 result = FPgt(key->high.y, query->y);
1302 break;
1304 result = FPlt(key->low.y, query->y);
1305 break;
1307 if (isLeaf)
1308 {
1309 /* key.high must equal key.low, so we can disregard it */
1310 result = (FPeq(key->low.x, query->x) &&
1311 FPeq(key->low.y, query->y));
1312 }
1313 else
1314 {
1315 result = (FPle(query->x, key->high.x) &&
1316 FPge(query->x, key->low.x) &&
1317 FPle(query->y, key->high.y) &&
1318 FPge(query->y, key->low.y));
1319 }
1320 break;
1321 default:
1322 elog(ERROR, "unrecognized strategy number: %d", strategy);
1323 result = false; /* keep compiler quiet */
1324 break;
1325 }
1326
1327 return result;
1328}
static bool FPlt(double A, double B)
Definition: geo_decls.h:59
static bool FPge(double A, double B)
Definition: geo_decls.h:77
static bool FPgt(double A, double B)
Definition: geo_decls.h:71
static bool FPle(double A, double B)
Definition: geo_decls.h:65
static bool FPeq(double A, double B)
Definition: geo_decls.h:47

References elog, ERROR, FPeq(), FPge(), FPgt(), FPle(), FPlt(), sort-test::key, RTAboveStrategyNumber, RTBelowStrategyNumber, RTLeftStrategyNumber, RTRightStrategyNumber, RTSameStrategyNumber, Point::x, and Point::y.

Referenced by gist_point_consistent().

◆ gist_point_distance()

Datum gist_point_distance ( PG_FUNCTION_ARGS  )

Definition at line 1455 of file gistproc.c.

1456{
1457 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1459 float8 distance;
1460 StrategyNumber strategyGroup = strategy / GeoStrategyNumberOffset;
1461
1462 switch (strategyGroup)
1463 {
1465 distance = computeDistance(GIST_LEAF(entry),
1466 DatumGetBoxP(entry->key),
1468 break;
1469 default:
1470 elog(ERROR, "unrecognized strategy number: %d", strategy);
1471 distance = 0.0; /* keep compiler quiet */
1472 break;
1473 }
1474
1475 PG_RETURN_FLOAT8(distance);
1476}

References computeDistance(), DatumGetBoxP(), elog, ERROR, GeoStrategyNumberOffset, GIST_LEAF, GISTENTRY::key, PG_GETARG_POINT_P, PG_GETARG_POINTER, PG_GETARG_UINT16, PG_RETURN_FLOAT8, and PointStrategyNumberGroup.

◆ gist_point_fetch()

Datum gist_point_fetch ( PG_FUNCTION_ARGS  )

Definition at line 1196 of file gistproc.c.

1197{
1198 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1199 BOX *in = DatumGetBoxP(entry->key);
1200 Point *r;
1201 GISTENTRY *retval;
1202
1203 retval = palloc(sizeof(GISTENTRY));
1204
1205 r = (Point *) palloc(sizeof(Point));
1206 r->x = in->high.x;
1207 r->y = in->high.y;
1208 gistentryinit(*retval, PointerGetDatum(r),
1209 entry->rel, entry->page,
1210 entry->offset, false);
1211
1212 PG_RETURN_POINTER(retval);
1213}

References DatumGetBoxP(), gistentryinit, BOX::high, GISTENTRY::key, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum(), GISTENTRY::rel, Point::x, and Point::y.

◆ gist_point_sortsupport()

Datum gist_point_sortsupport ( PG_FUNCTION_ARGS  )

Definition at line 1745 of file gistproc.c.

1746{
1748
1749 if (ssup->abbreviate)
1750 {
1755 }
1756 else
1757 {
1759 }
1761}
#define PG_RETURN_VOID()
Definition: fmgr.h:349
static int gist_bbox_zorder_cmp(Datum a, Datum b, SortSupport ssup)
Definition: gistproc.c:1681
static Datum gist_bbox_zorder_abbrev_convert(Datum original, SortSupport ssup)
Definition: gistproc.c:1714
static bool gist_bbox_zorder_abbrev_abort(int memtupcount, SortSupport ssup)
Definition: gistproc.c:1736
struct SortSupportData * SortSupport
Definition: sortsupport.h:58
int(* comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:106
Datum(* abbrev_converter)(Datum original, SortSupport ssup)
Definition: sortsupport.h:172
int(* abbrev_full_comparator)(Datum x, Datum y, SortSupport ssup)
Definition: sortsupport.h:191
bool(* abbrev_abort)(int memtupcount, SortSupport ssup)
Definition: sortsupport.h:182
int ssup_datum_unsigned_cmp(Datum x, Datum y, SortSupport ssup)
Definition: tuplesort.c:3139

References SortSupportData::abbrev_abort, SortSupportData::abbrev_converter, SortSupportData::abbrev_full_comparator, SortSupportData::abbreviate, SortSupportData::comparator, gist_bbox_zorder_abbrev_abort(), gist_bbox_zorder_abbrev_convert(), gist_bbox_zorder_cmp(), PG_GETARG_POINTER, PG_RETURN_VOID, and ssup_datum_unsigned_cmp().

◆ gist_poly_compress()

Datum gist_poly_compress ( PG_FUNCTION_ARGS  )

Definition at line 1035 of file gistproc.c.

1036{
1037 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1038 GISTENTRY *retval;
1039
1040 if (entry->leafkey)
1041 {
1042 POLYGON *in = DatumGetPolygonP(entry->key);
1043 BOX *r;
1044
1045 r = (BOX *) palloc(sizeof(BOX));
1046 memcpy(r, &(in->boundbox), sizeof(BOX));
1047
1048 retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
1049 gistentryinit(*retval, PointerGetDatum(r),
1050 entry->rel, entry->page,
1051 entry->offset, false);
1052 }
1053 else
1054 retval = entry;
1055 PG_RETURN_POINTER(retval);
1056}
static POLYGON * DatumGetPolygonP(Datum X)
Definition: geo_decls.h:247
BOX boundbox
Definition: geo_decls.h:155

References POLYGON::boundbox, DatumGetPolygonP(), gistentryinit, GISTENTRY::key, GISTENTRY::leafkey, GISTENTRY::offset, GISTENTRY::page, palloc(), PG_GETARG_POINTER, PG_RETURN_POINTER, PointerGetDatum(), and GISTENTRY::rel.

◆ gist_poly_consistent()

Datum gist_poly_consistent ( PG_FUNCTION_ARGS  )

Definition at line 1062 of file gistproc.c.

1063{
1064 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1065 POLYGON *query = PG_GETARG_POLYGON_P(1);
1067
1068 /* Oid subtype = PG_GETARG_OID(3); */
1069 bool *recheck = (bool *) PG_GETARG_POINTER(4);
1070 bool result;
1071
1072 /* All cases served by this function are inexact */
1073 *recheck = true;
1074
1075 if (DatumGetBoxP(entry->key) == NULL || query == NULL)
1076 PG_RETURN_BOOL(false);
1077
1078 /*
1079 * Since the operators require recheck anyway, we can just use
1080 * rtree_internal_consistent even at leaf nodes. (This works in part
1081 * because the index entries are bounding boxes not polygons.)
1082 */
1084 &(query->boundbox), strategy);
1085
1086 /* Avoid memory leak if supplied poly is toasted */
1087 PG_FREE_IF_COPY(query, 1);
1088
1089 PG_RETURN_BOOL(result);
1090}
#define PG_FREE_IF_COPY(ptr, n)
Definition: fmgr.h:260

References POLYGON::boundbox, DatumGetBoxP(), GISTENTRY::key, PG_FREE_IF_COPY, PG_GETARG_POINTER, PG_GETARG_POLYGON_P, PG_GETARG_UINT16, PG_RETURN_BOOL, and rtree_internal_consistent().

Referenced by gist_point_consistent().

◆ gist_poly_distance()

Datum gist_poly_distance ( PG_FUNCTION_ARGS  )

Definition at line 1543 of file gistproc.c.

1544{
1545 GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
1546 Datum query = PG_GETARG_DATUM(1);
1548
1549 /* Oid subtype = PG_GETARG_OID(3); */
1550 bool *recheck = (bool *) PG_GETARG_POINTER(4);
1551 float8 distance;
1552
1553 distance = gist_bbox_distance(entry, query, strategy);
1554 *recheck = true;
1555
1556 PG_RETURN_FLOAT8(distance);
1557}

References gist_bbox_distance(), PG_GETARG_DATUM, PG_GETARG_POINTER, PG_GETARG_UINT16, and PG_RETURN_FLOAT8.

◆ ieee_float32_to_uint32()

static uint32 ieee_float32_to_uint32 ( float  f)
static

Definition at line 1603 of file gistproc.c.

1604{
1605 /*----
1606 *
1607 * IEEE 754 floating point format
1608 * ------------------------------
1609 *
1610 * IEEE 754 floating point numbers have this format:
1611 *
1612 * exponent (8 bits)
1613 * |
1614 * s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
1615 * | |
1616 * sign mantissa (23 bits)
1617 *
1618 * Infinity has all bits in the exponent set and the mantissa is all
1619 * zeros. Negative infinity is the same but with the sign bit set.
1620 *
1621 * NaNs are represented with all bits in the exponent set, and the least
1622 * significant bit in the mantissa also set. The rest of the mantissa bits
1623 * can be used to distinguish different kinds of NaNs.
1624 *
1625 * The IEEE format has the nice property that when you take the bit
1626 * representation and interpret it as an integer, the order is preserved,
1627 * except for the sign. That holds for the +-Infinity values too.
1628 *
1629 * Mapping to uint32
1630 * -----------------
1631 *
1632 * In order to have a smooth transition from negative to positive numbers,
1633 * we map floats to unsigned integers like this:
1634 *
1635 * x < 0 to range 0-7FFFFFFF
1636 * x = 0 to value 8000000 (both positive and negative zero)
1637 * x > 0 to range 8000001-FFFFFFFF
1638 *
1639 * We don't care to distinguish different kind of NaNs, so they are all
1640 * mapped to the same arbitrary value, FFFFFFFF. Because of the IEEE bit
1641 * representation of NaNs, there aren't any non-NaN values that would be
1642 * mapped to FFFFFFFF. In fact, there is a range of unused values on both
1643 * ends of the uint32 space.
1644 */
1645 if (isnan(f))
1646 return 0xFFFFFFFF;
1647 else
1648 {
1649 union
1650 {
1651 float f;
1652 uint32 i;
1653 } u;
1654
1655 u.f = f;
1656
1657 /* Check the sign bit */
1658 if ((u.i & 0x80000000) != 0)
1659 {
1660 /*
1661 * Map the negative value to range 0-7FFFFFFF. This flips the sign
1662 * bit to 0 in the same instruction.
1663 */
1664 Assert(f <= 0); /* can be -0 */
1665 u.i ^= 0xFFFFFFFF;
1666 }
1667 else
1668 {
1669 /* Map the positive value (or 0) to range 80000000-FFFFFFFF */
1670 u.i |= 0x80000000;
1671 }
1672
1673 return u.i;
1674 }
1675}
uint32_t uint32
Definition: c.h:488

References Assert, and i.

Referenced by point_zorder_internal().

◆ interval_cmp_lower()

static int interval_cmp_lower ( const void *  i1,
const void *  i2 
)
static

Definition at line 315 of file gistproc.c.

316{
317 float8 lower1 = ((const SplitInterval *) i1)->lower,
318 lower2 = ((const SplitInterval *) i2)->lower;
319
320 return float8_cmp_internal(lower1, lower2);
321}

References float8_cmp_internal().

Referenced by gist_box_picksplit().

◆ interval_cmp_upper()

static int interval_cmp_upper ( const void *  i1,
const void *  i2 
)
static

Definition at line 327 of file gistproc.c.

328{
329 float8 upper1 = ((const SplitInterval *) i1)->upper,
330 upper2 = ((const SplitInterval *) i2)->upper;
331
332 return float8_cmp_internal(upper1, upper2);
333}

References float8_cmp_internal().

Referenced by gist_box_picksplit().

◆ non_negative()

static float non_negative ( float  val)
inlinestatic

Definition at line 339 of file gistproc.c.

340{
341 if (val >= 0.0f)
342 return val;
343 else
344 return 0.0f;
345}
long val
Definition: informix.c:689

References val.

Referenced by g_box_consider_split().

◆ part_bits32_by2()

static uint64 part_bits32_by2 ( uint32  x)
static

Definition at line 1586 of file gistproc.c.

1587{
1588 uint64 n = x;
1589
1590 n = (n | (n << 16)) & UINT64CONST(0x0000FFFF0000FFFF);
1591 n = (n | (n << 8)) & UINT64CONST(0x00FF00FF00FF00FF);
1592 n = (n | (n << 4)) & UINT64CONST(0x0F0F0F0F0F0F0F0F);
1593 n = (n | (n << 2)) & UINT64CONST(0x3333333333333333);
1594 n = (n | (n << 1)) & UINT64CONST(0x5555555555555555);
1595
1596 return n;
1597}
#define UINT64CONST(x)
Definition: c.h:503
int x
Definition: isn.c:70

References UINT64CONST, and x.

Referenced by point_zorder_internal().

◆ point_zorder_internal()

static uint64 point_zorder_internal ( float4  x,
float4  y 
)
static

Definition at line 1575 of file gistproc.c.

1576{
1579
1580 /* Interleave the bits */
1581 return part_bits32_by2(ix) | (part_bits32_by2(iy) << 1);
1582}
static uint64 part_bits32_by2(uint32 x)
Definition: gistproc.c:1586
static uint32 ieee_float32_to_uint32(float f)
Definition: gistproc.c:1603
int y
Definition: isn.c:71

References ieee_float32_to_uint32(), part_bits32_by2(), x, and y.

Referenced by gist_bbox_zorder_abbrev_convert(), and gist_bbox_zorder_cmp().

◆ rt_box_union()

static void rt_box_union ( BOX n,
const BOX a,
const BOX b 
)
static

Definition at line 55 of file gistproc.c.

56{
57 n->high.x = float8_max(a->high.x, b->high.x);
58 n->high.y = float8_max(a->high.y, b->high.y);
59 n->low.x = float8_min(a->low.x, b->low.x);
60 n->low.y = float8_min(a->low.y, b->low.y);
61}
static float8 float8_min(const float8 val1, const float8 val2)
Definition: float.h:340
static float8 float8_max(const float8 val1, const float8 val2)
Definition: float.h:352

References a, b, float8_max(), float8_min(), BOX::high, BOX::low, Point::x, and Point::y.

Referenced by box_penalty().

◆ rtree_internal_consistent()

static bool rtree_internal_consistent ( BOX key,
BOX query,
StrategyNumber  strategy 
)
static

Definition at line 957 of file gistproc.c.

958{
959 bool retval;
960
961 switch (strategy)
962 {
966 PointerGetDatum(query)));
967 break;
971 PointerGetDatum(query)));
972 break;
976 PointerGetDatum(query)));
977 break;
981 PointerGetDatum(query)));
982 break;
986 PointerGetDatum(query)));
987 break;
992 PointerGetDatum(query)));
993 break;
997 PointerGetDatum(query)));
998 break;
1002 PointerGetDatum(query)));
1003 break;
1007 PointerGetDatum(query)));
1008 break;
1012 PointerGetDatum(query)));
1013 break;
1017 PointerGetDatum(query)));
1018 break;
1019 default:
1020 elog(ERROR, "unrecognized strategy number: %d", strategy);
1021 retval = false; /* keep compiler quiet */
1022 break;
1023 }
1024 return retval;
1025}

References box_above(), box_below(), box_contain(), box_left(), box_overabove(), box_overbelow(), box_overlap(), box_overleft(), box_overright(), box_right(), DatumGetBool(), DirectFunctionCall2, elog, ERROR, sort-test::key, PointerGetDatum(), RTAboveStrategyNumber, RTBelowStrategyNumber, RTContainedByStrategyNumber, RTContainsStrategyNumber, RTLeftStrategyNumber, RTOverAboveStrategyNumber, RTOverBelowStrategyNumber, RTOverlapStrategyNumber, RTOverLeftStrategyNumber, RTOverRightStrategyNumber, RTRightStrategyNumber, and RTSameStrategyNumber.

Referenced by gist_box_consistent(), gist_circle_consistent(), and gist_poly_consistent().

◆ size_box()

static float8 size_box ( const BOX box)
static

Definition at line 68 of file gistproc.c.

69{
70 /*
71 * Check for zero-width cases. Note that we define the size of a zero-
72 * by-infinity box as zero. It's important to special-case this somehow,
73 * as naively multiplying infinity by zero will produce NaN.
74 *
75 * The less-than cases should not happen, but if they do, say "zero".
76 */
77 if (float8_le(box->high.x, box->low.x) ||
78 float8_le(box->high.y, box->low.y))
79 return 0.0;
80
81 /*
82 * We treat NaN as larger than +Infinity, so any distance involving a NaN
83 * and a non-NaN is infinite. Note the previous check eliminated the
84 * possibility that the low fields are NaNs.
85 */
86 if (isnan(box->high.x) || isnan(box->high.y))
87 return get_float8_infinity();
88 return float8_mul(float8_mi(box->high.x, box->low.x),
89 float8_mi(box->high.y, box->low.y));
90}
static float8 float8_mul(const float8 val1, const float8 val2)
Definition: float.h:208
static float8 get_float8_infinity(void)
Definition: float.h:94

References float8_le(), float8_mi(), float8_mul(), get_float8_infinity(), BOX::high, BOX::low, Point::x, and Point::y.

Referenced by box_penalty().