The changes I have made are described in CHANGES. This was based on

diffs to 7.3-devel and may not be applicable to 7.2. I have included a
change covered by a previous bugfix patch I submitted (the problem with
-.1 not being accepted by cube_in). It does not include a fix for the
potential buffer overrun issue I reported for cube_yyerror in
cubeparse.y.


Bruno Wolff III
This commit is contained in:
Bruce Momjian 2002-08-29 23:03:58 +00:00
parent 6d27cfdd89
commit 32784cddf1
8 changed files with 696 additions and 256 deletions

View File

@ -99,7 +99,7 @@ Tokens
n [0-9]+ n [0-9]+
integer [+-]?{n} integer [+-]?{n}
real [+-]?({n}\.{n}?)|(\.{n}) real [+-]?({n}\.{n}?|\.{n})
FLOAT ({integer}|{real})([eE]{integer})? FLOAT ({integer}|{real})([eE]{integer})?
O_BRACKET \[ O_BRACKET \[
C_BRACKET \] C_BRACKET \]
@ -182,8 +182,8 @@ t
PRECISION PRECISION
========= =========
Values are stored internally as 32-bit floating point numbers. This means that Values are stored internally as 64-bit floating point numbers. This means that
numbers with more than 7 significant digits will be truncated. numbers with more than about 16 significant digits will be truncated.
USAGE USAGE
@ -253,6 +253,44 @@ Other operators:
reasonably good sorting in most cases, which is useful if reasonably good sorting in most cases, which is useful if
you want to use ORDER BY with this type 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 There are a few other potentially useful functions defined in cube.c
that vanished from the schema because I stopped using them. Some of 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: these were meant to support type casting. Let me know if I was wrong:
@ -287,3 +325,11 @@ Building 221
Argonne, IL 60439-4844 Argonne, IL 60439-4844
selkovjr@mcs.anl.gov 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.

View File

@ -28,6 +28,7 @@ extern int cube_yyparse();
** Input/Output routines ** Input/Output routines
*/ */
NDBOX *cube_in(char *str); NDBOX *cube_in(char *str);
NDBOX *cube(text *str);
char *cube_out(NDBOX * cube); char *cube_out(NDBOX * cube);
@ -55,8 +56,8 @@ bool cube_contained(NDBOX * a, NDBOX * b);
bool cube_overlap(NDBOX * a, NDBOX * b); bool cube_overlap(NDBOX * a, NDBOX * b);
NDBOX *cube_union(NDBOX * a, NDBOX * b); NDBOX *cube_union(NDBOX * a, NDBOX * b);
NDBOX *cube_inter(NDBOX * a, NDBOX * b); NDBOX *cube_inter(NDBOX * a, NDBOX * b);
float *cube_size(NDBOX * a); double *cube_size(NDBOX * a);
void rt_cube_size(NDBOX * a, float *sz); void rt_cube_size(NDBOX * a, double *sz);
/* /*
** These make no sense for this type, but R-tree wants them ** 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_lt(NDBOX * a, NDBOX * b);
bool cube_gt(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 ** Auxiliary funxtions
*/ */
static float distance_1D(float a1, float a2, float b1, float b2); static double distance_1D(double a1, double a2, double b1, double b2);
static NDBOX *swap_corners(NDBOX * a);
/***************************************************************************** /*****************************************************************************
@ -99,6 +105,15 @@ cube_in(char *str)
return ((NDBOX *) result); 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 * char *
cube_out(NDBOX *cube) cube_out(NDBOX *cube)
{ {
@ -118,7 +133,7 @@ cube_out(NDBOX *cube)
{ {
if (i > 0) if (i > 0)
appendStringInfo(&buf, ", "); appendStringInfo(&buf, ", ");
appendStringInfo(&buf, "%g", cube->x[i]); appendStringInfo(&buf, "%.16g", cube->x[i]);
if (cube->x[i] != cube->x[i + dim]) if (cube->x[i] != cube->x[i + dim])
equal = false; equal = false;
} }
@ -131,7 +146,7 @@ cube_out(NDBOX *cube)
{ {
if (i > 0) if (i > 0)
appendStringInfo(&buf, ", "); appendStringInfo(&buf, ", ");
appendStringInfo(&buf, "%g", cube->x[i + dim]); appendStringInfo(&buf, "%.16g", cube->x[i + dim]);
} }
appendStringInfoChar(&buf, ')'); appendStringInfoChar(&buf, ')');
} }
@ -228,14 +243,14 @@ float *
g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result) g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
{ {
NDBOX *ud; NDBOX *ud;
float tmp1, double tmp1,
tmp2; tmp2;
ud = cube_union((NDBOX *) DatumGetPointer(origentry->key), ud = cube_union((NDBOX *) DatumGetPointer(origentry->key),
(NDBOX *) DatumGetPointer(newentry->key)); (NDBOX *) DatumGetPointer(newentry->key));
rt_cube_size(ud, &tmp1); rt_cube_size(ud, &tmp1);
rt_cube_size((NDBOX *) DatumGetPointer(origentry->key), &tmp2); rt_cube_size((NDBOX *) DatumGetPointer(origentry->key), &tmp2);
*result = tmp1 - tmp2; *result = (float) (tmp1 - tmp2);
pfree(ud); pfree(ud);
/* /*
@ -265,13 +280,13 @@ g_cube_picksplit(bytea *entryvec,
*union_dr; *union_dr;
NDBOX *inter_d; NDBOX *inter_d;
bool firsttime; bool firsttime;
float size_alpha, double size_alpha,
size_beta, size_beta,
size_union, size_union,
size_inter; size_inter;
float size_waste, double size_waste,
waste; waste;
float size_l, double size_l,
size_r; size_r;
int nbytes; int nbytes;
OffsetNumber seed_1 = 0, OffsetNumber seed_1 = 0,
@ -519,22 +534,22 @@ g_cube_binary_union(NDBOX * r1, NDBOX * r2, int *sizep)
/* cube_union */ /* cube_union */
NDBOX * NDBOX *
cube_union(NDBOX * box_a, NDBOX * box_b) cube_union(NDBOX * a, NDBOX * b)
{ {
int i; int i;
NDBOX *result; NDBOX *result;
NDBOX *a = swap_corners(box_a);
NDBOX *b = swap_corners(box_b);
if (a->dim >= b->dim) if (a->dim >= b->dim)
{ {
result = palloc(a->size); result = palloc(a->size);
memset(result, 0, a->size);
result->size = a->size; result->size = a->size;
result->dim = a->dim; result->dim = a->dim;
} }
else else
{ {
result = palloc(b->size); result = palloc(b->size);
memset(result, 0, b->size);
result->size = b->size; result->size = b->size;
result->dim = b->dim; result->dim = b->dim;
} }
@ -554,8 +569,8 @@ cube_union(NDBOX * box_a, NDBOX * box_b)
*/ */
for (i = 0; i < b->dim; i++) for (i = 0; i < b->dim; i++)
{ {
result->x[i] = b->x[i]; result->x[i] = min(b->x[i], b->x[i + b->dim]);
result->x[i + a->dim] = 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++) for (i = b->dim; i < a->dim; i++)
{ {
@ -565,34 +580,34 @@ cube_union(NDBOX * box_a, NDBOX * box_b)
/* compute the union */ /* compute the union */
for (i = 0; i < a->dim; i++) 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] =
result->x[i] = max(a->x[i], 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],
pfree(a); a->x[i + a->dim]), result->x[i + a->dim]);
pfree(b); }
return (result); return (result);
} }
/* cube_inter */ /* cube_inter */
NDBOX * NDBOX *
cube_inter(NDBOX * box_a, NDBOX * box_b) cube_inter(NDBOX * a, NDBOX * b)
{ {
int i; int i;
NDBOX *result; NDBOX *result;
NDBOX *a = swap_corners(box_a);
NDBOX *b = swap_corners(box_b);
if (a->dim >= b->dim) if (a->dim >= b->dim)
{ {
result = palloc(a->size); result = palloc(a->size);
memset(result, 0, a->size);
result->size = a->size; result->size = a->size;
result->dim = a->dim; result->dim = a->dim;
} }
else else
{ {
result = palloc(b->size); result = palloc(b->size);
memset(result, 0, b->size);
result->size = b->size; result->size = b->size;
result->dim = b->dim; result->dim = b->dim;
} }
@ -612,8 +627,8 @@ cube_inter(NDBOX * box_a, NDBOX * box_b)
*/ */
for (i = 0; i < b->dim; i++) for (i = 0; i < b->dim; i++)
{ {
result->x[i] = b->x[i]; result->x[i] = min(b->x[i], b->x[i + b->dim]);
result->x[i + a->dim] = 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++) for (i = b->dim; i < a->dim; i++)
{ {
@ -623,12 +638,12 @@ cube_inter(NDBOX * box_a, NDBOX * box_b)
/* compute the intersection */ /* compute the intersection */
for (i = 0; i < a->dim; i++) 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] =
result->x[i] = min(a->x[i], 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],
pfree(a); a->x[i + a->dim]), result->x[i + a->dim]);
pfree(b); }
/* /*
* Is it OK to return a non-null intersection for non-overlapping * 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 */ /* cube_size */
float * double *
cube_size(NDBOX * a) cube_size(NDBOX * a)
{ {
int i, int i,
j; j;
float *result; double *result;
result = (float *) palloc(sizeof(float)); result = (double *) palloc(sizeof(double));
*result = 1.0; *result = 1.0;
for (i = 0, j = a->dim; i < a->dim; i++, j++) for (i = 0, j = a->dim; i < a->dim; i++, j++)
@ -655,7 +670,7 @@ cube_size(NDBOX * a)
} }
void void
rt_cube_size(NDBOX * a, float *size) rt_cube_size(NDBOX * a, double *size)
{ {
int i, int i,
j; j;
@ -679,114 +694,84 @@ rt_cube_size(NDBOX * a, float *size)
/* is the right edge of (a) located to the left of /* is the right edge of (a) located to the left of
the right edge of (b)? */ the right edge of (b)? */
bool bool
cube_over_left(NDBOX * box_a, NDBOX * box_b) cube_over_left(NDBOX * a, NDBOX * b)
{ {
NDBOX *a; if ((a == NULL) || (b == NULL))
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a); return (min(a->x[a->dim - 1], a->x[2 * a->dim - 1]) <=
b = swap_corners(box_b); min(b->x[b->dim - 1], b->x[2 * b->dim - 1]) &&
!cube_left(a, b) && !cube_right(a, b));
return (a->x[a->dim - 1] <= b->x[b->dim - 1] && !cube_left(a, b) && !cube_right(a, b));
} }
/* is the left edge of (a) located to the right of /* is the left edge of (a) located to the right of
the left edge of (b)? */ the left edge of (b)? */
bool bool
cube_over_right(NDBOX * box_a, NDBOX * box_b) cube_over_right(NDBOX * a, NDBOX * b)
{ {
NDBOX *a; if ((a == NULL) || (b == NULL))
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a); return (min(a->x[a->dim - 1], a->x[2 * a->dim - 1]) >=
b = swap_corners(box_b); min(b->x[b->dim - 1], b->x[2 * b->dim - 1]) &&
!cube_left(a, b) && !cube_right(a, b));
return (a->x[a->dim - 1] >= b->x[b->dim - 1] && !cube_left(a, b) && !cube_right(a, b));
} }
/* return 'true' if the projection of 'a' is /* return 'true' if the projection of 'a' is
entirely on the left of the projection of 'b' */ entirely on the left of the projection of 'b' */
bool bool
cube_left(NDBOX * box_a, NDBOX * box_b) cube_left(NDBOX * a, NDBOX * b)
{ {
NDBOX *a; if ((a == NULL) || (b == NULL))
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a); return (min(a->x[a->dim - 1], a->x[2 * a->dim - 1]) <
b = swap_corners(box_b); min(b->x[0], b->x[b->dim]));
return (a->x[a->dim - 1] < b->x[0]);
} }
/* return 'true' if the projection of 'a' is /* return 'true' if the projection of 'a' is
entirely on the right of the projection of 'b' */ entirely on the right of the projection of 'b' */
bool bool
cube_right(NDBOX * box_a, NDBOX * box_b) cube_right(NDBOX * a, NDBOX * b)
{ {
NDBOX *a; if ((a == NULL) || (b == NULL))
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a); return (min(a->x[0], a->x[a->dim]) >
b = swap_corners(box_b); min(b->x[b->dim - 1], b->x[2 * b->dim - 1]));
return (a->x[0] > b->x[b->dim - 1]);
} }
/* make up a metric in which one box will be 'lower' than the other /* 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 bool
cube_lt(NDBOX * box_a, NDBOX * box_b) cube_lt(NDBOX * a, NDBOX * b)
{ {
int i; int i;
int dim; int dim;
NDBOX *a;
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL)) if ((a == NULL) || (b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a);
b = swap_corners(box_b);
dim = min(a->dim, b->dim); 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 */ /* compare the common dimensions */
for (i = 0; i < dim; i++) 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); 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); return (TRUE);
} }
for (i = 0; i < dim; i++) 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); 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); return (TRUE);
} }
@ -795,35 +780,45 @@ cube_lt(NDBOX * box_a, NDBOX * box_b)
{ {
for (i = dim; i < a->dim; i++) 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); return (FALSE);
if (a->x[i] < 0) if (min(a->x[i], a->x[a->dim + i]) < 0)
return (TRUE); 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); return (FALSE);
if (a->x[i + a->dim] < 0) if (max(a->x[i], a->x[a->dim + i]) < 0)
return (TRUE); return (TRUE);
} }
/*
* if all common dimensions are equal, the cube with more
* dimensions wins
*/
return (FALSE);
} }
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
for (i = dim; i < b->dim; i++) 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); return (TRUE);
if (b->x[i] < 0) if (min(b->x[i], b->x[b->dim + i]) < 0)
return (FALSE); 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); return (TRUE);
if (b->x[i + b->dim] < 0) if (max(b->x[i], b->x[b->dim + i]) < 0)
return (FALSE); return (FALSE);
} }
/*
* if all common dimensions are equal, the cube with more
* dimensions wins
*/
return (TRUE);
} }
return (FALSE); return (FALSE);
@ -831,45 +826,33 @@ cube_lt(NDBOX * box_a, NDBOX * box_b)
bool bool
cube_gt(NDBOX * box_a, NDBOX * box_b) cube_gt(NDBOX * a, NDBOX * b)
{ {
int i; int i;
int dim; int dim;
NDBOX *a;
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL)) if ((a == NULL) || (b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a);
b = swap_corners(box_b);
dim = min(a->dim, b->dim); 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 */ /* compare the common dimensions */
for (i = 0; i < dim; i++) 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); 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); return (TRUE);
} }
for (i = 0; i < dim; i++) 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); 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); return (TRUE);
} }
@ -879,35 +862,45 @@ cube_gt(NDBOX * box_a, NDBOX * box_b)
{ {
for (i = dim; i < a->dim; i++) 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); return (FALSE);
if (a->x[i] > 0) if (min(a->x[i], a->x[a->dim + i]) > 0)
return (TRUE); 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); return (FALSE);
if (a->x[i + a->dim] > 0) if (max(a->x[i], a->x[a->dim + i]) > 0)
return (TRUE); return (TRUE);
} }
/*
* if all common dimensions are equal, the cube with more
* dimensions wins
*/
return (TRUE);
} }
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
for (i = dim; i < b->dim; i++) 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); return (TRUE);
if (b->x[i] > 0) if (min(b->x[i], b->x[b->dim + i]) > 0)
return (FALSE); 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); return (TRUE);
if (b->x[i + b->dim] > 0) if (max(b->x[i], b->x[b->dim + i]) > 0)
return (FALSE); return (FALSE);
} }
/*
* if all common dimensions are equal, the cube with more
* dimensions wins
*/
return (FALSE);
} }
return (FALSE); return (FALSE);
@ -916,18 +909,13 @@ cube_gt(NDBOX * box_a, NDBOX * box_b)
/* Equal */ /* Equal */
bool bool
cube_same(NDBOX * box_a, NDBOX * box_b) cube_same(NDBOX * a, NDBOX * b)
{ {
int i; int i;
NDBOX *a;
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL)) if ((a == NULL) || (b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a);
b = swap_corners(box_b);
/* swap the box pointers if necessary */ /* swap the box pointers if necessary */
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
@ -939,15 +927,19 @@ cube_same(NDBOX * box_a, NDBOX * box_b)
for (i = 0; i < b->dim; i++) 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); 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); return (FALSE);
} }
/* /*
* all dimensions of (b) are compared to those of (a); instead of * all dimensions of (b) are compared to those of (a); instead of
* those in (a) absent in (b), compare (a) to zero * 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++) for (i = b->dim; i < a->dim; i++)
{ {
@ -957,40 +949,34 @@ cube_same(NDBOX * box_a, NDBOX * box_b)
return (FALSE); return (FALSE);
} }
pfree(a);
pfree(b);
return (TRUE); return (TRUE);
} }
/* Different */ /* Different */
bool 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 */ /* Contains */
/* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */ /* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
bool bool
cube_contains(NDBOX * box_a, NDBOX * box_b) cube_contains(NDBOX * a, NDBOX * b)
{ {
int i; int i;
NDBOX *a;
NDBOX *b;
if ((box_a == NULL) || (box_b == NULL)) if ((a == NULL) || (b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a);
b = swap_corners(box_b);
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
/* /*
* the further comparisons will make sense if the excess * the further comparisons will make sense if the excess
* dimensions of (b) were zeroes * 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 = 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 */ /* 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(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); 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); return (FALSE);
} }
pfree(a);
pfree(b);
return (TRUE); return (TRUE);
} }
@ -1030,22 +1015,17 @@ cube_contained(NDBOX * a, NDBOX * b)
/* Overlap */ /* Overlap */
/* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */ /* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
bool bool
cube_overlap(NDBOX * box_a, NDBOX * box_b) cube_overlap(NDBOX * a, NDBOX * b)
{ {
int i; int i;
NDBOX *a;
NDBOX *b;
/* /*
* This *very bad* error was found in the source: if ( (a==NULL) || * This *very bad* error was found in the source: if ( (a==NULL) ||
* (b=NULL) ) return(FALSE); * (b=NULL) ) return(FALSE);
*/ */
if ((box_a == NULL) || (box_b == NULL)) if ((a == NULL) || (b == NULL))
return (FALSE); return (FALSE);
a = swap_corners(box_a);
b = swap_corners(box_b);
/* swap the box pointers if needed */ /* swap the box pointers if needed */
if (a->dim < b->dim) if (a->dim < b->dim)
{ {
@ -1058,24 +1038,23 @@ cube_overlap(NDBOX * box_a, NDBOX * box_b)
/* compare within the dimensions of (b) */ /* compare within the dimensions of (b) */
for (i = 0; i < b->dim; i++) 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); 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); return (FALSE);
} }
/* compare to zero those dimensions in (a) absent in (b) */ /* compare to zero those dimensions in (a) absent in (b) */
for (i = b->dim; i < a->dim; i++) 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); return (FALSE);
if (a->x[i + a->dim] < 0) if (max(a->x[i], a->x[a->dim + i]) < 0)
return (FALSE); return (FALSE);
} }
pfree(a);
pfree(b);
return (TRUE); 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 between 1D projections of the boxes onto Cartesian axes. Assuming zero
distance between overlapping projections, this metric coincides with the distance between overlapping projections, this metric coincides with the
"common sense" geometric distance */ "common sense" geometric distance */
float * double *
cube_distance(NDBOX * a, NDBOX * b) cube_distance(NDBOX * a, NDBOX * b)
{ {
int i; int i;
double d, double d,
distance; distance;
float *result; double *result;
result = (float *) palloc(sizeof(float)); result = (double *) palloc(sizeof(double));
/* swap the box pointers if needed */ /* swap the box pointers if needed */
if (a->dim < b->dim) if (a->dim < b->dim)
@ -1119,13 +1098,13 @@ cube_distance(NDBOX * a, NDBOX * b)
distance += d * d; distance += d * d;
} }
*result = (float) sqrt(distance); *result = (double) sqrt(distance);
return (result); return (result);
} }
static float static double
distance_1D(float a1, float a2, float b1, float b2) distance_1D(double a1, double a2, double b1, double b2)
{ {
/* interval (a) is entirely on the left of (b) */ /* interval (a) is entirely on the left of (b) */
if ((a1 <= b1) && (a2 <= b1) && (a1 <= b2) && (a2 <= b2)) 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); return (0.0);
} }
/* normalize the box's co-ordinates by placing min(xLL,xUR) to LL /* Test if a box is also a point */
and max(xLL,xUR) to UR bool
*/ cube_is_point(NDBOX * a)
static NDBOX *
swap_corners(NDBOX * a)
{ {
int i, int i,
j; j;
NDBOX *result;
result = palloc(a->size);
result->size = a->size;
result->dim = a->dim;
for (i = 0, j = a->dim; i < a->dim; i++, j++) for (i = 0, j = a->dim; i < a->dim; i++, j++)
{ {
result->x[i] = min(a->x[i], a->x[j]); if (a->x[i] != a->x[j]) return FALSE;
result->x[j] = max(a->x[i], a->x[j]); }
}
return (result); return TRUE;
}
/* 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 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;
} }

View File

@ -8,12 +8,12 @@ SET search_path = public;
CREATE FUNCTION cube_in(cstring) CREATE FUNCTION cube_in(cstring)
RETURNS cube RETURNS cube
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'c' WITH (isStrict); LANGUAGE 'c'IMMUTABLE STRICT;
CREATE FUNCTION cube_out(cube) CREATE FUNCTION cube_out(cube)
RETURNS cstring RETURNS cstring
AS 'MODULE_PATHNAME' AS 'MODULE_PATHNAME'
LANGUAGE 'c' WITH (isStrict); LANGUAGE 'c'IMMUTABLE STRICT;
CREATE TYPE cube ( CREATE TYPE cube (
internallength = variable, internallength = variable,
@ -24,6 +24,16 @@ output = cube_out
COMMENT ON TYPE cube IS COMMENT ON TYPE cube IS
'multi-dimensional cube ''(FLOAT-1, FLOAT-2, ..., FLOAT-N), (FLOAT-1, FLOAT-2, ..., FLOAT-N)'''; '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 -- External C-functions for R-tree methods
-- --
@ -31,25 +41,25 @@ COMMENT ON TYPE cube IS
-- Left/Right methods -- Left/Right methods
CREATE FUNCTION cube_over_left(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_over_left(cube, cube) IS
'is over and left of (NOT IMPLEMENTED)'; 'is over and left of (NOT IMPLEMENTED)';
CREATE FUNCTION cube_over_right(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_over_right(cube, cube) IS
'is over and right of (NOT IMPLEMENTED)'; 'is over and right of (NOT IMPLEMENTED)';
CREATE FUNCTION cube_left(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_left(cube, cube) IS
'is left of (NOT IMPLEMENTED)'; 'is left of (NOT IMPLEMENTED)';
CREATE FUNCTION cube_right(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_right(cube, cube) IS
'is right of (NOT IMPLEMENTED)'; 'is right of (NOT IMPLEMENTED)';
@ -58,43 +68,43 @@ COMMENT ON FUNCTION cube_right(cube, cube) IS
-- Comparison methods -- Comparison methods
CREATE FUNCTION cube_lt(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_lt(cube, cube) IS
'lower than'; 'lower than';
CREATE FUNCTION cube_gt(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_gt(cube, cube) IS
'greater than'; 'greater than';
CREATE FUNCTION cube_contains(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_contains(cube, cube) IS
'contains'; 'contains';
CREATE FUNCTION cube_contained(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_contained(cube, cube) IS
'contained in'; 'contained in';
CREATE FUNCTION cube_overlap(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_overlap(cube, cube) IS
'overlaps'; 'overlaps';
CREATE FUNCTION cube_same(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_same(cube, cube) IS
'same as'; 'same as';
CREATE FUNCTION cube_different(cube, cube) RETURNS bool 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 COMMENT ON FUNCTION cube_different(cube, cube) IS
'different'; 'different';
@ -102,22 +112,42 @@ COMMENT ON FUNCTION cube_different(cube, cube) IS
-- support routines for indexing -- support routines for indexing
CREATE FUNCTION cube_union(cube, cube) RETURNS cube 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 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 CREATE FUNCTION cube_size(cube) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict); AS 'MODULE_PATHNAME' LANGUAGE 'c' IMMUTABLE STRICT;
-- Misc N-dimensional functions -- Misc N-dimensional functions
-- proximity routines -- proximity routines
CREATE FUNCTION cube_distance(cube, cube) RETURNS float4 CREATE FUNCTION cube_distance(cube, cube) RETURNS float8
AS 'MODULE_PATHNAME' LANGUAGE 'c' with (isstrict); 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 -- OPERATORS
@ -202,7 +232,7 @@ CREATE FUNCTION g_cube_decompress(internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c'; AS 'MODULE_PATHNAME' LANGUAGE 'c';
CREATE FUNCTION g_cube_penalty(internal,internal,internal) RETURNS internal 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 CREATE FUNCTION g_cube_picksplit(internal, internal) RETURNS internal
AS 'MODULE_PATHNAME' LANGUAGE 'c'; AS 'MODULE_PATHNAME' LANGUAGE 'c';

View File

@ -2,5 +2,5 @@ typedef struct NDBOX
{ {
unsigned int size; /* required to be a Postgres varlena type */ unsigned int size; /* required to be a Postgres varlena type */
unsigned int dim; unsigned int dim;
float x[1]; double x[1];
} NDBOX; } NDBOX;

View File

@ -198,9 +198,10 @@ write_box(unsigned int dim, char *str1, char *str2)
NDBOX * bp; NDBOX * bp;
char * s; char * s;
int i; 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); bp = palloc(size);
memset(bp, 0, size);
bp->size = size; bp->size = size;
bp->dim = dim; bp->dim = dim;
@ -217,7 +218,7 @@ write_box(unsigned int dim, char *str1, char *str2)
s++; i++; s++; i++;
bp->x[i] = strtod(s, NULL); bp->x[i] = strtod(s, NULL);
} }
return(bp); return(bp);
} }
@ -230,9 +231,10 @@ static NDBOX * write_point_as_box(char *str)
int dim = delim_count(str, ',') + 1; int dim = delim_count(str, ',') + 1;
char * s = str; char * s = str;
size = offsetof(NDBOX, x[0]) + sizeof(float) * dim * 2; size = offsetof(NDBOX, x[0]) + sizeof(double) * dim * 2;
bp = palloc(size); bp = palloc(size);
memset(bp, 0, size);
bp->size = size; bp->size = size;
bp->dim = dim; bp->dim = dim;

View File

@ -34,7 +34,7 @@ void cube_flush_scanner_buffer(void);
n [0-9]+ n [0-9]+
integer [+-]?{n} integer [+-]?{n}
real [+-]?({n}\.{n}?)|(\.{n}) real [+-]?({n}\.{n}?|\.{n})
float ({integer}|{real})([eE]{integer})? float ({integer}|{real})([eE]{integer})?
%% %%

View File

@ -43,7 +43,10 @@ SELECT '.1'::cube AS cube;
(1 row) (1 row)
SELECT '-.1'::cube AS cube; 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; SELECT '1.0'::cube AS cube;
cube cube
@ -57,52 +60,52 @@ SELECT '-1.0'::cube AS cube;
(-1) (-1)
(1 row) (1 row)
SELECT '1e7'::cube AS cube; SELECT '1e27'::cube AS cube;
cube cube
--------- ---------
(1e+07) (1e+27)
(1 row) (1 row)
SELECT '-1e7'::cube AS cube; SELECT '-1e27'::cube AS cube;
cube cube
---------- ----------
(-1e+07) (-1e+27)
(1 row) (1 row)
SELECT '1.0e7'::cube AS cube; SELECT '1.0e27'::cube AS cube;
cube cube
--------- ---------
(1e+07) (1e+27)
(1 row) (1 row)
SELECT '-1.0e7'::cube AS cube; SELECT '-1.0e27'::cube AS cube;
cube cube
---------- ----------
(-1e+07) (-1e+27)
(1 row) (1 row)
SELECT '1e+7'::cube AS cube; SELECT '1e+27'::cube AS cube;
cube cube
--------- ---------
(1e+07) (1e+27)
(1 row) (1 row)
SELECT '-1e+7'::cube AS cube; SELECT '-1e+27'::cube AS cube;
cube cube
---------- ----------
(-1e+07) (-1e+27)
(1 row) (1 row)
SELECT '1.0e+7'::cube AS cube; SELECT '1.0e+27'::cube AS cube;
cube cube
--------- ---------
(1e+07) (1e+27)
(1 row) (1 row)
SELECT '-1.0e+7'::cube AS cube; SELECT '-1.0e+27'::cube AS cube;
cube cube
---------- ----------
(-1e+07) (-1e+27)
(1 row) (1 row)
SELECT '1e-7'::cube AS cube; SELECT '1e-7'::cube AS cube;
@ -141,6 +144,42 @@ SELECT '-1e-700'::cube AS cube;
(0) (0)
(1 row) (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) -- simple lists (points)
SELECT '1,2'::cube AS cube; SELECT '1,2'::cube AS cube;
cube cube
@ -924,6 +963,224 @@ SELECT '(-1,-1),(1,1)'::cube @ '(-2),(1)'::cube AS bool;
f f
(1 row) (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 -- Load some example data and build the index
-- --
CREATE TABLE test_cube (c cube); CREATE TABLE test_cube (c cube);

View File

@ -23,20 +23,26 @@ SELECT '.1'::cube AS cube;
SELECT '-.1'::cube AS cube; SELECT '-.1'::cube AS cube;
SELECT '1.0'::cube AS cube; SELECT '1.0'::cube AS cube;
SELECT '-1.0'::cube AS cube; SELECT '-1.0'::cube AS cube;
SELECT '1e7'::cube AS cube; SELECT '1e27'::cube AS cube;
SELECT '-1e7'::cube AS cube; SELECT '-1e27'::cube AS cube;
SELECT '1.0e7'::cube AS cube; SELECT '1.0e27'::cube AS cube;
SELECT '-1.0e7'::cube AS cube; SELECT '-1.0e27'::cube AS cube;
SELECT '1e+7'::cube AS cube; SELECT '1e+27'::cube AS cube;
SELECT '-1e+7'::cube AS cube; SELECT '-1e+27'::cube AS cube;
SELECT '1.0e+7'::cube AS cube; SELECT '1.0e+27'::cube AS cube;
SELECT '-1.0e+7'::cube AS cube; SELECT '-1.0e+27'::cube AS cube;
SELECT '1e-7'::cube AS cube; SELECT '1e-7'::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 '-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 '-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) -- simple lists (points)
SELECT '1,2'::cube AS cube; 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)'::cube @ '(-2),(1)'::cube AS bool;
SELECT '(-1,-1),(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 -- Load some example data and build the index
-- --