diff --git a/contrib/cube/README.cube b/contrib/cube/README.cube
index cba90f67448058f4cae9797cb90108990855f577..6cd57ab35346634bd284473c28c3417dcc9c2d60 100644
--- a/contrib/cube/README.cube
+++ b/contrib/cube/README.cube
@@ -99,7 +99,7 @@ Tokens
 
 n		[0-9]+
 integer		[+-]?{n}
-real		[+-]?({n}\.{n}?)|(\.{n})
+real		[+-]?({n}\.{n}?|\.{n})
 FLOAT		({integer}|{real})([eE]{integer})?
 O_BRACKET	\[
 C_BRACKET	\]
@@ -182,8 +182,8 @@ t
 PRECISION
 =========
 
-Values are stored internally as 32-bit floating point numbers. This means that
-numbers with more than 7 significant digits will be truncated.
+Values are stored internally as 64-bit floating point numbers. This means that
+numbers with more than about 16 significant digits will be truncated.
 
 
 USAGE
@@ -253,6 +253,44 @@ Other operators:
 	reasonably good sorting in most cases, which is useful if
 	you want to use ORDER BY with this type
 
+The following functions are available:
+
+cube_distance(cube, cube) returns double
+  cube_distance returns the distance between two cubes. If both cubes are
+  points, this is the normal distance function.
+
+cube(text) returns cube
+  cube takes text input and returns a cube. This is useful for making cubes
+  from computed strings.
+
+cube_dim(cube) returns int
+  cube_dim returns the number of dimensions stored in the the data structure
+  for a cube. This is useful for constraints on the dimensions of a cube.
+
+cube_ll_coord(cube, int) returns double
+  cube_ll_coord returns the nth coordinate value for the lower left corner
+  of a cube. This is useful for doing coordinate transformations.
+
+cube_ur_coord(cube, int) returns double
+  cube_ur_coord returns the nth coordinate value for the upper right corner
+  of a cube. This is useful for doing coordinate transformations.
+
+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.
+
+cube_enlarge(cube, double, int) returns cube
+  cube_enlarge increases the size of a cube by a specified radius in at least
+  n dimensions. If the radius is negative the box is shrunk instead. This
+  is useful for creating bounding boxes around a point for searching for
+  nearby points. All defined dimensions are changed by the radius. If n
+  is greater than the number of defined dimensions and the cube is being
+  increased (r >= 0) then 0 is used as the base for the extra coordinates.
+  LL coordinates are decreased by r and UR coordinates are increased by r. If
+  a LL coordinate is increased to larger than the corresponding UR coordinate
+  (this can only happen when r < 0) than both coordinates are set to their
+  average.
+
 There are a few other potentially useful functions defined in cube.c 
 that vanished from the schema because I stopped using them. Some of 
 these were meant to support type casting. Let me know if I was wrong: 
@@ -287,3 +325,11 @@ Building 221
 Argonne, IL 60439-4844
 
 selkovjr@mcs.anl.gov
+
+------------------------------------------------------------------------
+
+Minor updates to this package were made by Bruno Wolff III <bruno@wolff.to>
+in August of 2002.
+
+These include changing the precision from single precision to double
+precision and adding some new functions.
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index afd69029c95b9d206c8937bcdd46a10f4f461564..ddf6fb0fecf81f1470dbb3633623e21ab0fc493c 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -28,6 +28,7 @@ extern int	cube_yyparse();
 ** Input/Output routines
 */
 NDBOX	   *cube_in(char *str);
+NDBOX	   *cube(text *str);
 char	   *cube_out(NDBOX * cube);
 
 
@@ -55,8 +56,8 @@ 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);
-float	   *cube_size(NDBOX * a);
-void		rt_cube_size(NDBOX * a, float *sz);
+double	   *cube_size(NDBOX * a);
+void		rt_cube_size(NDBOX * a, double *sz);
 
 /*
 ** These make no sense for this type, but R-tree wants them
@@ -71,13 +72,18 @@ bool		cube_right(NDBOX * a, NDBOX * b);
 */
 bool		cube_lt(NDBOX * a, NDBOX * b);
 bool		cube_gt(NDBOX * a, NDBOX * b);
-float	   *cube_distance(NDBOX * a, NDBOX * b);
+double	   *cube_distance(NDBOX * a, NDBOX * b);
+int	cube_dim(NDBOX *a);
+double	*cube_ll_coord(NDBOX * a, int n);
+double	*cube_ur_coord(NDBOX * a, int n);
+bool	cube_is_point(NDBOX * a);
+NDBOX	   *cube_enlarge(NDBOX * a, double * r, int n);
+
 
 /*
 ** Auxiliary funxtions
 */
-static float distance_1D(float a1, float a2, float b1, float b2);
-static NDBOX *swap_corners(NDBOX * a);
+static double distance_1D(double a1, double a2, double b1, double b2);
 
 
 /*****************************************************************************
@@ -99,6 +105,15 @@ cube_in(char *str)
 	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)
 {
@@ -118,7 +133,7 @@ cube_out(NDBOX *cube)
 	{
 		if (i > 0)
 			appendStringInfo(&buf, ", ");
-		appendStringInfo(&buf, "%g", cube->x[i]);
+		appendStringInfo(&buf, "%.16g", cube->x[i]);
 		if (cube->x[i] != cube->x[i + dim])
 			equal = false;
 	}
@@ -131,7 +146,7 @@ cube_out(NDBOX *cube)
 		{
 			if (i > 0)
 				appendStringInfo(&buf, ", ");
-			appendStringInfo(&buf, "%g", cube->x[i + dim]);
+			appendStringInfo(&buf, "%.16g", cube->x[i + dim]);
 		}
 		appendStringInfoChar(&buf, ')');
 	}
@@ -228,14 +243,14 @@ float *
 g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
 {
 	NDBOX	   *ud;
-	float		tmp1,
+	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);
-	*result = tmp1 - tmp2;
+	*result = (float) (tmp1 - tmp2);
 	pfree(ud);
 
 	/*
@@ -265,13 +280,13 @@ g_cube_picksplit(bytea *entryvec,
 			   *union_dr;
 	NDBOX	   *inter_d;
 	bool		firsttime;
-	float		size_alpha,
+	double		size_alpha,
 				size_beta,
 				size_union,
 				size_inter;
-	float		size_waste,
+	double		size_waste,
 				waste;
-	float		size_l,
+	double		size_l,
 				size_r;
 	int			nbytes;
 	OffsetNumber seed_1 = 0,
@@ -519,22 +534,22 @@ g_cube_binary_union(NDBOX * r1, NDBOX * r2, int *sizep)
 
 /* cube_union */
 NDBOX *
-cube_union(NDBOX * box_a, NDBOX * box_b)
+cube_union(NDBOX * a, NDBOX * b)
 {
 	int			i;
 	NDBOX	   *result;
-	NDBOX	   *a = swap_corners(box_a);
-	NDBOX	   *b = swap_corners(box_b);
 
 	if (a->dim >= b->dim)
 	{
 		result = palloc(a->size);
+                memset(result, 0, a->size);
 		result->size = a->size;
 		result->dim = a->dim;
 	}
 	else
 	{
 		result = palloc(b->size);
+                memset(result, 0, b->size);
 		result->size = b->size;
 		result->dim = b->dim;
 	}
@@ -554,8 +569,8 @@ cube_union(NDBOX * box_a, NDBOX * box_b)
 	 */
 	for (i = 0; i < b->dim; i++)
 	{
-		result->x[i] = b->x[i];
-		result->x[i + a->dim] = b->x[i + b->dim];
+		result->x[i] = min(b->x[i], b->x[i + b->dim]);
+		result->x[i + a->dim] = max(b->x[i], b->x[i + b->dim]);
 	}
 	for (i = b->dim; i < a->dim; i++)
 	{
@@ -565,34 +580,34 @@ cube_union(NDBOX * box_a, NDBOX * box_b)
 
 	/* compute the union */
 	for (i = 0; i < a->dim; i++)
-		result->x[i] = min(a->x[i], result->x[i]);
-	for (i = a->dim; i < a->dim * 2; i++)
-		result->x[i] = max(a->x[i], result->x[i]);
-
-	pfree(a);
-	pfree(b);
+        {
+		result->x[i] =
+                  min(min(a->x[i], a->x[i + a->dim]), result->x[i]);
+		result->x[i + a->dim] = max(max(a->x[i],
+                  a->x[i + a->dim]), result->x[i + a->dim]);
+        }
 
 	return (result);
 }
 
 /* cube_inter */
 NDBOX *
-cube_inter(NDBOX * box_a, NDBOX * box_b)
+cube_inter(NDBOX * a, NDBOX * b)
 {
 	int			i;
 	NDBOX	   *result;
-	NDBOX	   *a = swap_corners(box_a);
-	NDBOX	   *b = swap_corners(box_b);
 
 	if (a->dim >= b->dim)
 	{
 		result = palloc(a->size);
+                memset(result, 0, a->size);
 		result->size = a->size;
 		result->dim = a->dim;
 	}
 	else
 	{
 		result = palloc(b->size);
+                memset(result, 0, b->size);
 		result->size = b->size;
 		result->dim = b->dim;
 	}
@@ -612,8 +627,8 @@ cube_inter(NDBOX * box_a, NDBOX * box_b)
 	 */
 	for (i = 0; i < b->dim; i++)
 	{
-		result->x[i] = b->x[i];
-		result->x[i + a->dim] = b->x[i + b->dim];
+		result->x[i] = min(b->x[i], b->x[i + b->dim]);
+		result->x[i + a->dim] = max(b->x[i], b->x[i + b->dim]);
 	}
 	for (i = b->dim; i < a->dim; i++)
 	{
@@ -623,12 +638,12 @@ cube_inter(NDBOX * box_a, NDBOX * box_b)
 
 	/* compute the intersection */
 	for (i = 0; i < a->dim; i++)
-		result->x[i] = max(a->x[i], result->x[i]);
-	for (i = a->dim; i < a->dim * 2; i++)
-		result->x[i] = min(a->x[i], result->x[i]);
-
-	pfree(a);
-	pfree(b);
+        {
+		result->x[i] =
+                  max(min(a->x[i], a->x[i + a->dim]), result->x[i]);
+		result->x[i + a->dim] = min(max(a->x[i],
+                  a->x[i + a->dim]), result->x[i + a->dim]);
+        }
 
 	/*
 	 * Is it OK to return a non-null intersection for non-overlapping
@@ -638,14 +653,14 @@ cube_inter(NDBOX * box_a, NDBOX * box_b)
 }
 
 /* cube_size */
-float *
+double *
 cube_size(NDBOX * a)
 {
 	int			i,
 				j;
-	float	   *result;
+	double	   *result;
 
-	result = (float *) palloc(sizeof(float));
+	result = (double *) palloc(sizeof(double));
 
 	*result = 1.0;
 	for (i = 0, j = a->dim; i < a->dim; i++, j++)
@@ -655,7 +670,7 @@ cube_size(NDBOX * a)
 }
 
 void
-rt_cube_size(NDBOX * a, float *size)
+rt_cube_size(NDBOX * a, double *size)
 {
 	int			i,
 				j;
@@ -679,114 +694,84 @@ rt_cube_size(NDBOX * a, float *size)
 /*	is the right edge of (a) located to the left of
 	the right edge of (b)? */
 bool
-cube_over_left(NDBOX * box_a, NDBOX * box_b)
+cube_over_left(NDBOX * a, NDBOX * b)
 {
-	NDBOX	   *a;
-	NDBOX	   *b;
-
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
-	return (a->x[a->dim - 1] <= b->x[b->dim - 1] && !cube_left(a, b) && !cube_right(a, b));
+	return (min(a->x[a->dim - 1], a->x[2 * a->dim - 1]) <=
+          min(b->x[b->dim - 1], b->x[2 * b->dim - 1]) &&
+          !cube_left(a, b) && !cube_right(a, b));
 }
 
 /*	is the left edge of (a) located to the right of
 	the left edge of (b)? */
 bool
-cube_over_right(NDBOX * box_a, NDBOX * box_b)
+cube_over_right(NDBOX * a, NDBOX * b)
 {
-	NDBOX	   *a;
-	NDBOX	   *b;
-
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
-	return (a->x[a->dim - 1] >= b->x[b->dim - 1] && !cube_left(a, b) && !cube_right(a, b));
+	return (min(a->x[a->dim - 1], a->x[2 * a->dim - 1]) >=
+          min(b->x[b->dim - 1], b->x[2 * b->dim - 1]) &&
+          !cube_left(a, b) && !cube_right(a, b));
 }
 
 
 /* return 'true' if the projection of 'a' is
    entirely on the left of the projection of 'b' */
 bool
-cube_left(NDBOX * box_a, NDBOX * box_b)
+cube_left(NDBOX * a, NDBOX * b)
 {
-	NDBOX	   *a;
-	NDBOX	   *b;
-
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
-	return (a->x[a->dim - 1] < b->x[0]);
+	return (min(a->x[a->dim - 1], a->x[2 * a->dim - 1]) <
+          min(b->x[0], b->x[b->dim]));
 }
 
 /* return 'true' if the projection of 'a' is
    entirely on the right  of the projection of 'b' */
 bool
-cube_right(NDBOX * box_a, NDBOX * box_b)
+cube_right(NDBOX * a, NDBOX * b)
 {
-	NDBOX	   *a;
-	NDBOX	   *b;
-
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
-	return (a->x[0] > b->x[b->dim - 1]);
+	return (min(a->x[0], a->x[a->dim]) >
+          min(b->x[b->dim - 1], b->x[2 * b->dim - 1]));
 }
 
 /* make up a metric in which one box will be 'lower' than the other
-   -- this can be useful for srting and to determine uniqueness */
+   -- this can be useful for sorting and to determine uniqueness */
 bool
-cube_lt(NDBOX * box_a, NDBOX * box_b)
+cube_lt(NDBOX * a, NDBOX * b)
 {
 	int			i;
 	int			dim;
-	NDBOX	   *a;
-	NDBOX	   *b;
 
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
 	dim = min(a->dim, b->dim);
 
-	/*
-	 * if all common dimensions are equal, the cube with more dimensions
-	 * wins
-	 */
-	if (cube_same(a, b))
-	{
-		if (a->dim < b->dim)
-			return (TRUE);
-		else
-			return (FALSE);
-	}
-
 	/* compare the common dimensions */
 	for (i = 0; i < dim; i++)
 	{
-		if (a->x[i] > b->x[i])
+		if (min(a->x[i], a->x[a->dim + i]) >
+                    min(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i] < b->x[i])
+		if (min(a->x[i], a->x[a->dim + i]) <
+                    min(b->x[i], b->x[b->dim + i]))
 			return (TRUE);
 	}
 	for (i = 0; i < dim; i++)
 	{
-		if (a->x[i + a->dim] > b->x[i + b->dim])
+		if (max(a->x[i], a->x[a->dim + i]) >
+                    max(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i + a->dim] < b->x[i + b->dim])
+		if (max(a->x[i], a->x[a->dim + i]) <
+                    max(b->x[i], b->x[b->dim + i]))
 			return (TRUE);
 	}
 
@@ -795,35 +780,45 @@ cube_lt(NDBOX * box_a, NDBOX * box_b)
 	{
 		for (i = dim; i < a->dim; i++)
 		{
-			if (a->x[i] > 0)
+			if (min(a->x[i], a->x[a->dim + i]) > 0)
 				return (FALSE);
-			if (a->x[i] < 0)
+			if (min(a->x[i], a->x[a->dim + i]) < 0)
 				return (TRUE);
 		}
-		for (i = 0; i < dim; i++)
+		for (i = dim; i < a->dim; i++)
 		{
-			if (a->x[i + a->dim] > 0)
+			if (max(a->x[i], a->x[a->dim + i]) > 0)
 				return (FALSE);
-			if (a->x[i + a->dim] < 0)
+			if (max(a->x[i], a->x[a->dim + i]) < 0)
 				return (TRUE);
 		}
+	        /*
+	         * if all common dimensions are equal, the cube with more
+	         * dimensions wins
+	         */
+                return (FALSE);
 	}
 	if (a->dim < b->dim)
 	{
 		for (i = dim; i < b->dim; i++)
 		{
-			if (b->x[i] > 0)
+			if (min(b->x[i], b->x[b->dim + i]) > 0)
 				return (TRUE);
-			if (b->x[i] < 0)
+			if (min(b->x[i], b->x[b->dim + i]) < 0)
 				return (FALSE);
 		}
-		for (i = 0; i < dim; i++)
+		for (i = dim; i < b->dim; i++)
 		{
-			if (b->x[i + b->dim] > 0)
+			if (max(b->x[i], b->x[b->dim + i]) > 0)
 				return (TRUE);
-			if (b->x[i + b->dim] < 0)
+			if (max(b->x[i], b->x[b->dim + i]) < 0)
 				return (FALSE);
 		}
+	        /*
+	         * if all common dimensions are equal, the cube with more
+	         * dimensions wins
+	         */
+                return (TRUE);
 	}
 
 	return (FALSE);
@@ -831,45 +826,33 @@ cube_lt(NDBOX * box_a, NDBOX * box_b)
 
 
 bool
-cube_gt(NDBOX * box_a, NDBOX * box_b)
+cube_gt(NDBOX * a, NDBOX * b)
 {
 	int			i;
 	int			dim;
-	NDBOX	   *a;
-	NDBOX	   *b;
 
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
 	dim = min(a->dim, b->dim);
 
-	/*
-	 * if all common dimensions are equal, the cube with more dimensions
-	 * wins
-	 */
-	if (cube_same(a, b))
-	{
-		if (a->dim > b->dim)
-			return (TRUE);
-		else
-			return (FALSE);
-	}
-
 	/* compare the common dimensions */
 	for (i = 0; i < dim; i++)
 	{
-		if (a->x[i] < b->x[i])
+		if (min(a->x[i], a->x[a->dim + i]) <
+                    min(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i] > b->x[i])
+		if (min(a->x[i], a->x[a->dim + i]) >
+                    min(b->x[i], b->x[b->dim + i]))
 			return (TRUE);
 	}
 	for (i = 0; i < dim; i++)
 	{
-		if (a->x[i + a->dim] < b->x[i + b->dim])
+		if (max(a->x[i], a->x[a->dim + i]) <
+                    max(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i + a->dim] > b->x[i + b->dim])
+		if (max(a->x[i], a->x[a->dim + i]) >
+                    max(b->x[i], b->x[b->dim + i]))
 			return (TRUE);
 	}
 
@@ -879,35 +862,45 @@ cube_gt(NDBOX * box_a, NDBOX * box_b)
 	{
 		for (i = dim; i < a->dim; i++)
 		{
-			if (a->x[i] < 0)
+			if (min(a->x[i], a->x[a->dim + i]) < 0)
 				return (FALSE);
-			if (a->x[i] > 0)
+			if (min(a->x[i], a->x[a->dim + i]) > 0)
 				return (TRUE);
 		}
-		for (i = 0; i < dim; i++)
+		for (i = dim; i < a->dim; i++)
 		{
-			if (a->x[i + a->dim] < 0)
+			if (max(a->x[i], a->x[a->dim + i]) < 0)
 				return (FALSE);
-			if (a->x[i + a->dim] > 0)
+			if (max(a->x[i], a->x[a->dim + i]) > 0)
 				return (TRUE);
 		}
+	        /*
+	         * if all common dimensions are equal, the cube with more
+	         * dimensions wins
+	         */
+                return (TRUE);
 	}
 	if (a->dim < b->dim)
 	{
 		for (i = dim; i < b->dim; i++)
 		{
-			if (b->x[i] < 0)
+			if (min(b->x[i], b->x[b->dim + i]) < 0)
 				return (TRUE);
-			if (b->x[i] > 0)
+			if (min(b->x[i], b->x[b->dim + i]) > 0)
 				return (FALSE);
 		}
-		for (i = 0; i < dim; i++)
+		for (i = dim; i < b->dim; i++)
 		{
-			if (b->x[i + b->dim] < 0)
+			if (max(b->x[i], b->x[b->dim + i]) < 0)
 				return (TRUE);
-			if (b->x[i + b->dim] > 0)
+			if (max(b->x[i], b->x[b->dim + i]) > 0)
 				return (FALSE);
 		}
+	        /*
+	         * if all common dimensions are equal, the cube with more
+	         * dimensions wins
+	         */
+                return (FALSE);
 	}
 
 	return (FALSE);
@@ -916,18 +909,13 @@ cube_gt(NDBOX * box_a, NDBOX * box_b)
 
 /* Equal */
 bool
-cube_same(NDBOX * box_a, NDBOX * box_b)
+cube_same(NDBOX * a, NDBOX * b)
 {
 	int			i;
-	NDBOX	   *a;
-	NDBOX	   *b;
 
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
 	/* swap the box pointers if necessary */
 	if (a->dim < b->dim)
 	{
@@ -939,15 +927,19 @@ cube_same(NDBOX * box_a, NDBOX * box_b)
 
 	for (i = 0; i < b->dim; i++)
 	{
-		if (a->x[i] != b->x[i])
+		if (min(a->x[i], a->x[a->dim + i]) !=
+                  min(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i + a->dim] != b->x[i + b->dim])
+		if (max(a->x[i], a->x[a->dim + i]) !=
+                  max(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
 	}
 
 	/*
 	 * all dimensions of (b) are compared to those of (a); instead of
 	 * those in (a) absent in (b), compare (a) to zero
+         * Since both LL and UR coordinates are compared to zero, we can
+         * just check them all without worrying about which is which.
 	 */
 	for (i = b->dim; i < a->dim; i++)
 	{
@@ -957,40 +949,34 @@ cube_same(NDBOX * box_a, NDBOX * box_b)
 			return (FALSE);
 	}
 
-	pfree(a);
-	pfree(b);
-
 	return (TRUE);
 }
 
 /* Different */
 bool
-cube_different(NDBOX * box_a, NDBOX * box_b)
+cube_different(NDBOX * a, NDBOX * b)
 {
-	return (!cube_same(box_a, box_b));
+	return (!cube_same(a, b));
 }
 
 
 /* Contains */
 /* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
 bool
-cube_contains(NDBOX * box_a, NDBOX * box_b)
+cube_contains(NDBOX * a, NDBOX * b)
 {
 	int			i;
-	NDBOX	   *a;
-	NDBOX	   *b;
 
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
 	if (a->dim < b->dim)
 	{
 		/*
 		 * the further comparisons will make sense if the excess
 		 * dimensions of (b) were zeroes
+                 * Since both UL and UR coordinates must be zero, we can
+                 * check them all without worrying about which is which.
 		 */
 		for (i = a->dim; i < b->dim; i++)
 		{
@@ -1004,15 +990,14 @@ cube_contains(NDBOX * box_a, NDBOX * box_b)
 	/* Can't care less about the excess dimensions of (a), if any */
 	for (i = 0; i < min(a->dim, b->dim); i++)
 	{
-		if (a->x[i] > b->x[i])
+		if (min(a->x[i], a->x[a->dim + i]) >
+                  min(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i + a->dim] < b->x[i + b->dim])
+		if (max(a->x[i], a->x[a->dim + i]) <
+                  max(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
 	}
 
-	pfree(a);
-	pfree(b);
-
 	return (TRUE);
 }
 
@@ -1030,22 +1015,17 @@ cube_contained(NDBOX * a, NDBOX * b)
 /* Overlap */
 /* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
 bool
-cube_overlap(NDBOX * box_a, NDBOX * box_b)
+cube_overlap(NDBOX * a, NDBOX * b)
 {
 	int			i;
-	NDBOX	   *a;
-	NDBOX	   *b;
 
 	/*
 	 * This *very bad* error was found in the source: if ( (a==NULL) ||
 	 * (b=NULL) ) return(FALSE);
 	 */
-	if ((box_a == NULL) || (box_b == NULL))
+	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	a = swap_corners(box_a);
-	b = swap_corners(box_b);
-
 	/* swap the box pointers if needed */
 	if (a->dim < b->dim)
 	{
@@ -1058,24 +1038,23 @@ cube_overlap(NDBOX * box_a, NDBOX * box_b)
 	/* compare within the dimensions of (b) */
 	for (i = 0; i < b->dim; i++)
 	{
-		if (a->x[i] > b->x[i + b->dim])
+		if (min(a->x[i], a->x[a->dim + i]) >
+                  max(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
-		if (a->x[i + a->dim] < b->x[i])
+		if (max(a->x[i], a->x[a->dim + i]) <
+                  min(b->x[i], b->x[b->dim + i]))
 			return (FALSE);
 	}
 
 	/* compare to zero those dimensions in (a) absent in (b) */
 	for (i = b->dim; i < a->dim; i++)
 	{
-		if (a->x[i] > 0)
+		if (min(a->x[i], a->x[a->dim + i]) > 0)
 			return (FALSE);
-		if (a->x[i + a->dim] < 0)
+		if (max(a->x[i], a->x[a->dim + i]) < 0)
 			return (FALSE);
 	}
 
-	pfree(a);
-	pfree(b);
-
 	return (TRUE);
 }
 
@@ -1085,15 +1064,15 @@ cube_overlap(NDBOX * box_a, NDBOX * box_b)
    between 1D projections of the boxes onto Cartesian axes. Assuming zero
    distance between overlapping projections, this metric coincides with the
    "common sense" geometric distance */
-float *
+double *
 cube_distance(NDBOX * a, NDBOX * b)
 {
 	int			i;
 	double		d,
 				distance;
-	float	   *result;
+	double	   *result;
 
-	result = (float *) palloc(sizeof(float));
+	result = (double *) palloc(sizeof(double));
 
 	/* swap the box pointers if needed */
 	if (a->dim < b->dim)
@@ -1119,13 +1098,13 @@ cube_distance(NDBOX * a, NDBOX * b)
 		distance += d * d;
 	}
 
-	*result = (float) sqrt(distance);
+	*result = (double) sqrt(distance);
 
 	return (result);
 }
 
-static float
-distance_1D(float a1, float a2, float b1, float b2)
+static double
+distance_1D(double a1, double a2, double b1, double b2)
 {
 	/* interval (a) is entirely on the left of (b) */
 	if ((a1 <= b1) && (a2 <= b1) && (a1 <= b2) && (a2 <= b2))
@@ -1139,25 +1118,91 @@ distance_1D(float a1, float a2, float b1, float b2)
 	return (0.0);
 }
 
-/* normalize the box's co-ordinates by placing min(xLL,xUR) to LL
-   and max(xLL,xUR) to UR
-*/
-static NDBOX *
-swap_corners(NDBOX * a)
+/* Test if a box is also a point */
+bool
+cube_is_point(NDBOX * a)
 {
-	int			i,
-				j;
-	NDBOX	   *result;
+        int i,
+            j;
+	for (i = 0, j = a->dim; i < a->dim; i++, j++)
+        {
+                if (a->x[i] != a->x[j]) return FALSE;
+        }
 
-	result = palloc(a->size);
-	result->size = a->size;
-	result->dim = a->dim;
+        return TRUE;
+}
 
-	for (i = 0, j = a->dim; i < a->dim; i++, j++)
-	{
-		result->x[i] = min(a->x[i], a->x[j]);
-		result->x[j] = max(a->x[i], a->x[j]);
-	}
+/* Return dimensions in use in the data structure */
+int
+cube_dim(NDBOX * a)
+{
+        /* Other things will break before unsigned int doesn't fit. */
+        return a->dim;
+}
 
-	return (result);
+/* Return a specific normalized LL coordinate */
+double *
+cube_ll_coord(NDBOX * a, int 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, int 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, int n)
+{
+        NDBOX *result;
+        int dim = 0;
+        int size;
+        int i,
+            j;
+        if (*r > 0 && n > 0) dim = n;
+        if (a->dim > dim) dim = a->dim;
+        size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
+        result = (NDBOX *) palloc(size);
+        memset(result, 0, size);
+        result->size = size;
+        result->dim = dim;
+	for (i = 0, j = dim; i < a->dim; i++, j++)
+        {
+                if (a->x[i] >= a->x[j])
+                {
+                        result->x[i] = a->x[j] - *r;
+                        result->x[j] = a->x[i] + *r;
+                }
+                else
+                {
+                        result->x[i] = a->x[i] - *r;
+                        result->x[j] = a->x[j] + *r;
+                }
+                if (result->x[i] > result->x[j])
+                {
+                        result->x[i] = (result->x[i] + result->x[j]) / 2;
+                        result->x[j] = result->x[i];
+                }
+        }
+        /* dim > a->dim only if r > 0 */
+	for (; i < dim; i++, j++)
+        {
+                result->x[i] = -*r;
+                result->x[j] = *r;
+        }
+        return result;
 }
diff --git a/contrib/cube/cube.sql.in b/contrib/cube/cube.sql.in
index 5889c687a58fb059d8ee7e49511ab9564dde255a..ecc9215070fe8934548694c37d46aca1b1d45475 100644
--- a/contrib/cube/cube.sql.in
+++ b/contrib/cube/cube.sql.in
@@ -8,12 +8,12 @@ SET search_path = public;
 CREATE FUNCTION cube_in(cstring)
 RETURNS cube
 AS 'MODULE_PATHNAME'
-LANGUAGE 'c' WITH (isStrict);
+LANGUAGE 'c'IMMUTABLE STRICT;
 
 CREATE FUNCTION cube_out(cube)
 RETURNS cstring
 AS 'MODULE_PATHNAME'
-LANGUAGE 'c' WITH (isStrict);
+LANGUAGE 'c'IMMUTABLE STRICT;
 
 CREATE TYPE cube (
 internallength = variable,
@@ -24,6 +24,16 @@ output = cube_out
 COMMENT ON TYPE cube IS
 'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-N), (FLOAT-1, FLOAT-2, ..., FLOAT-N)''';
 
+-- Convert from text to cube
+
+CREATE FUNCTION cube(text)
+RETURNS cube
+AS 'MODULE_PATHNAME'
+LANGUAGE 'c' IMMUTABLE STRICT;
+
+COMMENT ON FUNCTION cube(text) IS
+'convert text to cube';
+
 --
 -- External C-functions for R-tree methods
 --
@@ -31,25 +41,25 @@ COMMENT ON TYPE cube IS
 -- Left/Right methods
 
 CREATE FUNCTION cube_over_left(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_over_left(cube, cube) IS
 'is over and left of (NOT IMPLEMENTED)';
 
 CREATE FUNCTION cube_over_right(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_over_right(cube, cube) IS
 'is over and right of (NOT IMPLEMENTED)';
 
 CREATE FUNCTION cube_left(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_left(cube, cube) IS
 'is left of (NOT IMPLEMENTED)';
 
 CREATE FUNCTION cube_right(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_right(cube, cube) IS
 'is right of (NOT IMPLEMENTED)';
@@ -58,43 +68,43 @@ COMMENT ON FUNCTION cube_right(cube, cube) IS
 -- Comparison methods
 
 CREATE FUNCTION cube_lt(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_lt(cube, cube) IS
 'lower than';
 
 CREATE FUNCTION cube_gt(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_gt(cube, cube) IS
 'greater than';
 
 CREATE FUNCTION cube_contains(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_contains(cube, cube) IS
 'contains';
 
 CREATE FUNCTION cube_contained(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_contained(cube, cube) IS
 'contained in';
 
 CREATE FUNCTION cube_overlap(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_overlap(cube, cube) IS
 'overlaps';
 
 CREATE FUNCTION cube_same(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_same(cube, cube) IS
 'same as';
 
 CREATE FUNCTION cube_different(cube, cube) RETURNS bool
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 COMMENT ON FUNCTION cube_different(cube, cube) IS
 'different';
@@ -102,22 +112,42 @@ COMMENT ON FUNCTION cube_different(cube, cube) IS
 -- support routines for indexing
 
 CREATE FUNCTION cube_union(cube, cube) RETURNS cube
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 CREATE FUNCTION cube_inter(cube, cube) RETURNS cube
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
-CREATE FUNCTION cube_size(cube) RETURNS float4
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+CREATE FUNCTION cube_size(cube) RETURNS float8
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 
 -- Misc N-dimensional functions
 
 -- proximity routines
 
-CREATE FUNCTION cube_distance(cube, cube) RETURNS float4
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+CREATE FUNCTION cube_distance(cube, cube) RETURNS float8
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Extracting elements functions
+
+CREATE FUNCTION cube_dim(cube) RETURNS int4
+        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
+
+CREATE FUNCTION cube_ll_coord(cube, int4) RETURNS float8
+        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
+
+CREATE FUNCTION cube_ur_coord(cube, int4) RETURNS float8
+        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Test if cube is also a point
+
+CREATE FUNCTION cube_is_point(cube) RETURNS bool
+        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
+
+-- Increasing the size of a cube by a radius in at least n dimensions
 
+CREATE FUNCTION cube_enlarge(cube, float8, int4) RETURNS cube
+        AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
 
 --
 -- OPERATORS
@@ -202,7 +232,7 @@ CREATE FUNCTION g_cube_decompress(internal) RETURNS internal
 	AS 'MODULE_PATHNAME' LANGUAGE 'c';
 
 CREATE FUNCTION g_cube_penalty(internal,internal,internal) RETURNS internal
-	AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict);
+	AS 'MODULE_PATHNAME' LANGUAGE 'c' STRICT;
 
 CREATE FUNCTION g_cube_picksplit(internal, internal) RETURNS internal
 	AS 'MODULE_PATHNAME' LANGUAGE 'c';
diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h
index a1c5e8efcdfb3e40d16b2bd303c3276a3fc149e9..5fef512c9e96aa633b4c8391aa74a52cee47400f 100644
--- a/contrib/cube/cubedata.h
+++ b/contrib/cube/cubedata.h
@@ -2,5 +2,5 @@ typedef struct NDBOX
 {
 	unsigned int size;			/* required to be a Postgres varlena type */
 	unsigned int dim;
-	float		x[1];
+	double		x[1];
 }	NDBOX;
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
index 33b7c1ef6b0c93ee8e9a67bd97343f4801e81543..accad12511a11cc5418166393f953cc00ecb96b9 100644
--- a/contrib/cube/cubeparse.y
+++ b/contrib/cube/cubeparse.y
@@ -198,9 +198,10 @@ write_box(unsigned int dim, char *str1, char *str2)
   NDBOX * bp;
   char * s;
   int i; 
-  int size = offsetof(NDBOX, x[0]) + sizeof(float) * dim * 2;
+  int size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
 	    
   bp = palloc(size);
+  memset(bp, 0, size);
   bp->size = size;
   bp->dim = dim;
 	    
@@ -217,7 +218,7 @@ write_box(unsigned int dim, char *str1, char *str2)
     s++; i++;
     bp->x[i] = strtod(s, NULL);
   }	
-  
+
   return(bp);
 }
 
@@ -230,9 +231,10 @@ static NDBOX * write_point_as_box(char *str)
   int dim = delim_count(str, ',') + 1;
   char * s = str;
   
-  size = offsetof(NDBOX, x[0]) + sizeof(float) * dim * 2;
+  size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
 
   bp = palloc(size);
+  memset(bp, 0, size);
   bp->size = size;
   bp->dim = dim;
   
diff --git a/contrib/cube/cubescan.l b/contrib/cube/cubescan.l
index d1aed4c75ae8bd83f868d1209d6e8268e0f6a588..d160937c2f7942f271cc5ca232d0afb5fe20ab6c 100644
--- a/contrib/cube/cubescan.l
+++ b/contrib/cube/cubescan.l
@@ -34,7 +34,7 @@ void cube_flush_scanner_buffer(void);
 
 n            [0-9]+
 integer      [+-]?{n}
-real         [+-]?({n}\.{n}?)|(\.{n})
+real         [+-]?({n}\.{n}?|\.{n})
 float        ({integer}|{real})([eE]{integer})?
 
 %%
diff --git a/contrib/cube/expected/cube.out b/contrib/cube/expected/cube.out
index e69ce9f2f5f9dc65a25784569b0e0dbf3dd64682..e7191396a9e83de7685c660441d5bdff3dfdc63d 100644
--- a/contrib/cube/expected/cube.out
+++ b/contrib/cube/expected/cube.out
@@ -43,7 +43,10 @@ SELECT '.1'::cube AS cube;
 (1 row)
 
 SELECT '-.1'::cube AS cube;
-ERROR:  parse error, expecting `FLOAT' or `O_PAREN' or `O_BRACKET' at or before position 2, character ('.', \056), input: '-.1'
+  cube  
+--------
+ (-0.1)
+(1 row)
 
 SELECT '1.0'::cube AS cube;
  cube 
@@ -57,52 +60,52 @@ SELECT '-1.0'::cube AS cube;
  (-1)
 (1 row)
 
-SELECT '1e7'::cube AS cube;
+SELECT '1e27'::cube AS cube;
   cube   
 ---------
- (1e+07)
+ (1e+27)
 (1 row)
 
-SELECT '-1e7'::cube AS cube;
+SELECT '-1e27'::cube AS cube;
    cube   
 ----------
- (-1e+07)
+ (-1e+27)
 (1 row)
 
-SELECT '1.0e7'::cube AS cube;
+SELECT '1.0e27'::cube AS cube;
   cube   
 ---------
- (1e+07)
+ (1e+27)
 (1 row)
 
-SELECT '-1.0e7'::cube AS cube;
+SELECT '-1.0e27'::cube AS cube;
    cube   
 ----------
- (-1e+07)
+ (-1e+27)
 (1 row)
 
-SELECT '1e+7'::cube AS cube;
+SELECT '1e+27'::cube AS cube;
   cube   
 ---------
- (1e+07)
+ (1e+27)
 (1 row)
 
-SELECT '-1e+7'::cube AS cube;
+SELECT '-1e+27'::cube AS cube;
    cube   
 ----------
- (-1e+07)
+ (-1e+27)
 (1 row)
 
-SELECT '1.0e+7'::cube AS cube;
+SELECT '1.0e+27'::cube AS cube;
   cube   
 ---------
- (1e+07)
+ (1e+27)
 (1 row)
 
-SELECT '-1.0e+7'::cube AS cube;
+SELECT '-1.0e+27'::cube AS cube;
    cube   
 ----------
- (-1e+07)
+ (-1e+27)
 (1 row)
 
 SELECT '1e-7'::cube AS cube;
@@ -141,6 +144,42 @@ SELECT '-1e-700'::cube AS cube;
  (0)
 (1 row)
 
+SELECT '1234567890123456'::cube AS cube;
+        cube        
+--------------------
+ (1234567890123456)
+(1 row)
+
+SELECT '+1234567890123456'::cube AS cube;
+        cube        
+--------------------
+ (1234567890123456)
+(1 row)
+
+SELECT '-1234567890123456'::cube AS cube;
+        cube         
+---------------------
+ (-1234567890123456)
+(1 row)
+
+SELECT '.1234567890123456'::cube AS cube;
+         cube         
+----------------------
+ (0.1234567890123456)
+(1 row)
+
+SELECT '+.1234567890123456'::cube AS cube;
+         cube         
+----------------------
+ (0.1234567890123456)
+(1 row)
+
+SELECT '-.1234567890123456'::cube AS cube;
+         cube          
+-----------------------
+ (-0.1234567890123456)
+(1 row)
+
 -- simple lists (points)
 SELECT '1,2'::cube AS cube;
   cube  
@@ -924,6 +963,224 @@ SELECT '(-1,-1),(1,1)'::cube            @ '(-2),(1)'::cube          AS bool;
  f
 (1 row)
 
+-- Test of distance function
+--
+SELECT cube_distance('(0)'::cube,'(2,2,2,2)'::cube);
+ cube_distance 
+---------------
+             4
+(1 row)
+
+SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
+ cube_distance 
+---------------
+           0.5
+(1 row)
+
+-- Test of cube function (text to cube)
+--
+SELECT cube('('||1||','||1.2||')');
+   cube   
+----------
+ (1, 1.2)
+(1 row)
+
+SELECT cube(NULL);
+ cube 
+------
+ 
+(1 row)
+
+-- Test of cube_dim function (dimensions stored in cube)
+--
+SELECT cube_dim('(0)'::cube);
+ cube_dim 
+----------
+        1
+(1 row)
+
+SELECT cube_dim('(0,0)'::cube);
+ cube_dim 
+----------
+        2
+(1 row)
+
+SELECT cube_dim('(0,0,0)'::cube);
+ cube_dim 
+----------
+        3
+(1 row)
+
+-- Test of cube_ll_coord function (retrieves LL coodinate values)
+--
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 1);
+ cube_ll_coord 
+---------------
+            -1
+(1 row)
+
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 2);
+ cube_ll_coord 
+---------------
+            -2
+(1 row)
+
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 3);
+ cube_ll_coord 
+---------------
+             0
+(1 row)
+
+-- Test of cube_ur_coord function (retrieves UR coodinate values)
+--
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 1);
+ cube_ur_coord 
+---------------
+             2
+(1 row)
+
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 2);
+ cube_ur_coord 
+---------------
+             1
+(1 row)
+
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 3);
+ cube_ur_coord 
+---------------
+             0
+(1 row)
+
+-- Test of cube_is_point
+--
+SELECT cube_is_point('(0)'::cube);
+ cube_is_point 
+---------------
+ t
+(1 row)
+
+SELECT cube_is_point('(0,1,2)'::cube);
+ cube_is_point 
+---------------
+ t
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(0,1,2)'::cube);
+ cube_is_point 
+---------------
+ t
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(-1,1,2)'::cube);
+ cube_is_point 
+---------------
+ f
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(0,-1,2)'::cube);
+ cube_is_point 
+---------------
+ f
+(1 row)
+
+SELECT cube_is_point('(0,1,2),(0,1,-2)'::cube);
+ cube_is_point 
+---------------
+ f
+(1 row)
+
+-- Test of cube_enlarge (enlarging and shrinking cubes)
+--
+SELECT cube_enlarge('(0)'::cube, 0, 0);
+ cube_enlarge 
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 0, 1);
+ cube_enlarge 
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 0, 2);
+ cube_enlarge 
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 1, 0);
+ cube_enlarge 
+--------------
+ (-1),(1)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 1, 1);
+ cube_enlarge 
+--------------
+ (-1),(1)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, 1, 2);
+  cube_enlarge   
+-----------------
+ (-1, -1),(1, 1)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, -1, 0);
+ cube_enlarge 
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, -1, 1);
+ cube_enlarge 
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0)'::cube, -1, 2);
+ cube_enlarge 
+--------------
+ (0)
+(1 row)
+
+SELECT cube_enlarge('(0,0,0)'::cube, 1, 0);
+      cube_enlarge      
+------------------------
+ (-1, -1, -1),(1, 1, 1)
+(1 row)
+
+SELECT cube_enlarge('(0,0,0)'::cube, 1, 2);
+      cube_enlarge      
+------------------------
+ (-1, -1, -1),(1, 1, 1)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 1, 2);
+  cube_enlarge   
+-----------------
+ (-4, -3),(3, 8)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 3, 2);
+   cube_enlarge   
+------------------
+ (-6, -5),(5, 10)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -1, 2);
+  cube_enlarge   
+-----------------
+ (-2, -1),(1, 6)
+(1 row)
+
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
+    cube_enlarge     
+---------------------
+ (-0.5, 1),(-0.5, 4)
+(1 row)
+
 -- Load some example data and build the index
 -- 
 CREATE TABLE test_cube (c cube);
diff --git a/contrib/cube/sql/cube.sql b/contrib/cube/sql/cube.sql
index 0e0de38bc4c97d1e299b90f1ecbc1c383abb83cf..e8a77d9c0aa92e0723e20ab4bb52ef6c3ab779b1 100644
--- a/contrib/cube/sql/cube.sql
+++ b/contrib/cube/sql/cube.sql
@@ -23,20 +23,26 @@ SELECT '.1'::cube AS cube;
 SELECT '-.1'::cube AS cube;
 SELECT '1.0'::cube AS cube;
 SELECT '-1.0'::cube AS cube;
-SELECT '1e7'::cube AS cube;
-SELECT '-1e7'::cube AS cube;
-SELECT '1.0e7'::cube AS cube;
-SELECT '-1.0e7'::cube AS cube;
-SELECT '1e+7'::cube AS cube;
-SELECT '-1e+7'::cube AS cube;
-SELECT '1.0e+7'::cube AS cube;
-SELECT '-1.0e+7'::cube AS cube;
+SELECT '1e27'::cube AS cube;
+SELECT '-1e27'::cube AS cube;
+SELECT '1.0e27'::cube AS cube;
+SELECT '-1.0e27'::cube AS cube;
+SELECT '1e+27'::cube AS cube;
+SELECT '-1e+27'::cube AS cube;
+SELECT '1.0e+27'::cube AS cube;
+SELECT '-1.0e+27'::cube AS cube;
 SELECT '1e-7'::cube AS cube;
 SELECT '-1e-7'::cube AS cube;
 SELECT '1.0e-7'::cube AS cube;
 SELECT '-1.0e-7'::cube AS cube;
 SELECT '1e-700'::cube AS cube;
 SELECT '-1e-700'::cube AS cube;
+SELECT '1234567890123456'::cube AS cube;
+SELECT '+1234567890123456'::cube AS cube;
+SELECT '-1234567890123456'::cube AS cube;
+SELECT '.1234567890123456'::cube AS cube;
+SELECT '+.1234567890123456'::cube AS cube;
+SELECT '-.1234567890123456'::cube AS cube;
 
 -- simple lists (points)
 SELECT '1,2'::cube AS cube;
@@ -230,6 +236,60 @@ SELECT '(-1,-1),(1,1)'::cube            @ '(-1),(1)'::cube          AS bool;
 SELECT '(-1),(1)'::cube                 @ '(-2),(1)'::cube          AS bool;
 SELECT '(-1,-1),(1,1)'::cube            @ '(-2),(1)'::cube          AS bool;
 
+-- Test of distance function
+--
+SELECT cube_distance('(0)'::cube,'(2,2,2,2)'::cube);
+SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
+
+-- Test of cube function (text to cube)
+--
+SELECT cube('('||1||','||1.2||')');
+SELECT cube(NULL);
+
+-- Test of cube_dim function (dimensions stored in cube)
+--
+SELECT cube_dim('(0)'::cube);
+SELECT cube_dim('(0,0)'::cube);
+SELECT cube_dim('(0,0,0)'::cube);
+
+-- Test of cube_ll_coord function (retrieves LL coodinate values)
+--
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 1);
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 2);
+SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 3);
+
+-- Test of cube_ur_coord function (retrieves UR coodinate values)
+--
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 1);
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 2);
+SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 3);
+
+-- Test of cube_is_point
+--
+SELECT cube_is_point('(0)'::cube);
+SELECT cube_is_point('(0,1,2)'::cube);
+SELECT cube_is_point('(0,1,2),(0,1,2)'::cube);
+SELECT cube_is_point('(0,1,2),(-1,1,2)'::cube);
+SELECT cube_is_point('(0,1,2),(0,-1,2)'::cube);
+SELECT cube_is_point('(0,1,2),(0,1,-2)'::cube);
+
+-- Test of cube_enlarge (enlarging and shrinking cubes)
+--
+SELECT cube_enlarge('(0)'::cube, 0, 0);
+SELECT cube_enlarge('(0)'::cube, 0, 1);
+SELECT cube_enlarge('(0)'::cube, 0, 2);
+SELECT cube_enlarge('(0)'::cube, 1, 0);
+SELECT cube_enlarge('(0)'::cube, 1, 1);
+SELECT cube_enlarge('(0)'::cube, 1, 2);
+SELECT cube_enlarge('(0)'::cube, -1, 0);
+SELECT cube_enlarge('(0)'::cube, -1, 1);
+SELECT cube_enlarge('(0)'::cube, -1, 2);
+SELECT cube_enlarge('(0,0,0)'::cube, 1, 0);
+SELECT cube_enlarge('(0,0,0)'::cube, 1, 2);
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 1, 2);
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, 3, 2);
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -1, 2);
+SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
 
 -- Load some example data and build the index
 --