diff options
author | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2013-10-21 20:59:42 +0300 |
---|---|---|
committer | Heikki Linnakangas <heikki.linnakangas@iki.fi> | 2013-10-21 22:00:15 +0300 |
commit | 08612f45a0e236bd01db3fc96cc1fa7bfabc927c (patch) | |
tree | c309b6559b71c44320eda3bc0bfb891676f822e7 /contrib/cube/cube.c | |
parent | a5963efa8f2b46700c0591281c57aeea3d429c34 (diff) | |
download | postgresql-08612f45a0e236bd01db3fc96cc1fa7bfabc927c.tar.gz postgresql-08612f45a0e236bd01db3fc96cc1fa7bfabc927c.zip |
Extend cube on-disk format to pack points more tightly.
If the lower left and upper right corners of a cube are the same, set a
flag in the cube header, and only store one copy of the coordinates. That
cuts the on-disk size into half for the common case that the cube datatype
is used to represent points rather than boxes.
The new format is backwards-compatible with the old one, so pg_upgrade
still works. However, to get the space savings, the data needs to be
rewritten. A simple VACUUM FULL or REINDEX is not enough, as the old
Datums will just be moved to the new heap/index as is. A pg_dump and
reload, or something similar like casting to text and back, will do the
trick.
This patch deliberately doesn't update all the alternative expected output
files, as I don't have access to machines that produce those outputs. I'm
not sure if they are still relevant, but if they are, the buildfarm will
tell us and produce the diff required to fix it. If none of the buildfarm
animals need them, they should be removed altogether.
Patch by Stas Kelvich.
Diffstat (limited to 'contrib/cube/cube.c')
-rw-r--r-- | contrib/cube/cube.c | 483 |
1 files changed, 289 insertions, 194 deletions
diff --git a/contrib/cube/cube.c b/contrib/cube/cube.c index dab0e6e7586..dadda133b91 100644 --- a/contrib/cube/cube.c +++ b/contrib/cube/cube.c @@ -144,6 +144,7 @@ bool g_cube_internal_consistent(NDBOX *key, NDBOX *query, StrategyNumber strate ** Auxiliary funxtions */ static double distance_1D(double a1, double a2, double b1, double b2); +static bool cube_is_point_internal(NDBOX *cube); /***************************************************************************** @@ -181,6 +182,7 @@ cube_a_f8_f8(PG_FUNCTION_ARGS) int i; int dim; int size; + bool point; double *dur, *dll; @@ -198,16 +200,32 @@ cube_a_f8_f8(PG_FUNCTION_ARGS) dur = ARRPTR(ur); dll = ARRPTR(ll); - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim; + /* Check if it's a point */ + point = true; + for (i = 0; i < dim; i++) + { + if (dur[i] != dll[i]) + { + point = false; + break; + } + } + + size = point ? POINT_SIZE(dim) : CUBE_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = dim; + SET_DIM(result, dim); for (i = 0; i < dim; i++) - { result->x[i] = dur[i]; - result->x[i + dim] = dll[i]; + + if (!point) + { + for (i = 0; i < dim; i++) + result->x[i + dim] = dll[i]; } + else + SET_POINT_BIT(result); PG_RETURN_NDBOX(result); } @@ -234,16 +252,14 @@ cube_a_f8(PG_FUNCTION_ARGS) dur = ARRPTR(ur); - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim; + size = POINT_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = dim; + SET_DIM(result, dim); + SET_POINT_BIT(result); for (i = 0; i < dim; i++) - { result->x[i] = dur[i]; - result->x[i + dim] = dur[i]; - } PG_RETURN_NDBOX(result); } @@ -267,14 +283,17 @@ cube_subset(PG_FUNCTION_ARGS) dx = (int32 *) ARR_DATA_PTR(idx); dim = ARRNELEMS(idx); - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2 * dim; + size = IS_POINT(c) ? POINT_SIZE(dim) : CUBE_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = dim; + SET_DIM(result, dim); + + if (IS_POINT(c)) + SET_POINT_BIT(result); for (i = 0; i < dim; i++) { - if ((dx[i] <= 0) || (dx[i] > c->dim)) + if ((dx[i] <= 0) || (dx[i] > DIM(c))) { pfree(result); ereport(ERROR, @@ -282,7 +301,8 @@ cube_subset(PG_FUNCTION_ARGS) errmsg("Index out of bounds"))); } result->x[i] = c->x[dx[i] - 1]; - result->x[i + dim] = c->x[dx[i] + c->dim - 1]; + if (!IS_POINT(c)) + result->x[i + dim] = c->x[dx[i] + DIM(c) - 1]; } PG_FREE_IF_COPY(c, 0); @@ -294,8 +314,7 @@ cube_out(PG_FUNCTION_ARGS) { NDBOX *cube = PG_GETARG_NDBOX(0); StringInfoData buf; - int dim = cube->dim; - bool equal = true; + int dim = DIM(cube); int i; int ndig; @@ -317,20 +336,18 @@ cube_out(PG_FUNCTION_ARGS) { if (i > 0) appendStringInfo(&buf, ", "); - appendStringInfo(&buf, "%.*g", ndig, cube->x[i]); - if (cube->x[i] != cube->x[i + dim]) - equal = false; + appendStringInfo(&buf, "%.*g", ndig, LL_COORD(cube, i)); } appendStringInfoChar(&buf, ')'); - if (!equal) + if (!cube_is_point_internal(cube)) { appendStringInfo(&buf, ",("); for (i = 0; i < dim; i++) { if (i > 0) appendStringInfo(&buf, ", "); - appendStringInfo(&buf, "%.*g", ndig, cube->x[i + dim]); + appendStringInfo(&buf, "%.*g", ndig, UR_COORD(cube, i)); } appendStringInfoChar(&buf, ')'); } @@ -729,51 +746,60 @@ cube_union_v0(NDBOX *a, NDBOX *b) { int i; NDBOX *result; + int dim; + int size; - if (a->dim >= b->dim) - { - result = palloc0(VARSIZE(a)); - SET_VARSIZE(result, VARSIZE(a)); - result->dim = a->dim; - } - else - { - result = palloc0(VARSIZE(b)); - SET_VARSIZE(result, VARSIZE(b)); - result->dim = b->dim; - } + /* trivial case */ + if (a == b) + return a; - /* swap the box pointers if needed */ - if (a->dim < b->dim) + /* swap the arguments if needed, so that 'a' is always larger than 'b' */ + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; b = a; a = tmp; } + dim = DIM(a); - /* - * use the potentially smaller of the two boxes (b) to fill in the result, - * padding absent dimensions with zeroes - */ - for (i = 0; i < b->dim; i++) + size = CUBE_SIZE(dim); + result = palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, dim); + + /* First compute the union of the dimensions present in both args */ + for (i = 0; i < DIM(b); i++) { - result->x[i] = Min(b->x[i], b->x[i + b->dim]); - result->x[i + a->dim] = Max(b->x[i], b->x[i + b->dim]); + result->x[i] = Min( + Min(LL_COORD(a, i), UR_COORD(a, i)), + Min(LL_COORD(b, i), UR_COORD(b, i)) + ); + result->x[i + DIM(a)] = Max( + Max(LL_COORD(a, i), UR_COORD(a, i)), + Max(LL_COORD(b, i), UR_COORD(b, i)) + ); } - for (i = b->dim; i < a->dim; i++) + /* continue on the higher dimensions only present in 'a' */ + for (; i < DIM(a); i++) { - result->x[i] = 0; - result->x[i + a->dim] = 0; + result->x[i] = Min(0, + Min(LL_COORD(a, i), UR_COORD(a, i)) + ); + result->x[i + dim] = Max(0, + Max(LL_COORD(a, i), UR_COORD(a, i)) + ); } - /* compute the union */ - for (i = 0; i < a->dim; i++) + /* + * Check if the result was in fact a point, and set the flag in the datum + * accordingly. (we don't bother to repalloc it smaller) + */ + if (cube_is_point_internal(result)) { - result->x[i] = - Min(Min(a->x[i], a->x[i + a->dim]), result->x[i]); - result->x[i + a->dim] = Max(Max(a->x[i], - a->x[i + a->dim]), result->x[i + a->dim]); + size = POINT_SIZE(dim); + SET_VARSIZE(result, size); + SET_POINT_BIT(result); } return (result); @@ -802,52 +828,57 @@ cube_inter(PG_FUNCTION_ARGS) NDBOX *result; bool swapped = false; int i; + int dim; + int size; - if (a->dim >= b->dim) - { - result = palloc0(VARSIZE(a)); - SET_VARSIZE(result, VARSIZE(a)); - result->dim = a->dim; - } - else - { - result = palloc0(VARSIZE(b)); - SET_VARSIZE(result, VARSIZE(b)); - result->dim = b->dim; - } - - /* swap the box pointers if needed */ - if (a->dim < b->dim) + /* swap the arguments if needed, so that 'a' is always larger than 'b' */ + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; - b = a; a = tmp; swapped = true; } + dim = DIM(a); - /* - * use the potentially smaller of the two boxes (b) to fill in the - * result, padding absent dimensions with zeroes - */ - for (i = 0; i < b->dim; i++) + size = CUBE_SIZE(dim); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, dim); + + /* First compute intersection of the dimensions present in both args */ + for (i = 0; i < DIM(b); i++) { - result->x[i] = Min(b->x[i], b->x[i + b->dim]); - result->x[i + a->dim] = Max(b->x[i], b->x[i + b->dim]); + result->x[i] = Max( + Min(LL_COORD(a, i), UR_COORD(a, i)), + Min(LL_COORD(b, i), UR_COORD(b, i)) + ); + result->x[i + DIM(a)] = Min( + Max(LL_COORD(a, i), UR_COORD(a, i)), + Max(LL_COORD(b, i), UR_COORD(b, i)) + ); } - for (i = b->dim; i < a->dim; i++) + /* continue on the higher dimemsions only present in 'a' */ + for (; i < DIM(a); i++) { - result->x[i] = 0; - result->x[i + a->dim] = 0; + result->x[i] = Max(0, + Min(LL_COORD(a, i), UR_COORD(a, i)) + ); + result->x[i + DIM(a)] = Min(0, + Max(LL_COORD(a, i), UR_COORD(a, i)) + ); } - /* compute the intersection */ - for (i = 0; i < a->dim; i++) + /* + * Check if the result was in fact a point, and set the flag in the datum + * accordingly. (we don't bother to repalloc it smaller) + */ + if (cube_is_point_internal(result)) { - result->x[i] = - Max(Min(a->x[i], a->x[i + a->dim]), result->x[i]); - result->x[i + a->dim] = Min(Max(a->x[i], - a->x[i + a->dim]), result->x[i + a->dim]); + size = POINT_SIZE(dim); + result = repalloc(result, size); + SET_VARSIZE(result, size); + SET_POINT_BIT(result); } if (swapped) @@ -873,12 +904,11 @@ cube_size(PG_FUNCTION_ARGS) { NDBOX *a = PG_GETARG_NDBOX(0); double result; - int i, - j; + int i; result = 1.0; - for (i = 0, j = a->dim; i < a->dim; i++, j++) - result = result * Abs((a->x[j] - a->x[i])); + for (i = 0; i < DIM(a); i++) + result = result * Abs((LL_COORD(a, i) - UR_COORD(a, i))); PG_FREE_IF_COPY(a, 0); PG_RETURN_FLOAT8(result); @@ -887,16 +917,15 @@ cube_size(PG_FUNCTION_ARGS) void rt_cube_size(NDBOX *a, double *size) { - int i, - j; + int i; if (a == (NDBOX *) NULL) *size = 0.0; else { *size = 1.0; - for (i = 0, j = a->dim; i < a->dim; i++, j++) - *size = (*size) * Abs((a->x[j] - a->x[i])); + for (i = 0; i < DIM(a); i++) + *size = (*size) * Abs(UR_COORD(a, i) - LL_COORD(a, i)); } return; } @@ -909,43 +938,43 @@ cube_cmp_v0(NDBOX *a, NDBOX *b) int i; int dim; - dim = Min(a->dim, b->dim); + dim = Min(DIM(a), DIM(b)); /* compare the common dimensions */ for (i = 0; i < dim; i++) { - if (Min(a->x[i], a->x[a->dim + i]) > - Min(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > + Min(LL_COORD(b, i), UR_COORD(b, i))) return 1; - if (Min(a->x[i], a->x[a->dim + i]) < - Min(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) < + Min(LL_COORD(b, i), UR_COORD(b, i))) return -1; } for (i = 0; i < dim; i++) { - if (Max(a->x[i], a->x[a->dim + i]) > - Max(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) > + Max(LL_COORD(b, i), UR_COORD(b, i))) return 1; - if (Max(a->x[i], a->x[a->dim + i]) < - Max(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < + Max(LL_COORD(b, i), UR_COORD(b, i))) return -1; } /* compare extra dimensions to zero */ - if (a->dim > b->dim) + if (DIM(a) > DIM(b)) { - for (i = dim; i < a->dim; i++) + for (i = dim; i < DIM(a); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > 0) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0) return 1; - if (Min(a->x[i], a->x[a->dim + i]) < 0) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) < 0) return -1; } - for (i = dim; i < a->dim; i++) + for (i = dim; i < DIM(a); i++) { - if (Max(a->x[i], a->x[a->dim + i]) > 0) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) > 0) return 1; - if (Max(a->x[i], a->x[a->dim + i]) < 0) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0) return -1; } @@ -955,20 +984,20 @@ cube_cmp_v0(NDBOX *a, NDBOX *b) */ return 1; } - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { - for (i = dim; i < b->dim; i++) + for (i = dim; i < DIM(b); i++) { - if (Min(b->x[i], b->x[b->dim + i]) > 0) + if (Min(LL_COORD(b, i), UR_COORD(b, i)) > 0) return -1; - if (Min(b->x[i], b->x[b->dim + i]) < 0) + if (Min(LL_COORD(b, i), UR_COORD(b, i)) < 0) return 1; } - for (i = dim; i < b->dim; i++) + for (i = dim; i < DIM(b); i++) { - if (Max(b->x[i], b->x[b->dim + i]) > 0) + if (Max(LL_COORD(b, i), UR_COORD(b, i)) > 0) return -1; - if (Max(b->x[i], b->x[b->dim + i]) < 0) + if (Max(LL_COORD(b, i), UR_COORD(b, i)) < 0) return 1; } @@ -1098,30 +1127,30 @@ cube_contains_v0(NDBOX *a, NDBOX *b) if ((a == NULL) || (b == NULL)) return (FALSE); - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { /* * the further comparisons will make sense if the excess dimensions of * (b) were zeroes Since both UL and UR coordinates must be zero, we * can check them all without worrying about which is which. */ - for (i = a->dim; i < b->dim; i++) + for (i = DIM(a); i < DIM(b); i++) { - if (b->x[i] != 0) + if (LL_COORD(b, i) != 0) return (FALSE); - if (b->x[i + b->dim] != 0) + if (UR_COORD(b, i) != 0) return (FALSE); } } /* Can't care less about the excess dimensions of (a), if any */ - for (i = 0; i < Min(a->dim, b->dim); i++) + for (i = 0; i < Min(DIM(a), DIM(b)); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > - Min(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > + Min(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); - if (Max(a->x[i], a->x[a->dim + i]) < - Max(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < + Max(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); } @@ -1173,7 +1202,7 @@ cube_overlap_v0(NDBOX *a, NDBOX *b) return (FALSE); /* swap the box pointers if needed */ - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; @@ -1182,22 +1211,20 @@ cube_overlap_v0(NDBOX *a, NDBOX *b) } /* compare within the dimensions of (b) */ - for (i = 0; i < b->dim; i++) + for (i = 0; i < DIM(b); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > - Max(b->x[i], b->x[b->dim + i])) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > Max(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); - if (Max(a->x[i], a->x[a->dim + i]) < - Min(b->x[i], b->x[b->dim + i])) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < Min(LL_COORD(b, i), UR_COORD(b, i))) return (FALSE); } /* compare to zero those dimensions in (a) absent in (b) */ - for (i = b->dim; i < a->dim; i++) + for (i = DIM(b); i < DIM(a); i++) { - if (Min(a->x[i], a->x[a->dim + i]) > 0) + if (Min(LL_COORD(a, i), UR_COORD(a, i)) > 0) return (FALSE); - if (Max(a->x[i], a->x[a->dim + i]) < 0) + if (Max(LL_COORD(a, i), UR_COORD(a, i)) < 0) return (FALSE); } @@ -1236,7 +1263,7 @@ cube_distance(PG_FUNCTION_ARGS) int i; /* swap the box pointers if needed */ - if (a->dim < b->dim) + if (DIM(a) < DIM(b)) { NDBOX *tmp = b; @@ -1247,16 +1274,16 @@ cube_distance(PG_FUNCTION_ARGS) distance = 0.0; /* compute within the dimensions of (b) */ - for (i = 0; i < b->dim; i++) + for (i = 0; i < DIM(b); i++) { - d = distance_1D(a->x[i], a->x[i + a->dim], b->x[i], b->x[i + b->dim]); + d = distance_1D(LL_COORD(a,i), UR_COORD(a,i), LL_COORD(b,i), UR_COORD(b,i)); distance += d * d; } /* compute distance to zero for those dimensions in (a) absent in (b) */ - for (i = b->dim; i < a->dim; i++) + for (i = DIM(b); i < DIM(a); i++) { - d = distance_1D(a->x[i], a->x[i + a->dim], 0.0, 0.0); + d = distance_1D(LL_COORD(a,i), UR_COORD(a,i), 0.0, 0.0); distance += d * d; } @@ -1293,18 +1320,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 */ @@ -1312,8 +1356,7 @@ Datum cube_dim(PG_FUNCTION_ARGS) { NDBOX *c = PG_GETARG_NDBOX(0); - int dim = c->dim; - + int dim = DIM(c); PG_FREE_IF_COPY(c, 0); PG_RETURN_INT32(dim); } @@ -1326,8 +1369,8 @@ cube_ll_coord(PG_FUNCTION_ARGS) int n = PG_GETARG_INT16(1); double result; - if (c->dim >= n && n > 0) - result = Min(c->x[n - 1], c->x[c->dim + n - 1]); + if (DIM(c) >= n && n > 0) + result = Min(LL_COORD(c, n-1), UR_COORD(c, n-1)); else result = 0; @@ -1343,8 +1386,8 @@ cube_ur_coord(PG_FUNCTION_ARGS) int n = PG_GETARG_INT16(1); double result; - if (c->dim >= n && n > 0) - result = Max(c->x[n - 1], c->x[c->dim + n - 1]); + if (DIM(c) >= n && n > 0) + result = Max(LL_COORD(c, n-1), UR_COORD(c, n-1)); else result = 0; @@ -1363,30 +1406,31 @@ cube_enlarge(PG_FUNCTION_ARGS) int dim = 0; int size; int i, - j, - k; + j; if (n > CUBE_MAX_DIM) n = CUBE_MAX_DIM; if (r > 0 && n > 0) dim = n; - if (a->dim > dim) - dim = a->dim; - size = offsetof(NDBOX, x[0]) +sizeof(double) * dim * 2; + if (DIM(a) > dim) + dim = DIM(a); + + size = CUBE_SIZE(dim); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = dim; - for (i = 0, j = dim, k = a->dim; i < a->dim; i++, j++, k++) + SET_DIM(result, dim); + + for (i = 0, j = dim; i < DIM(a); i++, j++) { - if (a->x[i] >= a->x[k]) + if (LL_COORD(a,i) >= UR_COORD(a,i)) { - result->x[i] = a->x[k] - r; - result->x[j] = a->x[i] + r; + result->x[i] = UR_COORD(a,i) - r; + result->x[j] = LL_COORD(a,i) + r; } else { - result->x[i] = a->x[i] - r; - result->x[j] = a->x[k] + r; + result->x[i] = LL_COORD(a,i) - r; + result->x[j] = UR_COORD(a,i) + r; } if (result->x[i] > result->x[j]) { @@ -1401,6 +1445,17 @@ cube_enlarge(PG_FUNCTION_ARGS) result->x[j] = r; } + /* + * Check if the result was in fact a point, and set the flag in the datum + * accordingly. (we don't bother to repalloc it smaller) + */ + if (cube_is_point_internal(result)) + { + size = POINT_SIZE(dim); + SET_VARSIZE(result, size); + SET_POINT_BIT(result); + } + PG_FREE_IF_COPY(a, 0); PG_RETURN_NDBOX(result); } @@ -1413,11 +1468,12 @@ cube_f8(PG_FUNCTION_ARGS) NDBOX *result; int size; - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2; + size = POINT_SIZE(1); result = (NDBOX *) palloc0(size); SET_VARSIZE(result, size); - result->dim = 1; - result->x[0] = result->x[1] = x; + SET_DIM(result, 1); + SET_POINT_BIT(result); + result->x[0] = x; PG_RETURN_NDBOX(result); } @@ -1431,12 +1487,24 @@ cube_f8_f8(PG_FUNCTION_ARGS) NDBOX *result; int size; - size = offsetof(NDBOX, x[0]) +sizeof(double) * 2; - result = (NDBOX *) palloc0(size); - SET_VARSIZE(result, size); - result->dim = 1; - result->x[0] = x0; - result->x[1] = x1; + if (x0 == x1) + { + size = POINT_SIZE(1); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, 1); + SET_POINT_BIT(result); + result->x[0] = x0; + } + else + { + size = CUBE_SIZE(1); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, 1); + result->x[0] = x0; + result->x[1] = x1; + } PG_RETURN_NDBOX(result); } @@ -1446,25 +1514,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)) + { + size = POINT_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + SET_POINT_BIT(result); + for (i = 0; i < DIM(cube); i++) + result->x[i] = cube->x[i]; + result->x[DIM(result) - 1] = x; + } + else { - result->x[i] = c->x[i]; - result->x[result->dim + i] = c->x[c->dim + i]; + size = CUBE_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + for (i = 0; i < DIM(cube); i++) + { + result->x[i] = cube->x[i]; + result->x[DIM(result) + i] = cube->x[DIM(cube) + i]; + } + result->x[DIM(result) - 1] = x; + result->x[2*DIM(result) - 1] = x; } - result->x[result->dim - 1] = x; - result->x[2 * result->dim - 1] = x; - PG_FREE_IF_COPY(c, 0); + PG_FREE_IF_COPY(cube, 0); PG_RETURN_NDBOX(result); } @@ -1472,25 +1554,38 @@ cube_c_f8(PG_FUNCTION_ARGS) Datum cube_c_f8_f8(PG_FUNCTION_ARGS) { - NDBOX *c = PG_GETARG_NDBOX(0); + NDBOX *cube = PG_GETARG_NDBOX(0); double x1 = PG_GETARG_FLOAT8(1); double x2 = PG_GETARG_FLOAT8(2); NDBOX *result; int size; int i; - size = offsetof(NDBOX, x[0]) +sizeof(double) * (c->dim + 1) *2; - result = (NDBOX *) palloc0(size); - SET_VARSIZE(result, size); - result->dim = c->dim + 1; - for (i = 0; i < c->dim; i++) + if (IS_POINT(cube) && (x1 == x2)){ + size = POINT_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + SET_POINT_BIT(result); + for (i = 0; i < DIM(cube); i++) + result->x[i] = cube->x[i]; + result->x[DIM(result) - 1] = x1; + } + else { - result->x[i] = c->x[i]; - result->x[result->dim + i] = c->x[c->dim + i]; + size = CUBE_SIZE((DIM(cube) + 1)); + result = (NDBOX *) palloc0(size); + SET_VARSIZE(result, size); + SET_DIM(result, DIM(cube) + 1); + for (i = 0; i < DIM(cube); i++) + { + result->x[i] = LL_COORD(cube, i); + result->x[DIM(result) + i] = UR_COORD(cube, i); + } + result->x[DIM(result) - 1] = x1; + result->x[2 * DIM(result) - 1] = x2; } - result->x[result->dim - 1] = x1; - result->x[2 * result->dim - 1] = x2; - PG_FREE_IF_COPY(c, 0); + PG_FREE_IF_COPY(cube, 0); PG_RETURN_NDBOX(result); } |