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