** Auxiliary funxtions
*/
static double distance_1D(double a1, double a2, double b1, double b2);
+static bool cube_is_point_internal(NDBOX *cube);
/*****************************************************************************
int i;
int dim;
int size;
+ bool point;
double *dur,
*dll;
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);
}
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);
}
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,
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);
{
NDBOX *cube = PG_GETARG_NDBOX(0);
StringInfoData buf;
- int dim = cube->dim;
- bool equal = true;
+ int dim = DIM(cube);
int i;
int ndig;
{
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, ')');
}
{
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);
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)
{
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);
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;
}
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;
}
*/
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;
}
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);
}
return (FALSE);
/* swap the box pointers if needed */
- if (a->dim < b->dim)
+ if (DIM(a) < DIM(b))
{
NDBOX *tmp = 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);
}
int i;
/* swap the box pointers if needed */
- if (a->dim < b->dim)
+ if (DIM(a) < DIM(b))
{
NDBOX *tmp = b;
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;
}
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);
+}
- for (i = 0, j = a->dim; i < a->dim; i++, j++)
+static bool
+cube_is_point_internal(NDBOX *cube)
+{
+ int i;
+
+ if (IS_POINT(cube))
+ return true;
+
+ /*
+ * 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 */
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);
}
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;
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;
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])
{
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);
}
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);
}
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);
}
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))
+ {
+ 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
{
- 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] = 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);
}
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);
}
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 : unused, initialize to zero;
+ * bit 31 : point flag. If set, the upper right coordinates are not
+ * stored, and are implicitly the same as the lower left
+ * coordinates.
+ *----------
+ */
+ unsigned int header;
+
+ /*
+ * Variable length array. The lower left coordinates for each dimension
+ * come first, followed by upper right coordinates unless the point flag
+ * is set.
+ */
double x[1];
} NDBOX;
+#define POINT_BIT 0x80000000
+#define DIM_MASK 0x7fffffff
+
+#define IS_POINT(cube) ( ((cube)->header & POINT_BIT) != 0 )
+#define SET_POINT_BIT(cube) ( (cube)->header |= POINT_BIT )
+#define DIM(cube) ( (cube)->header & DIM_MASK )
+#define SET_DIM(cube, _dim) ( (cube)->header = ((cube)->header & ~DIM_MASK) | (_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)
+
#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)
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);
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);
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"
(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.
--
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);
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);
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);
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);
(-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);
(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.
--
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);
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);
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);
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);
(-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);
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.
--
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)
--
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
--
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
--