コード例 #1
0
ファイル: seg.c プロジェクト: 0x0FFF/postgres
SEG *
gseg_binary_union(SEG *r1, SEG *r2, int *sizep)
{
	SEG		   *retval;

	retval = seg_union(r1, r2);
	*sizep = sizeof(SEG);

	return (retval);
}
コード例 #2
0
ファイル: seg.c プロジェクト: 0x0FFF/postgres
/*
** The GiST Penalty method for segments
** As in the R-tree paper, we use change in area as our penalty metric
*/
float *
gseg_penalty(GISTENTRY *origentry, GISTENTRY *newentry, float *result)
{
	SEG		   *ud;
	float		tmp1,
				tmp2;

	ud = seg_union((SEG *) DatumGetPointer(origentry->key),
				   (SEG *) DatumGetPointer(newentry->key));
	rt_seg_size(ud, &tmp1);
	rt_seg_size((SEG *) DatumGetPointer(origentry->key), &tmp2);
	*result = tmp1 - tmp2;

#ifdef GIST_DEBUG
	fprintf(stderr, "penalty\n");
	fprintf(stderr, "\t%g\n", *result);
#endif

	return (result);
}
コード例 #3
0
ファイル: seg.c プロジェクト: 0x0FFF/postgres
/*
 * The GiST PickSplit method for segments
 *
 * We used to use Guttman's split algorithm here, but since the data is 1-D
 * it's easier and more robust to just sort the segments by center-point and
 * split at the middle.
 */
GIST_SPLITVEC *
gseg_picksplit(GistEntryVector *entryvec,
			   GIST_SPLITVEC *v)
{
	int			i;
	SEG		   *datum_l,
			   *datum_r,
			   *seg;
	gseg_picksplit_item *sort_items;
	OffsetNumber *left,
			   *right;
	OffsetNumber maxoff;
	OffsetNumber firstright;

#ifdef GIST_DEBUG
	fprintf(stderr, "picksplit\n");
#endif

	/* Valid items in entryvec->vector[] are indexed 1..maxoff */
	maxoff = entryvec->n - 1;

	/*
	 * Prepare the auxiliary array and sort it.
	 */
	sort_items = (gseg_picksplit_item *)
		palloc(maxoff * sizeof(gseg_picksplit_item));
	for (i = 1; i <= maxoff; i++)
	{
		seg = (SEG *) DatumGetPointer(entryvec->vector[i].key);
		/* center calculation is done this way to avoid possible overflow */
		sort_items[i - 1].center = seg->lower * 0.5f + seg->upper * 0.5f;
		sort_items[i - 1].index = i;
		sort_items[i - 1].data = seg;
	}
	qsort(sort_items, maxoff, sizeof(gseg_picksplit_item),
		  gseg_picksplit_item_cmp);

	/* sort items below "firstright" will go into the left side */
	firstright = maxoff / 2;

	v->spl_left = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
	v->spl_right = (OffsetNumber *) palloc(maxoff * sizeof(OffsetNumber));
	left = v->spl_left;
	v->spl_nleft = 0;
	right = v->spl_right;
	v->spl_nright = 0;

	/*
	 * Emit segments to the left output page, and compute its bounding box.
	 */
	datum_l = (SEG *) palloc(sizeof(SEG));
	memcpy(datum_l, sort_items[0].data, sizeof(SEG));
	*left++ = sort_items[0].index;
	v->spl_nleft++;
	for (i = 1; i < firstright; i++)
	{
		datum_l = seg_union(datum_l, sort_items[i].data);
		*left++ = sort_items[i].index;
		v->spl_nleft++;
	}

	/*
	 * Likewise for the right page.
	 */
	datum_r = (SEG *) palloc(sizeof(SEG));
	memcpy(datum_r, sort_items[firstright].data, sizeof(SEG));
	*right++ = sort_items[firstright].index;
	v->spl_nright++;
	for (i = firstright + 1; i < maxoff; i++)
	{
		datum_r = seg_union(datum_r, sort_items[i].data);
		*right++ = sort_items[i].index;
		v->spl_nright++;
	}

	v->spl_ldatum = PointerGetDatum(datum_l);
	v->spl_rdatum = PointerGetDatum(datum_r);

	return v;
}
コード例 #4
0
ファイル: seg.c プロジェクト: adunstan/pg-cvs-mirror
/*
** The GiST PickSplit method for segments
** We use Guttman's poly time split algorithm
*/
GIST_SPLITVEC *
gseg_picksplit(GistEntryVector *entryvec,
               GIST_SPLITVEC *v)
{
    OffsetNumber i,
                 j;
    SEG		   *datum_alpha,
               *datum_beta;
    SEG		   *datum_l,
               *datum_r;
    SEG		   *union_d,
               *union_dl,
               *union_dr;
    SEG		   *inter_d;
    bool		firsttime;
    float		size_alpha,
                size_beta,
                size_union,
                size_inter;
    float		size_waste,
                waste;
    float		size_l,
                size_r;
    int			nbytes;
    OffsetNumber seed_1 = 1,
                 seed_2 = 2;
    OffsetNumber *left,
                 *right;
    OffsetNumber maxoff;

#ifdef GIST_DEBUG
    fprintf(stderr, "picksplit\n");
#endif

    maxoff = entryvec->n - 2;
    nbytes = (maxoff + 2) * sizeof(OffsetNumber);
    v->spl_left = (OffsetNumber *) palloc(nbytes);
    v->spl_right = (OffsetNumber *) palloc(nbytes);

    firsttime = true;
    waste = 0.0;

    for (i = FirstOffsetNumber; i < maxoff; i = OffsetNumberNext(i))
    {
        datum_alpha = (SEG *) DatumGetPointer(entryvec->vector[i].key);
        for (j = OffsetNumberNext(i); j <= maxoff; j = OffsetNumberNext(j))
        {
            datum_beta = (SEG *) DatumGetPointer(entryvec->vector[j].key);

            /* compute the wasted space by unioning these guys */
            /* size_waste = size_union - size_inter; */
            union_d = seg_union(datum_alpha, datum_beta);
            rt_seg_size(union_d, &size_union);
            inter_d = seg_inter(datum_alpha, datum_beta);
            rt_seg_size(inter_d, &size_inter);
            size_waste = size_union - size_inter;

            /*
             * are these a more promising split that what we've already seen?
             */
            if (size_waste > waste || firsttime)
            {
                waste = size_waste;
                seed_1 = i;
                seed_2 = j;
                firsttime = false;
            }
        }
    }

    left = v->spl_left;
    v->spl_nleft = 0;
    right = v->spl_right;
    v->spl_nright = 0;

    datum_alpha = (SEG *) DatumGetPointer(entryvec->vector[seed_1].key);
    datum_l = seg_union(datum_alpha, datum_alpha);
    rt_seg_size(datum_l, &size_l);
    datum_beta = (SEG *) DatumGetPointer(entryvec->vector[seed_2].key);
    datum_r = seg_union(datum_beta, datum_beta);
    rt_seg_size(datum_r, &size_r);

    /*
     * 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
     * page.
     *
     * For efficiency, we also place the new index tuple in this loop. This is
     * handled at the very end, when we have placed all the existing tuples
     * and i == maxoff + 1.
     */

    maxoff = OffsetNumberNext(maxoff);
    for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i))
    {
        /*
         * 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 least enlargement in order to store the item.
         */

        if (i == seed_1)
        {
            *left++ = i;
            v->spl_nleft++;
            continue;
        }
        else if (i == seed_2)
        {
            *right++ = i;
            v->spl_nright++;
            continue;
        }

        /* okay, which page needs least enlargement? */
        datum_alpha = (SEG *) DatumGetPointer(entryvec->vector[i].key);
        union_dl = seg_union(datum_l, datum_alpha);
        union_dr = seg_union(datum_r, datum_alpha);
        rt_seg_size(union_dl, &size_alpha);
        rt_seg_size(union_dr, &size_beta);

        /* pick which page to add it to */
        if (size_alpha - size_l < size_beta - size_r)
        {
            datum_l = union_dl;
            size_l = size_alpha;
            *left++ = i;
            v->spl_nleft++;
        }
        else
        {
            datum_r = union_dr;
            size_r = size_alpha;
            *right++ = i;
            v->spl_nright++;
        }
    }
    *left = *right = FirstOffsetNumber; /* sentinel value, see dosplit() */

    v->spl_ldatum = PointerGetDatum(datum_l);
    v->spl_rdatum = PointerGetDatum(datum_r);

    return v;
}