LCOV - differential code coverage report
Current view: top level - contrib/seg - seg.c (source / functions) Coverage Total Hit UNC LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 74.9 % 431 323 1 9 40 58 6 179 4 134 44 179 1
Current Date: 2023-04-08 17:13:01 Functions: 87.9 % 66 58 8 58 8 58
Baseline: 15 Line coverage date bins:
Baseline Date: 2023-04-08 15:09:40 (60,120] days: 80.0 % 5 4 1 2 2 1
Legend: Lines: hit not hit (180,240] days: 66.7 % 3 2 1 2
(240..) days: 74.9 % 423 317 8 40 58 6 177 134 43 179
Function coverage date bins:
(240..) days: 43.9 % 132 58 8 58 8 58

 Age         Owner                  TLA  Line data    Source code
                                  1                 : /*
                                  2                 :  * contrib/seg/seg.c
                                  3                 :  *
                                  4                 :  ******************************************************************************
                                  5                 :   This file contains routines that can be bound to a Postgres backend and
                                  6                 :   called by the backend in the process of processing queries.  The calling
                                  7                 :   format for these routines is dictated by Postgres architecture.
                                  8                 : ******************************************************************************/
                                  9                 : 
                                 10                 : #include "postgres.h"
                                 11                 : 
                                 12                 : #include <float.h>
                                 13                 : #include <math.h>
                                 14                 : 
                                 15                 : #include "access/gist.h"
                                 16                 : #include "access/stratnum.h"
                                 17                 : #include "fmgr.h"
                                 18                 : 
                                 19                 : #include "segdata.h"
                                 20                 : 
                                 21                 : 
                                 22                 : #define DatumGetSegP(X) ((SEG *) DatumGetPointer(X))
                                 23                 : #define PG_GETARG_SEG_P(n) DatumGetSegP(PG_GETARG_DATUM(n))
                                 24                 : 
                                 25                 : 
                                 26                 : /*
                                 27                 : #define GIST_DEBUG
                                 28                 : #define GIST_QUERY_DEBUG
                                 29                 : */
                                 30                 : 
 6158 tgl                        31 GIC           1 : PG_MODULE_MAGIC;
 6158 tgl                        32 ECB             : 
                                 33                 : /*
                                 34                 :  * Auxiliary data structure for picksplit method.
                                 35                 :  */
                                 36                 : typedef struct
                                 37                 : {
                                 38                 :     float       center;
                                 39                 :     OffsetNumber index;
                                 40                 :     SEG        *data;
                                 41                 : } gseg_picksplit_item;
                                 42                 : 
                                 43                 : /*
                                 44                 : ** Input/Output routines
                                 45                 : */
 5469 alvherre                   46 GIC           2 : PG_FUNCTION_INFO_V1(seg_in);
 5469 alvherre                   47 CBC           2 : PG_FUNCTION_INFO_V1(seg_out);
 5468 tgl                        48               1 : PG_FUNCTION_INFO_V1(seg_size);
 5469 alvherre                   49               2 : PG_FUNCTION_INFO_V1(seg_lower);
                                 50               2 : PG_FUNCTION_INFO_V1(seg_upper);
                                 51               2 : PG_FUNCTION_INFO_V1(seg_center);
 5469 alvherre                   52 ECB             : 
                                 53                 : /*
                                 54                 : ** GiST support methods
                                 55                 : */
 2202 andres                     56 GIC           2 : PG_FUNCTION_INFO_V1(gseg_consistent);
 2202 andres                     57 CBC           1 : PG_FUNCTION_INFO_V1(gseg_compress);
                                 58               1 : PG_FUNCTION_INFO_V1(gseg_decompress);
                                 59               2 : PG_FUNCTION_INFO_V1(gseg_picksplit);
                                 60               2 : PG_FUNCTION_INFO_V1(gseg_penalty);
                                 61               2 : PG_FUNCTION_INFO_V1(gseg_union);
                                 62               2 : PG_FUNCTION_INFO_V1(gseg_same);
 2202 andres                     63 ECB             : static Datum gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy);
                                 64                 : static Datum gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy);
                                 65                 : static Datum gseg_binary_union(Datum r1, Datum r2, int *sizep);
                                 66                 : 
                                 67                 : 
                                 68                 : /*
                                 69                 : ** R-tree support functions
                                 70                 : */
 2202 andres                     71 GIC           2 : PG_FUNCTION_INFO_V1(seg_same);
 2202 andres                     72 CBC           2 : PG_FUNCTION_INFO_V1(seg_contains);
                                 73               2 : PG_FUNCTION_INFO_V1(seg_contained);
                                 74               2 : PG_FUNCTION_INFO_V1(seg_overlap);
                                 75               2 : PG_FUNCTION_INFO_V1(seg_left);
                                 76               2 : PG_FUNCTION_INFO_V1(seg_over_left);
                                 77               2 : PG_FUNCTION_INFO_V1(seg_right);
                                 78               2 : PG_FUNCTION_INFO_V1(seg_over_right);
                                 79               1 : PG_FUNCTION_INFO_V1(seg_union);
                                 80               1 : PG_FUNCTION_INFO_V1(seg_inter);
 2202 andres                     81 ECB             : static void rt_seg_size(SEG *a, float *size);
                                 82                 : 
                                 83                 : /*
                                 84                 : ** Various operators
                                 85                 : */
 2202 andres                     86 GIC           2 : PG_FUNCTION_INFO_V1(seg_cmp);
 2202 andres                     87 CBC           1 : PG_FUNCTION_INFO_V1(seg_lt);
                                 88               1 : PG_FUNCTION_INFO_V1(seg_le);
                                 89               1 : PG_FUNCTION_INFO_V1(seg_gt);
                                 90               1 : PG_FUNCTION_INFO_V1(seg_ge);
                                 91               2 : PG_FUNCTION_INFO_V1(seg_different);
 8053 bruce                      92 ECB             : 
                                 93                 : /*
                                 94                 : ** Auxiliary functions
                                 95                 : */
                                 96                 : static int  restore(char *result, float val, int n);
                                 97                 : 
                                 98                 : 
                                 99                 : /*****************************************************************************
                                100                 :  * Input/Output functions
                                101                 :  *****************************************************************************/
                                102                 : 
                                103                 : Datum
 5469 alvherre                  104 GIC        2823 : seg_in(PG_FUNCTION_ARGS)
 8154 tgl                       105 ECB             : {
 5469 alvherre                  106 GIC        2823 :     char       *str = PG_GETARG_CSTRING(0);
 8053 bruce                     107 CBC        2823 :     SEG        *result = palloc(sizeof(SEG));
 8053 bruce                     108 ECB             : 
 7147 tgl                       109 GIC        2823 :     seg_scanner_init(str);
 8053 bruce                     110 ECB             : 
  107 andrew                    111 GNC        2823 :     if (seg_yyparse(result, fcinfo->context) != 0)
                                112               8 :         seg_yyerror(result, fcinfo->context, "bogus input");
 7147 tgl                       113 ECB             : 
 7147 tgl                       114 GIC        2814 :     seg_scanner_finish();
 7147 tgl                       115 ECB             : 
 5469 alvherre                  116 GIC        2814 :     PG_RETURN_POINTER(result);
 8154 tgl                       117 ECB             : }
                                118                 : 
                                119                 : Datum
 5469 alvherre                  120 GIC         209 : seg_out(PG_FUNCTION_ARGS)
 8154 tgl                       121 ECB             : {
 2202 andres                    122 GIC         209 :     SEG        *seg = PG_GETARG_SEG_P(0);
 8053 bruce                     123 ECB             :     char       *result;
                                124                 :     char       *p;
                                125                 : 
 8053 bruce                     126 GIC         209 :     p = result = (char *) palloc(40);
 8053 bruce                     127 ECB             : 
 8053 bruce                     128 GIC         209 :     if (seg->l_ext == '>' || seg->l_ext == '<' || seg->l_ext == '~')
 8053 bruce                     129 CBC          22 :         p += sprintf(p, "%c", seg->l_ext);
 8053 bruce                     130 ECB             : 
 8053 bruce                     131 GIC         209 :     if (seg->lower == seg->upper && seg->l_ext == seg->u_ext)
 8053 bruce                     132 ECB             :     {
                                133                 :         /*
                                134                 :          * indicates that this interval was built by seg_in off a single point
                                135                 :          */
 8053 bruce                     136 GIC          47 :         p += restore(p, seg->lower, seg->l_sigd);
 8053 bruce                     137 ECB             :     }
                                138                 :     else
                                139                 :     {
 8053 bruce                     140 GIC         162 :         if (seg->l_ext != '-')
 8053 bruce                     141 ECB             :         {
                                142                 :             /* print the lower boundary if exists */
 8053 bruce                     143 GIC         155 :             p += restore(p, seg->lower, seg->l_sigd);
 8053 bruce                     144 CBC         155 :             p += sprintf(p, " ");
 8053 bruce                     145 ECB             :         }
 8053 bruce                     146 GIC         162 :         p += sprintf(p, "..");
 8053 bruce                     147 CBC         162 :         if (seg->u_ext != '-')
 8053 bruce                     148 ECB             :         {
                                149                 :             /* print the upper boundary if exists */
 8053 bruce                     150 GIC         123 :             p += sprintf(p, " ");
 8053 bruce                     151 CBC         123 :             if (seg->u_ext == '>' || seg->u_ext == '<' || seg->l_ext == '~')
                                152              32 :                 p += sprintf(p, "%c", seg->u_ext);
                                153             123 :             p += restore(p, seg->upper, seg->u_sigd);
 8053 bruce                     154 ECB             :         }
                                155                 :     }
                                156                 : 
 5469 alvherre                  157 GIC         209 :     PG_RETURN_CSTRING(result);
 8154 tgl                       158 ECB             : }
                                159                 : 
                                160                 : Datum
 5469 alvherre                  161 GIC         143 : seg_center(PG_FUNCTION_ARGS)
 8154 tgl                       162 ECB             : {
 2202 andres                    163 GIC         143 :     SEG        *seg = PG_GETARG_SEG_P(0);
 5469 alvherre                  164 ECB             : 
 5469 alvherre                  165 GIC         143 :     PG_RETURN_FLOAT4(((float) seg->lower + (float) seg->upper) / 2.0);
 8154 tgl                       166 ECB             : }
                                167                 : 
                                168                 : Datum
 5469 alvherre                  169 GIC         143 : seg_lower(PG_FUNCTION_ARGS)
 8154 tgl                       170 ECB             : {
 2202 andres                    171 GIC         143 :     SEG        *seg = PG_GETARG_SEG_P(0);
 5469 alvherre                  172 ECB             : 
 5469 alvherre                  173 GIC         143 :     PG_RETURN_FLOAT4(seg->lower);
 8154 tgl                       174 ECB             : }
                                175                 : 
                                176                 : Datum
 5469 alvherre                  177 GIC         143 : seg_upper(PG_FUNCTION_ARGS)
 8154 tgl                       178 ECB             : {
 2202 andres                    179 GIC         143 :     SEG        *seg = PG_GETARG_SEG_P(0);
 5469 alvherre                  180 ECB             : 
 5469 alvherre                  181 GIC         143 :     PG_RETURN_FLOAT4(seg->upper);
 8154 tgl                       182 ECB             : }
                                183                 : 
                                184                 : 
                                185                 : /*****************************************************************************
                                186                 :  *                         GiST functions
                                187                 :  *****************************************************************************/
                                188                 : 
                                189                 : /*
                                190                 : ** The GiST Consistent method for segments
                                191                 : ** Should return false if for all data items x below entry,
                                192                 : ** the predicate x op query == false, where op is the oper
                                193                 : ** corresponding to strategy in the pg_amop table.
                                194                 : */
                                195                 : Datum
 2202 andres                    196 GIC        5892 : gseg_consistent(PG_FUNCTION_ARGS)
 8154 tgl                       197 ECB             : {
 2202 andres                    198 GIC        5892 :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
 2202 andres                    199 CBC        5892 :     Datum       query = PG_GETARG_DATUM(1);
                                200            5892 :     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
 2202 andres                    201 ECB             : 
                                202                 :     /* Oid      subtype = PG_GETARG_OID(3); */
 2202 andres                    203 GIC        5892 :     bool       *recheck = (bool *) PG_GETARG_POINTER(4);
 2202 andres                    204 ECB             : 
                                205                 :     /* All cases served by this function are exact */
 5473 tgl                       206 GIC        5892 :     *recheck = false;
 5473 tgl                       207 ECB             : 
                                208                 :     /*
                                209                 :      * if entry is not leaf, use gseg_internal_consistent, else use
                                210                 :      * gseg_leaf_consistent
                                211                 :      */
 8053 bruce                     212 GIC        5892 :     if (GIST_LEAF(entry))
 2202 andres                    213 CBC        5820 :         return gseg_leaf_consistent(entry->key, query, strategy);
 8053 bruce                     214 ECB             :     else
 2202 andres                    215 GIC          72 :         return gseg_internal_consistent(entry->key, query, strategy);
 8154 tgl                       216 ECB             : }
                                217                 : 
                                218                 : /*
                                219                 : ** The GiST Union method for segments
                                220                 : ** returns the minimal bounding seg that encloses all the entries in entryvec
                                221                 : */
                                222                 : Datum
 2202 andres                    223 GIC        2316 : gseg_union(PG_FUNCTION_ARGS)
 8154 tgl                       224 ECB             : {
 2202 andres                    225 GIC        2316 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 2202 andres                    226 CBC        2316 :     int        *sizep = (int *) PG_GETARG_POINTER(1);
 8053 bruce                     227 ECB             :     int         numranges,
                                228                 :                 i;
 2202 andres                    229 GIC        2316 :     Datum       out = 0;
 2202 andres                    230 ECB             :     Datum       tmp;
                                231                 : 
                                232                 : #ifdef GIST_DEBUG
                                233                 :     fprintf(stderr, "union\n");
                                234                 : #endif
                                235                 : 
 6949 teodor                    236 GIC        2316 :     numranges = entryvec->n;
 2202 andres                    237 CBC        2316 :     tmp = entryvec->vector[0].key;
 8053 bruce                     238            2316 :     *sizep = sizeof(SEG);
 8154 tgl                       239 ECB             : 
 8053 bruce                     240 GIC        4632 :     for (i = 1; i < numranges; i++)
 8053 bruce                     241 ECB             :     {
 2202 andres                    242 GIC        2316 :         out = gseg_binary_union(tmp, entryvec->vector[i].key, sizep);
 8053 bruce                     243 CBC        2316 :         tmp = out;
 8053 bruce                     244 ECB             :     }
                                245                 : 
 2202 andres                    246 GIC        2316 :     PG_RETURN_DATUM(out);
 8154 tgl                       247 ECB             : }
                                248                 : 
                                249                 : /*
                                250                 : ** GiST Compress and Decompress methods for segments
                                251                 : ** do not do anything.
                                252                 : */
                                253                 : Datum
 2202 andres                    254 UIC           0 : gseg_compress(PG_FUNCTION_ARGS)
 8154 tgl                       255 EUB             : {
 2202 andres                    256 UIC           0 :     PG_RETURN_POINTER(PG_GETARG_POINTER(0));
 8154 tgl                       257 EUB             : }
                                258                 : 
                                259                 : Datum
 2202 andres                    260 UIC           0 : gseg_decompress(PG_FUNCTION_ARGS)
 8154 tgl                       261 EUB             : {
 2202 andres                    262 UIC           0 :     PG_RETURN_POINTER(PG_GETARG_POINTER(0));
 8154 tgl                       263 EUB             : }
                                264                 : 
                                265                 : /*
                                266                 : ** The GiST Penalty method for segments
                                267                 : ** As in the R-tree paper, we use change in area as our penalty metric
                                268                 : */
                                269                 : Datum
 2202 andres                    270 GIC        5157 : gseg_penalty(PG_FUNCTION_ARGS)
 8154 tgl                       271 ECB             : {
 2202 andres                    272 GIC        5157 :     GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
 2202 andres                    273 CBC        5157 :     GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
                                274            5157 :     float      *result = (float *) PG_GETARG_POINTER(2);
 7983 tgl                       275 ECB             :     SEG        *ud;
                                276                 :     float       tmp1,
                                277                 :                 tmp2;
                                278                 : 
 2202 andres                    279 GIC        5157 :     ud = DatumGetSegP(DirectFunctionCall2(seg_union,
 2202 andres                    280 ECB             :                                           origentry->key,
                                281                 :                                           newentry->key));
 7983 tgl                       282 GIC        5157 :     rt_seg_size(ud, &tmp1);
 2202 andres                    283 CBC        5157 :     rt_seg_size(DatumGetSegP(origentry->key), &tmp2);
 8053 bruce                     284            5157 :     *result = tmp1 - tmp2;
 8154 tgl                       285 ECB             : 
                                286                 : #ifdef GIST_DEBUG
                                287                 :     fprintf(stderr, "penalty\n");
                                288                 :     fprintf(stderr, "\t%g\n", *result);
                                289                 : #endif
                                290                 : 
 2202 andres                    291 GIC        5157 :     PG_RETURN_POINTER(result);
 8154 tgl                       292 ECB             : }
                                293                 : 
                                294                 : /*
                                295                 :  * Compare function for gseg_picksplit_item: sort by center.
                                296                 :  */
                                297                 : static int
 4498 tgl                       298 GIC       29102 : gseg_picksplit_item_cmp(const void *a, const void *b)
 4498 tgl                       299 ECB             : {
 4498 tgl                       300 GIC       29102 :     const gseg_picksplit_item *i1 = (const gseg_picksplit_item *) a;
 4498 tgl                       301 CBC       29102 :     const gseg_picksplit_item *i2 = (const gseg_picksplit_item *) b;
 8154 tgl                       302 ECB             : 
 4498 tgl                       303 GIC       29102 :     if (i1->center < i2->center)
 4498 tgl                       304 CBC       11931 :         return -1;
                                305           17171 :     else if (i1->center == i2->center)
                                306            5238 :         return 0;
 4498 tgl                       307 ECB             :     else
 4498 tgl                       308 GIC       11933 :         return 1;
 4498 tgl                       309 ECB             : }
                                310                 : 
                                311                 : /*
                                312                 :  * The GiST PickSplit method for segments
                                313                 :  *
                                314                 :  * We used to use Guttman's split algorithm here, but since the data is 1-D
                                315                 :  * it's easier and more robust to just sort the segments by center-point and
                                316                 :  * split at the middle.
                                317                 :  */
                                318                 : Datum
 2202 andres                    319 GIC          17 : gseg_picksplit(PG_FUNCTION_ARGS)
 8154 tgl                       320 ECB             : {
 2202 andres                    321 GIC          17 :     GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
 2202 andres                    322 CBC          17 :     GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
 4498 tgl                       323 ECB             :     int         i;
                                324                 :     SEG        *seg,
                                325                 :                *seg_l,
                                326                 :                *seg_r;
                                327                 :     gseg_picksplit_item *sort_items;
                                328                 :     OffsetNumber *left,
                                329                 :                *right;
                                330                 :     OffsetNumber maxoff;
                                331                 :     OffsetNumber firstright;
                                332                 : 
                                333                 : #ifdef GIST_DEBUG
                                334                 :     fprintf(stderr, "picksplit\n");
                                335                 : #endif
                                336                 : 
                                337                 :     /* Valid items in entryvec->vector[] are indexed 1..maxoff */
 4498 tgl                       338 GIC          17 :     maxoff = entryvec->n - 1;
 8053 bruce                     339 ECB             : 
                                340                 :     /*
                                341                 :      * Prepare the auxiliary array and sort it.
                                342                 :      */
                                343                 :     sort_items = (gseg_picksplit_item *)
 4498 tgl                       344 GIC          17 :         palloc(maxoff * sizeof(gseg_picksplit_item));
 4498 tgl                       345 CBC        4471 :     for (i = 1; i <= maxoff; i++)
 8053 bruce                     346 ECB             :     {
 2202 andres                    347 GIC        4454 :         seg = DatumGetSegP(entryvec->vector[i].key);
 4498 tgl                       348 ECB             :         /* center calculation is done this way to avoid possible overflow */
 4382 bruce                     349 GIC        4454 :         sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f;
 4498 tgl                       350 CBC        4454 :         sort_items[i - 1].index = i;
                                351            4454 :         sort_items[i - 1].data = seg;
 8154 tgl                       352 ECB             :     }
 4498 tgl                       353 GIC          17 :     qsort(sort_items, maxoff, sizeof(gseg_picksplit_item),
 4498 tgl                       354 ECB             :           gseg_picksplit_item_cmp);
                                355                 : 
                                356                 :     /* sort items below "firstright" will go into the left side */
 4498 tgl                       357 GIC          17 :     firstright = maxoff / 2;
 8053 bruce                     358 ECB             : 
 4498 tgl                       359 GIC          17 :     v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
 4498 tgl                       360 CBC          17 :     v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
 8053 bruce                     361              17 :     left = v->spl_left;
                                362              17 :     v->spl_nleft = 0;
                                363              17 :     right = v->spl_right;
                                364              17 :     v->spl_nright = 0;
 8053 bruce                     365 ECB             : 
                                366                 :     /*
                                367                 :      * Emit segments to the left output page, and compute its bounding box.
                                368                 :      */
 2202 andres                    369 GIC          17 :     seg_l = (SEG *) palloc(sizeof(SEG));
 2202 andres                    370 CBC          17 :     memcpy(seg_l, sort_items[0].data, sizeof(SEG));
 4498 tgl                       371              17 :     *left++ = sort_items[0].index;
                                372              17 :     v->spl_nleft++;
                                373            2227 :     for (i = 1; i < firstright; i++)
 8053 bruce                     374 ECB             :     {
 2202 andres                    375 GIC        2210 :         Datum       sortitem = PointerGetDatum(sort_items[i].data);
 2202 andres                    376 ECB             : 
 2202 andres                    377 GIC        2210 :         seg_l = DatumGetSegP(DirectFunctionCall2(seg_union,
 2202 andres                    378 ECB             :                                                  PointerGetDatum(seg_l),
                                379                 :                                                  sortitem));
 4498 tgl                       380 GIC        2210 :         *left++ = sort_items[i].index;
 4498 tgl                       381 CBC        2210 :         v->spl_nleft++;
 4498 tgl                       382 ECB             :     }
                                383                 : 
                                384                 :     /*
                                385                 :      * Likewise for the right page.
                                386                 :      */
 2202 andres                    387 GIC          17 :     seg_r = (SEG *) palloc(sizeof(SEG));
 2202 andres                    388 CBC          17 :     memcpy(seg_r, sort_items[firstright].data, sizeof(SEG));
 4498 tgl                       389              17 :     *right++ = sort_items[firstright].index;
                                390              17 :     v->spl_nright++;
                                391            2227 :     for (i = firstright + 1; i < maxoff; i++)
 4498 tgl                       392 ECB             :     {
 2202 andres                    393 GIC        2210 :         Datum       sortitem = PointerGetDatum(sort_items[i].data);
 2202 andres                    394 ECB             : 
 2202 andres                    395 GIC        2210 :         seg_r = DatumGetSegP(DirectFunctionCall2(seg_union,
 2202 andres                    396 ECB             :                                                  PointerGetDatum(seg_r),
                                397                 :                                                  sortitem));
 4498 tgl                       398 GIC        2210 :         *right++ = sort_items[i].index;
 4498 tgl                       399 CBC        2210 :         v->spl_nright++;
 8154 tgl                       400 ECB             :     }
                                401                 : 
 2202 andres                    402 GIC          17 :     v->spl_ldatum = PointerGetDatum(seg_l);
 2202 andres                    403 CBC          17 :     v->spl_rdatum = PointerGetDatum(seg_r);
 8154 tgl                       404 ECB             : 
 2202 andres                    405 GIC          17 :     PG_RETURN_POINTER(v);
 8154 tgl                       406 ECB             : }
                                407                 : 
                                408                 : /*
                                409                 : ** Equality methods
                                410                 : */
                                411                 : Datum
 2202 andres                    412 GIC        2315 : gseg_same(PG_FUNCTION_ARGS)
 8154 tgl                       413 ECB             : {
 2202 andres                    414 GIC        2315 :     bool       *result = (bool *) PG_GETARG_POINTER(2);
 2202 andres                    415 ECB             : 
 2202 andres                    416 GIC        2315 :     if (DirectFunctionCall2(seg_same, PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)))
 2062 peter_e                   417 CBC        2286 :         *result = true;
 8053 bruce                     418 ECB             :     else
 2062 peter_e                   419 GIC          29 :         *result = false;
 8154 tgl                       420 ECB             : 
                                421                 : #ifdef GIST_DEBUG
                                422                 :     fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE"));
                                423                 : #endif
                                424                 : 
 2202 andres                    425 GIC        2315 :     PG_RETURN_POINTER(result);
 8154 tgl                       426 ECB             : }
                                427                 : 
                                428                 : /*
                                429                 : ** SUPPORT ROUTINES
                                430                 : */
                                431                 : static Datum
 2202 andres                    432 GIC        5820 : gseg_leaf_consistent(Datum key, Datum query, StrategyNumber strategy)
 8154 tgl                       433 ECB             : {
                                434                 :     Datum       retval;
                                435                 : 
                                436                 : #ifdef GIST_QUERY_DEBUG
                                437                 :     fprintf(stderr, "leaf_consistent, %d\n", strategy);
                                438                 : #endif
                                439                 : 
 8053 bruce                     440 GIC        5820 :     switch (strategy)
 8053 bruce                     441 ECB             :     {
 8053 bruce                     442 UIC           0 :         case RTLeftStrategyNumber:
 2202 andres                    443 UBC           0 :             retval = DirectFunctionCall2(seg_left, key, query);
 8053 bruce                     444               0 :             break;
                                445               0 :         case RTOverLeftStrategyNumber:
 2202 andres                    446               0 :             retval = DirectFunctionCall2(seg_over_left, key, query);
 8053 bruce                     447               0 :             break;
                                448               0 :         case RTOverlapStrategyNumber:
 2202 andres                    449               0 :             retval = DirectFunctionCall2(seg_overlap, key, query);
 8053 bruce                     450               0 :             break;
                                451               0 :         case RTOverRightStrategyNumber:
 2202 andres                    452               0 :             retval = DirectFunctionCall2(seg_over_right, key, query);
 8053 bruce                     453               0 :             break;
                                454               0 :         case RTRightStrategyNumber:
 2202 andres                    455               0 :             retval = DirectFunctionCall2(seg_right, key, query);
 8053 bruce                     456               0 :             break;
                                457               0 :         case RTSameStrategyNumber:
 2202 andres                    458               0 :             retval = DirectFunctionCall2(seg_same, key, query);
 8053 bruce                     459               0 :             break;
 8053 bruce                     460 GBC        5820 :         case RTContainsStrategyNumber:
 6055 tgl                       461 ECB             :         case RTOldContainsStrategyNumber:
 2202 andres                    462 GIC        5820 :             retval = DirectFunctionCall2(seg_contains, key, query);
 8053 bruce                     463 CBC        5820 :             break;
 8053 bruce                     464 LBC           0 :         case RTContainedByStrategyNumber:
 6055 tgl                       465 EUB             :         case RTOldContainedByStrategyNumber:
 2202 andres                    466 UIC           0 :             retval = DirectFunctionCall2(seg_contained, key, query);
 8053 bruce                     467 UBC           0 :             break;
                                468               0 :         default:
 2062 peter_e                   469               0 :             retval = false;
 8053 bruce                     470 EUB             :     }
                                471                 : 
 2202 andres                    472 GIC        5820 :     PG_RETURN_DATUM(retval);
 8154 tgl                       473 ECB             : }
                                474                 : 
                                475                 : static Datum
 2202 andres                    476 GIC          72 : gseg_internal_consistent(Datum key, Datum query, StrategyNumber strategy)
 8154 tgl                       477 ECB             : {
                                478                 :     bool        retval;
                                479                 : 
                                480                 : #ifdef GIST_QUERY_DEBUG
                                481                 :     fprintf(stderr, "internal_consistent, %d\n", strategy);
                                482                 : #endif
                                483                 : 
 8053 bruce                     484 GIC          72 :     switch (strategy)
 8053 bruce                     485 ECB             :     {
 8053 bruce                     486 UIC           0 :         case RTLeftStrategyNumber:
 2202 andres                    487 UBC           0 :             retval =
                                488               0 :                 !DatumGetBool(DirectFunctionCall2(seg_over_right, key, query));
 6495 tgl                       489               0 :             break;
 8053 bruce                     490               0 :         case RTOverLeftStrategyNumber:
 2202 andres                    491               0 :             retval =
                                492               0 :                 !DatumGetBool(DirectFunctionCall2(seg_right, key, query));
 8053 bruce                     493               0 :             break;
                                494               0 :         case RTOverlapStrategyNumber:
 2202 andres                    495 EUB             :             retval =
 2202 andres                    496 UIC           0 :                 DatumGetBool(DirectFunctionCall2(seg_overlap, key, query));
 8053 bruce                     497 UBC           0 :             break;
                                498               0 :         case RTOverRightStrategyNumber:
 2202 andres                    499               0 :             retval =
                                500               0 :                 !DatumGetBool(DirectFunctionCall2(seg_left, key, query));
 6495 tgl                       501               0 :             break;
 8053 bruce                     502               0 :         case RTRightStrategyNumber:
 2202 andres                    503               0 :             retval =
                                504               0 :                 !DatumGetBool(DirectFunctionCall2(seg_over_left, key, query));
 8053 bruce                     505               0 :             break;
 8053 bruce                     506 GBC          72 :         case RTSameStrategyNumber:
 8053 bruce                     507 ECB             :         case RTContainsStrategyNumber:
                                508                 :         case RTOldContainsStrategyNumber:
                                509                 :             retval =
 2202 andres                    510 GIC          72 :                 DatumGetBool(DirectFunctionCall2(seg_contains, key, query));
 8053 bruce                     511 CBC          72 :             break;
 8053 bruce                     512 LBC           0 :         case RTContainedByStrategyNumber:
 6055 tgl                       513 EUB             :         case RTOldContainedByStrategyNumber:
                                514                 :             retval =
 2202 andres                    515 UIC           0 :                 DatumGetBool(DirectFunctionCall2(seg_overlap, key, query));
 8053 bruce                     516 UBC           0 :             break;
                                517               0 :         default:
 2062 peter_e                   518               0 :             retval = false;
 8053 bruce                     519 EUB             :     }
                                520                 : 
 2202 andres                    521 GIC          72 :     PG_RETURN_BOOL(retval);
 8154 tgl                       522 ECB             : }
                                523                 : 
                                524                 : static Datum
 2202 andres                    525 GIC        2316 : gseg_binary_union(Datum r1, Datum r2, int *sizep)
 8154 tgl                       526 ECB             : {
                                527                 :     Datum       retval;
                                528                 : 
 2202 andres                    529 GIC        2316 :     retval = DirectFunctionCall2(seg_union, r1, r2);
 8053 bruce                     530 CBC        2316 :     *sizep = sizeof(SEG);
 8154 tgl                       531 ECB             : 
 2061 peter_e                   532 GIC        2316 :     return retval;
 8154 tgl                       533 ECB             : }
                                534                 : 
                                535                 : 
                                536                 : Datum
 2202 andres                    537 GIC        5907 : seg_contains(PG_FUNCTION_ARGS)
 8154 tgl                       538 ECB             : {
 2202 andres                    539 GIC        5907 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    540 CBC        5907 :     SEG        *b = PG_GETARG_SEG_P(1);
 2202 andres                    541 ECB             : 
 2202 andres                    542 GIC        5907 :     PG_RETURN_BOOL((a->lower <= b->lower) && (a->upper >= b->upper));
 8154 tgl                       543 ECB             : }
                                544                 : 
                                545                 : Datum
 2202 andres                    546 GIC          14 : seg_contained(PG_FUNCTION_ARGS)
 8154 tgl                       547 ECB             : {
 2202 andres                    548 GIC          14 :     Datum       a = PG_GETARG_DATUM(0);
 2202 andres                    549 CBC          14 :     Datum       b = PG_GETARG_DATUM(1);
 2202 andres                    550 ECB             : 
 2202 andres                    551 GIC          14 :     PG_RETURN_DATUM(DirectFunctionCall2(seg_contains, b, a));
 8154 tgl                       552 ECB             : }
                                553                 : 
                                554                 : /*****************************************************************************
                                555                 :  * Operator class for R-tree indexing
                                556                 :  *****************************************************************************/
                                557                 : 
                                558                 : Datum
 2202 andres                    559 GIC        2459 : seg_same(PG_FUNCTION_ARGS)
 8154 tgl                       560 ECB             : {
 1165 alvherre                  561 GIC        2459 :     int         cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp,
 1165 alvherre                  562 ECB             :                                                         PG_GETARG_DATUM(0),
                                563                 :                                                         PG_GETARG_DATUM(1)));
                                564                 : 
 2202 andres                    565 GIC        2459 :     PG_RETURN_BOOL(cmp == 0);
 8154 tgl                       566 ECB             : }
                                567                 : 
                                568                 : /*  seg_overlap -- does a overlap b?
                                569                 :  */
                                570                 : Datum
 2202 andres                    571 GIC          15 : seg_overlap(PG_FUNCTION_ARGS)
 8154 tgl                       572 ECB             : {
 2202 andres                    573 GIC          15 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    574 CBC          15 :     SEG        *b = PG_GETARG_SEG_P(1);
 2202 andres                    575 ECB             : 
 2202 andres                    576 GIC          15 :     PG_RETURN_BOOL(((a->upper >= b->upper) && (a->lower <= b->upper)) ||
 2202 andres                    577 ECB             :                    ((b->upper >= a->upper) && (b->lower <= a->upper)));
                                578                 : }
                                579                 : 
                                580                 : /*  seg_over_left -- is the right edge of (a) located at or left of the right edge of (b)?
                                581                 :  */
                                582                 : Datum
 2202 andres                    583 GIC          11 : seg_over_left(PG_FUNCTION_ARGS)
 8154 tgl                       584 ECB             : {
 2202 andres                    585 GIC          11 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    586 CBC          11 :     SEG        *b = PG_GETARG_SEG_P(1);
 2202 andres                    587 ECB             : 
 2202 andres                    588 GIC          11 :     PG_RETURN_BOOL(a->upper <= b->upper);
 8154 tgl                       589 ECB             : }
                                590                 : 
                                591                 : /*  seg_left -- is (a) entirely on the left of (b)?
                                592                 :  */
                                593                 : Datum
 2202 andres                    594 GIC          11 : seg_left(PG_FUNCTION_ARGS)
 8154 tgl                       595 ECB             : {
 2202 andres                    596 GIC          11 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    597 CBC          11 :     SEG        *b = PG_GETARG_SEG_P(1);
 2202 andres                    598 ECB             : 
 2202 andres                    599 GIC          11 :     PG_RETURN_BOOL(a->upper < b->lower);
 8154 tgl                       600 ECB             : }
                                601                 : 
                                602                 : /*  seg_right -- is (a) entirely on the right of (b)?
                                603                 :  */
                                604                 : Datum
 2202 andres                    605 GIC          11 : seg_right(PG_FUNCTION_ARGS)
 8154 tgl                       606 ECB             : {
 2202 andres                    607 GIC          11 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    608 CBC          11 :     SEG        *b = PG_GETARG_SEG_P(1);
 2202 andres                    609 ECB             : 
 2202 andres                    610 GIC          11 :     PG_RETURN_BOOL(a->lower > b->upper);
 8154 tgl                       611 ECB             : }
                                612                 : 
                                613                 : /*  seg_over_right -- is the left edge of (a) located at or right of the left edge of (b)?
                                614                 :  */
                                615                 : Datum
 2202 andres                    616 GIC          11 : seg_over_right(PG_FUNCTION_ARGS)
 8154 tgl                       617 ECB             : {
 2202 andres                    618 GIC          11 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    619 CBC          11 :     SEG        *b = PG_GETARG_SEG_P(1);
 8154 tgl                       620 ECB             : 
 2202 andres                    621 GIC          11 :     PG_RETURN_BOOL(a->lower >= b->lower);
 2202 andres                    622 ECB             : }
                                623                 : 
                                624                 : Datum
 2202 andres                    625 GIC       11893 : seg_union(PG_FUNCTION_ARGS)
 8154 tgl                       626 ECB             : {
 2202 andres                    627 GIC       11893 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    628 CBC       11893 :     SEG        *b = PG_GETARG_SEG_P(1);
 8053 bruce                     629 ECB             :     SEG        *n;
                                630                 : 
 8053 bruce                     631 GIC       11893 :     n = (SEG *) palloc(sizeof(*n));
 8053 bruce                     632 ECB             : 
                                633                 :     /* take max of upper endpoints */
 8053 bruce                     634 GIC       11893 :     if (a->upper > b->upper)
 8053 bruce                     635 ECB             :     {
 8053 bruce                     636 GIC       10498 :         n->upper = a->upper;
 8053 bruce                     637 CBC       10498 :         n->u_sigd = a->u_sigd;
                                638           10498 :         n->u_ext = a->u_ext;
 8053 bruce                     639 ECB             :     }
                                640                 :     else
                                641                 :     {
 8053 bruce                     642 GIC        1395 :         n->upper = b->upper;
 8053 bruce                     643 CBC        1395 :         n->u_sigd = b->u_sigd;
                                644            1395 :         n->u_ext = b->u_ext;
 8053 bruce                     645 ECB             :     }
                                646                 : 
                                647                 :     /* take min of lower endpoints */
 8053 bruce                     648 GIC       11893 :     if (a->lower < b->lower)
 8053 bruce                     649 ECB             :     {
 8053 bruce                     650 GIC       11597 :         n->lower = a->lower;
 8053 bruce                     651 CBC       11597 :         n->l_sigd = a->l_sigd;
                                652           11597 :         n->l_ext = a->l_ext;
 8053 bruce                     653 ECB             :     }
                                654                 :     else
                                655                 :     {
 8053 bruce                     656 GIC         296 :         n->lower = b->lower;
 8053 bruce                     657 CBC         296 :         n->l_sigd = b->l_sigd;
                                658             296 :         n->l_ext = b->l_ext;
 8053 bruce                     659 ECB             :     }
                                660                 : 
 2202 andres                    661 GIC       11893 :     PG_RETURN_POINTER(n);
 8154 tgl                       662 ECB             : }
                                663                 : 
                                664                 : Datum
 2202 andres                    665 UIC           0 : seg_inter(PG_FUNCTION_ARGS)
 8154 tgl                       666 EUB             : {
 2202 andres                    667 UIC           0 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    668 UBC           0 :     SEG        *b = PG_GETARG_SEG_P(1);
 8053 bruce                     669 EUB             :     SEG        *n;
                                670                 : 
 8053 bruce                     671 UIC           0 :     n = (SEG *) palloc(sizeof(*n));
 8053 bruce                     672 EUB             : 
                                673                 :     /* take min of upper endpoints */
 8053 bruce                     674 UIC           0 :     if (a->upper < b->upper)
 8053 bruce                     675 EUB             :     {
 8053 bruce                     676 UIC           0 :         n->upper = a->upper;
 8053 bruce                     677 UBC           0 :         n->u_sigd = a->u_sigd;
                                678               0 :         n->u_ext = a->u_ext;
 8053 bruce                     679 EUB             :     }
                                680                 :     else
                                681                 :     {
 8053 bruce                     682 UIC           0 :         n->upper = b->upper;
 8053 bruce                     683 UBC           0 :         n->u_sigd = b->u_sigd;
                                684               0 :         n->u_ext = b->u_ext;
 8053 bruce                     685 EUB             :     }
                                686                 : 
                                687                 :     /* take max of lower endpoints */
 8053 bruce                     688 UIC           0 :     if (a->lower > b->lower)
 8053 bruce                     689 EUB             :     {
 8053 bruce                     690 UIC           0 :         n->lower = a->lower;
 8053 bruce                     691 UBC           0 :         n->l_sigd = a->l_sigd;
                                692               0 :         n->l_ext = a->l_ext;
 8053 bruce                     693 EUB             :     }
                                694                 :     else
                                695                 :     {
 8053 bruce                     696 UIC           0 :         n->lower = b->lower;
 8053 bruce                     697 UBC           0 :         n->l_sigd = b->l_sigd;
                                698               0 :         n->l_ext = b->l_ext;
 8053 bruce                     699 EUB             :     }
                                700                 : 
 2202 andres                    701 UIC           0 :     PG_RETURN_POINTER(n);
 8154 tgl                       702 EUB             : }
                                703                 : 
                                704                 : static void
 5050 bruce                     705 GIC       10314 : rt_seg_size(SEG *a, float *size)
 8154 tgl                       706 ECB             : {
 8053 bruce                     707 GIC       10314 :     if (a == (SEG *) NULL || a->upper <= a->lower)
 8053 bruce                     708 LBC           0 :         *size = 0.0;
 8053 bruce                     709 EUB             :     else
  183 peter                     710 GNC       10314 :         *size = fabsf(a->upper - a->lower);
 8154 tgl                       711 CBC       10314 : }
 8154 tgl                       712 ECB             : 
                                713                 : Datum
 5468 tgl                       714 UIC           0 : seg_size(PG_FUNCTION_ARGS)
 8154 tgl                       715 EUB             : {
 2202 andres                    716 UIC           0 :     SEG        *seg = PG_GETARG_SEG_P(0);
 8154 tgl                       717 EUB             : 
  183 peter                     718 UNC           0 :     PG_RETURN_FLOAT4(fabsf(seg->upper - seg->lower));
 8154 tgl                       719 EUB             : }
                                720                 : 
                                721                 : 
                                722                 : /*****************************************************************************
                                723                 :  *                 Miscellaneous operators
                                724                 :  *****************************************************************************/
                                725                 : Datum
 2202 andres                    726 GIC        4433 : seg_cmp(PG_FUNCTION_ARGS)
 8154 tgl                       727 ECB             : {
 2202 andres                    728 GIC        4433 :     SEG        *a = PG_GETARG_SEG_P(0);
 2202 andres                    729 CBC        4433 :     SEG        *b = PG_GETARG_SEG_P(1);
 2202 andres                    730 ECB             : 
                                731                 :     /*
                                732                 :      * First compare on lower boundary position
                                733                 :      */
 8053 bruce                     734 GIC        4433 :     if (a->lower < b->lower)
 2202 andres                    735 CBC         904 :         PG_RETURN_INT32(-1);
 8053 bruce                     736            3529 :     if (a->lower > b->lower)
 2202 andres                    737             801 :         PG_RETURN_INT32(1);
 8053 bruce                     738 ECB             : 
                                739                 :     /*
                                740                 :      * a->lower == b->lower, so consider type of boundary.
                                741                 :      *
                                742                 :      * A '-' lower bound is < any other kind (this could only be relevant if
                                743                 :      * -HUGE_VAL is used as a regular data value). A '<' lower bound is < any
                                744                 :      * other kind except '-'. A '>' lower bound is > any other kind.
                                745                 :      */
 8053 bruce                     746 GIC        2728 :     if (a->l_ext != b->l_ext)
 8154 tgl                       747 ECB             :     {
 8053 bruce                     748 GIC          66 :         if (a->l_ext == '-')
 2202 andres                    749 LBC           0 :             PG_RETURN_INT32(-1);
 8053 bruce                     750 GBC          66 :         if (b->l_ext == '-')
 2202 andres                    751 LBC           0 :             PG_RETURN_INT32(1);
 8053 bruce                     752 GBC          66 :         if (a->l_ext == '<')
 2202 andres                    753 CBC          26 :             PG_RETURN_INT32(-1);
 8053 bruce                     754              40 :         if (b->l_ext == '<')
 2202 andres                    755              21 :             PG_RETURN_INT32(1);
 8053 bruce                     756              19 :         if (a->l_ext == '>')
 2202 andres                    757              13 :             PG_RETURN_INT32(1);
 8053 bruce                     758               6 :         if (b->l_ext == '>')
 2202 andres                    759               6 :             PG_RETURN_INT32(-1);
 8154 tgl                       760 ECB             :     }
                                761                 : 
                                762                 :     /*
                                763                 :      * For other boundary types, consider # of significant digits first.
                                764                 :      */
 6385 bruce                     765 GIC        2662 :     if (a->l_sigd < b->l_sigd) /* (a) is blurred and is likely to include (b) */
 2202 andres                    766 CBC          18 :         PG_RETURN_INT32(-1);
 8053 bruce                     767            2644 :     if (a->l_sigd > b->l_sigd) /* (a) is less blurred and is likely to be
 8053 bruce                     768 ECB             :                                  * included in (b) */
 2202 andres                    769 GIC          18 :         PG_RETURN_INT32(1);
 8053 bruce                     770 ECB             : 
                                771                 :     /*
                                772                 :      * For same # of digits, an approximate boundary is more blurred than
                                773                 :      * exact.
                                774                 :      */
 8053 bruce                     775 GIC        2626 :     if (a->l_ext != b->l_ext)
 8154 tgl                       776 ECB             :     {
 8053 bruce                     777 UIC           0 :         if (a->l_ext == '~') /* (a) is approximate, while (b) is exact */
 2202 andres                    778 UBC           0 :             PG_RETURN_INT32(-1);
 8053 bruce                     779               0 :         if (b->l_ext == '~')
 2202 andres                    780               0 :             PG_RETURN_INT32(1);
 8154 tgl                       781 EUB             :         /* can't get here unless data is corrupt */
 7199 tgl                       782 UIC           0 :         elog(ERROR, "bogus lower boundary types %d %d",
 8154 tgl                       783 EUB             :              (int) a->l_ext, (int) b->l_ext);
                                784                 :     }
                                785                 : 
                                786                 :     /* at this point, the lower boundaries are identical */
                                787                 : 
                                788                 :     /*
                                789                 :      * First compare on upper boundary position
                                790                 :      */
 8053 bruce                     791 GIC        2626 :     if (a->upper < b->upper)
 2202 andres                    792 CBC         164 :         PG_RETURN_INT32(-1);
 8053 bruce                     793            2462 :     if (a->upper > b->upper)
 2202 andres                    794             126 :         PG_RETURN_INT32(1);
 8053 bruce                     795 ECB             : 
                                796                 :     /*
                                797                 :      * a->upper == b->upper, so consider type of boundary.
                                798                 :      *
                                799                 :      * A '-' upper bound is > any other kind (this could only be relevant if
                                800                 :      * HUGE_VAL is used as a regular data value). A '<' upper bound is < any
                                801                 :      * other kind. A '>' upper bound is > any other kind except '-'.
                                802                 :      */
 8053 bruce                     803 GIC        2336 :     if (a->u_ext != b->u_ext)
 8154 tgl                       804 ECB             :     {
 8053 bruce                     805 GIC          39 :         if (a->u_ext == '-')
 2202 andres                    806 LBC           0 :             PG_RETURN_INT32(1);
 8053 bruce                     807 GBC          39 :         if (b->u_ext == '-')
 2202 andres                    808 LBC           0 :             PG_RETURN_INT32(-1);
 8053 bruce                     809 GBC          39 :         if (a->u_ext == '<')
 2202 andres                    810 CBC           3 :             PG_RETURN_INT32(-1);
 8053 bruce                     811              36 :         if (b->u_ext == '<')
 2202 andres                    812               1 :             PG_RETURN_INT32(1);
 8053 bruce                     813              35 :         if (a->u_ext == '>')
 2202 andres                    814              18 :             PG_RETURN_INT32(1);
 8053 bruce                     815              17 :         if (b->u_ext == '>')
 2202 andres                    816              17 :             PG_RETURN_INT32(-1);
 8154 tgl                       817 ECB             :     }
                                818                 : 
                                819                 :     /*
                                820                 :      * For other boundary types, consider # of significant digits first. Note
                                821                 :      * result here is converse of the lower-boundary case.
                                822                 :      */
 6385 bruce                     823 GIC        2297 :     if (a->u_sigd < b->u_sigd) /* (a) is blurred and is likely to include (b) */
 2202 andres                    824 CBC           5 :         PG_RETURN_INT32(1);
 8053 bruce                     825            2292 :     if (a->u_sigd > b->u_sigd) /* (a) is less blurred and is likely to be
 8053 bruce                     826 ECB             :                                  * included in (b) */
 2202 andres                    827 GIC           4 :         PG_RETURN_INT32(-1);
 8053 bruce                     828 ECB             : 
                                829                 :     /*
                                830                 :      * For same # of digits, an approximate boundary is more blurred than
                                831                 :      * exact.  Again, result is converse of lower-boundary case.
                                832                 :      */
 8053 bruce                     833 GIC        2288 :     if (a->u_ext != b->u_ext)
 8154 tgl                       834 ECB             :     {
 8053 bruce                     835 UIC           0 :         if (a->u_ext == '~') /* (a) is approximate, while (b) is exact */
 2202 andres                    836 UBC           0 :             PG_RETURN_INT32(1);
 8053 bruce                     837               0 :         if (b->u_ext == '~')
 2202 andres                    838               0 :             PG_RETURN_INT32(-1);
 8154 tgl                       839 EUB             :         /* can't get here unless data is corrupt */
 7199 tgl                       840 UIC           0 :         elog(ERROR, "bogus upper boundary types %d %d",
 8154 tgl                       841 EUB             :              (int) a->u_ext, (int) b->u_ext);
                                842                 :     }
                                843                 : 
 2202 andres                    844 GIC        2288 :     PG_RETURN_INT32(0);
 8154 tgl                       845 ECB             : }
                                846                 : 
                                847                 : Datum
 2202 andres                    848 UIC           0 : seg_lt(PG_FUNCTION_ARGS)
 8154 tgl                       849 EUB             : {
 1165 alvherre                  850 UIC           0 :     int         cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp,
 1165 alvherre                  851 EUB             :                                                         PG_GETARG_DATUM(0),
                                852                 :                                                         PG_GETARG_DATUM(1)));
                                853                 : 
 2202 andres                    854 UIC           0 :     PG_RETURN_BOOL(cmp < 0);
 8154 tgl                       855 EUB             : }
                                856                 : 
                                857                 : Datum
 2202 andres                    858 UIC           0 : seg_le(PG_FUNCTION_ARGS)
 8154 tgl                       859 EUB             : {
 1165 alvherre                  860 UIC           0 :     int         cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp,
 1165 alvherre                  861 EUB             :                                                         PG_GETARG_DATUM(0),
                                862                 :                                                         PG_GETARG_DATUM(1)));
                                863                 : 
 2202 andres                    864 UIC           0 :     PG_RETURN_BOOL(cmp <= 0);
 8154 tgl                       865 EUB             : }
                                866                 : 
                                867                 : Datum
 2202 andres                    868 UIC           0 : seg_gt(PG_FUNCTION_ARGS)
 8154 tgl                       869 EUB             : {
 1165 alvherre                  870 UIC           0 :     int         cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp,
 1165 alvherre                  871 EUB             :                                                         PG_GETARG_DATUM(0),
                                872                 :                                                         PG_GETARG_DATUM(1)));
                                873                 : 
 2202 andres                    874 UIC           0 :     PG_RETURN_BOOL(cmp > 0);
 8154 tgl                       875 EUB             : }
                                876                 : 
                                877                 : Datum
 2202 andres                    878 UIC           0 : seg_ge(PG_FUNCTION_ARGS)
 8154 tgl                       879 EUB             : {
 1165 alvherre                  880 UIC           0 :     int         cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp,
 1165 alvherre                  881 EUB             :                                                         PG_GETARG_DATUM(0),
                                882                 :                                                         PG_GETARG_DATUM(1)));
                                883                 : 
 2202 andres                    884 UIC           0 :     PG_RETURN_BOOL(cmp >= 0);
 8154 tgl                       885 EUB             : }
                                886                 : 
                                887                 : 
                                888                 : Datum
 2202 andres                    889 GIC           2 : seg_different(PG_FUNCTION_ARGS)
 8154 tgl                       890 ECB             : {
 1165 alvherre                  891 GIC           2 :     int         cmp = DatumGetInt32(DirectFunctionCall2(seg_cmp,
 1165 alvherre                  892 ECB             :                                                         PG_GETARG_DATUM(0),
                                893                 :                                                         PG_GETARG_DATUM(1)));
                                894                 : 
 2202 andres                    895 GIC           2 :     PG_RETURN_BOOL(cmp != 0);
 2543 tgl                       896 ECB             : }
                                897                 : 
                                898                 : 
                                899                 : 
                                900                 : /*****************************************************************************
                                901                 :  *                 Auxiliary functions
                                902                 :  *****************************************************************************/
                                903                 : 
                                904                 : /*
                                905                 :  * The purpose of this routine is to print the given floating point
                                906                 :  * value with exactly n significant digits.  Its behaviour
                                907                 :  * is similar to %.ng except it prints 8.00 where %.ng would
                                908                 :  * print 8.  Returns the length of the string written at "result".
                                909                 :  *
                                910                 :  * Caller must provide a sufficiently large result buffer; 16 bytes
                                911                 :  * should be enough for all known float implementations.
                                912                 :  */
                                913                 : static int
 8053 bruce                     914 GIC         325 : restore(char *result, float val, int n)
 8154 tgl                       915 ECB             : {
 8053 bruce                     916 GIC         325 :     char        buf[25] = {
 8053 bruce                     917 ECB             :         '0', '0', '0', '0', '0',
                                918                 :         '0', '0', '0', '0', '0',
                                919                 :         '0', '0', '0', '0', '0',
                                920                 :         '0', '0', '0', '0', '0',
                                921                 :         '0', '0', '0', '0', '\0'
                                922                 :     };
                                923                 :     char       *p;
                                924                 :     int         exp;
                                925                 :     int         i,
                                926                 :                 dp,
                                927                 :                 sign;
                                928                 : 
                                929                 :     /*
                                930                 :      * Put a cap on the number of significant digits to avoid garbage in the
                                931                 :      * output and ensure we don't overrun the result buffer.  (n should not be
                                932                 :      * negative, but check to protect ourselves against corrupted data.)
                                933                 :      */
  109 tgl                       934 GIC         325 :     if (n <= 0)
  109 tgl                       935 LBC           0 :         n = FLT_DIG;
  109 tgl                       936 EUB             :     else
  109 tgl                       937 GIC         325 :         n = Min(n, FLT_DIG);
 8053 bruce                     938 ECB             : 
                                939                 :     /* remember the sign */
 8053 bruce                     940 GIC         325 :     sign = (val < 0 ? 1 : 0);
 8053 bruce                     941 ECB             : 
                                942                 :     /* print, in %e style to start with */
 2562 tgl                       943 GIC         325 :     sprintf(result, "%.*e", n - 1, val);
 8053 bruce                     944 ECB             : 
                                945                 :     /* find the exponent */
 2562 tgl                       946 GIC         325 :     p = strchr(result, 'e');
 8053 bruce                     947 ECB             : 
                                948                 :     /* punt if we have 'inf' or similar */
 2562 tgl                       949 GIC         325 :     if (p == NULL)
 2562 tgl                       950 LBC           0 :         return strlen(result);
 8053 bruce                     951 EUB             : 
 2562 tgl                       952 GIC         325 :     exp = atoi(p + 1);
 8053 bruce                     953 CBC         325 :     if (exp == 0)
 8053 bruce                     954 ECB             :     {
                                955                 :         /* just truncate off the 'e+00' */
 2562 tgl                       956 GIC         169 :         *p = '\0';
 8154 tgl                       957 ECB             :     }
                                958                 :     else
                                959                 :     {
  184 peter                     960 GNC         156 :         if (abs(exp) <= 4)
 8053 bruce                     961 ECB             :         {
                                962                 :             /*
                                963                 :              * remove the decimal point from the mantissa and write the digits
                                964                 :              * to the buf array
                                965                 :              */
 8053 bruce                     966 GIC         637 :             for (p = result + sign, i = 10, dp = 0; *p != 'e'; p++, i++)
 8053 bruce                     967 ECB             :             {
 8053 bruce                     968 GIC         499 :                 buf[i] = *p;
 8053 bruce                     969 CBC         499 :                 if (*p == '.')
 8053 bruce                     970 ECB             :                 {
 8053 bruce                     971 GIC         130 :                     dp = i--;   /* skip the decimal point */
 8053 bruce                     972 ECB             :                 }
                                973                 :             }
 8053 bruce                     974 GIC         138 :             if (dp == 0)
 8053 bruce                     975 CBC           8 :                 dp = i--;       /* no decimal point was found in the above
 8053 bruce                     976 ECB             :                                  * for() loop */
                                977                 : 
 8053 bruce                     978 GIC         138 :             if (exp > 0)
 8053 bruce                     979 ECB             :             {
 8053 bruce                     980 GIC         133 :                 if (dp - 10 + exp >= n)
 8053 bruce                     981 ECB             :                 {
                                982                 :                     /*
                                983                 :                      * the decimal point is behind the last significant digit;
                                984                 :                      * the digits in between must be converted to the exponent
                                985                 :                      * and the decimal point placed after the first digit
                                986                 :                      */
 8053 bruce                     987 GIC          43 :                     exp = dp - 10 + exp - n;
 8053 bruce                     988 CBC          43 :                     buf[10 + n] = '\0';
 8053 bruce                     989 ECB             : 
                                990                 :                     /* insert the decimal point */
 8053 bruce                     991 GIC          43 :                     if (n > 1)
 8053 bruce                     992 ECB             :                     {
 8053 bruce                     993 GIC          39 :                         dp = 11;
 8053 bruce                     994 CBC         507 :                         for (i = 23; i > dp; i--)
                                995             468 :                             buf[i] = buf[i - 1];
                                996              39 :                         buf[dp] = '.';
 8053 bruce                     997 ECB             :                     }
                                998                 : 
                                999                 :                     /*
                               1000                 :                      * adjust the exponent by the number of digits after the
                               1001                 :                      * decimal point
                               1002                 :                      */
 8053 bruce                    1003 GIC          43 :                     if (n > 1)
 8053 bruce                    1004 CBC          39 :                         sprintf(&buf[11 + n], "e%d", exp + n - 1);
 8053 bruce                    1005 ECB             :                     else
 8053 bruce                    1006 GIC           4 :                         sprintf(&buf[11], "e%d", exp + n - 1);
 8053 bruce                    1007 ECB             : 
 8053 bruce                    1008 GIC          43 :                     if (sign)
 8053 bruce                    1009 ECB             :                     {
 8053 bruce                    1010 UIC           0 :                         buf[9] = '-';
 8053 bruce                    1011 UBC           0 :                         strcpy(result, &buf[9]);
 8053 bruce                    1012 EUB             :                     }
                               1013                 :                     else
 8053 bruce                    1014 GIC          43 :                         strcpy(result, &buf[10]);
 8053 bruce                    1015 ECB             :                 }
                               1016                 :                 else
                               1017                 :                 {               /* insert the decimal point */
 8053 bruce                    1018 GIC          90 :                     dp += exp;
 8053 bruce                    1019 CBC        1080 :                     for (i = 23; i > dp; i--)
                               1020             990 :                         buf[i] = buf[i - 1];
                               1021              90 :                     buf[11 + n] = '\0';
                               1022              90 :                     buf[dp] = '.';
                               1023              90 :                     if (sign)
 8053 bruce                    1024 ECB             :                     {
 8053 bruce                    1025 UIC           0 :                         buf[9] = '-';
 8053 bruce                    1026 UBC           0 :                         strcpy(result, &buf[9]);
 8053 bruce                    1027 EUB             :                     }
                               1028                 :                     else
 8053 bruce                    1029 GIC          90 :                         strcpy(result, &buf[10]);
 8053 bruce                    1030 ECB             :                 }
                               1031                 :             }
                               1032                 :             else
                               1033                 :             {                   /* exp <= 0 */
 8053 bruce                    1034 GIC           5 :                 dp += exp - 1;
 8053 bruce                    1035 CBC           5 :                 buf[10 + n] = '\0';
                               1036               5 :                 buf[dp] = '.';
                               1037               5 :                 if (sign)
 8053 bruce                    1038 ECB             :                 {
 8053 bruce                    1039 UIC           0 :                     buf[dp - 2] = '-';
 8053 bruce                    1040 UBC           0 :                     strcpy(result, &buf[dp - 2]);
 8053 bruce                    1041 EUB             :                 }
                               1042                 :                 else
 8053 bruce                    1043 GIC           5 :                     strcpy(result, &buf[dp - 1]);
 8053 bruce                    1044 ECB             :             }
                               1045                 :         }
                               1046                 : 
                               1047                 :         /* do nothing for abs(exp) > 4; %e must be OK */
                               1048                 :         /* just get rid of zeroes after [eE]- and +zeroes after [Ee]. */
                               1049                 : 
                               1050                 :         /* ... this is not done yet. */
                               1051                 :     }
 2061 peter_e                  1052 GIC         325 :     return strlen(result);
 8154 tgl                      1053 ECB             : }
                               1054                 : 
                               1055                 : 
                               1056                 : /*
                               1057                 : ** Miscellany
                               1058                 : */
                               1059                 : 
                               1060                 : /* find out the number of significant digits in a string representing
                               1061                 :  * a floating point number
                               1062                 :  */
                               1063                 : int
 1986 peter_e                  1064 GIC        5187 : significant_digits(const char *s)
 8154 tgl                      1065 ECB             : {
 1986 peter_e                  1066 GIC        5187 :     const char *p = s;
 8053 bruce                    1067 ECB             :     int         n,
                               1068                 :                 c,
                               1069                 :                 zeroes;
                               1070                 : 
 8053 bruce                    1071 GIC        5187 :     zeroes = 1;
 8053 bruce                    1072 ECB             :     /* skip leading zeroes and sign */
 8053 bruce                    1073 GIC        5324 :     for (c = *p; (c == '0' || c == '+' || c == '-') && c != 0; c = *(++p));
 8154 tgl                      1074 ECB             : 
                               1075                 :     /* skip decimal point and following zeroes */
 8053 bruce                    1076 GIC        5208 :     for (c = *p; (c == '0' || c == '.') && c != 0; c = *(++p))
 8053 bruce                    1077 ECB             :     {
 8053 bruce                    1078 GIC          21 :         if (c != '.')
 8053 bruce                    1079 CBC          11 :             zeroes++;
 8053 bruce                    1080 ECB             :     }
                               1081                 : 
                               1082                 :     /* count significant digits (n) */
 8053 bruce                    1083 GIC       20346 :     for (c = *p, n = 0; c != 0; c = *(++p))
 8053 bruce                    1084 ECB             :     {
 8053 bruce                    1085 GIC       15186 :         if (!((c >= '0' && c <= '9') || (c == '.')))
 8053 bruce                    1086 CBC          27 :             break;
                               1087           15159 :         if (c != '.')
                               1088           10614 :             n++;
 8053 bruce                    1089 ECB             :     }
                               1090                 : 
 8053 bruce                    1091 GIC        5187 :     if (!n)
 2061 peter_e                  1092 CBC          97 :         return zeroes;
 8154 tgl                      1093 ECB             : 
 2061 peter_e                  1094 GIC        5090 :     return n;
 8154 tgl                      1095 ECB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a