Here is new version of the patch.
Now function pack_float is commented better.
All inline keywords are removed. I haven't found any performance loss for that.
Remove of static's showed 1%-7% performance loss in SELECT computation
(3 test runs), so I left statics where they are.

Actually, to avoid this kind of hacks, probably, it would be better to
fork GiST to GiSTv2 and implement many API changes there:
1. Bulk load API
2. Richier choose subtree API
3. Allow for key test not just NO\MAYBE answers, but SURE answer to
skip key test for underlying tree
And some other improvements require breaking chanes for extensions.
GiST idea is almost 25, modern spatial indices vary a lot from things
that were there during 90th.

Best regards, Andrey Borodin, Octonica & Ural Federal University.
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index 3feddef..9ce3cd6 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -91,14 +91,16 @@ PG_FUNCTION_INFO_V1(cube_enlarge);
 /*
 ** For internal use only
 */
-int32          cube_cmp_v0(NDBOX *a, NDBOX *b);
-bool           cube_contains_v0(NDBOX *a, NDBOX *b);
-bool           cube_overlap_v0(NDBOX *a, NDBOX *b);
-NDBOX     *cube_union_v0(NDBOX *a, NDBOX *b);
-void           rt_cube_size(NDBOX *a, double *sz);
-NDBOX     *g_cube_binary_union(NDBOX *r1, NDBOX *r2, int *sizep);
-bool           g_cube_leaf_consistent(NDBOX *key, NDBOX *query, StrategyNumber 
strategy);
-bool           g_cube_internal_consistent(NDBOX *key, NDBOX *query, 
StrategyNumber strategy);
+static int32           cube_cmp_v0(NDBOX *a, NDBOX *b);
+static bool            cube_contains_v0(NDBOX *a, NDBOX *b);
+static bool            cube_overlap_v0(NDBOX *a, NDBOX *b);
+static NDBOX      *cube_union_v0(NDBOX *a, NDBOX *b);
+static float           pack_float(float actualValue, int realm);
+static void            rt_cube_size(NDBOX *a, double *sz);
+static void            rt_cube_edge(NDBOX *a, double *sz);
+static NDBOX      *g_cube_binary_union(NDBOX *r1, NDBOX *r2, int *sizep);
+static bool            g_cube_leaf_consistent(NDBOX *key, NDBOX *query, 
StrategyNumber strategy);
+static bool            g_cube_internal_consistent(NDBOX *key, NDBOX *query, 
StrategyNumber strategy);
 
 /*
 ** Auxiliary funxtions
@@ -419,7 +421,27 @@ g_cube_decompress(PG_FUNCTION_ARGS)
        }
        PG_RETURN_POINTER(entry);
 }
-
+/*
+ * Function to pack bit flags inside float type
+ * Resulted value represent can be from four different "realms"
+ * Every value from realm 3 is greater than any value from realms 2,1 and 0.
+ * Every value from realm 2 is less than every value from realm 3 and greater
+ * than any value from realm 1 and 0, and so on. Values from the same realm
+ * loose two bits of precision. This technique is possible due to floating
+ * point numbers specification according to IEEE 754: exponent bits are highest
+ * (excluding sign bits, but here penalty is always positive). If float a is
+ * greater than float b, integer A with same bit representation as a is greater
+ * than integer B with same bits as b.
+ */
+static float
+pack_float(float actualValue, int realm)
+{
+       /* two bits for realm, others for value */
+       /* we have 4 realms                                     */
+       int realmAjustment = *((int*)&actualValue)/4;
+       int realCode = realm * (INT32_MAX/4) + realmAjustment;
+       return *((float*)&realCode);
+}
 
 /*
 ** The GiST Penalty method for boxes
@@ -428,6 +450,11 @@ g_cube_decompress(PG_FUNCTION_ARGS)
 Datum
 g_cube_penalty(PG_FUNCTION_ARGS)
 {
+       /* REALM 0: No extension is required, volume is zero, return edge       
*/
+       /* REALM 1: No extension is required, return nonzero volume             
        */
+       /* REALM 2: Volume extension is zero, return nonzero edge extension     
*/
+       /* REALM 3: Volume extension is nonzero, return it                      
                */
+
        GISTENTRY  *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
        GISTENTRY  *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
        float      *result = (float *) PG_GETARG_POINTER(2);
@@ -441,9 +468,33 @@ g_cube_penalty(PG_FUNCTION_ARGS)
        rt_cube_size(DatumGetNDBOX(origentry->key), &tmp2);
        *result = (float) (tmp1 - tmp2);
 
-       /*
-        * fprintf(stderr, "penalty\n"); fprintf(stderr, "\t%g\n", *result);
-        */
+       if( *result == 0 )
+       {
+               double tmp3 = tmp1; /* remember entry volume */
+               rt_cube_edge(ud, &tmp1);
+               rt_cube_edge(DatumGetNDBOX(origentry->key), &tmp2);
+               *result = (float) (tmp1 - tmp2);
+               if( *result == 0 )
+               {
+                       if( tmp3 != 0 )
+                       {
+                               *result = pack_float(tmp3, 1); /* REALM 1 */
+                       }
+                       else
+                       {
+                               *result = pack_float(tmp1, 0); /* REALM 0 */
+                       }
+               }
+               else
+               {
+                       *result = pack_float(*result, 2); /* REALM 2 */
+               }
+       }
+       else
+       {
+               *result = pack_float(*result, 3); /* REALM 3 */
+       }
+
        PG_RETURN_FLOAT8(*result);
 }
 
@@ -626,7 +677,7 @@ g_cube_same(PG_FUNCTION_ARGS)
 /*
 ** SUPPORT ROUTINES
 */
-bool
+static bool
 g_cube_leaf_consistent(NDBOX *key,
                                           NDBOX *query,
                                           StrategyNumber strategy)
@@ -658,7 +709,7 @@ g_cube_leaf_consistent(NDBOX *key,
        return (retval);
 }
 
-bool
+static bool
 g_cube_internal_consistent(NDBOX *key,
                                                   NDBOX *query,
                                                   StrategyNumber strategy)
@@ -688,7 +739,7 @@ g_cube_internal_consistent(NDBOX *key,
        return (retval);
 }
 
-NDBOX *
+static NDBOX *
 g_cube_binary_union(NDBOX *r1, NDBOX *r2, int *sizep)
 {
        NDBOX      *retval;
@@ -701,7 +752,7 @@ g_cube_binary_union(NDBOX *r1, NDBOX *r2, int *sizep)
 
 
 /* cube_union_v0 */
-NDBOX *
+static NDBOX *
 cube_union_v0(NDBOX *a, NDBOX *b)
 {
        int                     i;
@@ -875,25 +926,40 @@ cube_size(PG_FUNCTION_ARGS)
        PG_RETURN_FLOAT8(result);
 }
 
-void
+static void
 rt_cube_size(NDBOX *a, double *size)
 {
        int                     i;
+       double          result = 0;
 
-       if (a == (NDBOX *) NULL)
-               *size = 0.0;
-       else
+       if (a != (NDBOX *) NULL)
+       {
+               result = 1.0;
+               for (i = 0; i < DIM(a); i++)
+                       result *= UR_COORD(a, i) - LL_COORD(a, i);
+       }
+       *size = Abs(result);
+       return;
+}
+
+static void
+rt_cube_edge(NDBOX *a, double *size)
+{
+       int                     i;
+       double          result = 0;
+
+       if (a != (NDBOX *) NULL)
        {
-               *size = 1.0;
                for (i = 0; i < DIM(a); i++)
-                       *size = (*size) * Abs(UR_COORD(a, i) - LL_COORD(a, i));
+                       result += Abs(UR_COORD(a, i) - LL_COORD(a, i));
        }
+       *size = result;
        return;
 }
 
 /* make up a metric in which one box will be 'lower' than the other
    -- this can be useful for sorting and to determine uniqueness */
-int32
+static int32
 cube_cmp_v0(NDBOX *a, NDBOX *b)
 {
        int                     i;
@@ -1080,7 +1146,7 @@ cube_ge(PG_FUNCTION_ARGS)
 
 /* Contains */
 /* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
-bool
+static bool
 cube_contains_v0(NDBOX *a, NDBOX *b)
 {
        int                     i;
@@ -1150,7 +1216,7 @@ cube_contained(PG_FUNCTION_ARGS)
 
 /* Overlap */
 /* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
-bool
+static bool
 cube_overlap_v0(NDBOX *a, NDBOX *b)
 {
        int                     i;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to