+ {
+ if ((dx[i] <= 0) || (dx[i] > c->dim))
+ {
+ pfree (result);
+ ereport(ERROR,
+ (errcode(ERRCODE_ARRAY_ELEMENT_ERROR),
+ errmsg("Index out of bounds")));
+ }
+ result->x[i] = c->x[dx[i]-1];
+ result->x[i+dim] = c->x[dx[i]+c->dim-1];
+ }
+
+ PG_RETURN_POINTER(result);
+}
+
+Datum
+cube_out(PG_FUNCTION_ARGS)
{
StringInfoData buf;
bool equal = true;
- int dim = cube->dim;
+ int dim;
int i;
int ndig;
+ NDBOX *cube;
initStringInfo(&buf);
+ cube = (NDBOX *) PG_GETARG_POINTER (0);
+
+ dim = cube->dim;
+
/*
* Get the number of digits to display.
*/
appendStringInfoChar(&buf, ')');
}
- return buf.data;
+ PG_RETURN_CSTRING (buf.data);
}
** the predicate x op query == FALSE, where op is the oper
** corresponding to strategy in the pg_amop table.
*/
-bool
-g_cube_consistent(GISTENTRY *entry,
- NDBOX * query,
- StrategyNumber strategy)
+Datum
+g_cube_consistent(PG_FUNCTION_ARGS)
{
+ GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ NDBOX *query = (NDBOX *) DatumGetPointer(PG_DETOAST_DATUM(PG_GETARG_DATUM(1)));
+ StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2);
+
/*
* if entry is not leaf, use g_cube_internal_consistent, else use
* g_cube_leaf_consistent
** The GiST Union method for boxes
** returns the minimal bounding box that encloses all the entries in entryvec
*/
-NDBOX *
-g_cube_union(GistEntryVector *entryvec, int *sizep)
+Datum
+g_cube_union(PG_FUNCTION_ARGS)
{
int i;
NDBOX *out = (NDBOX *) NULL;
NDBOX *tmp;
+ int *sizep;
+ GistEntryVector *entryvec;
+
+ entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+ sizep = (int *) PG_GETARG_POINTER(1);
/*
* fprintf(stderr, "union\n");
tmp = out;
}
- return (out);
+ PG_RETURN_POINTER(out);
}
/*
** GiST Compress and Decompress methods for boxes
** do not do anything.
*/
-GISTENTRY *
-g_cube_compress(GISTENTRY *entry)
+
+Datum
+g_cube_compress (PG_FUNCTION_ARGS)
{
- return (entry);
+ PG_RETURN_DATUM(PG_GETARG_DATUM(0));
}
-GISTENTRY *
-g_cube_decompress(GISTENTRY *entry)
+Datum
+g_cube_decompress (PG_FUNCTION_ARGS)
{
- return (entry);
+ PG_RETURN_DATUM(PG_GETARG_DATUM(0));
}
+
/*
** The GiST Penalty method for boxes
** As in the R-tree paper, we use change in area as our penalty metric
*/
-float *
-g_cube_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
+Datum
+g_cube_penalty (PG_FUNCTION_ARGS)
{
+ GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0);
+ GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1);
+ float *result = (float *) PG_GETARG_POINTER(2);
NDBOX *ud;
double tmp1,
tmp2;
- ud = cube_union((NDBOX *) DatumGetPointer(origentry->key),
+ ud = cube_union_v0((NDBOX *) DatumGetPointer(origentry->key),
(NDBOX *) DatumGetPointer(newentry->key));
rt_cube_size(ud, &tmp1);
rt_cube_size((NDBOX *) DatumGetPointer(origentry->key), &tmp2);
/*
* fprintf(stderr, "penalty\n"); fprintf(stderr, "\t%g\n", *result);
*/
- return (result);
+ PG_RETURN_FLOAT8 (*result);
}
** The GiST PickSplit method for boxes
** We use Guttman's poly time split algorithm
*/
-GIST_SPLITVEC *
-g_cube_picksplit(GistEntryVector *entryvec,
- GIST_SPLITVEC *v)
+Datum
+g_cube_picksplit(PG_FUNCTION_ARGS)
{
+ GistEntryVector *entryvec;
+ GIST_SPLITVEC *v;
OffsetNumber i,
j;
NDBOX *datum_alpha,
*right;
OffsetNumber maxoff;
+ entryvec = (GistEntryVector *) PG_GETARG_POINTER(0);
+ v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1);
+
/*
* fprintf(stderr, "picksplit\n");
*/
/* compute the wasted space by unioning these guys */
/* size_waste = size_union - size_inter; */
- union_d = cube_union(datum_alpha, datum_beta);
+ union_d = cube_union_v0(datum_alpha, datum_beta);
rt_cube_size(union_d, &size_union);
- inter_d = cube_inter(datum_alpha, datum_beta);
+ inter_d = (NDBOX *) DatumGetPointer (DirectFunctionCall2
+ (cube_inter,
+ entryvec->vector[i].key, entryvec->vector[j].key));
rt_cube_size(inter_d, &size_inter);
size_waste = size_union - size_inter;
v->spl_nright = 0;
datum_alpha = (NDBOX *) DatumGetPointer(entryvec->vector[seed_1].key);
- datum_l = cube_union(datum_alpha, datum_alpha);
+ datum_l = cube_union_v0(datum_alpha, datum_alpha);
rt_cube_size(datum_l, &size_l);
datum_beta = (NDBOX *) DatumGetPointer(entryvec->vector[seed_2].key);
- datum_r = cube_union(datum_beta, datum_beta);
+ datum_r = cube_union_v0(datum_beta, datum_beta);
rt_cube_size(datum_r, &size_r);
/*
/* okay, which page needs least enlargement? */
datum_alpha = (NDBOX *) DatumGetPointer(entryvec->vector[i].key);
- union_dl = cube_union(datum_l, datum_alpha);
- union_dr = cube_union(datum_r, datum_alpha);
+ union_dl = cube_union_v0(datum_l, datum_alpha);
+ union_dr = cube_union_v0(datum_r, datum_alpha);
rt_cube_size(union_dl, &size_alpha);
rt_cube_size(union_dr, &size_beta);
v->spl_ldatum = PointerGetDatum(datum_l);
v->spl_rdatum = PointerGetDatum(datum_r);
- return v;
+ PG_RETURN_POINTER(v);
}
/*
** Equality method
*/
-bool *
-g_cube_same(NDBOX * b1, NDBOX * b2, bool *result)
+Datum
+g_cube_same(PG_FUNCTION_ARGS)
{
- if (cube_eq(b1, b2))
+ NDBOX *b1, *b2;
+ bool *result;
+
+ b1 = (NDBOX *) PG_GETARG_POINTER (0);
+ b2 = (NDBOX *) PG_GETARG_POINTER (1);
+ result = (bool *) PG_GETARG_POINTER (2);
+
+ if (cube_cmp_v0(b1, b2) == 0)
*result = TRUE;
else
*result = FALSE;
/*
* fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE" ));
*/
- return (result);
+ PG_RETURN_POINTER (result);
}
/*
switch (strategy)
{
case RTOverlapStrategyNumber:
- retval = (bool) cube_overlap(key, query);
+ retval = (bool) cube_overlap_v0(key, query);
break;
case RTSameStrategyNumber:
- retval = (bool) cube_eq(key, query);
+ retval = (bool) (cube_cmp_v0(key, query) == 0);
break;
case RTContainsStrategyNumber:
- retval = (bool) cube_contains(key, query);
+ retval = (bool) cube_contains_v0(key, query);
break;
case RTContainedByStrategyNumber:
- retval = (bool) cube_contained(key, query);
+ retval = (bool) cube_contains_v0(query, key);
break;
default:
retval = FALSE;
switch (strategy)
{
case RTOverlapStrategyNumber:
- retval = (bool) cube_overlap(key, query);
+ retval = (bool) cube_overlap_v0(key, query);
break;
case RTSameStrategyNumber:
case RTContainsStrategyNumber:
- retval = (bool) cube_contains(key, query);
+ retval = (bool) cube_contains_v0(key, query);
break;
case RTContainedByStrategyNumber:
- retval = (bool) cube_overlap(key, query);
+ retval = (bool) cube_overlap_v0(key, query);
break;
default:
retval = FALSE;
{
NDBOX *retval;
- retval = cube_union(r1, r2);
+ retval = cube_union_v0(r1, r2);
*sizep = retval->size;
return (retval);
}
-/* cube_union */
+/* cube_union_v0 */
NDBOX *
-cube_union(NDBOX * a, NDBOX * b)
+cube_union_v0(NDBOX * a, NDBOX * b)
{
int i;
NDBOX *result;
return (result);
}
+Datum
+cube_union (PG_FUNCTION_ARGS)
+{
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_POINTER(cube_union_v0(a,b));
+}
+
/* cube_inter */
-NDBOX *
-cube_inter(NDBOX * a, NDBOX * b)
+Datum
+cube_inter(PG_FUNCTION_ARGS)
{
int i;
- NDBOX *result;
+ NDBOX *result, *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
if (a->dim >= b->dim)
{
/*
* Is it OK to return a non-null intersection for non-overlapping boxes?
*/
- return (result);
+ PG_RETURN_POINTER (result);
}
/* cube_size */
-double *
-cube_size(NDBOX * a)
+Datum
+cube_size(PG_FUNCTION_ARGS)
{
+ NDBOX *a;
int i,
j;
- double *result;
+ double result;
- result = (double *) palloc(sizeof(double));
+ a = (NDBOX *) PG_GETARG_POINTER(0);
- *result = 1.0;
+ result = 1.0;
for (i = 0, j = a->dim; i < a->dim; i++, j++)
- *result = (*result) * Abs((a->x[j] - a->x[i]));
+ result = result * Abs((a->x[j] - a->x[i]));
- return (result);
+ PG_RETURN_FLOAT8 (result);
}
void
/* make up a metric in which one box will be 'lower' than the other
-- this can be useful for sorting and to determine uniqueness */
int32
-cube_cmp(NDBOX * a, NDBOX * b)
+cube_cmp_v0(NDBOX * a, NDBOX * b)
{
int i;
int dim;
return 0;
}
+Datum
+cube_cmp(PG_FUNCTION_ARGS)
+{
+ NDBOX *a, *b;
-bool
-cube_eq(NDBOX * a, NDBOX * b)
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_INT16(cube_cmp_v0(a, b));
+}
+
+
+Datum
+cube_eq(PG_FUNCTION_ARGS)
{
- return (cube_cmp(a, b) == 0);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_cmp_v0(a, b) == 0);
}
-bool
-cube_ne(NDBOX * a, NDBOX * b)
+
+Datum
+cube_ne(PG_FUNCTION_ARGS)
{
- return (cube_cmp(a, b) != 0);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_cmp_v0(a, b) != 0);
}
-bool
-cube_lt(NDBOX * a, NDBOX * b)
+
+Datum
+cube_lt(PG_FUNCTION_ARGS)
{
- return (cube_cmp(a, b) < 0);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_cmp_v0(a, b) < 0);
}
-bool
-cube_gt(NDBOX * a, NDBOX * b)
+
+Datum
+cube_gt(PG_FUNCTION_ARGS)
{
- return (cube_cmp(a, b) > 0);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_cmp_v0(a, b) > 0);
}
-bool
-cube_le(NDBOX * a, NDBOX * b)
+
+Datum
+cube_le(PG_FUNCTION_ARGS)
{
- return (cube_cmp(a, b) <= 0);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_cmp_v0(a, b) <= 0);
}
-bool
-cube_ge(NDBOX * a, NDBOX * b)
+
+Datum
+cube_ge(PG_FUNCTION_ARGS)
{
- return (cube_cmp(a, b) >= 0);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_cmp_v0(a, b) >= 0);
}
+
/* Contains */
/* Box(A) CONTAINS Box(B) IFF pt(A) < pt(B) */
bool
-cube_contains(NDBOX * a, NDBOX * b)
+cube_contains_v0(NDBOX * a, NDBOX * b)
{
int i;
return (TRUE);
}
+Datum
+cube_contains(PG_FUNCTION_ARGS)
+{
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL(cube_contains_v0(a, b));
+}
+
/* Contained */
/* Box(A) Contained by Box(B) IFF Box(B) Contains Box(A) */
-bool
-cube_contained(NDBOX * a, NDBOX * b)
+Datum
+cube_contained(PG_FUNCTION_ARGS)
{
- if (cube_contains(b, a) == TRUE)
- return (TRUE);
- else
- return (FALSE);
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL (cube_contains_v0(b, a));
}
/* Overlap */
/* Box(A) Overlap Box(B) IFF (pt(a)LL < pt(B)UR) && (pt(b)LL < pt(a)UR) */
bool
-cube_overlap(NDBOX * a, NDBOX * b)
+cube_overlap_v0(NDBOX * a, NDBOX * b)
{
int i;
}
+Datum
+cube_overlap(PG_FUNCTION_ARGS)
+{
+ NDBOX *a, *b;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
+
+ PG_RETURN_BOOL (cube_overlap_v0(a, b));
+}
+
+
/* Distance */
/* The distance is computed as a per axis sum of the squared distances
between 1D projections of the boxes onto Cartesian axes. Assuming zero
distance between overlapping projections, this metric coincides with the
"common sense" geometric distance */
-double *
-cube_distance(NDBOX * a, NDBOX * b)
+Datum
+cube_distance(PG_FUNCTION_ARGS)
{
int i;
double d,
distance;
- double *result;
+ NDBOX *a, *b;
- result = (double *) palloc(sizeof(double));
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ b = (NDBOX *) PG_GETARG_POINTER(1);
/* swap the box pointers if needed */
if (a->dim < b->dim)
distance += d * d;
}
- *result = (double) sqrt(distance);
-
- return (result);
+ PG_RETURN_FLOAT8(sqrt(distance));
}
static double
}
/* Test if a box is also a point */
-bool
-cube_is_point(NDBOX * a)
+Datum
+cube_is_point(PG_FUNCTION_ARGS)
{
int i,
j;
+ NDBOX *a;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
for (i = 0, j = a->dim; i < a->dim; i++, j++)
{
if (a->x[i] != a->x[j])
- return FALSE;
+ PG_RETURN_BOOL(FALSE);
}
- return TRUE;
+ PG_RETURN_BOOL(TRUE);
}
/* Return dimensions in use in the data structure */
-int4
-cube_dim(NDBOX * a)
+Datum
+cube_dim(PG_FUNCTION_ARGS)
{
- /* Other things will break before unsigned int doesn't fit. */
- return a->dim;
+ NDBOX *c;
+
+ c = (NDBOX *) PG_GETARG_POINTER(0);
+
+ PG_RETURN_INT16 (c->dim);
}
/* Return a specific normalized LL coordinate */
-double *
-cube_ll_coord(NDBOX * a, int4 n)
+Datum
+cube_ll_coord(PG_FUNCTION_ARGS)
{
- double *result;
+ NDBOX *c;
+ 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;
+ c = (NDBOX *) PG_GETARG_POINTER(0);
+ n = PG_GETARG_INT16(1);
+
+ result = 0;
+ if (c->dim >= n && n > 0)
+ result = Min(c->x[n - 1], c->x[c->dim + n - 1]);
+
+ PG_RETURN_FLOAT8(result);
}
/* Return a specific normalized UR coordinate */
-double *
-cube_ur_coord(NDBOX * a, int4 n)
+Datum
+cube_ur_coord(PG_FUNCTION_ARGS)
{
- double *result;
+ NDBOX *c;
+ int n;
+ double result;
+
+ c = (NDBOX *) PG_GETARG_POINTER(0);
+ n = PG_GETARG_INT16(1);
- 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;
+ result = 0;
+ if (c->dim >= n && n > 0)
+ result = Max(c->x[n - 1], c->x[c->dim + n - 1]);
+
+ PG_RETURN_FLOAT8(result);
}
/* Increase or decrease box size by a radius in at least n dimensions. */
-NDBOX *
-cube_enlarge(NDBOX * a, double *r, int4 n)
+Datum
+cube_enlarge(PG_FUNCTION_ARGS)
{
NDBOX *result;
int dim = 0;
int i,
j,
k;
+ NDBOX *a;
+ double *r;
+ int4 n;
+
+ a = (NDBOX *) PG_GETARG_POINTER(0);
+ r = (double *) PG_GETARG_POINTER(1);
+ n = PG_GETARG_INT32(2);
if (n > CUBE_MAX_DIM)
n = CUBE_MAX_DIM;
result->x[i] = -*r;
result->x[j] = *r;
}
- return result;
+
+ PG_RETURN_POINTER(result);
}
/* Create a one dimensional box with identical upper and lower coordinates */
-NDBOX *
-cube_f8(double *x1)
+Datum
+cube_f8(PG_FUNCTION_ARGS)
{
NDBOX *result;
int size;
memset(result, 0, size);
result->size = size;
result->dim = 1;
- result->x[0] = *x1;
- result->x[1] = *x1;
- return result;
+ result->x[0] = PG_GETARG_FLOAT8(0);
+ result->x[1] = result->x[0];
+
+ PG_RETURN_POINTER (result);
}
/* Create a one dimensional box */
-NDBOX *
-cube_f8_f8(double *x1, double *x2)
+Datum
+cube_f8_f8(PG_FUNCTION_ARGS)
{
NDBOX *result;
int size;
memset(result, 0, size);
result->size = size;
result->dim = 1;
- result->x[0] = *x1;
- result->x[1] = *x2;
- return result;
+ result->x[0] = PG_GETARG_FLOAT8(0);
+ result->x[1] = PG_GETARG_FLOAT8(1);
+
+ PG_RETURN_POINTER (result);
}
/* Add a dimension to an existing cube with the same values for the new
coordinate */
-NDBOX *
-cube_c_f8(NDBOX * c, double *x1)
+Datum
+cube_c_f8(PG_FUNCTION_ARGS)
{
+ NDBOX *c;
NDBOX *result;
+ double x;
int size;
int i;
+ c = (NDBOX *) PG_GETARG_POINTER(0);
+ x = PG_GETARG_FLOAT8 (1);
+
size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) *2;
result = (NDBOX *) palloc(size);
memset(result, 0, size);
result->x[i] = c->x[i];
result->x[result->dim + i] = c->x[c->dim + i];
}
- result->x[result->dim - 1] = *x1;
- result->x[2 * result->dim - 1] = *x1;
- return result;
+ result->x[result->dim - 1] = x;
+ result->x[2 * result->dim - 1] = x;
+
+ PG_RETURN_POINTER(result);
}
/* Add a dimension to an existing cube */
-NDBOX *
-cube_c_f8_f8(NDBOX * c, double *x1, double *x2)
+Datum
+cube_c_f8_f8(PG_FUNCTION_ARGS)
{
+ NDBOX *c;
NDBOX *result;
+ double x1, x2;
int size;
int i;
+ c = (NDBOX *) PG_GETARG_POINTER(0);
+ x1 = PG_GETARG_FLOAT8 (1);
+ x2 = PG_GETARG_FLOAT8 (2);
+
size = offsetof(NDBOX, x[0]) + sizeof(double) * (c->dim + 1) *2;
result = (NDBOX *) palloc(size);
memset(result, 0, size);
result->x[i] = c->x[i];
result->x[result->dim + i] = c->x[c->dim + i];
}
- result->x[result->dim - 1] = *x1;
- result->x[2 * result->dim - 1] = *x2;
- return result;
+ result->x[result->dim - 1] = x1;
+ result->x[2 * result->dim - 1] = x2;
+
+ PG_RETURN_POINTER(result);
}
+
+