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 "btree_gist.h"
8 #include "access/gist.h"
9 #include "utils/rel.h"
10 
11 #include <math.h>
12 #include <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  * Note: The factor 0.49 in following macro avoids floating point overflows
63  */
64 #define penalty_num(result,olower,oupper,nlower,nupper) do { \
65   double	tmp = 0.0F; \
66   (*(result))	= 0.0F; \
67   if ( (nupper) > (oupper) ) \
68 	  tmp += ( ((double)nupper)*0.49F - ((double)oupper)*0.49F ); \
69   if (	(olower) > (nlower)  ) \
70 	  tmp += ( ((double)olower)*0.49F - ((double)nlower)*0.49F ); \
71   if (tmp > 0.0F) \
72   { \
73 	(*(result)) += FLT_MIN; \
74 	(*(result)) += (float) ( ((double)(tmp)) / ( (double)(tmp) + ( ((double)(oupper))*0.49F - ((double)(olower))*0.49F ) ) ); \
75 	(*(result)) *= (FLT_MAX / (((GISTENTRY *) PG_GETARG_POINTER(0))->rel->rd_att->natts + 1)); \
76   } \
77 } while (0)
78 
79 
80 /*
81  * Convert an Interval to an approximate equivalent number of seconds
82  * (as a double).  Here because we need it for time/timetz as well as
83  * interval.  See interval_cmp_internal for comparison.
84  */
85 #define INTERVAL_TO_SEC(ivp) \
86 	(((double) (ivp)->time) / ((double) USECS_PER_SEC) + \
87 	 (ivp)->day * (24.0 * SECS_PER_HOUR) + \
88 	 (ivp)->month * (30.0 * SECS_PER_DAY))
89 
90 #define GET_FLOAT_DISTANCE(t, arg1, arg2)	Abs( ((float8) *((const t *) (arg1))) - ((float8) *((const t *) (arg2))) )
91 
92 /*
93  * check to see if a float4/8 val has underflowed or overflowed
94  * borrowed from src/backend/utils/adt/float.c
95  */
96 #define CHECKFLOATVAL(val, inf_is_valid, zero_is_valid)			\
97 do {															\
98 	if (isinf(val) && !(inf_is_valid))							\
99 		ereport(ERROR,											\
100 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
101 		  errmsg("value out of range: overflow")));				\
102 																\
103 	if ((val) == 0.0 && !(zero_is_valid))						\
104 		ereport(ERROR,											\
105 				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),	\
106 		 errmsg("value out of range: underflow")));				\
107 } while(0)
108 
109 
110 extern Interval *abs_interval(Interval *a);
111 
112 extern bool gbt_num_consistent(const GBT_NUMKEY_R *key, const void *query,
113 				   const StrategyNumber *strategy, bool is_leaf,
114 				   const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
115 
116 extern float8 gbt_num_distance(const GBT_NUMKEY_R *key, const void *query,
117 				 bool is_leaf, const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
118 
119 extern GIST_SPLITVEC *gbt_num_picksplit(const GistEntryVector *entryvec, GIST_SPLITVEC *v,
120 				  const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
121 
122 extern GISTENTRY *gbt_num_compress(GISTENTRY *entry, const gbtree_ninfo *tinfo);
123 
124 extern GISTENTRY *gbt_num_fetch(GISTENTRY *entry, const gbtree_ninfo *tinfo);
125 
126 extern void *gbt_num_union(GBT_NUMKEY *out, const GistEntryVector *entryvec,
127 			  const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
128 
129 extern bool gbt_num_same(const GBT_NUMKEY *a, const GBT_NUMKEY *b,
130 			 const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
131 
132 extern void gbt_num_bin_union(Datum *u, GBT_NUMKEY *e,
133 				  const gbtree_ninfo *tinfo, FmgrInfo *flinfo);
134 
135 #endif
136