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: