Skip site navigation (1) Skip section navigation (2)

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 (view raw or flat)
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

pgsql-patches by date

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

Privacy Policy | About PostgreSQL
Copyright © 1996-2014 The PostgreSQL Global Development Group