Skip to content

Commit 1ba32cf

Browse files
committed
CHANGE: Use Adaptive Symmetry Partition Sort instead of Bentley & McIlroy's Qsort
1 parent 75d0f0d commit 1ba32cf

File tree

4 files changed

+203
-3
lines changed

4 files changed

+203
-3
lines changed

.version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
3.21.0
1+
3.21.1

NOTICE

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ Credits for Non-REBOL orginated C files and modules
6363
* qsort:
6464
Copyright (c) 1992, 1993 The Regents of the University of California.
6565

66+
* Adaptive Symmetry Partition Sort:
67+
Copyright (C) 2012, Jingchao Chen
68+
6669
* UTF-8 decoder:
6770
Copyright (c) 2008-2010 Bjoern Hoehrmann <bjoern@hoehrmann.de>
6871

make/rebol3.nest

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ temp: %make/tmp/
1818
stack-size: 4194304 ;= 4MB (4 * 1024 * 1024)
1919
optimize: 2
2020

21-
version: 3.21.0
21+
version: 3.21.1
2222

2323
;flags: "-ggdb3"
2424
;define: DEBUG
@@ -182,7 +182,8 @@ core-files: [
182182
%core/f-int.c
183183
%core/f-math.c
184184
%core/f-modify.c
185-
%core/f-qsort.c
185+
; %core/f-qsort.c ;pathologically slow for large partially sorted inputs
186+
%core/f-adp-symmetry-psort.c
186187
%core/f-random.c
187188
%core/f-round.c
188189
%core/f-series.c

src/core/f-adp-symmetry-psort.c

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
/* Date : 2011/03/04, version 2.0 */
2+
/* Copyright (C) 2012, Jingchao Chen */
3+
/* This library was written at Donghua University, China */
4+
/* Contact: chen-jc@dhu.edu.cn or chenjingchao@yahoo.com */
5+
/* https://arxiv.org/pdf/0706.0046 */
6+
/* */
7+
/* Permission to use, copy, modify, and distribute this software and its */
8+
/* documentation with or without modifications and for any purpose and */
9+
/* without fee is hereby granted, provided that any copyright notices */
10+
/* appear in all copies and that both those copyright notices and this */
11+
/* permission notice appear in supporting documentation, and that the */
12+
/* names of the contributors or copyright holders not be used in */
13+
/* advertising or publicity pertaining to distribution of the software */
14+
/* without specific prior permission. */
15+
/* */
16+
/* THE CONTRIBUTORS AND COPYRIGHT HOLDERS OF THIS SOFTWARE DISCLAIM ALL */
17+
/* WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED */
18+
/* WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL THE */
19+
/* CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT */
20+
/* OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS */
21+
/* OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE */
22+
/* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE */
23+
/* OR PERFORMANCE OF THIS SOFTWARE */
24+
25+
26+
#include <stdlib.h>
27+
28+
#define Adp_SymPSort reb_qsort
29+
30+
// the code for the sorting algorithm begins
31+
#define swapvector(TYPE,pi,pj,n) \
32+
do { \
33+
TYPE t= *(TYPE *) (pi); \
34+
*(TYPE *) (pi) = *(TYPE *) (pj); \
35+
*(TYPE *) (pj) = t; \
36+
pi+=sizeof(TYPE); pj+=sizeof(TYPE); \
37+
n-=sizeof(TYPE); \
38+
} while (n > 0)
39+
40+
void swapfunc(char *a, char *b, int n, int swaptype)
41+
{ if (swaptype <=1 ) swapvector(long,a,b,n);
42+
else swapvector(char,a,b,n);
43+
}
44+
45+
#define swap(a,b) \
46+
if (swaptype == 0) { \
47+
long t = * (long *) (a); \
48+
* (long *) (a) = * (long *) (b); \
49+
* (long *) (b) = t; \
50+
} \
51+
else swapfunc(a,b,es,swaptype)
52+
53+
#define SWAPINIT(a,es) swaptype = \
54+
(a - (char *) 0) % sizeof(long) || es % sizeof(long) ? 2 : \
55+
es == sizeof(long) ? 0 : 1
56+
57+
#define p 16
58+
#define beta1 256
59+
#define beta2 512
60+
// Symmetry Partition Sort
61+
void SymPartitionSort(char *a, int s, int n, int es, int (*cmp)(const void *,const void *))
62+
{ char *pm,*pb,*pc,*pi,*pj;
63+
int i,v,vL,m,left,right,swaptype,sp,eq,ineq,rc;
64+
left=right=0;
65+
SWAPINIT(a,es);
66+
while(1){
67+
if(n < 8){ //Insertion sort on small arrays
68+
for (s=1; s < n; s++)
69+
for (pb = a+s*es; cmp(pb-es,pb) > 0; ) {
70+
swap(pb,pb-es); pb-=es;
71+
if(pb <= a) break;
72+
}
73+
return;
74+
}
75+
m= s<0 ? -s:s;
76+
if(m <= 2){//First,middle,last items are ordered and placed 1st,2nd and last
77+
v = beta2 > n ? n : 63;
78+
pc=a+(v-1)*es;
79+
pm=a+es;
80+
swap(pm,a+(v/2)*es);
81+
if(cmp(a, pm) > 0) {swap(a,pm);}
82+
if((cmp(pm, pc) > 0)) {
83+
swap(pm,pc);
84+
if((cmp(a, pm) > 0)) {swap(a,pm);}
85+
}
86+
left=right=1; pc-=es;
87+
}
88+
else{
89+
v=m > n/beta1 ? n : p*m-1;
90+
if(s < 0) { //Move sorted items to left end
91+
if(v<n) {left=m; s=-s;}
92+
else {left=(m+1)/2; right=m/2;}
93+
swapfunc(a, a+(n-m)*es, left*es, swaptype);
94+
left--;
95+
}
96+
if(s>0){
97+
pb=a+m*es; pc=a+v*es;
98+
if(v < n){ //Extract sampling items
99+
sp=(n/v)*es; pj=pb; pi=pb;
100+
for(; pi < pc; pi+=es, pj+=sp) swap(pi,pj);
101+
}
102+
i=right=m/2; //Right move sorted items
103+
do{ pb-=es; pc-=es; swap(pb,pc); i--;} while (i);
104+
left=(m-1)/2;
105+
}
106+
pm=a+left*es; pc=pm+(v-m)*es;
107+
}
108+
//Fat partition begins
109+
pb=pi=pm+es;
110+
do {
111+
while ( (rc=cmp(pb,pm)) < 0 ) pb+=es;
112+
if(pb >= pc) break;
113+
if(rc==0){
114+
if(pi!=pb) {swap(pb,pi);}
115+
pi+=es; pb+=es;
116+
continue;
117+
}
118+
while ((rc=cmp(pc,pm)) > 0 ) pc-=es;
119+
if(pb >= pc) break;
120+
swap(pb,pc);
121+
if(rc==0){
122+
if(pi!=pb) { swap(pb,pi);}
123+
pi+=es;
124+
}
125+
pb+=es; pc-=es;
126+
} while (pb <= pc);
127+
//Move equal-key items
128+
eq=pi-pm, ineq=pb-pi;
129+
if( ineq < eq) pi=pm+ineq;
130+
pc=pb;
131+
while (pm < pi ) { pc-=es; swap(pc,pm); pm+=es;}
132+
//Fat partition ends
133+
vL=(pb-a)/es;
134+
if(right < v-vL) SymPartitionSort(pb, -right, v-vL, es, cmp);
135+
vL=vL-eq/es;
136+
if(v < n){
137+
if(left < vL) SymPartitionSort(a, left,vL,es,cmp);
138+
s=v; //Remove tail recursion
139+
}
140+
else{
141+
if(left >= vL) return;
142+
s=left; n=vL; //Remove tail recursion
143+
}
144+
}
145+
}
146+
147+
// Adaptive Symmetry Partition Sort
148+
void Adp_SymPSort(void *a, int n, int es, int (*cmp)(const void *,const void *))
149+
{ char *pb,*pc,*pi,*pj;
150+
int swaptype,i,j,ne,rc,D_inv,left,m,Rev=0;
151+
152+
SWAPINIT((char *)a,es);
153+
//Find 1st run
154+
ne = n * es;
155+
for (i=es; i < ne; i+=es){
156+
if((rc=cmp((char *)a+i-es, (char *)a+i)) != 0 ){
157+
if(Rev==0) Rev= rc < 0 ? 1 : -1;//Rev=1: increasing, -1: decreasing
158+
else if(rc*Rev > 0) break;
159+
}
160+
}
161+
D_inv= Rev*(i/es); //D_inv: difference of inversions & orders
162+
for(j=i+es; j < ne; j+=(97*es)){
163+
if((rc=cmp((char *)a+j-es, (char *)a+j)) < 0) D_inv++;
164+
if(rc>0) D_inv--;
165+
}
166+
pb=(char *)a+i-es;
167+
if(abs(D_inv) > n/512 ) {
168+
if(Rev*D_inv < 0) {pb=(char *)a; Rev=-Rev;} //If 1st run is reverse, re-find it
169+
pc=(char *)a+n*es; pj=pb;
170+
while(1){
171+
pj=pj+10*es; pi=pj-es;
172+
if(pj >= pc) break;
173+
while (pj < pc && Rev*cmp(pj-es, pj) <=0) pj+=es; //Find next run foreward
174+
while (pi > pb && Rev*cmp(pi-es, pi) <=0) pi-=es; //Find next run backward
175+
if(pj-pi < 4*es) continue;
176+
if(pb!=a) { //Find knots in 1st and 2nd run
177+
j=((pj-pi)/es)/2;
178+
m=((pb-(char *)a)/es)/4;
179+
if (j > m ) j=m;
180+
for(i=0; i<j; i++) if(Rev*cmp(pb-i*es,pi+i*es) <= 0) break;
181+
if(i>=j) continue;
182+
pb=pb+(1-i)*es; pi=pi+i*es;
183+
}
184+
// Merge two runs by moving 2nd knot to 1st knot
185+
if(pi!=pb) while(pi < pj ) { swap(pb,pi); pb+=es; pi+=es;}
186+
else pb=pj;
187+
pb-=es;
188+
}
189+
}
190+
left=(pb-(char *)a)/es+1;
191+
if(Rev==-1){ //if the longest run reverse, reverse it
192+
pc=(char *)a;
193+
while(pc < pb ) {swap(pc,pb); pc+=es; pb-=es; }
194+
}
195+
if(left < n) SymPartitionSort((char *)a, left, n, es, cmp);
196+
}

0 commit comments

Comments
 (0)