1 /*
2  * contrib/btree_gist/btree_float4.c
3  */
4 #include "postgres.h"
5 
6 #include "btree_gist.h"
7 #include "btree_utils_num.h"
8 
9 typedef struct float4key
10 {
11 	float4		lower;
12 	float4		upper;
13 } float4KEY;
14 
15 /*
16 ** float4 ops
17 */
18 PG_FUNCTION_INFO_V1(gbt_float4_compress);
19 PG_FUNCTION_INFO_V1(gbt_float4_fetch);
20 PG_FUNCTION_INFO_V1(gbt_float4_union);
21 PG_FUNCTION_INFO_V1(gbt_float4_picksplit);
22 PG_FUNCTION_INFO_V1(gbt_float4_consistent);
23 PG_FUNCTION_INFO_V1(gbt_float4_distance);
24 PG_FUNCTION_INFO_V1(gbt_float4_penalty);
25 PG_FUNCTION_INFO_V1(gbt_float4_same);
26 
27 static bool
28 gbt_float4gt(const void *a, const void *b, FmgrInfo *flinfo)
29 {
30 	return (*((const float4 *) a) > *((const float4 *) b));
31 }
32 static bool
33 gbt_float4ge(const void *a, const void *b, FmgrInfo *flinfo)
34 {
35 	return (*((const float4 *) a) >= *((const float4 *) b));
36 }
37 static bool
38 gbt_float4eq(const void *a, const void *b, FmgrInfo *flinfo)
39 {
40 	return (*((const float4 *) a) == *((const float4 *) b));
41 }
42 static bool
43 gbt_float4le(const void *a, const void *b, FmgrInfo *flinfo)
44 {
45 	return (*((const float4 *) a) <= *((const float4 *) b));
46 }
47 static bool
48 gbt_float4lt(const void *a, const void *b, FmgrInfo *flinfo)
49 {
50 	return (*((const float4 *) a) < *((const float4 *) b));
51 }
52 
53 static int
54 gbt_float4key_cmp(const void *a, const void *b, FmgrInfo *flinfo)
55 {
56 	float4KEY  *ia = (float4KEY *) (((const Nsrt *) a)->t);
57 	float4KEY  *ib = (float4KEY *) (((const Nsrt *) b)->t);
58 
59 	if (ia->lower == ib->lower)
60 	{
61 		if (ia->upper == ib->upper)
62 			return 0;
63 
64 		return (ia->upper > ib->upper) ? 1 : -1;
65 	}
66 
67 	return (ia->lower > ib->lower) ? 1 : -1;
68 }
69 
70 static float8
71 gbt_float4_dist(const void *a, const void *b, FmgrInfo *flinfo)
72 {
73 	return GET_FLOAT_DISTANCE(float4, a, b);
74 }
75 
76 
77 static const gbtree_ninfo tinfo =
78 {
79 	gbt_t_float4,
80 	sizeof(float4),
81 	8,							/* sizeof(gbtreekey8) */
82 	gbt_float4gt,
83 	gbt_float4ge,
84 	gbt_float4eq,
85 	gbt_float4le,
86 	gbt_float4lt,
87 	gbt_float4key_cmp,
88 	gbt_float4_dist
89 };
90 
91 
92 PG_FUNCTION_INFO_V1(float4_dist);
93 Datum
94 float4_dist(PG_FUNCTION_ARGS)
95 {
96 	float4		a = PG_GETARG_FLOAT4(0);
97 	float4		b = PG_GETARG_FLOAT4(1);
98 	float4		r;
99 
100 	r = a - b;
101 	CHECKFLOATVAL(r, isinf(a) || isinf(b), true);
102 
103 	PG_RETURN_FLOAT4(Abs(r));
104 }
105 
106 
107 /**************************************************
108  * float4 ops
109  **************************************************/
110 
111 
112 Datum
113 gbt_float4_compress(PG_FUNCTION_ARGS)
114 {
115 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
116 
117 	PG_RETURN_POINTER(gbt_num_compress(entry, &tinfo));
118 }
119 
120 Datum
121 gbt_float4_fetch(PG_FUNCTION_ARGS)
122 {
123 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
124 
125 	PG_RETURN_POINTER(gbt_num_fetch(entry, &tinfo));
126 }
127 
128 Datum
129 gbt_float4_consistent(PG_FUNCTION_ARGS)
130 {
131 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
132 	float4		query = PG_GETARG_FLOAT4(1);
133 	StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
134 
135 	/* Oid		subtype = PG_GETARG_OID(3); */
136 	bool	   *recheck = (bool *) PG_GETARG_POINTER(4);
137 	float4KEY  *kkk = (float4KEY *) DatumGetPointer(entry->key);
138 	GBT_NUMKEY_R key;
139 
140 	/* All cases served by this function are exact */
141 	*recheck = false;
142 
143 	key.lower = (GBT_NUMKEY *) &kkk->lower;
144 	key.upper = (GBT_NUMKEY *) &kkk->upper;
145 
146 	PG_RETURN_BOOL(
147 				   gbt_num_consistent(&key, (void *) &query, &strategy, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
148 		);
149 }
150 
151 
152 Datum
153 gbt_float4_distance(PG_FUNCTION_ARGS)
154 {
155 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
156 	float4		query = PG_GETARG_FLOAT4(1);
157 
158 	/* Oid		subtype = PG_GETARG_OID(3); */
159 	float4KEY  *kkk = (float4KEY *) DatumGetPointer(entry->key);
160 	GBT_NUMKEY_R key;
161 
162 	key.lower = (GBT_NUMKEY *) &kkk->lower;
163 	key.upper = (GBT_NUMKEY *) &kkk->upper;
164 
165 	PG_RETURN_FLOAT8(
166 					 gbt_num_distance(&key, (void *) &query, GIST_LEAF(entry), &tinfo, fcinfo->flinfo)
167 		);
168 }
169 
170 
171 Datum
172 gbt_float4_union(PG_FUNCTION_ARGS)
173 {
174 	GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
175 	void	   *out = palloc(sizeof(float4KEY));
176 
177 	*(int *) PG_GETARG_POINTER(1) = sizeof(float4KEY);
178 	PG_RETURN_POINTER(gbt_num_union((void *) out, entryvec, &tinfo, fcinfo->flinfo));
179 }
180 
181 
182 Datum
183 gbt_float4_penalty(PG_FUNCTION_ARGS)
184 {
185 	float4KEY  *origentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(0))->key);
186 	float4KEY  *newentry = (float4KEY *) DatumGetPointer(((GISTENTRY *) PG_GETARG_POINTER(1))->key);
187 	float	   *result = (float *) PG_GETARG_POINTER(2);
188 
189 	penalty_num(result, origentry->lower, origentry->upper, newentry->lower, newentry->upper);
190 
191 	PG_RETURN_POINTER(result);
192 
193 }
194 
195 Datum
196 gbt_float4_picksplit(PG_FUNCTION_ARGS)
197 {
198 	PG_RETURN_POINTER(gbt_num_picksplit(
199 										(GistEntryVector *) PG_GETARG_POINTER(0),
200 										(GIST_SPLITVEC *) PG_GETARG_POINTER(1),
201 										&tinfo, fcinfo->flinfo
202 										));
203 }
204 
205 Datum
206 gbt_float4_same(PG_FUNCTION_ARGS)
207 {
208 	float4KEY  *b1 = (float4KEY *) PG_GETARG_POINTER(0);
209 	float4KEY  *b2 = (float4KEY *) PG_GETARG_POINTER(1);
210 	bool	   *result = (bool *) PG_GETARG_POINTER(2);
211 
212 	*result = gbt_num_same((void *) b1, (void *) b2, &tinfo, fcinfo->flinfo);
213 	PG_RETURN_POINTER(result);
214 }
215