1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36: #include <stdlib.h>
37: #define LIBGAUCHE_BODY
38: #include "gauche.h"
39:
40:
41:
42:
43:
44: int Scm_Compare(ScmObj x, ScmObj y)
45: {
46: ScmClass *cx, *cy;
47:
48:
49: if (SCM_NUMBERP(x) && SCM_NUMBERP(y))
50: return Scm_NumCmp(x, y);
51: if (SCM_STRINGP(x) && SCM_STRINGP(y))
52: return Scm_StringCmp(SCM_STRING(x), SCM_STRING(y));
53: if (SCM_CHARP(x) && SCM_CHARP(y))
54: return SCM_CHAR_VALUE(x) == SCM_CHAR_VALUE(y)? 0 :
55: SCM_CHAR_VALUE(x) < SCM_CHAR_VALUE(y)? -1 : 1;
56:
57: cx = Scm_ClassOf(x);
58: cy = Scm_ClassOf(y);
59: if (Scm_SubtypeP(cx, cy)) {
60: if (cy->compare) return cy->compare(x, y, FALSE);
61: } else {
62: if (cx->compare) return cx->compare(x, y, FALSE);
63: }
64: Scm_Error("can't compare %S and %S", x, y);
65: return 0;
66: }
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99: static inline void shift_up(ScmObj *elts, int root, int nelts,
100: int (*cmp)(ScmObj, ScmObj, ScmObj), ScmObj data)
101: {
102: int l = root+1, maxchild;
103: while (l*2 <= nelts) {
104: if (l*2 == nelts) {
105: maxchild = nelts-1;
106: } else if (cmp(elts[l*2-1], elts[l*2], data) < 0) {
107: maxchild = l*2;
108: } else {
109: maxchild = l*2-1;
110: }
111: if (cmp(elts[l-1], elts[maxchild], data) < 0) {
112: ScmObj tmp = elts[maxchild];
113: elts[maxchild] = elts[l-1];
114: elts[l-1] = tmp;
115: l = maxchild+1;
116: } else {
117: break;
118: }
119: }
120: }
121:
122: static void sort_h(ScmObj *elts, int nelts,
123: int (*cmp)(ScmObj, ScmObj, ScmObj), ScmObj data)
124: {
125: int l, r;
126: for (l=nelts/2-1; l>=0; l--) {
127: shift_up(elts, l, nelts, cmp, data);
128: }
129: for (r=nelts-1; r>=1; r--) {
130: ScmObj tmp = elts[r];
131: elts[r] = elts[0];
132: elts[0] = tmp;
133: shift_up(elts, 0, r, cmp, data);
134: }
135: }
136:
137:
138: static void sort_q(ScmObj *elts, int lo, int hi, int depth, int limit,
139: int (*cmp)(ScmObj, ScmObj, ScmObj), ScmObj data)
140: {
141: while (lo < hi) {
142: if (depth >= limit) {
143: sort_h(elts+lo, (hi-lo+1), cmp, data);
144: break;
145: } else {
146: int l = lo, r = hi;
147: ScmObj pivot = elts[lo], tmp;
148: while (l <= r) {
149: while (l <= r && cmp(elts[l], pivot, data) < 0) l++;
150: while (l <= r && cmp(pivot, elts[r], data) < 0) r--;
151: if (l > r) break;
152: tmp = elts[l]; elts[l] = elts[r]; elts[r] = tmp;
153: l++;
154: r--;
155: }
156: if (lo < r) sort_q(elts, lo, r, depth+1, limit, cmp, data);
157:
158:
159: lo = l;
160: depth++;
161: }
162: }
163: }
164:
165: static int cmp_scm(ScmObj x, ScmObj y, ScmObj fn)
166: {
167: ScmObj r = Scm_ApplyRec(fn, SCM_LIST2(x, y));
168: if (SCM_TRUEP(r) || (SCM_INTP(r) && SCM_INT_VALUE(r) < 0))
169: return -1;
170: else
171: return 1;
172: }
173:
174: static int cmp_int(ScmObj x, ScmObj y, ScmObj dummy)
175: {
176: return Scm_Compare(x, y);
177: }
178:
179: void Scm_SortArray(ScmObj *elts, int nelts, ScmObj cmpfn)
180: {
181: int limit, i;
182: if (nelts <= 1) return;
183:
184: for (i=nelts,limit=1; i > 0; limit++) {i>>=1;}
185: if (SCM_PROCEDUREP(cmpfn)) {
186: sort_q(elts, 0, nelts-1, 0, limit, cmp_scm, cmpfn);
187: } else {
188: sort_q(elts, 0, nelts-1, 0, limit, cmp_int, NULL);
189: }
190: }
191:
192:
193:
194:
195:
196: #define STATIC_SIZE 32
197:
198: static ScmObj sort_list_int(ScmObj objs, ScmObj fn, int destructive)
199: {
200: ScmObj cp;
201: ScmObj starray[STATIC_SIZE], *array;
202: int len = STATIC_SIZE, i;
203: array = Scm_ListToArray(objs, &len, starray, TRUE);
204: Scm_SortArray(array, len, fn);
205: if (destructive) {
206: for (i=0, cp=objs; i<len; i++, cp = SCM_CDR(cp)) {
207: SCM_SET_CAR(cp, array[i]);
208: }
209: return objs;
210: } else {
211: return Scm_ArrayToList(array, len);
212: }
213: }
214:
215: ScmObj Scm_SortList(ScmObj objs, ScmObj fn)
216: {
217: return sort_list_int(objs, fn, FALSE);
218: }
219:
220: ScmObj Scm_SortListX(ScmObj objs, ScmObj fn)
221: {
222: return sort_list_int(objs, fn, TRUE);
223: }