PostgreSQL Source Code git master
Loading...
Searching...
No Matches
btree_utils_num.h
Go to the documentation of this file.
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
14typedef char GBT_NUMKEY;
15
16/* Better readable key */
17typedef struct
18{
22
23
24/* for sorting */
25typedef struct
26{
27 int i;
29} Nsrt;
30
31
32/* type description */
33
34typedef 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 */
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 */
68static inline float
70 double nlower, double nupper,
71 int natts)
72{
73 float result = 0.0F;
74 double tmp = 0.0;
75
76 /* Add penalty for expanding upper bound */
77 if (nupper > oupper)
78 tmp += nupper - oupper;
79 /* Add penalty for expanding lower bound */
80 if (olower > nlower)
81 tmp += olower - nlower;
82 if (tmp > 0.0)
83 {
84 /* Ensure result is non-zero, even if next step underflows to zero */
85 result += FLT_MIN;
86 /* Scale penalty to 0 .. 1 */
87 result += (float) (tmp / (tmp + (oupper - olower)));
88 /* Scale to 0 .. FLT_MAX / (natts + 1) */
89 result *= FLT_MAX / (natts + 1);
90 }
91 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 */
98static inline float
100 double nlower, double nupper,
101 int natts)
102{
103 float result = 0.0F;
104 double tmp = 0.0;
105
106 /* Add penalty for expanding upper bound */
107 if (float8_gt(nupper, oupper))
108 {
109 double delta = nupper - oupper;
110
111 if (unlikely(isnan(delta)))
112 {
113 /* oupper couldn't be NaN here, see float8_gt */
114 if (isnan(nupper))
115 delta = FLT_MAX; /* max penalty for NaN vs non-NaN */
116 else
117 delta = 0.0; /* must be Inf - Inf case */
118 }
119 else if (delta > FLT_MAX)
120 delta = FLT_MAX; /* clamp to FLT_MAX, esp for infinity */
121 tmp += delta;
122 }
123 /* Add penalty for expanding lower bound */
124 if (float8_gt(olower, nlower))
125 {
126 double delta = olower - nlower;
127
128 if (unlikely(isnan(delta)))
129 {
130 /* nlower couldn't be NaN here, see float8_gt */
131 if (isnan(olower))
132 delta = FLT_MAX; /* max penalty for NaN vs non-NaN */
133 else
134 delta = 0.0; /* must be Inf - Inf case */
135 }
136 else if (delta > FLT_MAX)
137 delta = FLT_MAX; /* clamp to FLT_MAX, esp for infinity */
138 tmp += delta;
139 }
140 if (tmp > 0.0)
141 {
142 double delta = oupper - olower;
143
144 /* Clamp delta (the original range size) to 0 .. FLT_MAX */
145 if (unlikely(isnan(delta)))
146 {
147 /* here, we must deal with olower possibly being NaN */
148 if (isnan(oupper) && isnan(olower))
149 delta = 0.0; /* treat NaNs as equal */
150 else if (isnan(oupper) || isnan(olower))
151 delta = FLT_MAX; /* max penalty for NaN vs non-NaN */
152 else
153 delta = 0.0; /* must be Inf - Inf case */
154 }
155 else if (delta > FLT_MAX)
156 delta = FLT_MAX; /* clamp to FLT_MAX, esp for infinity */
157 /* Ensure result is non-zero, even if next step underflows to zero */
158 result += FLT_MIN;
159 /* Scale penalty to 0 .. 1 */
160 result += (float) (tmp / (tmp + delta));
161 /* Scale to 0 .. FLT_MAX / (natts + 1) */
162 result *= FLT_MAX / (natts + 1);
163 }
164 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
198
199extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
200 const StrategyNumber *strategy, bool is_leaf,
201 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
202
203extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
204 bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
205
207 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
208
210
211extern GISTENTRY *gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo);
212
213extern void *gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec,
214 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
215
216extern bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b,
217 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
218
219extern void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e,
220 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
221
222#endif
static const gbtree_vinfo tinfo
Definition btree_bit.c:109
gbtree_type
Definition btree_gist.h:15
GISTENTRY * gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo)
void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
Interval * abs_interval(Interval *a)
float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query, bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
static float float_penalty_num_impl(double olower, double oupper, double nlower, double nupper, int natts)
static float penalty_num_impl(double olower, double oupper, double nlower, double nupper, int natts)
bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query, const StrategyNumber *strategy, bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
GISTENTRY * gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo)
GIST_SPLITVEC * gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
void * gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec, const gbtree_ninfo *tinfo, FmgrInfo *flinfo)
char GBT_NUMKEY
double float8
Definition c.h:773
int32_t int32
Definition c.h:679
#define unlikely(x)
Definition c.h:497
uint32 result
static bool float8_gt(const float8 val1, const float8 val2)
Definition float.h:298
int b
Definition isn.c:74
int a
Definition isn.c:73
uint64_t Datum
Definition postgres.h:70
e
static int fb(int x)
uint16 StrategyNumber
Definition stratnum.h:22
const GBT_NUMKEY * upper
const GBT_NUMKEY * lower
GBT_NUMKEY * t
enum gbtree_type t