⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gdk_ssort.c

📁 这个是内存数据库中的一个管理工具
💻 C
📖 第 1 页 / 共 5 页
字号:
	SucceedB:		if (nb)			COPY(PTRADD(dest, 1 - nb, ms->width), baseb, nb * ms->width);		return 0;	CopyA:		assert(nb == 1 && na > 0);		/* The first element of pb belongs at the front of the merge. */		dest = PTRADD(dest, -na, ms->width);		pa = PTRADD(pa, -na, ms->width);		memmove(PTRADD(dest, 1, ms->width),			PTRADD(pa, 1, ms->width),			na * ms->width);		COPY(dest, pb, ms->width);		return 0;	}}#line 741 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_ssort.mx"#endif#ifndef NOEXPAND_BTE#line 199 "/export/scratch0/monet/monet.GNU.64.64.d.14791/MonetDB/src/gdk/gdk_ssort.mx"/* binarysort is the best method for sorting small arrays: it does   few compares, but can do data movement quadratic in the number of   elements.   [lo, hi) is a contiguous slice of a list, and is sorted via   binary insertion.  This sort is stable.   On entry, must have lo <= start <= hi, and that [lo, start) is already   sorted (pass start == lo if you don't know!). */static voidbinarysort_bte(void *lo, void *hi, void *start, MergeState *ms){	register void *l, *p, *r;	assert(lo <= start && start <= hi);	/* assert [lo, start) is sorted */	if (lo == start)		start = PTRADD(start, 1, ms->width);	/* [lo,start) is sorted, insert start (the pivot) into this	   area, finding its position using binary search. */	for (; start < hi; start = PTRADD(start, 1, ms->width)) {		/* set l to where start belongs */		l = lo;		r = start;		/* ms->t is the pivot */		COPY(ms->t, r, ms->width);		/* Invariants:		   pivot >= all in [lo, l).		   pivot  < all in [r, start).		   The second is vacuously true at the start.		 */		assert(l < r);		do {			p = PTRADD(l, (((char *) r - (char *) l) / ms->width) >> 1, ms->width);			if (ISLT_bte(ms->t, p, ms))				r = p;			else				l = PTRADD(p, 1, ms->width);		} while (l < r);		assert(l == r);		/* The invariants still hold, so pivot >= all in [lo, l) and		   pivot < all in [l, start), so pivot belongs at l.  Note		   that if there are elements equal to pivot, l points to the		   first slot after them -- that's why this sort is stable.		   Slide over to make room.		   Caution: using memmove is much slower under MSVC 5;		   we're not usually moving many slots. */		for (p = start, r = PTRADD(p, -1, ms->width); p > l; p = r, r = PTRADD(p, -1, ms->width))			COPY(p, r, ms->width);		COPY(l, ms->t, ms->width);	}}/* Locate the proper position of key in a sorted vector; if the vector contains   an element equal to key, return the position immediately to the left of   the leftmost equal element.  [gallop_right() does the same except returns   the position to the right of the rightmost equal element (if any).]   "a" is a sorted vector with n elements, starting at a[0].  n must be > 0.   "hint" is an index at which to begin the search, 0 <= hint < n.  The closer   hint is to the final result, the faster this runs.   The return value is the int k in 0..n such that	a[k-1] < key <= a[k]   pretending that *(a-1) is minus infinity and a[n] is plus infinity.  IOW,   key belongs at index k; or, IOW, the first k elements of a should precede   key, and the last n-k should follow key.   Returns -1 on error.  See listsort.txt for info on the method. */static ssize_tgallop_left_bte(void *key, void *a, ssize_t n, ssize_t hint, MergeState *ms){	ssize_t ofs;	ssize_t lastofs;	ssize_t k;	assert(key && a && n > 0 && hint >= 0 && hint < n);	a = PTRADD(a, hint, ms->width);	lastofs = 0;	ofs = 1;	if (ISLT_bte(a, key, ms)) {		/* a[hint] < key -- gallop right, until		   a[hint + lastofs] < key <= a[hint + ofs]		 */		const ssize_t maxofs = n - hint;	/* &a[n-1] is highest */		while (ofs < maxofs) {			if (ISLT_bte(PTRADD(a, ofs, ms->width), key, ms)) {				lastofs = ofs;				ofs = (ofs << 1) + 1;				if (ofs <= 0)	/* int overflow */					ofs = maxofs;			} else	/* key <= a[hint + ofs] */				break;		}		if (ofs > maxofs)			ofs = maxofs;		/* Translate back to offsets relative to &a[0]. */		lastofs += hint;		ofs += hint;	} else {		/* key <= a[hint] -- gallop left, until		   a[hint - ofs] < key <= a[hint - lastofs]		 */		const ssize_t maxofs = hint + 1;	/* &a[0] is lowest */		while (ofs < maxofs) {			if (ISLT_bte(PTRADD(a, -ofs, ms->width), key, ms))				break;			/* key <= a[hint - ofs] */			lastofs = ofs;			ofs = (ofs << 1) + 1;			if (ofs <= 0)	/* int overflow */				ofs = maxofs;		}		if (ofs > maxofs)			ofs = maxofs;		/* Translate back to positive offsets relative to &a[0]. */		k = lastofs;		lastofs = hint - ofs;		ofs = hint - k;	}	a = PTRADD(a, -hint, ms->width);	assert(-1 <= lastofs && lastofs < ofs && ofs <= n);	/* Now a[lastofs] < key <= a[ofs], so key belongs somewhere to the	   right of lastofs but no farther right than ofs.  Do a binary	   search, with invariant a[lastofs-1] < key <= a[ofs].	 */	++lastofs;	while (lastofs < ofs) {		ssize_t m = lastofs + ((ofs - lastofs) >> 1);		if (ISLT_bte(PTRADD(a, m, ms->width), key, ms))			lastofs = m + 1; /* a[m] < key */		else			ofs = m;	/* key <= a[m] */	}	assert(lastofs == ofs);		/* so a[ofs-1] < key <= a[ofs] */	return ofs;}/* Exactly like gallop_left(), except that if key already exists in a[0:n],   finds the position immediately to the right of the rightmost equal value.   The return value is the int k in 0..n such that	a[k-1] <= key < a[k]   or -1 if error.   The code duplication is massive, but this is enough different given that   we're sticking to "<" comparisons that it's much harder to follow if   written as one routine with yet another "left or right?" flag. */static ssize_tgallop_right_bte(void *key, void *a, ssize_t n, ssize_t hint, MergeState *ms){	ssize_t ofs;	ssize_t lastofs;	ssize_t k;	assert(key && a && n > 0 && hint >= 0 && hint < n);	a = PTRADD(a, hint, ms->width);	lastofs = 0;	ofs = 1;	if (ISLT_bte(key, a, ms)) {		/* key < a[hint] -- gallop left, until		   a[hint - ofs] <= key < a[hint - lastofs]		 */		const ssize_t maxofs = hint + 1;	/* &a[0] is lowest */		while (ofs < maxofs) {			if (ISLT_bte(key, PTRADD(a, -ofs, ms->width), ms)) {				lastofs = ofs;				ofs = (ofs << 1) + 1;				if (ofs <= 0)	/* int overflow */					ofs = maxofs;			} else	/* a[hint - ofs] <= key */				break;		}		if (ofs > maxofs)			ofs = maxofs;		/* Translate back to positive offsets relative to &a[0]. */		k = lastofs;		lastofs = hint - ofs;		ofs = hint - k;	} else {		/* a[hint] <= key -- gallop right, until		   a[hint + lastofs] <= key < a[hint + ofs]		*/		const ssize_t maxofs = n - hint;	/* &a[n-1] is highest */		while (ofs < maxofs) {			if (ISLT_bte(key, PTRADD(a, ofs, ms->width), ms))				break;			/* a[hint + ofs] <= key */			lastofs = ofs;			ofs = (ofs << 1) + 1;			if (ofs <= 0)	/* int overflow */				ofs = maxofs;		}		if (ofs > maxofs)			ofs = maxofs;		/* Translate back to offsets relative to &a[0]. */		lastofs += hint;		ofs += hint;	}	a = PTRADD(a, -hint, ms->width);	assert(-1 <= lastofs && lastofs < ofs && ofs <= n);	/* Now a[lastofs] <= key < a[ofs], so key belongs somewhere to the	   right of lastofs but no farther right than ofs.  Do a binary	   search, with invariant a[lastofs-1] <= key < a[ofs].	 */	++lastofs;	while (lastofs < ofs) {		ssize_t m = lastofs + ((ofs - lastofs) >> 1);		if (ISLT_bte(key, PTRADD(a, m, ms->width), ms))			ofs = m;	/* key < a[m] */		else			lastofs = m+1;	/* a[m] <= key */	}	assert(lastofs == ofs);		/* so a[ofs-1] <= key < a[ofs] */	return ofs;}/* Merge the two runs at stack indices i and i+1.   Returns 0 on success, -1 on error. */static ssize_tmerge_at_bte(MergeState *ms, ssize_t i){	void *pa, *pb;	ssize_t na, nb;	ssize_t k;	assert(ms != NULL);	assert(ms->n >= 2);	assert(i >= 0);	assert(i == ms->n - 2 || i == ms->n - 3);	pa = ms->pending[i].base;	na = ms->pending[i].len;	pb = ms->pending[i + 1].base;	nb = ms->pending[i + 1].len;	assert(na > 0 && nb > 0);	assert(PTRADD(pa, na, ms->width) == pb);	/* Record the length of the combined runs; if i is the 3rd-last	   run now, also slide over the last run (which isn't involved	   in this merge).  The current run i+1 goes away in any case.	 */	ms->pending[i].len = na + nb;	if (i == ms->n - 3)		ms->pending[i + 1] = ms->pending[i + 2];	--ms->n;	/* Where does b start in a?  Elements in a before that can be	   ignored (already in place).	 */	k = gallop_right_bte(pb, pa, na, 0, ms);	pa = PTRADD(pa, k, ms->width);	na -= k;	if (na == 0)		return 0;	/* Where does a end in b?  Elements in b after that can be	   ignored (already in place).	 */	nb = gallop_left_bte(PTRADD(pa, na - 1, ms->width), pb, nb, nb-1, ms);	if (nb <= 0)		return nb;	/* Merge what remains of the runs, using a temp array with	   min(na, nb) elements.	 */	if (na <= nb) {/* Merge the na elements starting at pa with the nb elements starting at pb   in a stable way, in-place.  na and nb must be > 0, and pa + na == pb.   Must also have that *pb < *pa, that pa[na-1] belongs at the end of the   merge, and should have na <= nb.  See listsort.txt for more info.   Return 0 if successful, -1 if error. */		void *dest;		ssize_t min_gallop = ms->min_gallop;		assert(ms && pa && pb && na > 0 && nb > 0 && PTRADD(pa, na, ms->width) == pb);		if (MERGE_GETMEM(ms, na) < 0)			return -1;		COPY(ms->a, pa, na * ms->width);		dest = pa;		pa = ms->a;		COPY(dest, pb, ms->width);		dest = PTRADD(dest, 1, ms->width);		pb = PTRADD(pb, 1, ms->width);		--nb;		if (nb == 0)			goto SucceedA;		if (na == 1)			goto CopyB;		for (;;) {			ssize_t acount = 0;	/* # of times A won in a row */			ssize_t bcount = 0;	/* # of times B won in a row */			/* Do the straightforward thing until (if ever) one run			   appears to win consistently.			 */			for (;;) {				assert(na > 1 && nb > 0);				k = ISLT_bte(pb, pa, ms);				if (k) {					COPY(dest, pb, ms->width);					dest = PTRADD(dest, 1, ms->width);					pb = PTRADD(pb, 1, ms->width);					++bcount;					acount = 0;					--nb;					if (nb == 0)						goto SucceedA;					if (bcount >= min_gallop)						break;				} else {					COPY(dest, pa, ms->width);					dest = PTRADD(dest, 1, ms->width);					pa = PTRADD(pa, 1, ms->width);					++acount;					bcount = 0;					--na;					if (na == 1)						goto CopyB;					if (acount >= min_gallop)						break;				}			}			/* One run is winning so consistently that galloping may			   be a huge win.  So try that, and continue galloping until			   (if ever) neither run appears to be winning consistently			   anymore.			 */			++min_gallop;			do {				assert(na > 1 && nb > 0);				min_gallop -= min_gallop > 1;				ms->min_gallop = min_gallop;				k = gallop_right_bte(pb, pa, na, 0, ms);				acount = k;				if (k) {					COPY(dest, pa, k * ms->width);					dest = PTRADD(dest, k, ms->width);					pa = PTRADD(pa, k, ms->width);					na -= k;					if (na == 1)						goto CopyB;					/* na==0 is impossible now if the comparison					   function is consistent, but we can't assume					   that it is.					 */					if (na == 0)						goto SucceedA;				}				COPY(dest, pb, ms->width);				dest = PTRADD(dest, 1, ms->width);				pb = PTRADD(pb, 1, ms->width);				--nb;				if (nb == 0)					goto SucceedA;				k = gallop_left_bte(pa, pb, nb, 0, ms);				bcount = k;				if (k) {					memmove(dest, pb, k * ms->width);					dest = PTRADD(dest, k, ms->width);					pb = PTRADD(pb, k, ms->width);					nb -= k;					if (nb == 0)						goto SucceedA;				}				COPY(dest, pa, ms->width);				dest = PTRADD(dest, 1, ms->width);				pa = PTRADD(pa, 1, ms->width);				--na;				if (na == 1)					goto CopyB;			} while (acount >= MIN_GALLOP || bcount >= MIN_GALLOP);			++min_gallop;	/* penalize it for leaving galloping mode */			ms->min_gallop = min_gallop;		}	SucceedA:		if (na)			COPY(dest, pa, na * ms->width);		return 0;	CopyB:		assert(na == 1 && nb > 0);		/* The last element of pa belongs at the end of the merge. */		memmove(dest, pb, nb * ms->width);		COPY(PTRADD(dest, nb, ms->width), pa, ms->width);		return 0;	} else {/* Merge the na elements starting at pa with the nb elements starting at pb   in a stable way, in-place.  na and nb must be > 0, and pa + na == pb.   Must also have that *pb < *pa, that pa[na-1] belongs at the end of the   merge, and should have na >= nb.  See listsort.txt for more info.   Return 0 if successful, -1 if error. */		void *dest;		void *basea;		void *baseb;		ssize_t min_gallop = ms->min_gallop;		assert(ms && pa && pb && na > 0 && nb > 0 && PTRADD(pa, na, ms->width) == pb);		if (MERGE_GETMEM(ms, nb) < 0)			return -1;		dest = PTRADD(pb, nb - 1, ms->width);		COPY(ms->a, pb, nb * ms->width);		basea = pa;		baseb = ms->a;		pb = PTRADD(ms->a, nb - 1, ms->width);		pa = PTRADD(pa, na - 1, ms->width);		COPY(dest, pa, ms->width);		dest = PTRADD(dest, -1, ms->width);		pa = PTRADD(pa, -1, ms->width);		--na;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -