diff options
Diffstat (limited to 'contrib/cube/cube.c')
-rw-r--r-- | contrib/cube/cube.c | 538 |
1 files changed, 297 insertions, 241 deletions
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c index 37cbfdd20b..b0305ef431 100644 --- a/contrib/cube/cube.c +++ b/contrib/cube/cube.c @@ -35,7 +35,6 @@ extern void cube_scanner_finish(void); ** Input/Output routines */ PG_FUNCTION_INFO_V1(cube_in); -PG_FUNCTION_INFO_V1(cube); PG_FUNCTION_INFO_V1(cube_a_f8_f8); PG_FUNCTION_INFO_V1(cube_a_f8); PG_FUNCTION_INFO_V1(cube_out); @@ -48,20 +47,6 @@ PG_FUNCTION_INFO_V1(cube_ll_coord); PG_FUNCTION_INFO_V1(cube_ur_coord); PG_FUNCTION_INFO_V1(cube_subset); -Datum cube_in(PG_FUNCTION_ARGS); -Datum cube(PG_FUNCTION_ARGS); -Datum cube_a_f8_f8(PG_FUNCTION_ARGS); -Datum cube_a_f8(PG_FUNCTION_ARGS); -Datum cube_out(PG_FUNCTION_ARGS); -Datum cube_f8(PG_FUNCTION_ARGS); -Datum cube_f8_f8(PG_FUNCTION_ARGS); -Datum cube_c_f8(PG_FUNCTION_ARGS); -Datum cube_c_f8_f8(PG_FUNCTION_ARGS); -Datum cube_dim(PG_FUNCTION_ARGS); -Datum cube_ll_coord(PG_FUNCTION_ARGS); -Datum cube_ur_coord(PG_FUNCTION_ARGS); -Datum cube_subset(PG_FUNCTION_ARGS); - /* ** GiST support methods */ @@ -74,14 +59,6 @@ PG_FUNCTION_INFO_V1(g_cube_picksplit); PG_FUNCTION_INFO_V1(g_cube_union); PG_FUNCTION_INFO_V1(g_cube_same); -Datum g_cube_consistent(PG_FUNCTION_ARGS); -Datum g_cube_compress(PG_FUNCTION_ARGS); -Datum g_cube_decompress(PG_FUNCTION_ARGS); -Datum g_cube_penalty(PG_FUNCTION_ARGS); -Datum g_cube_picksplit(PG_FUNCTION_ARGS); -Datum g_cube_union(PG_FUNCTION_ARGS); -Datum g_cube_same(PG_FUNCTION_ARGS); - /* ** B-tree support functions */ @@ -93,14 +70,6 @@ PG_FUNCTION_INFO_V1(cube_le); PG_FUNCTION_INFO_V1(cube_ge); PG_FUNCTION_INFO_V1(cube_cmp); -Datum cube_eq(PG_FUNCTION_ARGS); -Datum cube_ne(PG_FUNCTION_ARGS); -Datum cube_lt(PG_FUNCTION_ARGS); -Datum cube_gt(PG_FUNCTION_ARGS); -Datum cube_le(PG_FUNCTION_ARGS); -Datum cube_ge(PG_FUNCTION_ARGS); -Datum cube_cmp(PG_FUNCTION_ARGS); - /* ** R-tree support functions */ @@ -112,13 +81,6 @@ PG_FUNCTION_INFO_V1(cube_union); PG_FUNCTION_INFO_V1(cube_inter); PG_FUNCTION_INFO_V1(cube_size); -Datum cube_contains(PG_FUNCTION_ARGS); -Datum cube_contained(PG_FUNCTION_ARGS); -Datum cube_overlap(PG_FUNCTION_ARGS); -Datum cube_union(PG_FUNCTION_ARGS); -Datum cube_inter(PG_FUNCTION_ARGS); -Datum cube_size(PG_FUNCTION_ARGS); - /* ** miscellaneous */ @@ -126,10 +88,6 @@ PG_FUNCTION_INFO_V1(cube_distance); PG_FUNCTION_INFO_V1(cube_is_point); PG_FUNCTION_INFO_V1(cube_enlarge); -Datum cube_distance(PG_FUNCTION_ARGS); -Datum cube_is_point(PG_FUNCTION_ARGS); -Datum cube_enlarge(PG_FUNCTION_ARGS); - /* ** For internal use only */ @@ -146,6 +104,7 @@ bool g_cube_internal_consistent(NDBOX *key, NDBOX *query, StrategyNumber strate ** Auxiliary funxtions */ static double distance_1D(double a1, double a2, double b1, double b2); +static bool cube_is_point_internal(NDBOX *cube); /***************************************************************************** @@ -183,6 +142,7 @@ cube_a_f8_f8(PG_FUNCTION_ARGS) int i; int dim; int size; + bool point; double *dur, *dll; @@ -200,16 +160,32 @@ cube_a_f8_f8(PG_FUNCTION_ARGS) dur = ARRPTR(ur); dll = ARRPTR(ll); - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim; + /* Check if it's a point */ + point = true; + for (i = 0; i < dim; i++) + { + if (dur[i] != dll[i]) + { + point = false; + break; + } + } + + size = point ? POINT_SIZE(dim) : CUBE_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = dim; + SET_DIM(result, dim); for (i = 0; i < dim; i++) - { result->x[i] = dur[i]; - result->x[i + dim] = dll[i]; + + if (!point) + { + for (i = 0; i < dim; i++) + result->x[i + dim] = dll[i]; } + else + SET_POINT_BIT(result); PG_RETURN_NDBOX(result); } @@ -236,16 +212,14 @@ cube_a_f8(PG_FUNCTION_ARGS) dur = ARRPTR(ur); - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim; + size = POINT_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = dim; + SET_DIM(result, dim); + SET_POINT_BIT(result); for (i = 0; i < dim; i++) - { result->x[i] = dur[i]; - result->x[i + dim] = dur[i]; - } PG_RETURN_NDBOX(result); } @@ -266,17 +240,20 @@ cube_subset(PG_FUNCTION_ARGS) (errcode(ERRCODE_ARRAY_ELEMENT_ERROR), errmsg("cannot work with arrays containing NULLs"))); - dx = (int4 *) ARR_DATA_PTR(idx); + 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, @@ -284,7 +261,8 @@ cube_subset(PG_FUNCTION_ARGS) errmsg("Index out of bounds"))); } result->x[i] = c->x[dx[i] - 1]; - result->x[i + dim] = c->x[dx[i] + c->dim - 1]; + if (!IS_POINT(c)) + result->x[i + dim] = c->x[dx[i] + DIM(c) - 1]; } PG_FREE_IF_COPY(c, 0); @@ -296,8 +274,7 @@ cube_out(PG_FUNCTION_ARGS) { NDBOX *cube = PG_GETARG_NDBOX(0); StringInfoData buf; - int dim = cube->dim; - bool equal = true; + int dim = DIM(cube); int i; int ndig; @@ -318,21 +295,19 @@ cube_out(PG_FUNCTION_ARGS) for (i = 0; i < dim; i++) { if (i > 0) - appendStringInfo(&buf, ", "); - appendStringInfo(&buf, "%.*g", ndig, cube->x[i]); - if (cube->x[i] != cube->x[i + dim]) - equal = false; + appendStringInfoString(&buf, ", "); + appendStringInfo(&buf, "%.*g", ndig, LL_COORD(cube, i)); } appendStringInfoChar(&buf, ')'); - if (!equal) + if (!cube_is_point_internal(cube)) { - appendStringInfo(&buf, ",("); + appendStringInfoString(&buf, ",("); for (i = 0; i < dim; i++) { if (i > 0) - appendStringInfo(&buf, ", "); - appendStringInfo(&buf, "%.*g", ndig, cube->x[i + dim]); + appendStringInfoString(&buf, ", "); + appendStringInfo(&buf, "%.*g", ndig, UR_COORD(cube, i)); } appendStringInfoChar(&buf, ')'); } @@ -563,7 +538,7 @@ g_cube_picksplit(PG_FUNCTION_ARGS) rt_cube_size(datum_r, &size_r); /* - * Now split up the regions between the two seeds. An important property + * Now split up the regions between the two seeds. An important property * of this split algorithm is that the split vector v has the indices of * items to be split in order in its left and right vectors. We exploit * this property by doing a merge in the code that actually splits the @@ -579,7 +554,7 @@ g_cube_picksplit(PG_FUNCTION_ARGS) { /* * If we've already decided where to place this item, just put it on - * the right list. Otherwise, we need to figure out which page needs + * the right list. Otherwise, we need to figure out which page needs * the least enlargement in order to store the item. */ @@ -731,51 +706,60 @@ cube_union_v0(NDBOX *a, NDBOX *b) { int i; NDBOX *result; + int dim; + int size; - if (a->dim >= b->dim) - { - result = palloc0(VARSIZE(a)); - SET_VARSIZE(result, VARSIZE(a)); - result->dim = a->dim; - } - else - { - result = palloc0(VARSIZE(b)); - SET_VARSIZE(result, VARSIZE(b)); - result->dim = b->dim; - } + /* trivial case */ + if (a == b) + return a; - /* swap the box pointers if needed */ - if (a->dim < b->dim) + /* swap the arguments if needed, so that 'a' is always larger than 'b' */ + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; b = a; a = tmp; } + dim = DIM(a); - /* - * use the potentially smaller of the two boxes (b) to fill in the result, - * padding absent dimensions with zeroes - */ - for (i = 0; i < b->dim; i++) + size = CUBE_SIZE(dim); + result = palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, dim); + + /* First compute the union of the dimensions present in both args */ + for (i = 0; i < DIM(b); i++) { - result->x[i] = Min(b->x[i], b->x[i + b->dim]); - result->x[i + a->dim] = Max(b->x[i], b->x[i + b->dim]); + result->x[i] = Min( + Min(LL_COORD(a, i), UR_COORD(a, i)), + Min(LL_COORD(b, i), UR_COORD(b, i)) + ); + result->x[i + DIM(a)] = Max( + Max(LL_COORD(a, i), UR_COORD(a, i)), + Max(LL_COORD(b, i), UR_COORD(b, i)) + ); } - for (i = b->dim; i < a->dim; i++) + /* continue on the higher dimensions only present in 'a' */ + for (; i < DIM(a); i++) { - result->x[i] = 0; - result->x[i + a->dim] = 0; + result->x[i] = Min(0, + Min(LL_COORD(a, i), UR_COORD(a, i)) + ); + result->x[i + dim] = Max(0, + Max(LL_COORD(a, i), UR_COORD(a, i)) + ); } - /* compute the union */ - for (i = 0; i < a->dim; i++) + /* + * Check if the result was in fact a point, and set the flag in the datum + * accordingly. (we don't bother to repalloc it smaller) + */ + if (cube_is_point_internal(result)) { - result->x[i] = - Min(Min(a->x[i], a->x[i + a->dim]), result->x[i]); - result->x[i + a->dim] = Max(Max(a->x[i], - a->x[i + a->dim]), result->x[i + a->dim]); + size = POINT_SIZE(dim); + SET_VARSIZE(result, size); + SET_POINT_BIT(result); } return (result); @@ -804,22 +788,11 @@ cube_inter(PG_FUNCTION_ARGS) NDBOX *result; bool swapped = false; int i; + int dim; + int size; - if (a->dim >= b->dim) - { - result = palloc0(VARSIZE(a)); - SET_VARSIZE(result, VARSIZE(a)); - result->dim = a->dim; - } - else - { - result = palloc0(VARSIZE(b)); - SET_VARSIZE(result, VARSIZE(b)); - result->dim = b->dim; - } - - /* swap the box pointers if needed */ - if (a->dim < b->dim) + /* swap the arguments if needed, so that 'a' is always larger than 'b' */ + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; @@ -827,29 +800,46 @@ cube_inter(PG_FUNCTION_ARGS) 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) @@ -875,12 +865,11 @@ cube_size(PG_FUNCTION_ARGS) { NDBOX *a = PG_GETARG_NDBOX(0); double result; - int i, - j; + int i; result = 1.0; - for (i = 0, j = a->dim; i < a->dim; i++, j++) - result = result * Abs((a->x[j] - a->x[i])); + for (i = 0; i < DIM(a); i++) + result = result * Abs((LL_COORD(a, i) - UR_COORD(a, i))); PG_FREE_IF_COPY(a, 0); PG_RETURN_FLOAT8(result); @@ -889,16 +878,15 @@ cube_size(PG_FUNCTION_ARGS) void rt_cube_size(NDBOX *a, double *size) { - int i, - j; + int i; if (a == (NDBOX *) NULL) *size = 0.0; else { *size = 1.0; - for (i = 0, j = a->dim; i < a->dim; i++, j++) - *size = (*size) * Abs((a->x[j] - a->x[i])); + for (i = 0; i < DIM(a); i++) + *size = (*size) * Abs(UR_COORD(a, i) - LL_COORD(a, i)); } return; } @@ -911,43 +899,43 @@ cube_cmp_v0(NDBOX *a, NDBOX *b) int i; int dim; - dim = Min(a->dim, b->dim); + dim = Min(DIM(a), DIM(b)); /* compare the common dimensions */ for (i = 0; i < dim; i++) { - if (Min(a->x[i], a->x[a->dim + i]) > - Min(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > + Min(LL_COORD(b, i), UR_COORD(b, i))) return 1; - if (Min(a->x[i], a->x[a->dim + i]) < - Min(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) < + Min(LL_COORD(b, i), UR_COORD(b, i))) return -1; } for (i = 0; i < dim; i++) { - if (Max(a->x[i], a->x[a->dim + i]) > - Max(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) > + Max(LL_COORD(b, i), UR_COORD(b, i))) return 1; - if (Max(a->x[i], a->x[a->dim + i]) < - Max(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < + Max(LL_COORD(b, i), UR_COORD(b, i))) return -1; } /* compare extra dimensions to zero */ - if (a->dim > b->dim) + if (DIM(a) > DIM(b)) { - for (i = dim; i < a->dim; i++) + for (i = dim; i < DIM(a); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > 0) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0) return 1; - if (Min(a->x[i], a->x[a->dim + i]) < 0) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) < 0) return -1; } - for (i = dim; i < a->dim; i++) + for (i = dim; i < DIM(a); i++) { - if (Max(a->x[i], a->x[a->dim + i]) > 0) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) > 0) return 1; - if (Max(a->x[i], a->x[a->dim + i]) < 0) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0) return -1; } @@ -957,20 +945,20 @@ cube_cmp_v0(NDBOX *a, NDBOX *b) */ return 1; } - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { - for (i = dim; i < b->dim; i++) + for (i = dim; i < DIM(b); i++) { - if (Min(b->x[i], b->x[b->dim + i]) > 0) + if (Min(LL_COORD(b, i), UR_COORD(b, i)) > 0) return -1; - if (Min(b->x[i], b->x[b->dim + i]) < 0) + if (Min(LL_COORD(b, i), UR_COORD(b, i)) < 0) return 1; } - for (i = dim; i < b->dim; i++) + for (i = dim; i < DIM(b); i++) { - if (Max(b->x[i], b->x[b->dim + i]) > 0) + if (Max(LL_COORD(b, i), UR_COORD(b, i)) > 0) return -1; - if (Max(b->x[i], b->x[b->dim + i]) < 0) + if (Max(LL_COORD(b, i), UR_COORD(b, i)) < 0) return 1; } @@ -1100,30 +1088,30 @@ cube_contains_v0(NDBOX *a, NDBOX *b) if ((a == NULL) || (b == NULL)) return (FALSE); - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { /* * the further comparisons will make sense if the excess dimensions of * (b) were zeroes Since both UL and UR coordinates must be zero, we * can check them all without worrying about which is which. */ - for (i = a->dim; i < b->dim; i++) + for (i = DIM(a); i < DIM(b); i++) { - if (b->x[i] != 0) + if (LL_COORD(b, i) != 0) return (FALSE); - if (b->x[i + b->dim] != 0) + if (UR_COORD(b, i) != 0) return (FALSE); } } /* Can't care less about the excess dimensions of (a), if any */ - for (i = 0; i < Min(a->dim, b->dim); i++) + for (i = 0; i < Min(DIM(a), DIM(b)); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > - Min(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > + Min(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); - if (Max(a->x[i], a->x[a->dim + i]) < - Max(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < + Max(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); } @@ -1175,7 +1163,7 @@ cube_overlap_v0(NDBOX *a, NDBOX *b) return (FALSE); /* swap the box pointers if needed */ - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; @@ -1184,22 +1172,20 @@ cube_overlap_v0(NDBOX *a, NDBOX *b) } /* compare within the dimensions of (b) */ - for (i = 0; i < b->dim; i++) + for (i = 0; i < DIM(b); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > - Max(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > Max(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); - if (Max(a->x[i], a->x[a->dim + i]) < - Min(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < Min(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); } /* compare to zero those dimensions in (a) absent in (b) */ - for (i = b->dim; i < a->dim; i++) + for (i = DIM(b); i < DIM(a); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > 0) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0) return (FALSE); - if (Max(a->x[i], a->x[a->dim + i]) < 0) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0) return (FALSE); } @@ -1238,7 +1224,7 @@ cube_distance(PG_FUNCTION_ARGS) int i; /* swap the box pointers if needed */ - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; @@ -1249,16 +1235,16 @@ cube_distance(PG_FUNCTION_ARGS) distance = 0.0; /* compute within the dimensions of (b) */ - for (i = 0; i < b->dim; i++) + for (i = 0; i < DIM(b); i++) { - d = distance_1D(a->x[i], a->x[i + a->dim], b->x[i], b->x[i + b->dim]); + d = distance_1D(LL_COORD(a, i), UR_COORD(a, i), LL_COORD(b, i), UR_COORD(b, i)); distance += d * d; } /* compute distance to zero for those dimensions in (a) absent in (b) */ - for (i = b->dim; i < a->dim; i++) + for (i = DIM(b); i < DIM(a); i++) { - d = distance_1D(a->x[i], a->x[i + a->dim], 0.0, 0.0); + d = distance_1D(LL_COORD(a, i), UR_COORD(a, i), 0.0, 0.0); distance += d * d; } @@ -1295,18 +1281,35 @@ distance_1D(double a1, double a2, double b1, double b2) Datum cube_is_point(PG_FUNCTION_ARGS) { - NDBOX *a = PG_GETARG_NDBOX(0); - int i, - j; + NDBOX *cube = PG_GETARG_NDBOX(0); + bool result; + + result = cube_is_point_internal(cube); + PG_FREE_IF_COPY(cube, 0); + PG_RETURN_BOOL(result); +} - 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 */ @@ -1314,7 +1317,7 @@ Datum cube_dim(PG_FUNCTION_ARGS) { NDBOX *c = PG_GETARG_NDBOX(0); - int dim = c->dim; + int dim = DIM(c); PG_FREE_IF_COPY(c, 0); PG_RETURN_INT32(dim); @@ -1328,8 +1331,8 @@ cube_ll_coord(PG_FUNCTION_ARGS) int n = PG_GETARG_INT16(1); double result; - if (c->dim >= n && n > 0) - result = Min(c->x[n - 1], c->x[c->dim + n - 1]); + if (DIM(c) >= n && n > 0) + result = Min(LL_COORD(c, n - 1), UR_COORD(c, n - 1)); else result = 0; @@ -1345,8 +1348,8 @@ cube_ur_coord(PG_FUNCTION_ARGS) int n = PG_GETARG_INT16(1); double result; - if (c->dim >= n && n > 0) - result = Max(c->x[n - 1], c->x[c->dim + n - 1]); + if (DIM(c) >= n && n > 0) + result = Max(LL_COORD(c, n - 1), UR_COORD(c, n - 1)); else result = 0; @@ -1360,35 +1363,36 @@ cube_enlarge(PG_FUNCTION_ARGS) { NDBOX *a = PG_GETARG_NDBOX(0); double r = PG_GETARG_FLOAT8(1); - int4 n = PG_GETARG_INT32(2); + int32 n = PG_GETARG_INT32(2); NDBOX *result; 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]) { @@ -1403,6 +1407,17 @@ cube_enlarge(PG_FUNCTION_ARGS) result->x[j] = r; } + /* + * Check if the result was in fact a point, and set the flag in the datum + * accordingly. (we don't bother to repalloc it smaller) + */ + if (cube_is_point_internal(result)) + { + size = POINT_SIZE(dim); + SET_VARSIZE(result, size); + SET_POINT_BIT(result); + } + PG_FREE_IF_COPY(a, 0); PG_RETURN_NDBOX(result); } @@ -1415,11 +1430,12 @@ cube_f8(PG_FUNCTION_ARGS) NDBOX *result; int size; - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2; + size = POINT_SIZE(1); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = 1; - result->x[0] = result->x[1] = x; + SET_DIM(result, 1); + SET_POINT_BIT(result); + result->x[0] = x; PG_RETURN_NDBOX(result); } @@ -1433,12 +1449,24 @@ cube_f8_f8(PG_FUNCTION_ARGS) NDBOX *result; int size; - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2; - result = (NDBOX *) palloc0(size); - SET_VARSIZE(result, size); - result->dim = 1; - result->x[0] = x0; - result->x[1] = x1; + if (x0 == x1) + { + size = POINT_SIZE(1); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, 1); + SET_POINT_BIT(result); + result->x[0] = x0; + } + else + { + size = CUBE_SIZE(1); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, 1); + result->x[0] = x0; + result->x[1] = x1; + } PG_RETURN_NDBOX(result); } @@ -1448,25 +1476,39 @@ cube_f8_f8(PG_FUNCTION_ARGS) Datum cube_c_f8(PG_FUNCTION_ARGS) { - NDBOX *c = PG_GETARG_NDBOX(0); + NDBOX *cube = PG_GETARG_NDBOX(0); double x = PG_GETARG_FLOAT8(1); NDBOX *result; int size; int i; - size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2; - result = (NDBOX *) palloc0(size); - SET_VARSIZE(result, size); - result->dim = c->dim + 1; - for (i = 0; i < c->dim; i++) + if (IS_POINT(cube)) { - result->x[i] = c->x[i]; - result->x[result->dim + i] = c->x[c->dim + i]; + size = POINT_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + SET_POINT_BIT(result); + for (i = 0; i < DIM(cube); i++) + result->x[i] = cube->x[i]; + result->x[DIM(result) - 1] = x; + } + else + { + size = CUBE_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + for (i = 0; i < DIM(cube); i++) + { + result->x[i] = cube->x[i]; + result->x[DIM(result) + i] = cube->x[DIM(cube) + i]; + } + result->x[DIM(result) - 1] = x; + result->x[2 * DIM(result) - 1] = x; } - result->x[result->dim - 1] = x; - result->x[2 * result->dim - 1] = x; - PG_FREE_IF_COPY(c, 0); + PG_FREE_IF_COPY(cube, 0); PG_RETURN_NDBOX(result); } @@ -1474,25 +1516,39 @@ cube_c_f8(PG_FUNCTION_ARGS) Datum cube_c_f8_f8(PG_FUNCTION_ARGS) { - NDBOX *c = PG_GETARG_NDBOX(0); + NDBOX *cube = PG_GETARG_NDBOX(0); double x1 = PG_GETARG_FLOAT8(1); double x2 = PG_GETARG_FLOAT8(2); NDBOX *result; int size; int i; - size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2; - result = (NDBOX *) palloc0(size); - SET_VARSIZE(result, size); - result->dim = c->dim + 1; - for (i = 0; i < c->dim; i++) + if (IS_POINT(cube) && (x1 == x2)) { - result->x[i] = c->x[i]; - result->x[result->dim + i] = c->x[c->dim + i]; + size = POINT_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + SET_POINT_BIT(result); + for (i = 0; i < DIM(cube); i++) + result->x[i] = cube->x[i]; + result->x[DIM(result) - 1] = x1; + } + else + { + size = CUBE_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + for (i = 0; i < DIM(cube); i++) + { + result->x[i] = 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); } |