LCOV - code coverage report
Current view: top level - contrib/btree_gist - btree_utils_num.h (source / functions) Coverage Total Hit
Test: PostgreSQL 20devel Lines: 87.2 % 47 41
Test Date: 2026-07-03 19:57:34 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
Branches: 72.2 % 36 26

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * contrib/btree_gist/btree_utils_num.h
       3                 :             :  */
       4                 :             : #ifndef __BTREE_UTILS_NUM_H__
       5                 :             : #define __BTREE_UTILS_NUM_H__
       6                 :             : 
       7                 :             : #include <math.h>
       8                 :             : #include <float.h>
       9                 :             : 
      10                 :             : #include "access/gist.h"
      11                 :             : #include "btree_gist.h"
      12                 :             : #include "utils/float.h"
      13                 :             : 
      14                 :             : typedef char GBT_NUMKEY;
      15                 :             : 
      16                 :             : /* Better readable key */
      17                 :             : typedef struct
      18                 :             : {
      19                 :             :     const GBT_NUMKEY *lower,
      20                 :             :                *upper;
      21                 :             : } GBT_NUMKEY_R;
      22                 :             : 
      23                 :             : 
      24                 :             : /* for sorting */
      25                 :             : typedef struct
      26                 :             : {
      27                 :             :     int         i;
      28                 :             :     GBT_NUMKEY *t;
      29                 :             : } Nsrt;
      30                 :             : 
      31                 :             : 
      32                 :             : /* type description */
      33                 :             : 
      34                 :             : typedef struct
      35                 :             : {
      36                 :             : 
      37                 :             :     /* Attribs */
      38                 :             : 
      39                 :             :     enum gbtree_type t;         /* data type */
      40                 :             :     int32       size;           /* size of type, 0 means variable */
      41                 :             :     int32       indexsize;      /* size of datums stored in index */
      42                 :             : 
      43                 :             :     /* Methods */
      44                 :             : 
      45                 :             :     bool        (*f_gt) (const void *, const void *, FmgrInfo *);   /* greater than */
      46                 :             :     bool        (*f_ge) (const void *, const void *, FmgrInfo *);   /* greater or equal */
      47                 :             :     bool        (*f_eq) (const void *, const void *, FmgrInfo *);   /* equal */
      48                 :             :     bool        (*f_le) (const void *, const void *, FmgrInfo *);   /* less or equal */
      49                 :             :     bool        (*f_lt) (const void *, const void *, FmgrInfo *);   /* less than */
      50                 :             :     int         (*f_cmp) (const void *, const void *, FmgrInfo *);  /* key compare function */
      51                 :             :     float8      (*f_dist) (const void *, const void *, FmgrInfo *); /* key distance function */
      52                 :             : } gbtree_ninfo;
      53                 :             : 
      54                 :             : 
      55                 :             : /*
      56                 :             :  *  Numeric btree functions
      57                 :             :  */
      58                 :             : 
      59                 :             : 
      60                 :             : 
      61                 :             : /*
      62                 :             :  * Compute penalty for expanding a range olower..oupper to nlower..nupper.
      63                 :             :  *
      64                 :             :  * Although the arguments are declared double, they must not be NaN nor
      65                 :             :  * large enough to risk overflows in the calculations herein.  We only
      66                 :             :  * actually use this for integral data types, so there's no hazard.
      67                 :             :  */
      68                 :             : static inline float
      69                 :        5830 : penalty_num_impl(double olower, double oupper,
      70                 :             :                  double nlower, double nupper,
      71                 :             :                  int natts)
      72                 :             : {
      73                 :        5830 :     float       result = 0.0F;
      74                 :        5830 :     double      tmp = 0.0;
      75                 :             : 
      76                 :             :     /* Add penalty for expanding upper bound */
      77         [ +  + ]:        5830 :     if (nupper > oupper)
      78                 :         659 :         tmp += nupper - oupper;
      79                 :             :     /* Add penalty for expanding lower bound */
      80         [ +  + ]:        5830 :     if (olower > nlower)
      81                 :         733 :         tmp += olower - nlower;
      82         [ +  + ]:        5830 :     if (tmp > 0.0)
      83                 :             :     {
      84                 :             :         /* Ensure result is non-zero, even if next step underflows to zero */
      85                 :        1392 :         result += FLT_MIN;
      86                 :             :         /* Scale penalty to 0 .. 1 */
      87                 :        1392 :         result += (float) (tmp / (tmp + (oupper - olower)));
      88                 :             :         /* Scale to 0 .. FLT_MAX / (natts + 1) */
      89                 :        1392 :         result *= FLT_MAX / (natts + 1);
      90                 :             :     }
      91                 :        5830 :     return result;
      92                 :             : }
      93                 :             : 
      94                 :             : /*
      95                 :             :  * As above, but the input values are float4 or float8, so we must cope
      96                 :             :  * with NaNs, infinities, and overflows.
      97                 :             :  */
      98                 :             : static inline float
      99                 :        1644 : float_penalty_num_impl(double olower, double oupper,
     100                 :             :                        double nlower, double nupper,
     101                 :             :                        int natts)
     102                 :             : {
     103                 :        1644 :     float       result = 0.0F;
     104                 :        1644 :     double      tmp = 0.0;
     105                 :             : 
     106                 :             :     /* Add penalty for expanding upper bound */
     107         [ +  + ]:        1644 :     if (float8_gt(nupper, oupper))
     108                 :             :     {
     109                 :         823 :         double      delta = nupper - oupper;
     110                 :             : 
     111         [ +  + ]:         823 :         if (unlikely(isnan(delta)))
     112                 :             :         {
     113                 :             :             /* oupper couldn't be NaN here, see float8_gt */
     114         [ +  - ]:           3 :             if (isnan(nupper))
     115                 :           3 :                 delta = FLT_MAX;    /* max penalty for NaN vs non-NaN */
     116                 :             :             else
     117                 :           0 :                 delta = 0.0;    /* must be Inf - Inf case */
     118                 :             :         }
     119         [ +  + ]:         820 :         else if (delta > FLT_MAX)
     120                 :           3 :             delta = FLT_MAX;    /* clamp to FLT_MAX, esp for infinity */
     121                 :         823 :         tmp += delta;
     122                 :             :     }
     123                 :             :     /* Add penalty for expanding lower bound */
     124         [ +  + ]:        1644 :     if (float8_gt(olower, nlower))
     125                 :             :     {
     126                 :         821 :         double      delta = olower - nlower;
     127                 :             : 
     128         [ -  + ]:         821 :         if (unlikely(isnan(delta)))
     129                 :             :         {
     130                 :             :             /* nlower couldn't be NaN here, see float8_gt */
     131         [ #  # ]:           0 :             if (isnan(olower))
     132                 :           0 :                 delta = FLT_MAX;    /* max penalty for NaN vs non-NaN */
     133                 :             :             else
     134                 :           0 :                 delta = 0.0;    /* must be Inf - Inf case */
     135                 :             :         }
     136         [ +  + ]:         821 :         else if (delta > FLT_MAX)
     137                 :           3 :             delta = FLT_MAX;    /* clamp to FLT_MAX, esp for infinity */
     138                 :         821 :         tmp += delta;
     139                 :             :     }
     140         [ +  - ]:        1644 :     if (tmp > 0.0)
     141                 :             :     {
     142                 :        1644 :         double      delta = oupper - olower;
     143                 :             : 
     144                 :             :         /* Clamp delta (the original range size) to 0 .. FLT_MAX */
     145         [ +  + ]:        1644 :         if (unlikely(isnan(delta)))
     146                 :             :         {
     147                 :             :             /* here, we must deal with olower possibly being NaN */
     148   [ +  -  -  + ]:         685 :             if (isnan(oupper) && isnan(olower))
     149                 :           0 :                 delta = 0.0;    /* treat NaNs as equal */
     150   [ -  +  -  - ]:         685 :             else if (isnan(oupper) || isnan(olower))
     151                 :         685 :                 delta = FLT_MAX;    /* max penalty for NaN vs non-NaN */
     152                 :             :             else
     153                 :           0 :                 delta = 0.0;    /* must be Inf - Inf case */
     154                 :             :         }
     155         [ +  + ]:         959 :         else if (delta > FLT_MAX)
     156                 :         686 :             delta = FLT_MAX;    /* clamp to FLT_MAX, esp for infinity */
     157                 :             :         /* Ensure result is non-zero, even if next step underflows to zero */
     158                 :        1644 :         result += FLT_MIN;
     159                 :             :         /* Scale penalty to 0 .. 1 */
     160                 :        1644 :         result += (float) (tmp / (tmp + delta));
     161                 :             :         /* Scale to 0 .. FLT_MAX / (natts + 1) */
     162                 :        1644 :         result *= FLT_MAX / (natts + 1);
     163                 :             :     }
     164                 :        1644 :     return result;
     165                 :             : }
     166                 :             : 
     167                 :             : /*
     168                 :             :  * These macros provide backwards-compatible notation for callers.
     169                 :             :  */
     170                 :             : #define penalty_num(result,olower,oupper,nlower,nupper) do { \
     171                 :             :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0); \
     172                 :             :     *(result) = penalty_num_impl(olower, oupper, nlower, nupper, \
     173                 :             :                                  entry->rel->rd_att->natts); \
     174                 :             : } while (0)
     175                 :             : 
     176                 :             : #define float_penalty_num(result,olower,oupper,nlower,nupper) do { \
     177                 :             :     GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0); \
     178                 :             :     *(result) = float_penalty_num_impl(olower, oupper, nlower, nupper, \
     179                 :             :                                        entry->rel->rd_att->natts); \
     180                 :             : } while (0)
     181                 :             : 
     182                 :             : 
     183                 :             : /*
     184                 :             :  * Convert an Interval to an approximate equivalent number of seconds
     185                 :             :  * (as a double).  Here because we need it for time/timetz as well as
     186                 :             :  * interval.  See interval_cmp_internal for comparison.
     187                 :             :  */
     188                 :             : #define INTERVAL_TO_SEC(ivp) \
     189                 :             :     (((double) (ivp)->time) / ((double) USECS_PER_SEC) + \
     190                 :             :      (ivp)->day * (24.0 * SECS_PER_HOUR) + \
     191                 :             :      (ivp)->month * (30.0 * SECS_PER_DAY))
     192                 :             : 
     193                 :             : /* This macro is not safe to use with actual float inputs, only integers */
     194                 :             : #define GET_FLOAT_DISTANCE(t, arg1, arg2)   fabs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
     195                 :             : 
     196                 :             : 
     197                 :             : extern Interval *abs_interval(Interval *a);
     198                 :             : 
     199                 :             : extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
     200                 :             :                                StrategyNumber strategy, bool is_leaf,
     201                 :             :                                const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
     202                 :             : 
     203                 :             : extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
     204                 :             :                                bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
     205                 :             : 
     206                 :             : extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
     207                 :             :                                         const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
     208                 :             : 
     209                 :             : extern GISTENTRY *gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo);
     210                 :             : 
     211                 :             : extern GISTENTRY *gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo);
     212                 :             : 
     213                 :             : extern void *gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec,
     214                 :             :                            const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
     215                 :             : 
     216                 :             : extern bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b,
     217                 :             :                          const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
     218                 :             : 
     219                 :             : extern void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e,
     220                 :             :                               const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
     221                 :             : 
     222                 :             : #endif
        

Generated by: LCOV version 2.0-1