Re: Final version of my cube patch - fixed test cases,

From: Bruce Momjian <bruce(at)momjian(dot)us>
To: Joshua Reich <josh(at)root(dot)net>
Cc: pgsql-patches(at)postgresql(dot)org
Subject: Re: Final version of my cube patch - fixed test cases,
Date: 2006-07-25 23:23:42
Message-ID: 200607252323.k6PNNgl23576@momjian.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: 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(at)root(dot)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(at)momjian(dot)us
EnterpriseDB http://www.enterprisedb.com

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

In response to

Browse pgsql-patches by date

  From Date Subject
Next Message Bruce Momjian 2006-07-25 23:23:45 pgsql: /contrib/cube improvements: Update the calling convention for
Previous Message David Fetter 2006-07-25 23:20:26 Re: Time zone definitions to config files