On 09.10.2013 21:07, Robert Haas wrote:
On Tue, Sep 24, 2013 at 9:07 AM, Stas Kelvich<stas.kelv...@gmail.com>  wrote:
Hello

There is new version of patch. I have separated ordering operators to different 
patch (https://commitfest.postgresql.org/action/patch_view?id=1243), fixed 
formatting issues and implemented backward compatibility with old-style points 
in cube_is_point() and cube_out().

Also comparing output files I've discovered that this four files is combination 
of two types of different behavior:

1) SELECT '-1e-700'::cube AS cube;
can be (0) or (-0)

2) Amount of zeros in exponent of floating point, i.e. SELECT '1e27'::cube AS 
cube;
  can be (1e+027) or (1e+27)

On my system (OSX) it is second option in both situations. I've also tested it 
on FreeBSD 9.0 and Ubuntu 12.04 with the same results. So is there some ideas 
how can I reproduce such results?

Heikki, are you going to review this further for this CommitFest?

Sorry, I didn't realize the ball was in my court.

I went through the patch now, kibitzing over some minor style issues. Attached is a new version.

This seems good for commit except for two things:

1. The alternative expected output files still need to be updated. Stas couldn't find a system where some of those file were used. One option is to simply commit the patch as is, and see if the buildfarm goes red. If it doesn't, we can simply remove the alternative files - they are not used on any supported platform. If some animals go red, we'll get the required diff from the buildfarm output and apply. So this isn't a show-stopper.

2. I didn't understand this change:

@@ -422,24 +439,14 @@ g_cube_union(PG_FUNCTION_ARGS)
 Datum
 g_cube_compress(PG_FUNCTION_ARGS)
 {
-       PG_RETURN_DATUM(PG_GETARG_DATUM(0));
+       GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+       PG_RETURN_POINTER(entry);
 }

 Datum
 g_cube_decompress(PG_FUNCTION_ARGS)
 {
        GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
-       NDBOX      *key = DatumGetNDBOX(PG_DETOAST_DATUM(entry->key));
-
-       if (key != DatumGetNDBOX(entry->key))
-       {
-               GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
-
-               gistentryinit(*retval, PointerGetDatum(key),
-                                         entry->rel, entry->page,
-                                         entry->offset, FALSE);
-               PG_RETURN_POINTER(retval);
-       }
        PG_RETURN_POINTER(entry);
 }


What did the removed code do, and why isn't it needed anymore?

Is there a prerequisite patch that hasn't been committed yet?

No.

- Heikki
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c
index dab0e6e..853acbe 100644
--- a/contrib/cube/cube.c
+++ b/contrib/cube/cube.c
@@ -144,6 +144,7 @@ bool		g_cube_internal_consistent(NDBOX *key, NDBOX *query, StrategyNumber strate
 ** Auxiliary funxtions
 */
 static double distance_1D(double a1, double a2, double b1, double b2);
+static bool	cube_is_point_internal(NDBOX *cube);
 
 
 /*****************************************************************************
@@ -181,6 +182,7 @@ cube_a_f8_f8(PG_FUNCTION_ARGS)
 	int			i;
 	int			dim;
 	int			size;
+	bool		point;
 	double	   *dur,
 			   *dll;
 
@@ -198,16 +200,32 @@ cube_a_f8_f8(PG_FUNCTION_ARGS)
 	dur = ARRPTR(ur);
 	dll = ARRPTR(ll);
 
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim;
+	/* Check if it's a point */
+	point = true;
+	for (i = 0; i < dim; i++)
+	{
+		if (dur[i] != dll[i])
+		{
+			point = false;
+			break;
+		}
+	}
+
+	size = point ? POINT_SIZE(dim) : CUBE_SIZE(dim);
 	result = (NDBOX *) palloc0(size);
 	SET_VARSIZE(result, size);
-	result->dim = dim;
+	SET_DIM(result, dim);
 
 	for (i = 0; i < dim; i++)
-	{
 		result->x[i] = dur[i];
-		result->x[i + dim] = dll[i];
+
+	if (!point)
+	{
+		for (i = 0; i < dim; i++)
+			result->x[i + dim] = dll[i];
 	}
+	else
+		SET_POINT_BIT(result);
 
 	PG_RETURN_NDBOX(result);
 }
@@ -234,16 +252,14 @@ cube_a_f8(PG_FUNCTION_ARGS)
 
 	dur = ARRPTR(ur);
 
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim;
+	size = POINT_SIZE(dim);
 	result = (NDBOX *) palloc0(size);
 	SET_VARSIZE(result, size);
-	result->dim = dim;
+	SET_DIM(result, dim);
+	SET_POINT_BIT(result);
 
 	for (i = 0; i < dim; i++)
-	{
 		result->x[i] = dur[i];
-		result->x[i + dim] = dur[i];
-	}
 
 	PG_RETURN_NDBOX(result);
 }
@@ -267,14 +283,17 @@ cube_subset(PG_FUNCTION_ARGS)
 	dx = (int32 *) ARR_DATA_PTR(idx);
 
 	dim = ARRNELEMS(idx);
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim;
+	size = IS_POINT(c) ? POINT_SIZE(dim) : CUBE_SIZE(dim);
 	result = (NDBOX *) palloc0(size);
 	SET_VARSIZE(result, size);
-	result->dim = dim;
+	SET_DIM(result, dim);
+
+	if (IS_POINT(c))
+		SET_POINT_BIT(result);
 
 	for (i = 0; i < dim; i++)
 	{
-		if ((dx[i] <= 0) || (dx[i] > c->dim))
+		if ((dx[i] <= 0) || (dx[i] > DIM(c)))
 		{
 			pfree(result);
 			ereport(ERROR,
@@ -282,7 +301,8 @@ cube_subset(PG_FUNCTION_ARGS)
 					 errmsg("Index out of bounds")));
 		}
 		result->x[i] = c->x[dx[i] - 1];
-		result->x[i + dim] = c->x[dx[i] + c->dim - 1];
+		if (!IS_POINT(c))
+			result->x[i + dim] = c->x[dx[i] + DIM(c) - 1];
 	}
 
 	PG_FREE_IF_COPY(c, 0);
@@ -294,8 +314,7 @@ cube_out(PG_FUNCTION_ARGS)
 {
 	NDBOX	   *cube = PG_GETARG_NDBOX(0);
 	StringInfoData buf;
-	int			dim = cube->dim;
-	bool		equal = true;
+	int			dim = DIM(cube);
 	int			i;
 	int			ndig;
 
@@ -317,20 +336,18 @@ cube_out(PG_FUNCTION_ARGS)
 	{
 		if (i > 0)
 			appendStringInfo(&buf, ", ");
-		appendStringInfo(&buf, "%.*g", ndig, cube->x[i]);
-		if (cube->x[i] != cube->x[i + dim])
-			equal = false;
+		appendStringInfo(&buf, "%.*g", ndig, LL_COORD(cube, i));
 	}
 	appendStringInfoChar(&buf, ')');
 
-	if (!equal)
+	if (!cube_is_point_internal(cube))
 	{
 		appendStringInfo(&buf, ",(");
 		for (i = 0; i < dim; i++)
 		{
 			if (i > 0)
 				appendStringInfo(&buf, ", ");
-			appendStringInfo(&buf, "%.*g", ndig, cube->x[i + dim]);
+			appendStringInfo(&buf, "%.*g", ndig, UR_COORD(cube, i));
 		}
 		appendStringInfoChar(&buf, ')');
 	}
@@ -422,24 +439,14 @@ g_cube_union(PG_FUNCTION_ARGS)
 Datum
 g_cube_compress(PG_FUNCTION_ARGS)
 {
-	PG_RETURN_DATUM(PG_GETARG_DATUM(0));
+	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+	PG_RETURN_POINTER(entry);
 }
 
 Datum
 g_cube_decompress(PG_FUNCTION_ARGS)
 {
 	GISTENTRY  *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
-	NDBOX	   *key = DatumGetNDBOX(PG_DETOAST_DATUM(entry->key));
-
-	if (key != DatumGetNDBOX(entry->key))
-	{
-		GISTENTRY  *retval = (GISTENTRY *) palloc(sizeof(GISTENTRY));
-
-		gistentryinit(*retval, PointerGetDatum(key),
-					  entry->rel, entry->page,
-					  entry->offset, FALSE);
-		PG_RETURN_POINTER(retval);
-	}
 	PG_RETURN_POINTER(entry);
 }
 
@@ -729,51 +736,60 @@ cube_union_v0(NDBOX *a, NDBOX *b)
 {
 	int			i;
 	NDBOX	   *result;
+	int			dim;
+	int			size;
 
-	if (a->dim >= b->dim)
-	{
-		result = palloc0(VARSIZE(a));
-		SET_VARSIZE(result, VARSIZE(a));
-		result->dim = a->dim;
-	}
-	else
-	{
-		result = palloc0(VARSIZE(b));
-		SET_VARSIZE(result, VARSIZE(b));
-		result->dim = b->dim;
-	}
+	/* trivial case */
+	if (a == b)
+		return a;
 
-	/* swap the box pointers if needed */
-	if (a->dim < b->dim)
+	/* swap the arguments if needed, so that 'a' is always larger than 'b' */
+	if (DIM(a) < DIM(b))
 	{
 		NDBOX	   *tmp = b;
 
 		b = a;
 		a = tmp;
 	}
+	dim = DIM(a);
 
-	/*
-	 * use the potentially smaller of the two boxes (b) to fill in the result,
-	 * padding absent dimensions with zeroes
-	 */
-	for (i = 0; i < b->dim; i++)
+	size = CUBE_SIZE(dim);
+	result = palloc0(size);
+	SET_VARSIZE(result, size);
+	SET_DIM(result, dim);
+
+	 /* First compute the union of the dimensions present in both args */
+	for (i = 0; i < DIM(b); i++)
 	{
-		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]);
+		result->x[i] = Min(
+			Min(LL_COORD(a, i), UR_COORD(a, i)),
+			Min(LL_COORD(b, i), UR_COORD(b, i))
+		);
+		result->x[i + DIM(a)] = Max(
+			Max(LL_COORD(a, i), UR_COORD(a, i)),
+			Max(LL_COORD(b, i), UR_COORD(b, i))
+		);
 	}
-	for (i = b->dim; i < a->dim; i++)
+	/* continue on the higher dimensions only present in 'a' */
+	for (; i < DIM(a); i++)
 	{
-		result->x[i] = 0;
-		result->x[i + a->dim] = 0;
+		result->x[i] = Min(0,
+			Min(LL_COORD(a, i), UR_COORD(a, i))
+		);
+		result->x[i + dim] = Max(0,
+			Max(LL_COORD(a, i), UR_COORD(a, i))
+		);
 	}
 
-	/* compute the union */
-	for (i = 0; i < a->dim; i++)
+	/*
+	 * Check if the result was in fact a point, and set the flag in the datum
+	 * accordingly. (we don't bother to repalloc it smaller)
+	 */
+	if (cube_is_point_internal(result))
 	{
-		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]);
+		size = POINT_SIZE(dim);
+		SET_VARSIZE(result, size);
+		SET_POINT_BIT(result);
 	}
 
 	return (result);
@@ -802,52 +818,57 @@ cube_inter(PG_FUNCTION_ARGS)
 	NDBOX	   *result;
 	bool		swapped = false;
 	int			i;
+	int			dim;
+	int			size;
 
-	if (a->dim >= b->dim)
-	{
-		result = palloc0(VARSIZE(a));
-		SET_VARSIZE(result, VARSIZE(a));
-		result->dim = a->dim;
-	}
-	else
-	{
-		result = palloc0(VARSIZE(b));
-		SET_VARSIZE(result, VARSIZE(b));
-		result->dim = b->dim;
-	}
-
-	/* swap the box pointers if needed */
-	if (a->dim < b->dim)
+	/* swap the arguments if needed, so that 'a' is always larger than 'b' */
+	if (DIM(a) < DIM(b))
 	{
 		NDBOX	   *tmp = b;
-
 		b = a;
 		a = tmp;
 		swapped = true;
 	}
+	dim = DIM(a);
 
-	/*
-	 * use the potentially	smaller of the two boxes (b) to fill in the
-	 * result, padding absent dimensions with zeroes
-	 */
-	for (i = 0; i < b->dim; i++)
+	size = CUBE_SIZE(dim);
+	result = (NDBOX *) palloc0(size);
+	SET_VARSIZE(result, size);
+	SET_DIM(result, dim);
+
+	 /* First compute intersection of the dimensions present in both args */
+	for (i = 0; i < DIM(b); i++)
 	{
-		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]);
+		result->x[i] = Max(
+			Min(LL_COORD(a, i), UR_COORD(a, i)),
+			Min(LL_COORD(b, i), UR_COORD(b, i))
+		);
+		result->x[i + DIM(a)] = Min(
+			Max(LL_COORD(a, i), UR_COORD(a, i)),
+			Max(LL_COORD(b, i), UR_COORD(b, i))
+		);
 	}
-	for (i = b->dim; i < a->dim; i++)
+	/* continue on the higher dimemsions only present in 'a' */
+	for (; i < DIM(a); i++)
 	{
-		result->x[i] = 0;
-		result->x[i + a->dim] = 0;
+		result->x[i] = Max(0,
+			Min(LL_COORD(a, i), UR_COORD(a, i))
+		);
+		result->x[i + DIM(a)] = Min(0,
+			Max(LL_COORD(a, i), UR_COORD(a, i))
+		);
 	}
 
-	/* compute the intersection */
-	for (i = 0; i < a->dim; i++)
+	/*
+	 * Check if the result was in fact a point, and set the flag in the datum
+	 * accordingly. (we don't bother to repalloc it smaller)
+	 */
+	if (cube_is_point_internal(result))
 	{
-		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]);
+		size = POINT_SIZE(dim);
+		result = repalloc(result, size);
+		SET_VARSIZE(result, size);
+		SET_POINT_BIT(result);
 	}
 
 	if (swapped)
@@ -873,12 +894,11 @@ cube_size(PG_FUNCTION_ARGS)
 {
 	NDBOX	   *a = PG_GETARG_NDBOX(0);
 	double		result;
-	int			i,
-				j;
+	int			i;
 
 	result = 1.0;
-	for (i = 0, j = a->dim; i < a->dim; i++, j++)
-		result = result * Abs((a->x[j] - a->x[i]));
+	for (i = 0; i < DIM(a); i++)
+		result = result * Abs((LL_COORD(a, i) - UR_COORD(a, i)));
 
 	PG_FREE_IF_COPY(a, 0);
 	PG_RETURN_FLOAT8(result);
@@ -887,16 +907,15 @@ cube_size(PG_FUNCTION_ARGS)
 void
 rt_cube_size(NDBOX *a, double *size)
 {
-	int			i,
-				j;
+	int			i;
 
 	if (a == (NDBOX *) NULL)
 		*size = 0.0;
 	else
 	{
 		*size = 1.0;
-		for (i = 0, j = a->dim; i < a->dim; i++, j++)
-			*size = (*size) * Abs((a->x[j] - a->x[i]));
+		for (i = 0; i < DIM(a); i++)
+			*size = (*size) * Abs(UR_COORD(a, i) - LL_COORD(a, i));
 	}
 	return;
 }
@@ -909,43 +928,43 @@ cube_cmp_v0(NDBOX *a, NDBOX *b)
 	int			i;
 	int			dim;
 
-	dim = Min(a->dim, b->dim);
+	dim = Min(DIM(a), DIM(b));
 
 	/* compare the common dimensions */
 	for (i = 0; i < dim; i++)
 	{
-		if (Min(a->x[i], a->x[a->dim + i]) >
-			Min(b->x[i], b->x[b->dim + i]))
+		if (Min(LL_COORD(a, i), UR_COORD(a, i)) >
+			Min(LL_COORD(b, i), UR_COORD(b, i)))
 			return 1;
-		if (Min(a->x[i], a->x[a->dim + i]) <
-			Min(b->x[i], b->x[b->dim + i]))
+		if (Min(LL_COORD(a, i), UR_COORD(a, i)) <
+			Min(LL_COORD(b, i), UR_COORD(b, i)))
 			return -1;
 	}
 	for (i = 0; i < dim; i++)
 	{
-		if (Max(a->x[i], a->x[a->dim + i]) >
-			Max(b->x[i], b->x[b->dim + i]))
+		if (Max(LL_COORD(a, i), UR_COORD(a, i)) >
+			Max(LL_COORD(b, i), UR_COORD(b, i)))
 			return 1;
-		if (Max(a->x[i], a->x[a->dim + i]) <
-			Max(b->x[i], b->x[b->dim + i]))
+		if (Max(LL_COORD(a, i), UR_COORD(a, i)) <
+			Max(LL_COORD(b, i), UR_COORD(b, i)))
 			return -1;
 	}
 
 	/* compare extra dimensions to zero */
-	if (a->dim > b->dim)
+	if (DIM(a) > DIM(b))
 	{
-		for (i = dim; i < a->dim; i++)
+		for (i = dim; i < DIM(a); i++)
 		{
-			if (Min(a->x[i], a->x[a->dim + i]) > 0)
+			if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0)
 				return 1;
-			if (Min(a->x[i], a->x[a->dim + i]) < 0)
+			if (Min(LL_COORD(a, i), UR_COORD(a, i)) < 0)
 				return -1;
 		}
-		for (i = dim; i < a->dim; i++)
+		for (i = dim; i < DIM(a); i++)
 		{
-			if (Max(a->x[i], a->x[a->dim + i]) > 0)
+			if (Max(LL_COORD(a, i), UR_COORD(a, i)) > 0)
 				return 1;
-			if (Max(a->x[i], a->x[a->dim + i]) < 0)
+			if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0)
 				return -1;
 		}
 
@@ -955,20 +974,20 @@ cube_cmp_v0(NDBOX *a, NDBOX *b)
 		 */
 		return 1;
 	}
-	if (a->dim < b->dim)
+	if (DIM(a) < DIM(b))
 	{
-		for (i = dim; i < b->dim; i++)
+		for (i = dim; i < DIM(b); i++)
 		{
-			if (Min(b->x[i], b->x[b->dim + i]) > 0)
+			if (Min(LL_COORD(b, i), UR_COORD(b, i)) > 0)
 				return -1;
-			if (Min(b->x[i], b->x[b->dim + i]) < 0)
+			if (Min(LL_COORD(b, i), UR_COORD(b, i)) < 0)
 				return 1;
 		}
-		for (i = dim; i < b->dim; i++)
+		for (i = dim; i < DIM(b); i++)
 		{
-			if (Max(b->x[i], b->x[b->dim + i]) > 0)
+			if (Max(LL_COORD(b, i), UR_COORD(b, i)) > 0)
 				return -1;
-			if (Max(b->x[i], b->x[b->dim + i]) < 0)
+			if (Max(LL_COORD(b, i), UR_COORD(b, i)) < 0)
 				return 1;
 		}
 
@@ -1098,30 +1117,30 @@ cube_contains_v0(NDBOX *a, NDBOX *b)
 	if ((a == NULL) || (b == NULL))
 		return (FALSE);
 
-	if (a->dim < b->dim)
+	if (DIM(a) < DIM(b))
 	{
 		/*
 		 * 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++)
+		for (i = DIM(a); i < DIM(b); i++)
 		{
-			if (b->x[i] != 0)
+			if (LL_COORD(b, i) != 0)
 				return (FALSE);
-			if (b->x[i + b->dim] != 0)
+			if (UR_COORD(b, i) != 0)
 				return (FALSE);
 		}
 	}
 
 	/* Can't care less about the excess dimensions of (a), if any */
-	for (i = 0; i < Min(a->dim, b->dim); i++)
+	for (i = 0; i < Min(DIM(a), DIM(b)); i++)
 	{
-		if (Min(a->x[i], a->x[a->dim + i]) >
-			Min(b->x[i], b->x[b->dim + i]))
+		if (Min(LL_COORD(a, i), UR_COORD(a, i)) >
+			Min(LL_COORD(b, i), UR_COORD(b, i)))
 			return (FALSE);
-		if (Max(a->x[i], a->x[a->dim + i]) <
-			Max(b->x[i], b->x[b->dim + i]))
+		if (Max(LL_COORD(a, i), UR_COORD(a, i)) <
+			Max(LL_COORD(b, i), UR_COORD(b, i)))
 			return (FALSE);
 	}
 
@@ -1173,7 +1192,7 @@ cube_overlap_v0(NDBOX *a, NDBOX *b)
 		return (FALSE);
 
 	/* swap the box pointers if needed */
-	if (a->dim < b->dim)
+	if (DIM(a) < DIM(b))
 	{
 		NDBOX	   *tmp = b;
 
@@ -1182,22 +1201,20 @@ cube_overlap_v0(NDBOX *a, NDBOX *b)
 	}
 
 	/* compare within the dimensions of (b) */
-	for (i = 0; i < b->dim; i++)
+	for (i = 0; i < DIM(b); i++)
 	{
-		if (Min(a->x[i], a->x[a->dim + i]) >
-			Max(b->x[i], b->x[b->dim + i]))
+		if (Min(LL_COORD(a, i), UR_COORD(a, i)) > Max(LL_COORD(b, i), UR_COORD(b, i)))
 			return (FALSE);
-		if (Max(a->x[i], a->x[a->dim + i]) <
-			Min(b->x[i], b->x[b->dim + i]))
+		if (Max(LL_COORD(a, i), UR_COORD(a, i)) < Min(LL_COORD(b, i), UR_COORD(b, i)))
 			return (FALSE);
 	}
 
 	/* compare to zero those dimensions in (a) absent in (b) */
-	for (i = b->dim; i < a->dim; i++)
+	for (i = DIM(b); i < DIM(a); i++)
 	{
-		if (Min(a->x[i], a->x[a->dim + i]) > 0)
+		if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0)
 			return (FALSE);
-		if (Max(a->x[i], a->x[a->dim + i]) < 0)
+		if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0)
 			return (FALSE);
 	}
 
@@ -1236,7 +1253,7 @@ cube_distance(PG_FUNCTION_ARGS)
 	int			i;
 
 	/* swap the box pointers if needed */
-	if (a->dim < b->dim)
+	if (DIM(a) < DIM(b))
 	{
 		NDBOX	   *tmp = b;
 
@@ -1247,16 +1264,16 @@ cube_distance(PG_FUNCTION_ARGS)
 
 	distance = 0.0;
 	/* compute within the dimensions of (b) */
-	for (i = 0; i < b->dim; i++)
+	for (i = 0; i < DIM(b); i++)
 	{
-		d = distance_1D(a->x[i], a->x[i + a->dim], b->x[i], b->x[i + b->dim]);
+		d = distance_1D(LL_COORD(a,i), UR_COORD(a,i), LL_COORD(b,i), UR_COORD(b,i));
 		distance += d * d;
 	}
 
 	/* compute distance to zero for those dimensions in (a) absent in (b) */
-	for (i = b->dim; i < a->dim; i++)
+	for (i = DIM(b); i < DIM(a); i++)
 	{
-		d = distance_1D(a->x[i], a->x[i + a->dim], 0.0, 0.0);
+		d = distance_1D(LL_COORD(a,i), UR_COORD(a,i), 0.0, 0.0);
 		distance += d * d;
 	}
 
@@ -1293,18 +1310,35 @@ distance_1D(double a1, double a2, double b1, double b2)
 Datum
 cube_is_point(PG_FUNCTION_ARGS)
 {
-	NDBOX	   *a = PG_GETARG_NDBOX(0);
-	int			i,
-				j;
+	NDBOX	   *cube = PG_GETARG_NDBOX(0);
+	bool		result;
+
+	result = cube_is_point_internal(cube);
+	PG_FREE_IF_COPY(cube, 0);
+	PG_RETURN_BOOL(result);
+}
+
+static bool
+cube_is_point_internal(NDBOX *cube)
+{
+	int			i;
+
+	if (IS_POINT(cube))
+		return true;
 
-	for (i = 0, j = a->dim; i < a->dim; i++, j++)
+	/*
+	 * Even if the point-flag is not set, all the lower-left coordinates
+	 * might match the upper-right coordinates, so that the value is in
+	 * fact a point. Such values don't arise with current code - the point
+	 * flag is always set if appropriate - but they might be present on-disk
+	 * in clusters upgraded from pre-9.4 versions.
+	 */
+	for (i = 0; i < DIM(cube); i++)
 	{
-		if (a->x[i] != a->x[j])
-			PG_RETURN_BOOL(FALSE);
+		if (LL_COORD(cube, i) != UR_COORD(cube, i))
+			return false;
 	}
-
-	PG_FREE_IF_COPY(a, 0);
-	PG_RETURN_BOOL(TRUE);
+	return true;
 }
 
 /* Return dimensions in use in the data structure */
@@ -1312,8 +1346,7 @@ Datum
 cube_dim(PG_FUNCTION_ARGS)
 {
 	NDBOX	   *c = PG_GETARG_NDBOX(0);
-	int			dim = c->dim;
-
+	int			dim = DIM(c);
 	PG_FREE_IF_COPY(c, 0);
 	PG_RETURN_INT32(dim);
 }
@@ -1326,8 +1359,8 @@ cube_ll_coord(PG_FUNCTION_ARGS)
 	int			n = PG_GETARG_INT16(1);
 	double		result;
 
-	if (c->dim >= n && n > 0)
-		result = Min(c->x[n - 1], c->x[c->dim + n - 1]);
+	if (DIM(c) >= n && n > 0)
+		result = Min(LL_COORD(c, n-1), UR_COORD(c, n-1));
 	else
 		result = 0;
 
@@ -1343,8 +1376,8 @@ cube_ur_coord(PG_FUNCTION_ARGS)
 	int			n = PG_GETARG_INT16(1);
 	double		result;
 
-	if (c->dim >= n && n > 0)
-		result = Max(c->x[n - 1], c->x[c->dim + n - 1]);
+	if (DIM(c) >= n && n > 0)
+		result = Max(LL_COORD(c, n-1), UR_COORD(c, n-1));
 	else
 		result = 0;
 
@@ -1363,30 +1396,31 @@ cube_enlarge(PG_FUNCTION_ARGS)
 	int			dim = 0;
 	int			size;
 	int			i,
-				j,
-				k;
+				j;
 
 	if (n > CUBE_MAX_DIM)
 		n = CUBE_MAX_DIM;
 	if (r > 0 && n > 0)
 		dim = n;
-	if (a->dim > dim)
-		dim = a->dim;
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * dim * 2;
+	if (DIM(a) > dim)
+		dim = DIM(a);
+
+	size = CUBE_SIZE(dim);
 	result = (NDBOX *) palloc0(size);
 	SET_VARSIZE(result, size);
-	result->dim = dim;
-	for (i = 0, j = dim, k = a->dim; i < a->dim; i++, j++, k++)
+	SET_DIM(result, dim);
+
+	for (i = 0, j = dim; i < DIM(a); i++, j++)
 	{
-		if (a->x[i] >= a->x[k])
+		if (LL_COORD(a,i) >= UR_COORD(a,i))
 		{
-			result->x[i] = a->x[k] - r;
-			result->x[j] = a->x[i] + r;
+			result->x[i] = UR_COORD(a,i) - r;
+			result->x[j] = LL_COORD(a,i) + r;
 		}
 		else
 		{
-			result->x[i] = a->x[i] - r;
-			result->x[j] = a->x[k] + r;
+			result->x[i] = LL_COORD(a,i) - r;
+			result->x[j] = UR_COORD(a,i) + r;
 		}
 		if (result->x[i] > result->x[j])
 		{
@@ -1401,6 +1435,17 @@ cube_enlarge(PG_FUNCTION_ARGS)
 		result->x[j] = r;
 	}
 
+	/*
+	 * Check if the result was in fact a point, and set the flag in the datum
+	 * accordingly. (we don't bother to repalloc it smaller)
+	 */
+	if (cube_is_point_internal(result))
+	{
+		size = POINT_SIZE(dim);
+		SET_VARSIZE(result, size);
+		SET_POINT_BIT(result);
+	}
+
 	PG_FREE_IF_COPY(a, 0);
 	PG_RETURN_NDBOX(result);
 }
@@ -1413,11 +1458,12 @@ cube_f8(PG_FUNCTION_ARGS)
 	NDBOX	   *result;
 	int			size;
 
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * 2;
+	size = POINT_SIZE(1);
 	result = (NDBOX *) palloc0(size);
 	SET_VARSIZE(result, size);
-	result->dim = 1;
-	result->x[0] = result->x[1] = x;
+	SET_DIM(result, 1);
+	SET_POINT_BIT(result);
+	result->x[0] = x;
 
 	PG_RETURN_NDBOX(result);
 }
@@ -1431,12 +1477,24 @@ cube_f8_f8(PG_FUNCTION_ARGS)
 	NDBOX	   *result;
 	int			size;
 
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * 2;
-	result = (NDBOX *) palloc0(size);
-	SET_VARSIZE(result, size);
-	result->dim = 1;
-	result->x[0] = x0;
-	result->x[1] = x1;
+	if (x0 == x1)
+	{
+		size = POINT_SIZE(1);
+		result = (NDBOX *) palloc0(size);
+		SET_VARSIZE(result, size);
+		SET_DIM(result, 1);
+		SET_POINT_BIT(result);
+		result->x[0] = x0;
+	}
+	else
+	{
+		size = CUBE_SIZE(1);
+		result = (NDBOX *) palloc0(size);
+		SET_VARSIZE(result, size);
+		SET_DIM(result, 1);
+		result->x[0] = x0;
+		result->x[1] = x1;
+	}
 
 	PG_RETURN_NDBOX(result);
 }
@@ -1446,25 +1504,39 @@ cube_f8_f8(PG_FUNCTION_ARGS)
 Datum
 cube_c_f8(PG_FUNCTION_ARGS)
 {
-	NDBOX	   *c = PG_GETARG_NDBOX(0);
+	NDBOX	   *cube = PG_GETARG_NDBOX(0);
 	double		x = PG_GETARG_FLOAT8(1);
 	NDBOX	   *result;
 	int			size;
 	int			i;
 
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2;
-	result = (NDBOX *) palloc0(size);
-	SET_VARSIZE(result, size);
-	result->dim = c->dim + 1;
-	for (i = 0; i < c->dim; i++)
+	if (IS_POINT(cube))
 	{
-		result->x[i] = c->x[i];
-		result->x[result->dim + i] = c->x[c->dim + i];
+		size = POINT_SIZE((DIM(cube) + 1));
+		result = (NDBOX *) palloc0(size);
+		SET_VARSIZE(result, size);
+		SET_DIM(result, DIM(cube) + 1);
+		SET_POINT_BIT(result);
+		for (i = 0; i < DIM(cube); i++)
+			result->x[i] = cube->x[i];
+		result->x[DIM(result) - 1] = x;
+	}
+	else
+	{
+		size = CUBE_SIZE((DIM(cube) + 1));
+		result = (NDBOX *) palloc0(size);
+		SET_VARSIZE(result, size);
+		SET_DIM(result, DIM(cube) + 1);
+		for (i = 0; i < DIM(cube); i++)
+		{
+			result->x[i] = cube->x[i];
+			result->x[DIM(result) + i] = cube->x[DIM(cube) + i];
+		}
+		result->x[DIM(result) - 1] = x;
+		result->x[2*DIM(result) - 1] = x;
 	}
-	result->x[result->dim - 1] = x;
-	result->x[2 * result->dim - 1] = x;
 
-	PG_FREE_IF_COPY(c, 0);
+	PG_FREE_IF_COPY(cube, 0);
 	PG_RETURN_NDBOX(result);
 }
 
@@ -1472,25 +1544,38 @@ cube_c_f8(PG_FUNCTION_ARGS)
 Datum
 cube_c_f8_f8(PG_FUNCTION_ARGS)
 {
-	NDBOX	   *c = PG_GETARG_NDBOX(0);
+	NDBOX	   *cube = PG_GETARG_NDBOX(0);
 	double		x1 = PG_GETARG_FLOAT8(1);
 	double		x2 = PG_GETARG_FLOAT8(2);
 	NDBOX	   *result;
 	int			size;
 	int			i;
 
-	size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2;
-	result = (NDBOX *) palloc0(size);
-	SET_VARSIZE(result, size);
-	result->dim = c->dim + 1;
-	for (i = 0; i < c->dim; i++)
+	if (IS_POINT(cube) && (x1 == x2)){
+		size = POINT_SIZE((DIM(cube) + 1));
+		result = (NDBOX *) palloc0(size);
+		SET_VARSIZE(result, size);
+		SET_DIM(result, DIM(cube) + 1);
+		SET_POINT_BIT(result);
+		for (i = 0; i < DIM(cube); i++)
+			result->x[i] = cube->x[i];
+		result->x[DIM(result) - 1] = x1;
+	}
+	else
 	{
-		result->x[i] = c->x[i];
-		result->x[result->dim + i] = c->x[c->dim + i];
+		size = CUBE_SIZE((DIM(cube) + 1));
+		result = (NDBOX *) palloc0(size);
+		SET_VARSIZE(result, size);
+		SET_DIM(result, DIM(cube) + 1);
+		for (i = 0; i < DIM(cube); i++)
+		{
+			result->x[i] = LL_COORD(cube, i);
+			result->x[DIM(result) + i] = UR_COORD(cube, i);
+		}
+		result->x[DIM(result) - 1] = x1;
+		result->x[2 * DIM(result) - 1] = x2;
 	}
-	result->x[result->dim - 1] = x1;
-	result->x[2 * result->dim - 1] = x2;
 
-	PG_FREE_IF_COPY(c, 0);
+	PG_FREE_IF_COPY(cube, 0);
 	PG_RETURN_NDBOX(result);
 }
diff --git a/contrib/cube/cubedata.h b/contrib/cube/cubedata.h
index fd0c26a..7903c8b 100644
--- a/contrib/cube/cubedata.h
+++ b/contrib/cube/cubedata.h
@@ -4,11 +4,36 @@
 
 typedef struct NDBOX
 {
-	int32		vl_len_;		/* varlena header (do not touch directly!) */
-	unsigned int dim;
+	/* varlena header (do not touch directly!) */
+	int32		vl_len_;
+
+	/*----------
+	 * Header contains info about NDBOX. For binary compatibility with old
+	 * versions, it is defined as "unsigned int".
+	 *
+	 * Following information is stored:
+	 *
+	 *  bits 0-7  : number of cube dimensions;
+	 *  bits 8-30 : not used;
+	 *  bit  31   : point flag. If set, then NDBOX stores
+	 *				n dimensions instead of 2*n;
+	 *----------
+	 */
+	unsigned int header;
 	double		x[1];
 } NDBOX;
 
 #define DatumGetNDBOX(x)	((NDBOX*)DatumGetPointer(x))
 #define PG_GETARG_NDBOX(x)	DatumGetNDBOX( PG_DETOAST_DATUM(PG_GETARG_DATUM(x)) )
 #define PG_RETURN_NDBOX(x)	PG_RETURN_POINTER(x)
+
+#define IS_POINT(cube)		( (cube)->header >> 31 )
+#define SET_POINT_BIT(cube)	( (cube)->header |= 0x80000000 )
+#define DIM(cube)			( (cube)->header & 0x7fffffff )
+#define SET_DIM(cube, _dim)	( (cube)->header = _dim )
+
+#define LL_COORD(cube, i) ( (cube)->x[i] )
+#define UR_COORD(cube, i) ( IS_POINT(cube) ? (cube)->x[i] : (cube)->x[i + DIM(cube)] )
+
+#define POINT_SIZE(_dim) (offsetof(NDBOX, x[0]) + sizeof(double)*(_dim))
+#define CUBE_SIZE(_dim) (offsetof(NDBOX, x[0]) + sizeof(double)*(_dim)*2)
diff --git a/contrib/cube/cubeparse.y b/contrib/cube/cubeparse.y
index d7205b8..0baee8e 100644
--- a/contrib/cube/cubeparse.y
+++ b/contrib/cube/cubeparse.y
@@ -175,11 +175,12 @@ write_box(unsigned int dim, char *str1, char *str2)
 	NDBOX	   *bp;
 	char	   *s;
 	int			i;
-	int			size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
+	int			size = CUBE_SIZE(dim);
+	bool		point = true;
 
 	bp = palloc0(size);
 	SET_VARSIZE(bp, size);
-	bp->dim = dim;
+	SET_DIM(bp, dim);
 
 	s = str1;
 	bp->x[i=0] = strtod(s, NULL);
@@ -191,10 +192,28 @@ write_box(unsigned int dim, char *str1, char *str2)
 
 	s = str2;
 	bp->x[i=dim] = strtod(s, NULL);
+	if (bp->x[dim] != bp->x[0])
+		point = false;
 	while ((s = strchr(s, ',')) != NULL)
 	{
 		s++; i++;
 		bp->x[i] = strtod(s, NULL);
+		if (bp->x[i] != bp->x[i-dim])
+			point = false;
+	}
+
+	if (point)
+	{
+		/*
+		 * The value turned out to be a point, ie. all the upper-right
+		 * coordinates were equal to the lower-left coordinates. Resize the
+		 * the cube we constructed. Note: we don't bother to repalloc() it
+		 * smaller, it's unlikely that the tiny amount of memory free'd that
+		 * way would be useful.
+		 */
+		size = POINT_SIZE(dim);
+		SET_VARSIZE(bp, size);
+		SET_POINT_BIT(bp);
 	}
 
 	return(bp);
@@ -203,31 +222,29 @@ write_box(unsigned int dim, char *str1, char *str2)
 static NDBOX *
 write_point_as_box(char *str, int dim)
 {
-  NDBOX		   *bp;
-  int			i,
+	NDBOX		*bp;
+	int			i,
 				size;
-  double		x;
-  char		   *s = str;
-
-  size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
-
-  bp = palloc0(size);
-  SET_VARSIZE(bp, size);
-  bp->dim = dim;
-
-  i = 0;
-  x = strtod(s, NULL);
-  bp->x[0] = x;
-  bp->x[dim] = x;
-  while ((s = strchr(s, ',')) != NULL)
-  {
-	  s++; i++;
-	  x = strtod(s, NULL);
-	  bp->x[i] = x;
-	  bp->x[i+dim] = x;
-  }
-
-  return(bp);
+	double		x;
+	char		*s = str;
+
+	size = POINT_SIZE(dim);
+	bp = palloc0(size);
+	SET_VARSIZE(bp, size);
+	SET_DIM(bp, dim);
+	SET_POINT_BIT(bp);
+
+	i = 0;
+	x = strtod(s, NULL);
+	bp->x[0] = x;
+	while ((s = strchr(s, ',')) != NULL)
+	{
+		s++; i++;
+		x = strtod(s, NULL);
+		bp->x[i] = x;
+	}
+
+	return(bp);
 }
 
 #include "cubescan.c"
diff --git a/contrib/cube/expected/cube_1.out b/contrib/cube/expected/cube_1.out
index fefebf5..c07d61d 100644
--- a/contrib/cube/expected/cube_1.out
+++ b/contrib/cube/expected/cube_1.out
@@ -473,8 +473,85 @@ SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[3,2,1,1]);
  (5, 3, 1, 1),(8, 7, 6, 6)
 (1 row)
 
+SELECT cube_subset(cube('(1,3,5),(1,3,5)'), ARRAY[3,2,1,1]);
+ cube_subset  
+--------------
+ (5, 3, 1, 1)
+(1 row)
+
 SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
 ERROR:  Index out of bounds
+SELECT cube_subset(cube('(6,7,8),(6,7,8)'), ARRAY[4,0]);
+ERROR:  Index out of bounds
+--
+-- Test point processing
+--
+SELECT cube('(1,2),(1,2)'); -- cube_in
+  cube  
+--------
+ (1, 2)
+(1 row)
+
+SELECT cube('{0,1,2}'::float[], '{0,1,2}'::float[]); -- cube_a_f8_f8
+   cube    
+-----------
+ (0, 1, 2)
+(1 row)
+
+SELECT cube('{5,6,7,8}'::float[]); -- cube_a_f8
+     cube     
+--------------
+ (5, 6, 7, 8)
+(1 row)
+
+SELECT cube(1.37); -- cube_f8
+  cube  
+--------
+ (1.37)
+(1 row)
+
+SELECT cube(1.37, 1.37); -- cube_f8_f8
+  cube  
+--------
+ (1.37)
+(1 row)
+
+SELECT cube(cube(1,1), 42); -- cube_c_f8
+  cube   
+---------
+ (1, 42)
+(1 row)
+
+SELECT cube(cube(1,2), 42); -- cube_c_f8
+      cube       
+-----------------
+ (1, 42),(2, 42)
+(1 row)
+
+SELECT cube(cube(1,1), 42, 42); -- cube_c_f8_f8
+  cube   
+---------
+ (1, 42)
+(1 row)
+
+SELECT cube(cube(1,1), 42, 24); -- cube_c_f8_f8
+      cube       
+-----------------
+ (1, 42),(1, 24)
+(1 row)
+
+SELECT cube(cube(1,2), 42, 42); -- cube_c_f8_f8
+      cube       
+-----------------
+ (1, 42),(2, 42)
+(1 row)
+
+SELECT cube(cube(1,2), 42, 24); -- cube_c_f8_f8
+      cube       
+-----------------
+ (1, 42),(2, 24)
+(1 row)
+
 --
 -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
 --
@@ -878,6 +955,24 @@ SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
            0.5
 (1 row)
 
+SELECT cube_distance('(2,3,4)'::cube,'(2,3,4)'::cube);
+ cube_distance 
+---------------
+             0
+(1 row)
+
+SELECT cube_distance('(42,42,42,42)'::cube,'(137,137,137,137)'::cube);
+ cube_distance 
+---------------
+           190
+(1 row)
+
+SELECT cube_distance('(42,42,42)'::cube,'(137,137)'::cube);
+  cube_distance   
+------------------
+ 140.762210837994
+(1 row)
+
 -- Test of cube function (text to cube)
 --
 SELECT cube('(1,1.2)'::text);
@@ -912,6 +1007,18 @@ SELECT cube_dim('(0,0,0)'::cube);
         3
 (1 row)
 
+SELECT cube_dim('(42,42,42),(42,42,42)'::cube);
+ cube_dim 
+----------
+        3
+(1 row)
+
+SELECT cube_dim('(4,8,15,16,23),(4,8,15,16,23)'::cube);
+ cube_dim 
+----------
+        5
+(1 row)
+
 -- Test of cube_ll_coord function (retrieves LL coodinate values)
 --
 SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 1);
@@ -932,6 +1039,42 @@ SELECT cube_ll_coord('(-1,1),(2,-2)'::cube, 3);
              0
 (1 row)
 
+SELECT cube_ll_coord('(1,2),(1,2)'::cube, 1);
+ cube_ll_coord 
+---------------
+             1
+(1 row)
+
+SELECT cube_ll_coord('(1,2),(1,2)'::cube, 2);
+ cube_ll_coord 
+---------------
+             2
+(1 row)
+
+SELECT cube_ll_coord('(1,2),(1,2)'::cube, 3);
+ cube_ll_coord 
+---------------
+             0
+(1 row)
+
+SELECT cube_ll_coord('(42,137)'::cube, 1);
+ cube_ll_coord 
+---------------
+            42
+(1 row)
+
+SELECT cube_ll_coord('(42,137)'::cube, 2);
+ cube_ll_coord 
+---------------
+           137
+(1 row)
+
+SELECT cube_ll_coord('(42,137)'::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);
@@ -952,6 +1095,42 @@ SELECT cube_ur_coord('(-1,1),(2,-2)'::cube, 3);
              0
 (1 row)
 
+SELECT cube_ur_coord('(1,2),(1,2)'::cube, 1);
+ cube_ur_coord 
+---------------
+             1
+(1 row)
+
+SELECT cube_ur_coord('(1,2),(1,2)'::cube, 2);
+ cube_ur_coord 
+---------------
+             2
+(1 row)
+
+SELECT cube_ur_coord('(1,2),(1,2)'::cube, 3);
+ cube_ur_coord 
+---------------
+             0
+(1 row)
+
+SELECT cube_ur_coord('(42,137)'::cube, 1);
+ cube_ur_coord 
+---------------
+            42
+(1 row)
+
+SELECT cube_ur_coord('(42,137)'::cube, 2);
+ cube_ur_coord 
+---------------
+           137
+(1 row)
+
+SELECT cube_ur_coord('(42,137)'::cube, 3);
+ cube_ur_coord 
+---------------
+             0
+(1 row)
+
 -- Test of cube_is_point
 --
 SELECT cube_is_point('(0)'::cube);
@@ -1100,6 +1279,108 @@ SELECT cube_enlarge('(2,-2),(-3,7)'::cube, -3, 2);
  (-0.5, 1),(-0.5, 4)
 (1 row)
 
+SELECT cube_enlarge('(42,-23,-23),(42,23,23)'::cube, -23, 5);
+ cube_enlarge 
+--------------
+ (42, 0, 0)
+(1 row)
+
+SELECT cube_enlarge('(42,-23,-23),(42,23,23)'::cube, -24, 5);
+ cube_enlarge 
+--------------
+ (42, 0, 0)
+(1 row)
+
+-- Test of cube_union (MBR for two cubes)
+--
+SELECT cube_union('(1,2),(3,4)'::cube, '(5,6,7),(8,9,10)'::cube);
+      cube_union      
+----------------------
+ (1, 2, 0),(8, 9, 10)
+(1 row)
+
+SELECT cube_union('(1,2)'::cube, '(4,2,0,0)'::cube);
+        cube_union         
+---------------------------
+ (1, 2, 0, 0),(4, 2, 0, 0)
+(1 row)
+
+SELECT cube_union('(1,2),(1,2)'::cube, '(4,2),(4,2)'::cube);
+  cube_union   
+---------------
+ (1, 2),(4, 2)
+(1 row)
+
+SELECT cube_union('(1,2),(1,2)'::cube, '(1,2),(1,2)'::cube);
+ cube_union 
+------------
+ (1, 2)
+(1 row)
+
+SELECT cube_union('(1,2),(1,2)'::cube, '(1,2,0),(1,2,0)'::cube);
+ cube_union 
+------------
+ (1, 2, 0)
+(1 row)
+
+-- Test of cube_inter
+--
+SELECT cube_inter('(1,2),(10,11)'::cube, '(3,4), (16,15)'::cube); -- intersects
+   cube_inter    
+-----------------
+ (3, 4),(10, 11)
+(1 row)
+
+SELECT cube_inter('(1,2),(10,11)'::cube, '(3,4), (6,5)'::cube); -- includes
+  cube_inter   
+---------------
+ (3, 4),(6, 5)
+(1 row)
+
+SELECT cube_inter('(1,2),(10,11)'::cube, '(13,14), (16,15)'::cube); -- no intersection
+    cube_inter     
+-------------------
+ (13, 14),(10, 11)
+(1 row)
+
+SELECT cube_inter('(1,2),(10,11)'::cube, '(3,14), (16,15)'::cube); -- no intersection, but one dimension intersects
+    cube_inter    
+------------------
+ (3, 14),(10, 11)
+(1 row)
+
+SELECT cube_inter('(1,2),(10,11)'::cube, '(10,11), (16,15)'::cube); -- point intersection
+ cube_inter 
+------------
+ (10, 11)
+(1 row)
+
+SELECT cube_inter('(1,2,3)'::cube, '(1,2,3)'::cube); -- point args
+ cube_inter 
+------------
+ (1, 2, 3)
+(1 row)
+
+SELECT cube_inter('(1,2,3)'::cube, '(5,6,3)'::cube); -- point args
+     cube_inter      
+---------------------
+ (5, 6, 3),(1, 2, 3)
+(1 row)
+
+-- Test of cube_size
+--
+SELECT cube_size('(4,8),(15,16)'::cube);
+ cube_size 
+-----------
+        88
+(1 row)
+
+SELECT cube_size('(42,137)'::cube);
+ cube_size 
+-----------
+         0
+(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 02e068e..d58974c 100644
--- a/contrib/cube/sql/cube.sql
+++ b/contrib/cube/sql/cube.sql
@@ -112,7 +112,24 @@ 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),(1,3,5)'), ARRAY[3,2,1,1]);
 SELECT cube_subset(cube('(1,3,5),(6,7,8)'), ARRAY[4,0]);
+SELECT cube_subset(cube('(6,7,8),(6,7,8)'), ARRAY[4,0]);
+
+--
+-- Test point processing
+--
+SELECT cube('(1,2),(1,2)'); -- cube_in
+SELECT cube('{0,1,2}'::float[], '{0,1,2}'::float[]); -- cube_a_f8_f8
+SELECT cube('{5,6,7,8}'::float[]); -- cube_a_f8
+SELECT cube(1.37); -- cube_f8
+SELECT cube(1.37, 1.37); -- cube_f8_f8
+SELECT cube(cube(1,1), 42); -- cube_c_f8
+SELECT cube(cube(1,2), 42); -- cube_c_f8
+SELECT cube(cube(1,1), 42, 42); -- cube_c_f8_f8
+SELECT cube(cube(1,1), 42, 24); -- cube_c_f8_f8
+SELECT cube(cube(1,2), 42, 42); -- cube_c_f8_f8
+SELECT cube(cube(1,2), 42, 24); -- cube_c_f8_f8
 
 --
 -- Testing limit of CUBE_MAX_DIM dimensions check in cube_in.
@@ -212,6 +229,9 @@ SELECT '(-1,-1),(1,1)'::cube            @> '(-2),(1)'::cube          AS bool;
 --
 SELECT cube_distance('(0)'::cube,'(2,2,2,2)'::cube);
 SELECT cube_distance('(0)'::cube,'(.3,.4)'::cube);
+SELECT cube_distance('(2,3,4)'::cube,'(2,3,4)'::cube);
+SELECT cube_distance('(42,42,42,42)'::cube,'(137,137,137,137)'::cube);
+SELECT cube_distance('(42,42,42)'::cube,'(137,137)'::cube);
 
 -- Test of cube function (text to cube)
 --
@@ -223,18 +243,32 @@ SELECT cube(NULL);
 SELECT cube_dim('(0)'::cube);
 SELECT cube_dim('(0,0)'::cube);
 SELECT cube_dim('(0,0,0)'::cube);
+SELECT cube_dim('(42,42,42),(42,42,42)'::cube);
+SELECT cube_dim('(4,8,15,16,23),(4,8,15,16,23)'::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);
+SELECT cube_ll_coord('(1,2),(1,2)'::cube, 1);
+SELECT cube_ll_coord('(1,2),(1,2)'::cube, 2);
+SELECT cube_ll_coord('(1,2),(1,2)'::cube, 3);
+SELECT cube_ll_coord('(42,137)'::cube, 1);
+SELECT cube_ll_coord('(42,137)'::cube, 2);
+SELECT cube_ll_coord('(42,137)'::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);
+SELECT cube_ur_coord('(1,2),(1,2)'::cube, 1);
+SELECT cube_ur_coord('(1,2),(1,2)'::cube, 2);
+SELECT cube_ur_coord('(1,2),(1,2)'::cube, 3);
+SELECT cube_ur_coord('(42,137)'::cube, 1);
+SELECT cube_ur_coord('(42,137)'::cube, 2);
+SELECT cube_ur_coord('(42,137)'::cube, 3);
 
 -- Test of cube_is_point
 --
@@ -265,6 +299,31 @@ 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);
+SELECT cube_enlarge('(42,-23,-23),(42,23,23)'::cube, -23, 5);
+SELECT cube_enlarge('(42,-23,-23),(42,23,23)'::cube, -24, 5);
+
+-- Test of cube_union (MBR for two cubes)
+--
+SELECT cube_union('(1,2),(3,4)'::cube, '(5,6,7),(8,9,10)'::cube);
+SELECT cube_union('(1,2)'::cube, '(4,2,0,0)'::cube);
+SELECT cube_union('(1,2),(1,2)'::cube, '(4,2),(4,2)'::cube);
+SELECT cube_union('(1,2),(1,2)'::cube, '(1,2),(1,2)'::cube);
+SELECT cube_union('(1,2),(1,2)'::cube, '(1,2,0),(1,2,0)'::cube);
+
+-- Test of cube_inter
+--
+SELECT cube_inter('(1,2),(10,11)'::cube, '(3,4), (16,15)'::cube); -- intersects
+SELECT cube_inter('(1,2),(10,11)'::cube, '(3,4), (6,5)'::cube); -- includes
+SELECT cube_inter('(1,2),(10,11)'::cube, '(13,14), (16,15)'::cube); -- no intersection
+SELECT cube_inter('(1,2),(10,11)'::cube, '(3,14), (16,15)'::cube); -- no intersection, but one dimension intersects
+SELECT cube_inter('(1,2),(10,11)'::cube, '(10,11), (16,15)'::cube); -- point intersection
+SELECT cube_inter('(1,2,3)'::cube, '(1,2,3)'::cube); -- point args
+SELECT cube_inter('(1,2,3)'::cube, '(5,6,3)'::cube); -- point args
+
+-- Test of cube_size
+--
+SELECT cube_size('(4,8),(15,16)'::cube);
+SELECT cube_size('(42,137)'::cube);
 
 -- Load some example data and build the index
 --
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to