Re: Final version of my cube patch - fixed test cases, - Mailing list pgsql-patches

From Bruce Momjian
Subject Re: Final version of my cube patch - fixed test cases,
Date
Msg-id 200607252323.k6PNNgl23576@momjian.us
Whole thread Raw
In response to Final version of my cube patch - fixed test cases, added documentation  (Joshua Reich <josh@root.net>)
List pgsql-patches
Patch applied.  Thanks.

---------------------------------------------------------------------------


Joshua Reich wrote:
> Any committers want to take ownership of this?
>
> Thanks,
>
> Joshua Reich
>
>
> ********************************************************************************
>   Changes that were made in July 2006 by Joshua Reich I.
>
> ********************************************************************************
>
>   Code Cleanup:
>
>   Update the calling convention for all external facing functions. By
> external
>   facing, I mean all functions that are directly referenced in cube.sql.
> Prior
>   to my update, all functions used the older V0 calling convention. They now
>   use V1.
>
>   New Functions:
>
>   cube(float[]), which makes a zero volume cube from a float array
>
>   cube(float[], float[]), which allows the user to create a cube from
>   two float arrays; one for the upper right and one for the lower left
>   coordinate.
>
>   cube_subset(cube, int4[]), to allow you to reorder or choose a subset of
>   dimensions from a cube, using index values specified in the array.
>

> ? cube.diff
> ? cubeparse.tab.c
> ? logfile
> Index: CHANGES
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/CHANGES,v
> retrieving revision 1.2
> diff -c -r1.2 CHANGES
> *** CHANGES    12 Sep 2002 00:26:00 -0000    1.2
> --- CHANGES    22 Jul 2006 05:15:44 -0000
> ***************
> *** 1,4 ****
> --- 1,28 ----
> + ********************************************************************************
> + Changes that were made in July 2006 by Joshua Reich I.
> + ********************************************************************************
> +
> + Code Cleanup:
> +
> + Update the calling convention for all external facing functions. By external
> + facing, I mean all functions that are directly referenced in cube.sql. Prior
> + to my update, all functions used the older V0 calling convention. They now
> + use V1.
> +
> + New Functions:
> +
> + cube(float[]), which makes a zero volume cube from a float array
> +
> + cube(float[], float[]), which allows the user to create a cube from
> + two float arrays; one for the upper right and one for the lower left
> + coordinate.
> +
> + cube_subset(cube, int4[]), to allow you to reorder or choose a subset of
> + dimensions from a cube, using index values specified in the array.
> +
> + ********************************************************************************
>   Changes that were made in August/September 2002 by Bruno Wolff III.
> + ********************************************************************************
>
>   Note that this was based on a 7.3 development version and changes may not
>   directly work with earlier versions.
> Index: README.cube
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/README.cube,v
> retrieving revision 1.7
> diff -c -r1.7 README.cube
> *** README.cube    27 Jun 2005 01:19:43 -0000    1.7
> --- README.cube    22 Jul 2006 05:15:45 -0000
> ***************
> *** 244,249 ****
> --- 244,259 ----
>     This makes a one dimensional cube.
>     cube(1,2) == '(1),(2)'
>
> + cube(float8[]) returns cube
> +   This makes a zero-volume cube using the coordinates defined by the
> +   array.
> +   cube(ARRAY[1,2]) == '(1,2)'
> +
> + cube(float8[], float8[]) returns cube
> +   This makes a cube, with upper right and lower left coordinates as
> +   defined by the 2 float arrays. Arrays must be of the same length.
> +   cube('{1,2}'::float[], '{3,4}'::float[]) == '(1,2),(3,4)'
> +
>   cube(cube, float8) returns cube
>     This builds a new cube by adding a dimension on to an existing cube with
>     the same values for both parts of the new coordinate. This is useful for
> ***************
> *** 267,272 ****
> --- 277,289 ----
>     cube_ur_coord returns the nth coordinate value for the upper right corner
>     of a cube. This is useful for doing coordinate transformations.
>
> + cube_subset(cube, int[]) returns cube
> +   Builds a new cube from an existing cube, using a list of dimension indexes
> +   from an array. Can be used to find both the ll and ur coordinate of single
> +   dimenion, e.g.: cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[2]) = '(3),(7)'
> +   Or can be used to drop dimensions, or reorder them as desired, e.g.:
> +   cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]) = '(5, 3, 1, 1),(8, 7, 6, 6)'
> +
>   cube_is_point(cube) returns bool
>     cube_is_point returns true if a cube is also a point. This is true when the
>     two defining corners are the same.
> ***************
> *** 327,329 ****
> --- 344,353 ----
>
>   These include changing the precision from single precision to double
>   precision and adding some new functions.
> +
> + ------------------------------------------------------------------------
> +
> + Additional updates were made by Joshua Reich <josh@root.net> in July 2006.
> +
> + These include cube(float8[], float8[]) and cleaning up the code to use
> + the V1 call protocol instead of the deprecated V0 form.
> Index: cube.c
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/cube.c,v
> retrieving revision 1.26
> diff -c -r1.26 cube.c
> *** cube.c    28 Jun 2006 11:59:59 -0000    1.26
> --- cube.c    22 Jul 2006 05:15:45 -0000
> ***************
> *** 28,90 ****
>   /*
>   ** Input/Output routines
>   */
> ! NDBOX       *cube_in(char *str);
> ! NDBOX       *cube(text *str);
> ! char       *cube_out(NDBOX * cube);
> ! NDBOX       *cube_f8(double *);
> ! NDBOX       *cube_f8_f8(double *, double *);
> ! NDBOX       *cube_c_f8(NDBOX *, double *);
> ! NDBOX       *cube_c_f8_f8(NDBOX *, double *, double *);
> ! int4        cube_dim(NDBOX * a);
> ! double       *cube_ll_coord(NDBOX * a, int4 n);
> ! double       *cube_ur_coord(NDBOX * a, int4 n);
> !
>
>   /*
>   ** GiST support methods
>   */
> ! bool        g_cube_consistent(GISTENTRY *entry, NDBOX * query, StrategyNumber strategy);
> ! GISTENTRY  *g_cube_compress(GISTENTRY *entry);
> ! GISTENTRY  *g_cube_decompress(GISTENTRY *entry);
> ! float       *g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result);
> ! GIST_SPLITVEC *g_cube_picksplit(GistEntryVector *entryvec, GIST_SPLITVEC *v);
> ! bool        g_cube_leaf_consistent(NDBOX * key, NDBOX * query, StrategyNumber strategy);
> ! bool        g_cube_internal_consistent(NDBOX * key, NDBOX * query, StrategyNumber strategy);
> ! NDBOX       *g_cube_union(GistEntryVector *entryvec, int *sizep);
> ! NDBOX       *g_cube_binary_union(NDBOX * r1, NDBOX * r2, int *sizep);
> ! bool       *g_cube_same(NDBOX * b1, NDBOX * b2, bool *result);
>
>   /*
>   ** B-tree support functions
>   */
> ! bool        cube_eq(NDBOX * a, NDBOX * b);
> ! bool        cube_ne(NDBOX * a, NDBOX * b);
> ! bool        cube_lt(NDBOX * a, NDBOX * b);
> ! bool        cube_gt(NDBOX * a, NDBOX * b);
> ! bool        cube_le(NDBOX * a, NDBOX * b);
> ! bool        cube_ge(NDBOX * a, NDBOX * b);
> ! int32        cube_cmp(NDBOX * a, NDBOX * b);
>
>   /*
>   ** R-tree support functions
>   */
> ! bool        cube_contains(NDBOX * a, NDBOX * b);
> ! bool        cube_contained(NDBOX * a, NDBOX * b);
> ! bool        cube_overlap(NDBOX * a, NDBOX * b);
> ! NDBOX       *cube_union(NDBOX * a, NDBOX * b);
> ! NDBOX       *cube_inter(NDBOX * a, NDBOX * b);
> ! double       *cube_size(NDBOX * a);
> ! void        rt_cube_size(NDBOX * a, double *sz);
>
>   /*
>   ** miscellaneous
>   */
> ! bool        cube_lt(NDBOX * a, NDBOX * b);
> ! bool        cube_gt(NDBOX * a, NDBOX * b);
> ! double       *cube_distance(NDBOX * a, NDBOX * b);
> ! bool        cube_is_point(NDBOX * a);
> ! NDBOX       *cube_enlarge(NDBOX * a, double *r, int4 n);
>
>
>   /*
>   ** Auxiliary funxtions
> --- 28,140 ----
>   /*
>   ** Input/Output routines
>   */
> ! PG_FUNCTION_INFO_V1(cube_in);
> ! PG_FUNCTION_INFO_V1(cube);
> ! PG_FUNCTION_INFO_V1(cube_a_f8_f8);
> ! PG_FUNCTION_INFO_V1(cube_a_f8);
> ! PG_FUNCTION_INFO_V1(cube_out);
> ! PG_FUNCTION_INFO_V1(cube_f8);
> ! PG_FUNCTION_INFO_V1(cube_f8_f8);
> ! PG_FUNCTION_INFO_V1(cube_c_f8);
> ! PG_FUNCTION_INFO_V1(cube_c_f8_f8);
> ! PG_FUNCTION_INFO_V1(cube_dim);
> ! PG_FUNCTION_INFO_V1(cube_ll_coord);
> ! PG_FUNCTION_INFO_V1(cube_ur_coord);
> ! PG_FUNCTION_INFO_V1(cube_subset);
> !
> ! Datum        cube_in(PG_FUNCTION_ARGS);
> ! Datum        cube(PG_FUNCTION_ARGS);
> ! Datum        cube_a_f8_f8(PG_FUNCTION_ARGS);
> ! Datum        cube_a_f8(PG_FUNCTION_ARGS);
> ! Datum        cube_out(PG_FUNCTION_ARGS);
> ! Datum        cube_f8(PG_FUNCTION_ARGS);
> ! Datum        cube_f8_f8(PG_FUNCTION_ARGS);
> ! Datum        cube_c_f8(PG_FUNCTION_ARGS);
> ! Datum        cube_c_f8_f8(PG_FUNCTION_ARGS);
> ! Datum        cube_dim(PG_FUNCTION_ARGS);
> ! Datum        cube_ll_coord(PG_FUNCTION_ARGS);
> ! Datum        cube_ur_coord(PG_FUNCTION_ARGS);
> ! Datum        cube_subset(PG_FUNCTION_ARGS);
>
>   /*
>   ** GiST support methods
>   */
> !
> ! PG_FUNCTION_INFO_V1(g_cube_consistent);
> ! PG_FUNCTION_INFO_V1(g_cube_compress);
> ! PG_FUNCTION_INFO_V1(g_cube_decompress);
> ! PG_FUNCTION_INFO_V1(g_cube_penalty);
> ! PG_FUNCTION_INFO_V1(g_cube_picksplit);
> ! PG_FUNCTION_INFO_V1(g_cube_union);
> ! PG_FUNCTION_INFO_V1(g_cube_same);
> !
> ! Datum        g_cube_consistent(PG_FUNCTION_ARGS);
> ! Datum        g_cube_compress(PG_FUNCTION_ARGS);
> ! Datum        g_cube_decompress(PG_FUNCTION_ARGS);
> ! Datum        g_cube_penalty(PG_FUNCTION_ARGS);
> ! Datum        g_cube_picksplit(PG_FUNCTION_ARGS);
> ! Datum        g_cube_union(PG_FUNCTION_ARGS);
> ! Datum        g_cube_same(PG_FUNCTION_ARGS);
>
>   /*
>   ** B-tree support functions
>   */
> ! PG_FUNCTION_INFO_V1(cube_eq);
> ! PG_FUNCTION_INFO_V1(cube_ne);
> ! PG_FUNCTION_INFO_V1(cube_lt);
> ! PG_FUNCTION_INFO_V1(cube_gt);
> ! PG_FUNCTION_INFO_V1(cube_le);
> ! PG_FUNCTION_INFO_V1(cube_ge);
> ! PG_FUNCTION_INFO_V1(cube_cmp);
> !
> ! Datum        cube_eq(PG_FUNCTION_ARGS);
> ! Datum        cube_ne(PG_FUNCTION_ARGS);
> ! Datum        cube_lt(PG_FUNCTION_ARGS);
> ! Datum        cube_gt(PG_FUNCTION_ARGS);
> ! Datum        cube_le(PG_FUNCTION_ARGS);
> ! Datum        cube_ge(PG_FUNCTION_ARGS);
> ! Datum        cube_cmp(PG_FUNCTION_ARGS);
>
>   /*
>   ** R-tree support functions
>   */
> !
> ! PG_FUNCTION_INFO_V1(cube_contains);
> ! PG_FUNCTION_INFO_V1(cube_contained);
> ! PG_FUNCTION_INFO_V1(cube_overlap);
> ! PG_FUNCTION_INFO_V1(cube_union);
> ! PG_FUNCTION_INFO_V1(cube_inter);
> ! PG_FUNCTION_INFO_V1(cube_size);
> !
> ! Datum        cube_contains(PG_FUNCTION_ARGS);
> ! Datum        cube_contained(PG_FUNCTION_ARGS);
> ! Datum        cube_overlap(PG_FUNCTION_ARGS);
> ! Datum        cube_union(PG_FUNCTION_ARGS);
> ! Datum        cube_inter(PG_FUNCTION_ARGS);
> ! Datum        cube_size(PG_FUNCTION_ARGS);
>
>   /*
>   ** miscellaneous
>   */
> ! PG_FUNCTION_INFO_V1(cube_distance);
> ! PG_FUNCTION_INFO_V1(cube_is_point);
> ! PG_FUNCTION_INFO_V1(cube_enlarge);
> !
> ! Datum        cube_distance(PG_FUNCTION_ARGS);
> ! Datum        cube_is_point(PG_FUNCTION_ARGS);
> ! Datum        cube_enlarge(PG_FUNCTION_ARGS);
>
> + /*
> + ** 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);
>
>   /*
>   ** Auxiliary funxtions
> ***************
> *** 98,107 ****
>
>   /* NdBox = [(lowerleft),(upperright)] */
>   /* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
> ! NDBOX *
> ! cube_in(char *str)
>   {
>       void       *result;
>
>       cube_scanner_init(str);
>
> --- 148,160 ----
>
>   /* NdBox = [(lowerleft),(upperright)] */
>   /* [(xLL(1)...xLL(N)),(xUR(1)...xUR(n))] */
> ! Datum
> ! cube_in(PG_FUNCTION_ARGS)
>   {
>       void       *result;
> +     char        *str;
> +
> +     str = PG_GETARG_CSTRING(0);
>
>       cube_scanner_init(str);
>
> ***************
> *** 110,138 ****
>
>       cube_scanner_finish();
>
> !     return ((NDBOX *) result);
>   }
>
>   /* Allow conversion from text to cube to allow input of computed strings */
>   /* There may be issues with toasted data here. I don't know enough to be sure.*/
> ! NDBOX *
> ! cube(text *str)
>   {
> !     return cube_in(DatumGetCString(DirectFunctionCall1(textout,
> !                                                      PointerGetDatum(str))));
>   }
>
> ! char *
> ! cube_out(NDBOX * cube)
>   {
>       StringInfoData buf;
>       bool        equal = true;
> !     int            dim = cube->dim;
>       int            i;
>       int            ndig;
>
>       initStringInfo(&buf);
>
>       /*
>        * Get the number of digits to display.
>        */
> --- 163,342 ----
>
>       cube_scanner_finish();
>
> !     PG_RETURN_POINTER (result);
>   }
>
>   /* Allow conversion from text to cube to allow input of computed strings */
>   /* There may be issues with toasted data here. I don't know enough to be sure.*/
> ! Datum
> ! cube(PG_FUNCTION_ARGS)
>   {
> !     char    *cstring;
> !
> !     cstring = DatumGetCString(DirectFunctionCall1(textout, PointerGetDatum(PG_GETARG_TEXT_P(0))));
> !
> !     PG_RETURN_DATUM (DirectFunctionCall1 (cube_in, PointerGetDatum(cstring)));
>   }
>
> !
> ! #include "utils/array.h"
> !
> ! /*
> ! ** Taken from the intarray contrib header
> ! */
> ! #define ARRPTR(x)  ( (double *) ARR_DATA_PTR(x) )
> ! #define ARRNELEMS(x)  ArrayGetNItems( ARR_NDIM(x), ARR_DIMS(x))
> !
> !
> ! /*
> ! ** Allows the construction of a cube from 2 float[]'s
> ! */
> ! Datum
> ! cube_a_f8_f8(PG_FUNCTION_ARGS)
> ! {
> !     int        i;
> !     int        dim;
> !     int        size;
> !     NDBOX    *result;
> !     ArrayType    *ur, *ll;
> !     double    *dur, *dll;
> !
> !     ur = (ArrayType *) PG_GETARG_VARLENA_P(0);
> !     ll = (ArrayType *) PG_GETARG_VARLENA_P(1);
> !
> !     if (ARR_HASNULL(ur) || ARR_HASNULL(ll))
> !     {
> !         ereport(ERROR,
> !             (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
> !             errmsg("Cannot work with NULL arrays")));
> !     }
> !
> !     dim = ARRNELEMS(ur);
> !     if (ARRNELEMS(ll) != dim)
> !     {
> !         ereport(ERROR,
> !             (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
> !             errmsg("UR and LL arrays must be of same length")));
> !     }
> !
> !     dur = ARRPTR(ur);
> !     dll = ARRPTR(ll);
> !
> !     size = offsetof(NDBOX, x[0]) + sizeof(double) * 2 * dim;
> !     result = (NDBOX *) palloc (size);
> !     memset (result, 0, size);
> !     result->size = size;
> !     result->dim = dim;
> !
> !     for (i=0; i<dim; i++)
> !     {
> !         result->x[i] = dur[i];
> !         result->x[i+dim] = dll[i];
> !     }
> !
> !     PG_RETURN_POINTER(result);
> ! }
> !
> ! /*
> ! ** Allows the construction of a zero-volume cube from a float[]
> ! */
> ! Datum
> ! cube_a_f8(PG_FUNCTION_ARGS)
> ! {
> !     int        i;
> !     int        dim;
> !     int        size;
> !     NDBOX    *result;
> !     ArrayType    *ur;
> !     double    *dur;
> !
> !     ur = (ArrayType *) PG_GETARG_VARLENA_P(0);
> !
> !     if (ARR_HASNULL(ur))
> !     {
> !         ereport(ERROR,
> !             (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
> !             errmsg("Cannot work with NULL arrays")));
> !     }
> !
> !     dim = ARRNELEMS(ur);
> !
> !     dur = ARRPTR(ur);
> !
> !     size = offsetof(NDBOX, x[0]) + sizeof(double) * 2 * dim;
> !     result = (NDBOX *) palloc (size);
> !     memset (result, 0, size);
> !     result->size = size;
> !     result->dim = dim;
> !
> !     for (i=0; i<dim; i++)
> !     {
> !         result->x[i] = dur[i];
> !         result->x[i+dim] = dur[i];
> !     }
> !
> !     PG_RETURN_POINTER(result);
> ! }
> !
> ! Datum
> ! cube_subset(PG_FUNCTION_ARGS)
> ! {
> !     NDBOX        *c, *result;
> !     ArrayType   *idx;
> !     int          size, dim, i;
> !     int         *dx;
> !
> !     c = (NDBOX *) PG_GETARG_POINTER(0);
> !     idx = (ArrayType *) PG_GETARG_VARLENA_P(1);
> !
> !     if (ARR_HASNULL(idx))
> !     {
> !         ereport(ERROR,
> !             (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
> !             errmsg("Cannot work with NULL arrays")));
> !     }
> !
> !     dx = (int4 *) ARR_DATA_PTR (idx);
> !
> !     dim = ARRNELEMS(idx);
> !     size = offsetof(NDBOX, x[0]) + sizeof(double) * 2 * dim;
> !     result = (NDBOX *) palloc (size);
> !     memset (result, 0, size);
> !     result->size = size;
> !     result->dim = dim;
> !
> !     for (i=0; i<dim; i++)
> !     {
> !         if ((dx[i] <= 0) || (dx[i] > c->dim))
> !         {
> !             pfree (result);
> !             ereport(ERROR,
> !                 (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
> !                 errmsg("Index out of bounds")));
> !         }
> !         result->x[i] = c->x[dx[i]-1];
> !         result->x[i+dim] = c->x[dx[i]+c->dim-1];
> !     }
> !
> !     PG_RETURN_POINTER(result);
> ! }
> !
> ! Datum
> ! cube_out(PG_FUNCTION_ARGS)
>   {
>       StringInfoData buf;
>       bool        equal = true;
> !     int            dim;
>       int            i;
>       int            ndig;
> +     NDBOX        *cube;
>
>       initStringInfo(&buf);
>
> +     cube = (NDBOX *) PG_GETARG_POINTER (0);
> +
> +     dim = cube->dim;
> +
>       /*
>        * Get the number of digits to display.
>        */
> ***************
> *** 167,173 ****
>           appendStringInfoChar(&buf, ')');
>       }
>
> !     return buf.data;
>   }
>
>
> --- 371,377 ----
>           appendStringInfoChar(&buf, ')');
>       }
>
> !     PG_RETURN_CSTRING (buf.data);
>   }
>
>
> ***************
> *** 181,191 ****
>   ** the predicate x op query == FALSE, where op is the oper
>   ** corresponding to strategy in the pg_amop table.
>   */
> ! bool
> ! g_cube_consistent(GISTENTRY *entry,
> !                   NDBOX * query,
> !                   StrategyNumber strategy)
>   {
>       /*
>        * if entry is not leaf, use g_cube_internal_consistent, else use
>        * g_cube_leaf_consistent
> --- 385,397 ----
>   ** the predicate x op query == FALSE, where op is the oper
>   ** corresponding to strategy in the pg_amop table.
>   */
> ! Datum
> ! g_cube_consistent(PG_FUNCTION_ARGS)
>   {
> +     GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
> +     NDBOX *query = (NDBOX *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
> +     StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
> +
>       /*
>        * if entry is not leaf, use g_cube_internal_consistent, else use
>        * g_cube_leaf_consistent
> ***************
> *** 203,214 ****
>   ** The GiST Union method for boxes
>   ** returns the minimal bounding box that encloses all the entries in entryvec
>   */
> ! NDBOX *
> ! g_cube_union(GistEntryVector *entryvec, int *sizep)
>   {
>       int            i;
>       NDBOX       *out = (NDBOX *) NULL;
>       NDBOX       *tmp;
>
>       /*
>        * fprintf(stderr, "union\n");
> --- 409,425 ----
>   ** The GiST Union method for boxes
>   ** returns the minimal bounding box that encloses all the entries in entryvec
>   */
> ! Datum
> ! g_cube_union(PG_FUNCTION_ARGS)
>   {
>       int            i;
>       NDBOX       *out = (NDBOX *) NULL;
>       NDBOX       *tmp;
> +     int           *sizep;
> +     GistEntryVector    *entryvec;
> +
> +     entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
> +     sizep = (int *) PG_GETARG_POINTER(1);
>
>       /*
>        * fprintf(stderr, "union\n");
> ***************
> *** 228,264 ****
>           tmp = out;
>       }
>
> !     return (out);
>   }
>
>   /*
>   ** GiST Compress and Decompress methods for boxes
>   ** do not do anything.
>   */
> ! GISTENTRY *
> ! g_cube_compress(GISTENTRY *entry)
>   {
> !     return (entry);
>   }
>
> ! GISTENTRY *
> ! g_cube_decompress(GISTENTRY *entry)
>   {
> !     return (entry);
>   }
>
>   /*
>   ** The GiST Penalty method for boxes
>   ** As in the R-tree paper, we use change in area as our penalty metric
>   */
> ! float *
> ! g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
>   {
>       NDBOX       *ud;
>       double        tmp1,
>                   tmp2;
>
> !     ud = cube_union((NDBOX *) DatumGetPointer(origentry->key),
>                       (NDBOX *) DatumGetPointer(newentry->key));
>       rt_cube_size(ud, &tmp1);
>       rt_cube_size((NDBOX *) DatumGetPointer(origentry->key), &tmp2);
> --- 439,480 ----
>           tmp = out;
>       }
>
> !     PG_RETURN_POINTER(out);
>   }
>
>   /*
>   ** GiST Compress and Decompress methods for boxes
>   ** do not do anything.
>   */
> !
> ! Datum
> ! g_cube_compress (PG_FUNCTION_ARGS)
>   {
> !     PG_RETURN_DATUM(PG_GETARG_DATUM(0));
>   }
>
> ! Datum
> ! g_cube_decompress (PG_FUNCTION_ARGS)
>   {
> !     PG_RETURN_DATUM(PG_GETARG_DATUM(0));
>   }
>
> +
>   /*
>   ** The GiST Penalty method for boxes
>   ** As in the R-tree paper, we use change in area as our penalty metric
>   */
> ! Datum
> ! g_cube_penalty (PG_FUNCTION_ARGS)
>   {
> +     GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
> +     GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
> +     float      *result = (float *) PG_GETARG_POINTER(2);
>       NDBOX       *ud;
>       double        tmp1,
>                   tmp2;
>
> !     ud = cube_union_v0((NDBOX *) DatumGetPointer(origentry->key),
>                       (NDBOX *) DatumGetPointer(newentry->key));
>       rt_cube_size(ud, &tmp1);
>       rt_cube_size((NDBOX *) DatumGetPointer(origentry->key), &tmp2);
> ***************
> *** 267,273 ****
>       /*
>        * fprintf(stderr, "penalty\n"); fprintf(stderr, "\t%g\n", *result);
>        */
> !     return (result);
>   }
>
>
> --- 483,489 ----
>       /*
>        * fprintf(stderr, "penalty\n"); fprintf(stderr, "\t%g\n", *result);
>        */
> !     PG_RETURN_FLOAT8 (*result);
>   }
>
>
> ***************
> *** 276,285 ****
>   ** The GiST PickSplit method for boxes
>   ** We use Guttman's poly time split algorithm
>   */
> ! GIST_SPLITVEC *
> ! g_cube_picksplit(GistEntryVector *entryvec,
> !                  GIST_SPLITVEC *v)
>   {
>       OffsetNumber i,
>                   j;
>       NDBOX       *datum_alpha,
> --- 492,502 ----
>   ** The GiST PickSplit method for boxes
>   ** We use Guttman's poly time split algorithm
>   */
> ! Datum
> ! g_cube_picksplit(PG_FUNCTION_ARGS)
>   {
> +     GistEntryVector    *entryvec;
> +     GIST_SPLITVEC    *v;
>       OffsetNumber i,
>                   j;
>       NDBOX       *datum_alpha,
> ***************
> *** 306,311 ****
> --- 523,531 ----
>                  *right;
>       OffsetNumber maxoff;
>
> +     entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
> +     v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
> +
>       /*
>        * fprintf(stderr, "picksplit\n");
>        */
> ***************
> *** 326,334 ****
>
>               /* compute the wasted space by unioning these guys */
>               /* size_waste = size_union - size_inter; */
> !             union_d = cube_union(datum_alpha, datum_beta);
>               rt_cube_size(union_d, &size_union);
> !             inter_d = cube_inter(datum_alpha, datum_beta);
>               rt_cube_size(inter_d, &size_inter);
>               size_waste = size_union - size_inter;
>
> --- 546,556 ----
>
>               /* compute the wasted space by unioning these guys */
>               /* size_waste = size_union - size_inter; */
> !             union_d = cube_union_v0(datum_alpha, datum_beta);
>               rt_cube_size(union_d, &size_union);
> !             inter_d = (NDBOX *) DatumGetPointer (DirectFunctionCall2
> !                                  (cube_inter,
> !                                   entryvec->vector[i].key, entryvec->vector[j].key));
>               rt_cube_size(inter_d, &size_inter);
>               size_waste = size_union - size_inter;
>
> ***************
> *** 352,361 ****
>       v->spl_nright = 0;
>
>       datum_alpha = (NDBOX *) DatumGetPointer(entryvec->vector[seed_1].key);
> !     datum_l = cube_union(datum_alpha, datum_alpha);
>       rt_cube_size(datum_l, &size_l);
>       datum_beta = (NDBOX *) DatumGetPointer(entryvec->vector[seed_2].key);
> !     datum_r = cube_union(datum_beta, datum_beta);
>       rt_cube_size(datum_r, &size_r);
>
>       /*
> --- 574,583 ----
>       v->spl_nright = 0;
>
>       datum_alpha = (NDBOX *) DatumGetPointer(entryvec->vector[seed_1].key);
> !     datum_l = cube_union_v0(datum_alpha, datum_alpha);
>       rt_cube_size(datum_l, &size_l);
>       datum_beta = (NDBOX *) DatumGetPointer(entryvec->vector[seed_2].key);
> !     datum_r = cube_union_v0(datum_beta, datum_beta);
>       rt_cube_size(datum_r, &size_r);
>
>       /*
> ***************
> *** 394,401 ****
>
>           /* okay, which page needs least enlargement? */
>           datum_alpha = (NDBOX *) DatumGetPointer(entryvec->vector[i].key);
> !         union_dl = cube_union(datum_l, datum_alpha);
> !         union_dr = cube_union(datum_r, datum_alpha);
>           rt_cube_size(union_dl, &size_alpha);
>           rt_cube_size(union_dr, &size_beta);
>
> --- 616,623 ----
>
>           /* okay, which page needs least enlargement? */
>           datum_alpha = (NDBOX *) DatumGetPointer(entryvec->vector[i].key);
> !         union_dl = cube_union_v0(datum_l, datum_alpha);
> !         union_dr = cube_union_v0(datum_r, datum_alpha);
>           rt_cube_size(union_dl, &size_alpha);
>           rt_cube_size(union_dr, &size_beta);
>
> ***************
> *** 420,435 ****
>       v->spl_ldatum = PointerGetDatum(datum_l);
>       v->spl_rdatum = PointerGetDatum(datum_r);
>
> !     return v;
>   }
>
>   /*
>   ** Equality method
>   */
> ! bool *
> ! g_cube_same(NDBOX * b1, NDBOX * b2, bool *result)
>   {
> !     if (cube_eq(b1, b2))
>           *result = TRUE;
>       else
>           *result = FALSE;
> --- 642,664 ----
>       v->spl_ldatum = PointerGetDatum(datum_l);
>       v->spl_rdatum = PointerGetDatum(datum_r);
>
> !     PG_RETURN_POINTER(v);
>   }
>
>   /*
>   ** Equality method
>   */
> ! Datum
> ! g_cube_same(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *b1, *b2;
> !     bool    *result;
> !
> !     b1 = (NDBOX *) PG_GETARG_POINTER (0);
> !     b2 = (NDBOX *) PG_GETARG_POINTER (1);
> !     result = (bool *) PG_GETARG_POINTER (2);
> !
> !     if (cube_cmp_v0(b1, b2) == 0)
>           *result = TRUE;
>       else
>           *result = FALSE;
> ***************
> *** 437,443 ****
>       /*
>        * fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" ));
>        */
> !     return (result);
>   }
>
>   /*
> --- 666,672 ----
>       /*
>        * fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" ));
>        */
> !     PG_RETURN_POINTER (result);
>   }
>
>   /*
> ***************
> *** 456,471 ****
>       switch (strategy)
>       {
>           case RTOverlapStrategyNumber:
> !             retval = (bool) cube_overlap(key, query);
>               break;
>           case RTSameStrategyNumber:
> !             retval = (bool) cube_eq(key, query);
>               break;
>           case RTContainsStrategyNumber:
> !             retval = (bool) cube_contains(key, query);
>               break;
>           case RTContainedByStrategyNumber:
> !             retval = (bool) cube_contained(key, query);
>               break;
>           default:
>               retval = FALSE;
> --- 685,700 ----
>       switch (strategy)
>       {
>           case RTOverlapStrategyNumber:
> !             retval = (bool) cube_overlap_v0(key, query);
>               break;
>           case RTSameStrategyNumber:
> !             retval = (bool) (cube_cmp_v0(key, query) == 0);
>               break;
>           case RTContainsStrategyNumber:
> !             retval = (bool) cube_contains_v0(key, query);
>               break;
>           case RTContainedByStrategyNumber:
> !             retval = (bool) cube_contains_v0(query, key);
>               break;
>           default:
>               retval = FALSE;
> ***************
> *** 486,499 ****
>       switch (strategy)
>       {
>           case RTOverlapStrategyNumber:
> !             retval = (bool) cube_overlap(key, query);
>               break;
>           case RTSameStrategyNumber:
>           case RTContainsStrategyNumber:
> !             retval = (bool) cube_contains(key, query);
>               break;
>           case RTContainedByStrategyNumber:
> !             retval = (bool) cube_overlap(key, query);
>               break;
>           default:
>               retval = FALSE;
> --- 715,728 ----
>       switch (strategy)
>       {
>           case RTOverlapStrategyNumber:
> !             retval = (bool) cube_overlap_v0(key, query);
>               break;
>           case RTSameStrategyNumber:
>           case RTContainsStrategyNumber:
> !             retval = (bool) cube_contains_v0(key, query);
>               break;
>           case RTContainedByStrategyNumber:
> !             retval = (bool) cube_overlap_v0(key, query);
>               break;
>           default:
>               retval = FALSE;
> ***************
> *** 506,521 ****
>   {
>       NDBOX       *retval;
>
> !     retval = cube_union(r1, r2);
>       *sizep = retval->size;
>
>       return (retval);
>   }
>
>
> ! /* cube_union */
>   NDBOX *
> ! cube_union(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>       NDBOX       *result;
> --- 735,750 ----
>   {
>       NDBOX       *retval;
>
> !     retval = cube_union_v0(r1, r2);
>       *sizep = retval->size;
>
>       return (retval);
>   }
>
>
> ! /* cube_union_v0 */
>   NDBOX *
> ! cube_union_v0(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>       NDBOX       *result;
> ***************
> *** 571,582 ****
>       return (result);
>   }
>
>   /* cube_inter */
> ! NDBOX *
> ! cube_inter(NDBOX * a, NDBOX * b)
>   {
>       int            i;
> !     NDBOX       *result;
>
>       if (a->dim >= b->dim)
>       {
> --- 800,825 ----
>       return (result);
>   }
>
> + Datum
> + cube_union (PG_FUNCTION_ARGS)
> + {
> +     NDBOX    *a, *b;
> +
> +     a = (NDBOX *) PG_GETARG_POINTER(0);
> +     b = (NDBOX *) PG_GETARG_POINTER(1);
> +
> +     PG_RETURN_POINTER(cube_union_v0(a,b));
> + }
> +
>   /* cube_inter */
> ! Datum
> ! cube_inter(PG_FUNCTION_ARGS)
>   {
>       int            i;
> !     NDBOX       *result, *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
>
>       if (a->dim >= b->dim)
>       {
> ***************
> *** 629,652 ****
>       /*
>        * Is it OK to return a non-null intersection for non-overlapping boxes?
>        */
> !     return (result);
>   }
>
>   /* cube_size */
> ! double *
> ! cube_size(NDBOX * a)
>   {
>       int            i,
>                   j;
> !     double       *result;
>
> !     result = (double *) palloc(sizeof(double));
>
> !     *result = 1.0;
>       for (i = 0, j = a->dim; i < a->dim; i++, j++)
> !         *result = (*result) * Abs((a->x[j] - a->x[i]));
>
> !     return (result);
>   }
>
>   void
> --- 872,896 ----
>       /*
>        * Is it OK to return a non-null intersection for non-overlapping boxes?
>        */
> !     PG_RETURN_POINTER (result);
>   }
>
>   /* cube_size */
> ! Datum
> ! cube_size(PG_FUNCTION_ARGS)
>   {
> +     NDBOX        *a;
>       int            i,
>                   j;
> !     double           result;
>
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
>
> !     result = 1.0;
>       for (i = 0, j = a->dim; i < a->dim; i++, j++)
> !         result = result * Abs((a->x[j] - a->x[i]));
>
> !     PG_RETURN_FLOAT8 (result);
>   }
>
>   void
> ***************
> *** 669,675 ****
>   /* 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
> ! cube_cmp(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>       int            dim;
> --- 913,919 ----
>   /* 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
> ! cube_cmp_v0(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>       int            dim;
> ***************
> *** 748,795 ****
>       return 0;
>   }
>
>
> ! bool
> ! cube_eq(NDBOX * a, NDBOX * b)
>   {
> !     return (cube_cmp(a, b) == 0);
>   }
>
> ! bool
> ! cube_ne(NDBOX * a, NDBOX * b)
>   {
> !     return (cube_cmp(a, b) != 0);
>   }
>
> ! bool
> ! cube_lt(NDBOX * a, NDBOX * b)
>   {
> !     return (cube_cmp(a, b) < 0);
>   }
>
> ! bool
> ! cube_gt(NDBOX * a, NDBOX * b)
>   {
> !     return (cube_cmp(a, b) > 0);
>   }
>
> ! bool
> ! cube_le(NDBOX * a, NDBOX * b)
>   {
> !     return (cube_cmp(a, b) <= 0);
>   }
>
> ! bool
> ! cube_ge(NDBOX * a, NDBOX * b)
>   {
> !     return (cube_cmp(a, b) >= 0);
>   }
>
>
>   /* Contains */
>   /* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
>   bool
> ! cube_contains(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>
> --- 992,1086 ----
>       return 0;
>   }
>
> + Datum
> + cube_cmp(PG_FUNCTION_ARGS)
> + {
> +     NDBOX    *a, *b;
>
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_INT16(cube_cmp_v0(a, b));
> ! }
> !
> !
> ! Datum
> ! cube_eq(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL(cube_cmp_v0(a, b) == 0);
>   }
>
> !
> ! Datum
> ! cube_ne(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL(cube_cmp_v0(a, b) != 0);
>   }
>
> !
> ! Datum
> ! cube_lt(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL(cube_cmp_v0(a, b) < 0);
>   }
>
> !
> ! Datum
> ! cube_gt(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL(cube_cmp_v0(a, b) > 0);
>   }
>
> !
> ! Datum
> ! cube_le(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL(cube_cmp_v0(a, b) <= 0);
>   }
>
> !
> ! Datum
> ! cube_ge(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL(cube_cmp_v0(a, b) >= 0);
>   }
>
>
> +
>   /* Contains */
>   /* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
>   bool
> ! cube_contains_v0(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>
> ***************
> *** 826,846 ****
>       return (TRUE);
>   }
>
>   /* Contained */
>   /* Box(A) Contained by Box(B) IFF Box(B) Contains Box(A) */
> ! bool
> ! cube_contained(NDBOX * a, NDBOX * b)
>   {
> !     if (cube_contains(b, a) == TRUE)
> !         return (TRUE);
> !     else
> !         return (FALSE);
>   }
>
>   /* Overlap */
>   /* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
>   bool
> ! cube_overlap(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>
> --- 1117,1150 ----
>       return (TRUE);
>   }
>
> + Datum
> + cube_contains(PG_FUNCTION_ARGS)
> + {
> +     NDBOX    *a, *b;
> +
> +     a = (NDBOX *) PG_GETARG_POINTER(0);
> +     b = (NDBOX *) PG_GETARG_POINTER(1);
> +
> +     PG_RETURN_BOOL(cube_contains_v0(a, b));
> + }
> +
>   /* Contained */
>   /* Box(A) Contained by Box(B) IFF Box(B) Contains Box(A) */
> ! Datum
> ! cube_contained(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *a, *b;
> !
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
> !
> !     PG_RETURN_BOOL (cube_contains_v0(b, a));
>   }
>
>   /* Overlap */
>   /* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
>   bool
> ! cube_overlap_v0(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>
> ***************
> *** 884,903 ****
>   }
>
>
>   /* Distance */
>   /* The distance is computed as a per axis sum of the squared distances
>      between 1D projections of the boxes onto Cartesian axes. Assuming zero
>      distance between overlapping projections, this metric coincides with the
>      "common sense" geometric distance */
> ! double *
> ! cube_distance(NDBOX * a, NDBOX * b)
>   {
>       int            i;
>       double        d,
>                   distance;
> !     double       *result;
>
> !     result = (double *) palloc(sizeof(double));
>
>       /* swap the box pointers if needed */
>       if (a->dim < b->dim)
> --- 1188,1220 ----
>   }
>
>
> + Datum
> + cube_overlap(PG_FUNCTION_ARGS)
> + {
> +     NDBOX    *a, *b;
> +
> +     a = (NDBOX *) PG_GETARG_POINTER(0);
> +     b = (NDBOX *) PG_GETARG_POINTER(1);
> +
> +     PG_RETURN_BOOL (cube_overlap_v0(a, b));
> + }
> +
> +
>   /* Distance */
>   /* The distance is computed as a per axis sum of the squared distances
>      between 1D projections of the boxes onto Cartesian axes. Assuming zero
>      distance between overlapping projections, this metric coincides with the
>      "common sense" geometric distance */
> ! Datum
> ! cube_distance(PG_FUNCTION_ARGS)
>   {
>       int            i;
>       double        d,
>                   distance;
> !     NDBOX       *a, *b;
>
> !     a = (NDBOX *) PG_GETARG_POINTER(0);
> !     b = (NDBOX *) PG_GETARG_POINTER(1);
>
>       /* swap the box pointers if needed */
>       if (a->dim < b->dim)
> ***************
> *** 923,931 ****
>           distance += d * d;
>       }
>
> !     *result = (double) sqrt(distance);
> !
> !     return (result);
>   }
>
>   static double
> --- 1240,1246 ----
>           distance += d * d;
>       }
>
> !     PG_RETURN_FLOAT8(sqrt(distance));
>   }
>
>   static double
> ***************
> *** 944,1001 ****
>   }
>
>   /* Test if a box is also a point */
> ! bool
> ! cube_is_point(NDBOX * a)
>   {
>       int            i,
>                   j;
>
>       for (i = 0, j = a->dim; i < a->dim; i++, j++)
>       {
>           if (a->x[i] != a->x[j])
> !             return FALSE;
>       }
>
> !     return TRUE;
>   }
>
>   /* Return dimensions in use in the data structure */
> ! int4
> ! cube_dim(NDBOX * a)
>   {
> !     /* Other things will break before unsigned int doesn't fit. */
> !     return a->dim;
>   }
>
>   /* Return a specific normalized LL coordinate */
> ! double *
> ! cube_ll_coord(NDBOX * a, int4 n)
>   {
> !     double       *result;
>
> !     result = (double *) palloc(sizeof(double));
> !     *result = 0;
> !     if (a->dim >= n && n > 0)
> !         *result = Min(a->x[n - 1], a->x[a->dim + n - 1]);
> !     return result;
>   }
>
>   /* Return a specific normalized UR coordinate */
> ! double *
> ! cube_ur_coord(NDBOX * a, int4 n)
>   {
> !     double       *result;
>
> !     result = (double *) palloc(sizeof(double));
> !     *result = 0;
> !     if (a->dim >= n && n > 0)
> !         *result = Max(a->x[n - 1], a->x[a->dim + n - 1]);
> !     return result;
>   }
>
>   /* Increase or decrease box size by a radius in at least n dimensions. */
> ! NDBOX *
> ! cube_enlarge(NDBOX * a, double *r, int4 n)
>   {
>       NDBOX       *result;
>       int            dim = 0;
> --- 1259,1332 ----
>   }
>
>   /* Test if a box is also a point */
> ! Datum
> ! cube_is_point(PG_FUNCTION_ARGS)
>   {
>       int            i,
>                   j;
> +     NDBOX        *a;
> +
> +     a = (NDBOX *) PG_GETARG_POINTER(0);
>
>       for (i = 0, j = a->dim; i < a->dim; i++, j++)
>       {
>           if (a->x[i] != a->x[j])
> !             PG_RETURN_BOOL(FALSE);
>       }
>
> !     PG_RETURN_BOOL(TRUE);
>   }
>
>   /* Return dimensions in use in the data structure */
> ! Datum
> ! cube_dim(PG_FUNCTION_ARGS)
>   {
> !     NDBOX    *c;
> !
> !     c = (NDBOX *) PG_GETARG_POINTER(0);
> !
> !     PG_RETURN_INT16 (c->dim);
>   }
>
>   /* Return a specific normalized LL coordinate */
> ! Datum
> ! cube_ll_coord(PG_FUNCTION_ARGS)
>   {
> !     NDBOX       *c;
> !     int            n;
> !     double        result;
> !
> !     c = (NDBOX *) PG_GETARG_POINTER(0);
> !     n = PG_GETARG_INT16(1);
> !
> !     result = 0;
> !     if (c->dim >= n && n > 0)
> !         result = Min(c->x[n - 1], c->x[c->dim + n - 1]);
>
> !     PG_RETURN_FLOAT8(result);
>   }
>
>   /* Return a specific normalized UR coordinate */
> ! Datum
> ! cube_ur_coord(PG_FUNCTION_ARGS)
>   {
> !     NDBOX       *c;
> !     int            n;
> !     double        result;
>
> !     c = (NDBOX *) PG_GETARG_POINTER(0);
> !     n = PG_GETARG_INT16(1);
> !
> !     result = 0;
> !     if (c->dim >= n && n > 0)
> !         result = Max(c->x[n - 1], c->x[c->dim + n - 1]);
> !
> !     PG_RETURN_FLOAT8(result);
>   }
>
>   /* Increase or decrease box size by a radius in at least n dimensions. */
> ! Datum
> ! cube_enlarge(PG_FUNCTION_ARGS)
>   {
>       NDBOX       *result;
>       int            dim = 0;
> ***************
> *** 1003,1008 ****
> --- 1334,1346 ----
>       int            i,
>                   j,
>                   k;
> +     NDBOX       *a;
> +     double       *r;
> +     int4        n;
> +
> +     a = (NDBOX *) PG_GETARG_POINTER(0);
> +     r = (double *) PG_GETARG_POINTER(1);
> +     n = PG_GETARG_INT32(2);
>
>       if (n > CUBE_MAX_DIM)
>           n = CUBE_MAX_DIM;
> ***************
> *** 1039,1050 ****
>           result->x[i] = -*r;
>           result->x[j] = *r;
>       }
> !     return result;
>   }
>
>   /* Create a one dimensional box with identical upper and lower coordinates */
> ! NDBOX *
> ! cube_f8(double *x1)
>   {
>       NDBOX       *result;
>       int            size;
> --- 1377,1389 ----
>           result->x[i] = -*r;
>           result->x[j] = *r;
>       }
> !
> !     PG_RETURN_POINTER(result);
>   }
>
>   /* Create a one dimensional box with identical upper and lower coordinates */
> ! Datum
> ! cube_f8(PG_FUNCTION_ARGS)
>   {
>       NDBOX       *result;
>       int            size;
> ***************
> *** 1054,1067 ****
>       memset(result, 0, size);
>       result->size = size;
>       result->dim = 1;
> !     result->x[0] = *x1;
> !     result->x[1] = *x1;
> !     return result;
>   }
>
>   /* Create a one dimensional box */
> ! NDBOX *
> ! cube_f8_f8(double *x1, double *x2)
>   {
>       NDBOX       *result;
>       int            size;
> --- 1393,1407 ----
>       memset(result, 0, size);
>       result->size = size;
>       result->dim = 1;
> !     result->x[0] = PG_GETARG_FLOAT8(0);
> !     result->x[1] = result->x[0];
> !
> !     PG_RETURN_POINTER (result);
>   }
>
>   /* Create a one dimensional box */
> ! Datum
> ! cube_f8_f8(PG_FUNCTION_ARGS)
>   {
>       NDBOX       *result;
>       int            size;
> ***************
> *** 1071,1090 ****
>       memset(result, 0, size);
>       result->size = size;
>       result->dim = 1;
> !     result->x[0] = *x1;
> !     result->x[1] = *x2;
> !     return result;
>   }
>
>   /* Add a dimension to an existing cube with the same values for the new
>      coordinate */
> ! NDBOX *
> ! cube_c_f8(NDBOX * c, double *x1)
>   {
>       NDBOX       *result;
>       int            size;
>       int            i;
>
>       size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) *2;
>       result = (NDBOX *) palloc(size);
>       memset(result, 0, size);
> --- 1411,1436 ----
>       memset(result, 0, size);
>       result->size = size;
>       result->dim = 1;
> !     result->x[0] = PG_GETARG_FLOAT8(0);
> !     result->x[1] = PG_GETARG_FLOAT8(1);
> !
> !     PG_RETURN_POINTER (result);
>   }
>
>   /* Add a dimension to an existing cube with the same values for the new
>      coordinate */
> ! Datum
> ! cube_c_f8(PG_FUNCTION_ARGS)
>   {
> +     NDBOX       *c;
>       NDBOX       *result;
> +     double        x;
>       int            size;
>       int            i;
>
> +     c = (NDBOX *) PG_GETARG_POINTER(0);
> +     x = PG_GETARG_FLOAT8 (1);
> +
>       size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) *2;
>       result = (NDBOX *) palloc(size);
>       memset(result, 0, size);
> ***************
> *** 1095,1113 ****
>           result->x[i] = c->x[i];
>           result->x[result->dim + i] = c->x[c->dim + i];
>       }
> !     result->x[result->dim - 1] = *x1;
> !     result->x[2 * result->dim - 1] = *x1;
> !     return result;
>   }
>
>   /* Add a dimension to an existing cube */
> ! NDBOX *
> ! cube_c_f8_f8(NDBOX * c, double *x1, double *x2)
>   {
>       NDBOX       *result;
>       int            size;
>       int            i;
>
>       size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) *2;
>       result = (NDBOX *) palloc(size);
>       memset(result, 0, size);
> --- 1441,1466 ----
>           result->x[i] = c->x[i];
>           result->x[result->dim + i] = c->x[c->dim + i];
>       }
> !     result->x[result->dim - 1] = x;
> !     result->x[2 * result->dim - 1] = x;
> !
> !     PG_RETURN_POINTER(result);
>   }
>
>   /* Add a dimension to an existing cube */
> ! Datum
> ! cube_c_f8_f8(PG_FUNCTION_ARGS)
>   {
> +     NDBOX       *c;
>       NDBOX       *result;
> +     double        x1, x2;
>       int            size;
>       int            i;
>
> +     c = (NDBOX *) PG_GETARG_POINTER(0);
> +     x1 = PG_GETARG_FLOAT8 (1);
> +     x2 = PG_GETARG_FLOAT8 (2);
> +
>       size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) *2;
>       result = (NDBOX *) palloc(size);
>       memset(result, 0, size);
> ***************
> *** 1118,1124 ****
>           result->x[i] = c->x[i];
>           result->x[result->dim + i] = c->x[c->dim + i];
>       }
> !     result->x[result->dim - 1] = *x1;
> !     result->x[2 * result->dim - 1] = *x2;
> !     return result;
>   }
> --- 1471,1480 ----
>           result->x[i] = c->x[i];
>           result->x[result->dim + i] = c->x[c->dim + i];
>       }
> !     result->x[result->dim - 1] = x1;
> !     result->x[2 * result->dim - 1] = x2;
> !
> !     PG_RETURN_POINTER(result);
>   }
> +
> +
> Index: cube.sql.in
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/cube.sql.in,v
> retrieving revision 1.17
> diff -c -r1.17 cube.sql.in
> *** cube.sql.in    27 Feb 2006 16:09:48 -0000    1.17
> --- cube.sql.in    22 Jul 2006 05:15:46 -0000
> ***************
> *** 9,14 ****
> --- 9,22 ----
>   AS 'MODULE_PATHNAME'
>   LANGUAGE C IMMUTABLE STRICT;
>
> + CREATE OR REPLACE FUNCTION cube(float8[], float8[]) RETURNS cube
> + AS 'MODULE_PATHNAME', 'cube_a_f8_f8'
> + LANGUAGE C IMMUTABLE STRICT;
> +
> + CREATE OR REPLACE FUNCTION cube(float8[]) RETURNS cube
> + AS 'MODULE_PATHNAME', 'cube_a_f8'
> + LANGUAGE C IMMUTABLE STRICT;
> +
>   CREATE OR REPLACE FUNCTION cube_out(cube)
>   RETURNS cstring
>   AS 'MODULE_PATHNAME'
> ***************
> *** 129,134 ****
> --- 137,147 ----
>
>   -- Misc N-dimensional functions
>
> + CREATE OR REPLACE FUNCTION cube_subset(cube, int4[])
> + RETURNS cube
> + AS 'MODULE_PATHNAME'
> + LANGUAGE C IMMUTABLE STRICT;
> +
>   -- proximity routines
>
>   CREATE OR REPLACE FUNCTION cube_distance(cube, cube)
> Index: uninstall_cube.sql
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/uninstall_cube.sql,v
> retrieving revision 1.2
> diff -c -r1.2 uninstall_cube.sql
> *** uninstall_cube.sql    13 Mar 2006 18:04:57 -0000    1.2
> --- uninstall_cube.sql    22 Jul 2006 05:15:46 -0000
> ***************
> *** 46,51 ****
> --- 46,57 ----
>
>   DROP FUNCTION cube(float8, float8);
>
> + DROP FUNCTION cube(float8[], float8[]);
> +
> + DROP FUNCTION cube(float8[]);
> +
> + DROP FUNCTION cube_subset(cube, int4[]);
> +
>   DROP FUNCTION cube(float8);
>
>   DROP FUNCTION cube_ur_coord(cube, int4);
> Index: expected/cube.out
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/expected/cube.out,v
> retrieving revision 1.16
> diff -c -r1.16 cube.out
> *** expected/cube.out    1 Mar 2006 21:09:31 -0000    1.16
> --- expected/cube.out    22 Jul 2006 05:15:46 -0000
> ***************
> *** 8,14 ****
>   \set ECHO none
>   psql:cube.sql:10: NOTICE:  type "cube" is not yet defined
>   DETAIL:  Creating a shell type definition.
> ! psql:cube.sql:15: NOTICE:  argument type cube is only a shell
>   --
>   -- testing the input and output functions
>   --
> --- 8,16 ----
>   \set ECHO none
>   psql:cube.sql:10: NOTICE:  type "cube" is not yet defined
>   DETAIL:  Creating a shell type definition.
> ! psql:cube.sql:14: NOTICE:  return type cube is only a shell
> ! psql:cube.sql:18: NOTICE:  return type cube is only a shell
> ! psql:cube.sql:23: NOTICE:  argument type cube is only a shell
>   --
>   -- testing the input and output functions
>   --
> ***************
> *** 396,401 ****
> --- 398,434 ----
>   (1 row)
>
>   --
> + -- Test the float[] -> cube cast
> + --
> + SELECT cube('{0,1,2}'::float[], '{3,4,5}'::float[]);
> +         cube
> + ---------------------
> +  (0, 1, 2),(3, 4, 5)
> + (1 row)
> +
> + SELECT cube('{0,1,2}'::float[], '{3}'::float[]);
> + ERROR:  UR and LL arrays must be of same length
> + SELECT cube(NULL::float[], '{3}'::float[]);
> +  cube
> + ------
> +
> + (1 row)
> +
> + SELECT cube('{0,1,2}'::float[]);
> +    cube
> + -----------
> +  (0, 1, 2)
> + (1 row)
> +
> + SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
> +         cube_subset
> + ---------------------------
> +  (5, 3, 1, 1),(8, 7, 6, 6)
> + (1 row)
> +
> + SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
> + ERROR:  Index out of bounds
> + --
>   -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
>   --
>   select
'(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0)'::cube;
> ***************
> *** 1021,1044 ****
>   CREATE TABLE test_cube (c cube);
>   \copy test_cube from 'data/test_cube.data'
>   CREATE INDEX test_cube_ix ON test_cube USING gist (c);
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)';
>               c
>   --------------------------
> -  (2424, 160),(2424, 81)
> -  (759, 187),(662, 163)
> -  (1444, 403),(1346, 344)
> -  (337, 455),(240, 359)
>    (1594, 1043),(1517, 971)
>   (5 rows)
>
>   -- Test sorting
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)' GROUP BY c;
>               c
>   --------------------------
>    (337, 455),(240, 359)
> -  (759, 187),(662, 163)
>    (1444, 403),(1346, 344)
> !  (1594, 1043),(1517, 971)
>    (2424, 160),(2424, 81)
>   (5 rows)
>
> --- 1054,1077 ----
>   CREATE TABLE test_cube (c cube);
>   \copy test_cube from 'data/test_cube.data'
>   CREATE INDEX test_cube_ix ON test_cube USING gist (c);
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)' ORDER BY c;
>               c
>   --------------------------
>    (1594, 1043),(1517, 971)
> +  (337, 455),(240, 359)
> +  (1444, 403),(1346, 344)
> +  (759, 187),(662, 163)
> +  (2424, 160),(2424, 81)
>   (5 rows)
>
>   -- Test sorting
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;
>               c
>   --------------------------
> +  (1594, 1043),(1517, 971)
>    (337, 455),(240, 359)
>    (1444, 403),(1346, 344)
> !  (759, 187),(662, 163)
>    (2424, 160),(2424, 81)
>   (5 rows)
>
> Index: sql/cube.sql
> ===================================================================
> RCS file: /projects/cvsroot/pgsql/contrib/cube/sql/cube.sql,v
> retrieving revision 1.8
> diff -c -r1.8 cube.sql
> *** sql/cube.sql    27 Jun 2005 01:19:43 -0000    1.8
> --- sql/cube.sql    22 Jul 2006 05:15:46 -0000
> ***************
> *** 111,116 ****
> --- 111,126 ----
>   SELECT '(0)'::text::cube;
>
>   --
> + -- Test the float[] -> cube cast
> + --
> + SELECT cube('{0,1,2}'::float[], '{3,4,5}'::float[]);
> + SELECT cube('{0,1,2}'::float[], '{3}'::float[]);
> + SELECT cube(NULL::float[], '{3}'::float[]);
> + SELECT cube('{0,1,2}'::float[]);
> + SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
> + SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
> +
> + --
>   -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
>   --
>
> ***************
> *** 269,275 ****
>   \copy test_cube from 'data/test_cube.data'
>
>   CREATE INDEX test_cube_ix ON test_cube USING gist (c);
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)';
>
>   -- Test sorting
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)' GROUP BY c;
> --- 279,285 ----
>   \copy test_cube from 'data/test_cube.data'
>
>   CREATE INDEX test_cube_ix ON test_cube USING gist (c);
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)' ORDER BY c;
>
>   -- Test sorting
> ! SELECT * FROM test_cube    WHERE c && '(3000,1000),(0,0)' GROUP BY c ORDER BY c;

>
> ---------------------------(end of broadcast)---------------------------
> TIP 4: Have you searched our list archives?
>
>                http://archives.postgresql.org

--
  Bruce Momjian   bruce@momjian.us
  EnterpriseDB    http://www.enterprisedb.com

  + If your life is a hard drive, Christ can be your backup. +

pgsql-patches by date:

Previous
From: David Fetter
Date:
Subject: Re: Time zone definitions to config files
Next
From: "Jaime Casanova"
Date:
Subject: Re: Patch for updatable views