ralgorithms 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/ext/sorting/extconf.rb +8 -0
- data/ext/sorting/sorting_common.c +401 -0
- data/ext/sorting/sorting_ext.c +112 -0
- data/lib/searching/skip_list.rb +135 -0
- data/lib/sorting/bubble_sort.rb +36 -0
- data/lib/sorting/heap_sort.rb +65 -0
- data/lib/sorting/helper.rb +11 -0
- data/lib/sorting/insertion_sort.rb +73 -0
- data/lib/sorting/intro_sort.rb +72 -0
- data/lib/sorting/library_sort.rb +80 -0
- data/lib/sorting/load_ext.rb +5 -0
- data/lib/sorting/merge_sort.rb +74 -0
- data/lib/sorting/quick_sort.rb +67 -0
- data/lib/sorting/selection_sort.rb +33 -0
- data/lib/sorting/shell_sort.rb +45 -0
- data/lib/sorting/smooth_sort.rb +172 -0
- data/lib/sorting/test_helper.rb +90 -0
- data/lib/sorting/tim_sort.rb +21 -0
- metadata +21 -2
@@ -0,0 +1,8 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
$CFLAGS << " -DRUBY19" if RUBY_VERSION >= '1.9.0'
|
3
|
+
$CFLAGS << " -DRUBY186" if RUBY_VERSION < '1.8.7'
|
4
|
+
$CFLAGS << " -Wall " unless RUBY_PLATFORM =~ /solaris/
|
5
|
+
$CFLAGS << ' -g -ggdb -rdynamic -O0 -DDEBUG' if ENV['DEBUG']
|
6
|
+
$CFLAGS << " -Wconversion -Wsign-compare -Wno-unused-parameter -Wwrite-strings -Wpointer-arith -fno-common -pedantic -Wno-long-long" if ENV['STRICT']
|
7
|
+
$CFLAGS << (ENV['CFLAGS'] || '')
|
8
|
+
create_makefile("sorting_ext")
|
@@ -0,0 +1,401 @@
|
|
1
|
+
#include "ruby/ruby.h"
|
2
|
+
#include <assert.h>
|
3
|
+
|
4
|
+
const char*
|
5
|
+
obj_inspect(VALUE obj) {
|
6
|
+
VALUE str = rb_funcall(obj, rb_intern("inspect"), 0);
|
7
|
+
const char * result = RSTRING_PTR(str);
|
8
|
+
return result;
|
9
|
+
}
|
10
|
+
|
11
|
+
void
|
12
|
+
print_ruby_obj(const char* prefix, VALUE obj)
|
13
|
+
{
|
14
|
+
const char* str = obj_inspect(obj);
|
15
|
+
printf("%s: %s\n", prefix, str);
|
16
|
+
}
|
17
|
+
|
18
|
+
void
|
19
|
+
printp_ruby_obj(const char* prefix, void* base)
|
20
|
+
{
|
21
|
+
VALUE obj = *(const VALUE*)base;
|
22
|
+
print_ruby_obj(prefix, obj);
|
23
|
+
}
|
24
|
+
|
25
|
+
static ID id_cmp;
|
26
|
+
struct ary_sort_data {
|
27
|
+
VALUE ary;
|
28
|
+
int opt_methods;
|
29
|
+
int opt_inited;
|
30
|
+
};
|
31
|
+
enum {
|
32
|
+
sort_opt_Fixnum,
|
33
|
+
sort_opt_String,
|
34
|
+
sort_optimizable_count
|
35
|
+
};
|
36
|
+
|
37
|
+
#define STRING_P(s) (TYPE(s) == T_STRING && CLASS_OF(s) == rb_cString)
|
38
|
+
|
39
|
+
#define SORT_OPTIMIZABLE_BIT(type) (1U << TOKEN_PASTE(sort_opt_,type))
|
40
|
+
#define SORT_OPTIMIZABLE(data, type) \
|
41
|
+
((data->opt_inited & SORT_OPTIMIZABLE_BIT(type)) ? \
|
42
|
+
(data->opt_methods & SORT_OPTIMIZABLE_BIT(type)) : \
|
43
|
+
((data->opt_inited |= SORT_OPTIMIZABLE_BIT(type)), \
|
44
|
+
rb_method_basic_definition_p(TOKEN_PASTE(rb_c,type), id_cmp) && \
|
45
|
+
(data->opt_methods |= SORT_OPTIMIZABLE_BIT(type))))
|
46
|
+
|
47
|
+
# define ARY_SHARED_P(ary) \
|
48
|
+
(assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
|
49
|
+
FL_TEST(ary,ELTS_SHARED)!=0)
|
50
|
+
# define ARY_EMBED_P(ary) \
|
51
|
+
(assert(!FL_TEST(ary, ELTS_SHARED) || !FL_TEST(ary, RARRAY_EMBED_FLAG)), \
|
52
|
+
FL_TEST(ary, RARRAY_EMBED_FLAG)!=0)
|
53
|
+
|
54
|
+
#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr)
|
55
|
+
#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len)
|
56
|
+
#define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary)
|
57
|
+
#define ARY_EMBED_LEN(a) \
|
58
|
+
(assert(ARY_EMBED_P(a)), \
|
59
|
+
(long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \
|
60
|
+
(RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT)))
|
61
|
+
|
62
|
+
#define ARY_OWNS_HEAP_P(a) (!FL_TEST(a, ELTS_SHARED|RARRAY_EMBED_FLAG))
|
63
|
+
#define FL_SET_EMBED(a) do { \
|
64
|
+
assert(!ARY_SHARED_P(a)); \
|
65
|
+
assert(!OBJ_FROZEN(a)); \
|
66
|
+
FL_SET(a, RARRAY_EMBED_FLAG); \
|
67
|
+
} while (0)
|
68
|
+
#define FL_UNSET_EMBED(ary) FL_UNSET(ary, RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK)
|
69
|
+
#define FL_SET_SHARED(ary) do { \
|
70
|
+
assert(!ARY_EMBED_P(ary)); \
|
71
|
+
FL_SET(ary, ELTS_SHARED); \
|
72
|
+
} while (0)
|
73
|
+
#define FL_UNSET_SHARED(ary) FL_UNSET(ary, ELTS_SHARED)
|
74
|
+
|
75
|
+
#define ARY_SET_PTR(ary, p) do { \
|
76
|
+
assert(!ARY_EMBED_P(ary)); \
|
77
|
+
assert(!OBJ_FROZEN(ary)); \
|
78
|
+
RARRAY(ary)->as.heap.ptr = (p); \
|
79
|
+
} while (0)
|
80
|
+
#define ARY_SET_EMBED_LEN(ary, n) do { \
|
81
|
+
long tmp_n = n; \
|
82
|
+
assert(ARY_EMBED_P(ary)); \
|
83
|
+
assert(!OBJ_FROZEN(ary)); \
|
84
|
+
RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \
|
85
|
+
RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \
|
86
|
+
} while (0)
|
87
|
+
#define ARY_SET_HEAP_LEN(ary, n) do { \
|
88
|
+
assert(!ARY_EMBED_P(ary)); \
|
89
|
+
RARRAY(ary)->as.heap.len = n; \
|
90
|
+
} while (0)
|
91
|
+
#define ARY_SET_LEN(ary, n) do { \
|
92
|
+
if (ARY_EMBED_P(ary)) { \
|
93
|
+
ARY_SET_EMBED_LEN(ary, n); \
|
94
|
+
} \
|
95
|
+
else { \
|
96
|
+
ARY_SET_HEAP_LEN(ary, n); \
|
97
|
+
} \
|
98
|
+
assert(RARRAY_LEN(ary) == n); \
|
99
|
+
} while (0)
|
100
|
+
#define ARY_INCREASE_PTR(ary, n) do { \
|
101
|
+
assert(!ARY_EMBED_P(ary)); \
|
102
|
+
assert(!OBJ_FROZEN(ary)); \
|
103
|
+
RARRAY(ary)->as.heap.ptr += n; \
|
104
|
+
} while (0)
|
105
|
+
#define ARY_INCREASE_LEN(ary, n) do { \
|
106
|
+
assert(!OBJ_FROZEN(ary)); \
|
107
|
+
if (ARY_EMBED_P(ary)) { \
|
108
|
+
ARY_SET_EMBED_LEN(ary, RARRAY_LEN(ary)+n); \
|
109
|
+
} \
|
110
|
+
else { \
|
111
|
+
RARRAY(ary)->as.heap.len += n; \
|
112
|
+
} \
|
113
|
+
} while (0)
|
114
|
+
|
115
|
+
#define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? RARRAY_EMBED_LEN_MAX : \
|
116
|
+
ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : RARRAY(ary)->as.heap.aux.capa)
|
117
|
+
#define ARY_SET_CAPA(ary, n) do { \
|
118
|
+
assert(!ARY_EMBED_P(ary)); \
|
119
|
+
assert(!ARY_SHARED_P(ary)); \
|
120
|
+
assert(!OBJ_FROZEN(ary)); \
|
121
|
+
RARRAY(ary)->as.heap.aux.capa = (n); \
|
122
|
+
} while (0)
|
123
|
+
|
124
|
+
#define ARY_SHARED(ary) (assert(ARY_SHARED_P(ary)), RARRAY(ary)->as.heap.aux.shared)
|
125
|
+
#define ARY_SET_SHARED(ary, value) do { \
|
126
|
+
assert(!ARY_EMBED_P(ary)); \
|
127
|
+
assert(ARY_SHARED_P(ary)); \
|
128
|
+
assert(ARY_SHARED_ROOT_P(value)); \
|
129
|
+
RARRAY(ary)->as.heap.aux.shared = (value); \
|
130
|
+
} while (0)
|
131
|
+
#define RARRAY_SHARED_ROOT_FLAG FL_USER5
|
132
|
+
#define ARY_SHARED_ROOT_P(ary) (FL_TEST(ary, RARRAY_SHARED_ROOT_FLAG))
|
133
|
+
#define ARY_SHARED_NUM(ary) \
|
134
|
+
(assert(ARY_SHARED_ROOT_P(ary)), RARRAY(ary)->as.heap.aux.capa)
|
135
|
+
#define ARY_SET_SHARED_NUM(ary, value) do { \
|
136
|
+
assert(ARY_SHARED_ROOT_P(ary)); \
|
137
|
+
RARRAY(ary)->as.heap.aux.capa = (value); \
|
138
|
+
} while (0)
|
139
|
+
#define FL_SET_SHARED_ROOT(ary) do { \
|
140
|
+
assert(!ARY_EMBED_P(ary)); \
|
141
|
+
FL_SET(ary, RARRAY_SHARED_ROOT_FLAG); \
|
142
|
+
} while (0)
|
143
|
+
|
144
|
+
static VALUE
|
145
|
+
rb_ary_increment_share(VALUE shared)
|
146
|
+
{
|
147
|
+
long num = ARY_SHARED_NUM(shared);
|
148
|
+
if (num >= 0) {
|
149
|
+
ARY_SET_SHARED_NUM(shared, num + 1);
|
150
|
+
}
|
151
|
+
return shared;
|
152
|
+
}
|
153
|
+
|
154
|
+
static void
|
155
|
+
rb_ary_decrement_share(VALUE shared)
|
156
|
+
{
|
157
|
+
if (shared) {
|
158
|
+
long num = ARY_SHARED_NUM(shared) - 1;
|
159
|
+
if (num == 0) {
|
160
|
+
rb_ary_free(shared);
|
161
|
+
rb_gc_force_recycle(shared);
|
162
|
+
}
|
163
|
+
else if (num > 0) {
|
164
|
+
ARY_SET_SHARED_NUM(shared, num);
|
165
|
+
}
|
166
|
+
}
|
167
|
+
}
|
168
|
+
|
169
|
+
static void
|
170
|
+
rb_ary_unshare(VALUE ary)
|
171
|
+
{
|
172
|
+
VALUE shared = RARRAY(ary)->as.heap.aux.shared;
|
173
|
+
rb_ary_decrement_share(shared);
|
174
|
+
FL_UNSET_SHARED(ary);
|
175
|
+
}
|
176
|
+
|
177
|
+
static VALUE
|
178
|
+
ary_make_shared(VALUE ary)
|
179
|
+
{
|
180
|
+
assert(!ARY_EMBED_P(ary));
|
181
|
+
if (ARY_SHARED_P(ary)) {
|
182
|
+
return ARY_SHARED(ary);
|
183
|
+
}
|
184
|
+
else if (ARY_SHARED_ROOT_P(ary)) {
|
185
|
+
return ary;
|
186
|
+
}
|
187
|
+
else if (OBJ_FROZEN(ary)) {
|
188
|
+
ary_resize_capa(ary, ARY_HEAP_LEN(ary));
|
189
|
+
FL_SET_SHARED_ROOT(ary);
|
190
|
+
ARY_SET_SHARED_NUM(ary, 1);
|
191
|
+
return ary;
|
192
|
+
}
|
193
|
+
else {
|
194
|
+
NEWOBJ(shared, struct RArray);
|
195
|
+
OBJSETUP(shared, 0, T_ARRAY);
|
196
|
+
FL_UNSET_EMBED(shared);
|
197
|
+
|
198
|
+
ARY_SET_LEN((VALUE)shared, RARRAY_LEN(ary));
|
199
|
+
ARY_SET_PTR((VALUE)shared, RARRAY_PTR(ary));
|
200
|
+
FL_SET_SHARED_ROOT(shared);
|
201
|
+
ARY_SET_SHARED_NUM((VALUE)shared, 1);
|
202
|
+
FL_SET_SHARED(ary);
|
203
|
+
ARY_SET_SHARED(ary, (VALUE)shared);
|
204
|
+
OBJ_FREEZE(shared);
|
205
|
+
return (VALUE)shared;
|
206
|
+
}
|
207
|
+
}
|
208
|
+
static VALUE
|
209
|
+
ary_make_substitution(VALUE ary)
|
210
|
+
{
|
211
|
+
if (RARRAY_LEN(ary) <= RARRAY_EMBED_LEN_MAX) {
|
212
|
+
VALUE subst = rb_ary_new2(RARRAY_LEN(ary));
|
213
|
+
MEMCPY(ARY_EMBED_PTR(subst), RARRAY_PTR(ary), VALUE, RARRAY_LEN(ary));
|
214
|
+
ARY_SET_EMBED_LEN(subst, RARRAY_LEN(ary));
|
215
|
+
return subst;
|
216
|
+
}
|
217
|
+
else {
|
218
|
+
return rb_ary_increment_share(ary_make_shared(ary));
|
219
|
+
}
|
220
|
+
}
|
221
|
+
|
222
|
+
static VALUE
|
223
|
+
sort_reentered(VALUE ary)
|
224
|
+
{
|
225
|
+
if (RBASIC(ary)->klass) {
|
226
|
+
rb_raise(rb_eRuntimeError, "sort reentered");
|
227
|
+
}
|
228
|
+
return Qnil;
|
229
|
+
}
|
230
|
+
|
231
|
+
static inline void
|
232
|
+
rb_ary_modify_check(VALUE ary)
|
233
|
+
{
|
234
|
+
if (OBJ_FROZEN(ary)) rb_error_frozen("array");
|
235
|
+
if (!OBJ_UNTRUSTED(ary) && rb_safe_level() >= 4)
|
236
|
+
rb_raise(rb_eSecurityError, "Insecure: can't modify array");
|
237
|
+
}
|
238
|
+
static void
|
239
|
+
rb_ary_modify(VALUE ary)
|
240
|
+
{
|
241
|
+
rb_ary_modify_check(ary);
|
242
|
+
if (ARY_SHARED_P(ary)) {
|
243
|
+
long len = RARRAY_LEN(ary);
|
244
|
+
if (len <= RARRAY_EMBED_LEN_MAX) {
|
245
|
+
VALUE *ptr = ARY_HEAP_PTR(ary);
|
246
|
+
VALUE shared = ARY_SHARED(ary);
|
247
|
+
FL_UNSET_SHARED(ary);
|
248
|
+
FL_SET_EMBED(ary);
|
249
|
+
MEMCPY(ARY_EMBED_PTR(ary), ptr, VALUE, len);
|
250
|
+
rb_ary_decrement_share(shared);
|
251
|
+
ARY_SET_EMBED_LEN(ary, len);
|
252
|
+
}
|
253
|
+
else {
|
254
|
+
VALUE *ptr = ALLOC_N(VALUE, len);
|
255
|
+
MEMCPY(ptr, RARRAY_PTR(ary), VALUE, len);
|
256
|
+
rb_ary_unshare(ary);
|
257
|
+
ARY_SET_CAPA(ary, len);
|
258
|
+
ARY_SET_PTR(ary, ptr);
|
259
|
+
}
|
260
|
+
}
|
261
|
+
}
|
262
|
+
|
263
|
+
static int
|
264
|
+
sort_1(const void *ap, const void *bp, void *dummy)
|
265
|
+
{
|
266
|
+
struct ary_sort_data *data = dummy;
|
267
|
+
VALUE retval = sort_reentered(data->ary);
|
268
|
+
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
|
269
|
+
int n;
|
270
|
+
|
271
|
+
retval = rb_yield_values(2, a, b);
|
272
|
+
n = rb_cmpint(retval, a, b);
|
273
|
+
sort_reentered(data->ary);
|
274
|
+
return n;
|
275
|
+
}
|
276
|
+
|
277
|
+
static int
|
278
|
+
sort_2(const void *ap, const void *bp, void *dummy)
|
279
|
+
{
|
280
|
+
struct ary_sort_data *data = dummy;
|
281
|
+
VALUE retval = sort_reentered(data->ary);
|
282
|
+
VALUE a = *(const VALUE *)ap, b = *(const VALUE *)bp;
|
283
|
+
int n;
|
284
|
+
|
285
|
+
if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
|
286
|
+
if ((long)a > (long)b) return 1;
|
287
|
+
if ((long)a < (long)b) return -1;
|
288
|
+
return 0;
|
289
|
+
}
|
290
|
+
if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
|
291
|
+
return rb_str_cmp(a, b);
|
292
|
+
}
|
293
|
+
|
294
|
+
retval = rb_funcall(a, id_cmp, 1, b);
|
295
|
+
n = rb_cmpint(retval, a, b);
|
296
|
+
sort_reentered(data->ary);
|
297
|
+
|
298
|
+
return n;
|
299
|
+
}
|
300
|
+
|
301
|
+
static int
|
302
|
+
sort_3(VALUE a, VALUE b, void *dummy)
|
303
|
+
{
|
304
|
+
struct ary_sort_data *data = dummy;
|
305
|
+
VALUE retval = sort_reentered(data->ary);
|
306
|
+
int n;
|
307
|
+
|
308
|
+
retval = rb_yield_values(2, a, b);
|
309
|
+
n = rb_cmpint(retval, a, b);
|
310
|
+
sort_reentered(data->ary);
|
311
|
+
return n;
|
312
|
+
}
|
313
|
+
|
314
|
+
static int
|
315
|
+
sort_4(VALUE a, VALUE b, void *dummy)
|
316
|
+
{
|
317
|
+
struct ary_sort_data *data = dummy;
|
318
|
+
VALUE retval = sort_reentered(data->ary);
|
319
|
+
int n;
|
320
|
+
|
321
|
+
if (FIXNUM_P(a) && FIXNUM_P(b) && SORT_OPTIMIZABLE(data, Fixnum)) {
|
322
|
+
if ((long)a > (long)b) return 1;
|
323
|
+
if ((long)a < (long)b) return -1;
|
324
|
+
return 0;
|
325
|
+
}
|
326
|
+
if (STRING_P(a) && STRING_P(b) && SORT_OPTIMIZABLE(data, String)) {
|
327
|
+
return rb_str_cmp(a, b);
|
328
|
+
}
|
329
|
+
|
330
|
+
retval = rb_funcall(a, id_cmp, 1, b);
|
331
|
+
n = rb_cmpint(retval, a, b);
|
332
|
+
sort_reentered(data->ary);
|
333
|
+
|
334
|
+
return n;
|
335
|
+
}
|
336
|
+
|
337
|
+
void
|
338
|
+
set_id_cmp(ID id)
|
339
|
+
{
|
340
|
+
id_cmp = id;
|
341
|
+
}
|
342
|
+
|
343
|
+
VALUE
|
344
|
+
dynamic_sort(VALUE ary, void(*sort_handler)(void*, const size_t, long, long, long, int(*)(const void*, const void*, void*), void*), long start, long l, long r)
|
345
|
+
{
|
346
|
+
rb_ary_modify(ary);
|
347
|
+
assert(!ARY_SHARED_P(ary));
|
348
|
+
if (RARRAY_LEN(ary) > 1) {
|
349
|
+
VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
|
350
|
+
struct ary_sort_data data;
|
351
|
+
|
352
|
+
RBASIC(tmp)->klass = 0;
|
353
|
+
data.ary = tmp;
|
354
|
+
data.opt_methods = 0;
|
355
|
+
data.opt_inited = 0;
|
356
|
+
sort_handler(RARRAY_PTR(tmp), RARRAY_LEN(tmp), start, l, r,
|
357
|
+
rb_block_given_p()?sort_3:sort_4, &data);
|
358
|
+
|
359
|
+
if (ARY_EMBED_P(tmp)) {
|
360
|
+
assert(ARY_EMBED_P(tmp));
|
361
|
+
if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
|
362
|
+
rb_ary_unshare(ary);
|
363
|
+
}
|
364
|
+
FL_SET_EMBED(ary);
|
365
|
+
MEMCPY(RARRAY_PTR(ary), ARY_EMBED_PTR(tmp), VALUE, ARY_EMBED_LEN(tmp));
|
366
|
+
ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
|
367
|
+
}
|
368
|
+
else {
|
369
|
+
assert(!ARY_EMBED_P(tmp));
|
370
|
+
if (ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
|
371
|
+
assert(!ARY_EMBED_P(ary));
|
372
|
+
FL_UNSET_SHARED(ary);
|
373
|
+
ARY_SET_CAPA(ary, ARY_CAPA(tmp));
|
374
|
+
}
|
375
|
+
else {
|
376
|
+
assert(!ARY_SHARED_P(tmp));
|
377
|
+
if (ARY_EMBED_P(ary)) {
|
378
|
+
FL_UNSET_EMBED(ary);
|
379
|
+
}
|
380
|
+
else if (ARY_SHARED_P(ary)) {
|
381
|
+
/* ary might be destructively operated in the given block */
|
382
|
+
rb_ary_unshare(ary);
|
383
|
+
}
|
384
|
+
else {
|
385
|
+
xfree(ARY_HEAP_PTR(ary));
|
386
|
+
}
|
387
|
+
ARY_SET_PTR(ary, RARRAY_PTR(tmp));
|
388
|
+
ARY_SET_HEAP_LEN(ary, RARRAY_LEN(tmp));
|
389
|
+
ARY_SET_CAPA(ary, ARY_CAPA(tmp));
|
390
|
+
}
|
391
|
+
/* tmp was lost ownership for the ptr */
|
392
|
+
FL_UNSET(tmp, FL_FREEZE);
|
393
|
+
FL_SET_EMBED(tmp);
|
394
|
+
ARY_SET_EMBED_LEN(tmp, 0);
|
395
|
+
FL_SET(tmp, FL_FREEZE);
|
396
|
+
}
|
397
|
+
/* tmp will be GC'ed. */
|
398
|
+
RBASIC(tmp)->klass = rb_cArray;
|
399
|
+
}
|
400
|
+
return ary;
|
401
|
+
}
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#include "ruby/ruby.h"
|
2
|
+
|
3
|
+
VALUE sortingModule;
|
4
|
+
VALUE sortingClass;
|
5
|
+
|
6
|
+
void
|
7
|
+
insert_sort_impl(VALUE* base, const size_t len, long start, long l, long r,
|
8
|
+
register int (*cmp)(const void*, const void*, void*), void *d)
|
9
|
+
{
|
10
|
+
VALUE obj;
|
11
|
+
VALUE previous;
|
12
|
+
register size_t i, j;
|
13
|
+
if (l == -1) l = 0;
|
14
|
+
if (r == -1) r = len - 1;
|
15
|
+
if (start == -1) start = l + 1;
|
16
|
+
for(i = start; i <=r; i++) {
|
17
|
+
obj = base[i];
|
18
|
+
j = i;
|
19
|
+
while (j > l) {
|
20
|
+
previous = base[j-1];
|
21
|
+
if((*cmp)(obj, previous, d) < 0) {
|
22
|
+
base[j] = previous;
|
23
|
+
j--;
|
24
|
+
} else break;
|
25
|
+
}
|
26
|
+
base[j] = obj;
|
27
|
+
}
|
28
|
+
|
29
|
+
}
|
30
|
+
|
31
|
+
void
|
32
|
+
binary_insert_sort_impl(VALUE* ary, const size_t len, long start, long l, long r,
|
33
|
+
register int (*cmp)(const void*, const void*, void*), void *d)
|
34
|
+
{
|
35
|
+
char *base = (char *)ary;
|
36
|
+
size_t size = sizeof(VALUE);
|
37
|
+
VALUE obj;
|
38
|
+
VALUE previous;
|
39
|
+
register size_t i, j;
|
40
|
+
long low, high, mid, found, length;
|
41
|
+
char *dest;
|
42
|
+
char *src;
|
43
|
+
if (l == -1) l = 0;
|
44
|
+
if (r == -1) r = len - 1;
|
45
|
+
if (start == -1) start = l + 1;
|
46
|
+
for(i = start; i <=r; i++) {
|
47
|
+
obj = ary[i];
|
48
|
+
low = l;
|
49
|
+
high = i - 1;
|
50
|
+
found = -1;
|
51
|
+
while (low <= high) {
|
52
|
+
mid = low + (high-low)/2;
|
53
|
+
if ((*cmp)(obj, ary[mid], d) > 0) {
|
54
|
+
low = mid + 1;
|
55
|
+
} else {
|
56
|
+
found = mid;
|
57
|
+
high = mid - 1;
|
58
|
+
}
|
59
|
+
}
|
60
|
+
if(found != -1) {
|
61
|
+
length = i - found;
|
62
|
+
if (length == 1) {
|
63
|
+
ary[i] = ary[found];
|
64
|
+
} else {
|
65
|
+
dest = base + (found+1)*size;
|
66
|
+
src = base + found*size;
|
67
|
+
memmove(dest, src, size*length);
|
68
|
+
}
|
69
|
+
ary[found] = obj;
|
70
|
+
}
|
71
|
+
}
|
72
|
+
|
73
|
+
}
|
74
|
+
|
75
|
+
void
|
76
|
+
insert_sort_bang(int argc, VALUE *argv, VALUE dummy)
|
77
|
+
{
|
78
|
+
VALUE ary = Qnil;
|
79
|
+
VALUE rb_start = Qnil;
|
80
|
+
VALUE rb_l = Qnil;
|
81
|
+
VALUE rb_r = Qnil;
|
82
|
+
long start = -1, l = -1, r = -1;
|
83
|
+
rb_scan_args(argc, argv, "13", &ary, &rb_l, &rb_r, &rb_start);
|
84
|
+
if (!NIL_P(rb_start)) start = NUM2LONG(rb_start);
|
85
|
+
if (!NIL_P(rb_l)) l = NUM2LONG(rb_l);
|
86
|
+
if (!NIL_P(rb_r)) r = NUM2LONG(rb_r);
|
87
|
+
dynamic_sort(ary, insert_sort_impl, start, l, r);
|
88
|
+
}
|
89
|
+
|
90
|
+
void
|
91
|
+
binary_insert_sort_bang(int argc, VALUE *argv, VALUE dummy)
|
92
|
+
{
|
93
|
+
VALUE ary = Qnil;
|
94
|
+
VALUE rb_start = Qnil;
|
95
|
+
VALUE rb_l = Qnil;
|
96
|
+
VALUE rb_r = Qnil;
|
97
|
+
long start = -1, l = -1, r = -1;
|
98
|
+
rb_scan_args(argc, argv, "13", &ary, &rb_l, &rb_r, &rb_start);
|
99
|
+
if (!NIL_P(rb_start)) start = NUM2LONG(rb_start);
|
100
|
+
if (!NIL_P(rb_l)) l = NUM2LONG(rb_l);
|
101
|
+
if (!NIL_P(rb_r)) r = NUM2LONG(rb_r);
|
102
|
+
dynamic_sort(ary, binary_insert_sort_impl, start, l, r);
|
103
|
+
}
|
104
|
+
|
105
|
+
void Init_sorting_ext(void) {
|
106
|
+
sortingModule = rb_define_module("Sorting");
|
107
|
+
sortingClass = rb_define_class_under(sortingModule, "InsertionSort", rb_cObject);
|
108
|
+
rb_define_singleton_method(sortingClass, "sort!", insert_sort_bang, -1);
|
109
|
+
rb_define_singleton_method(sortingClass, "binary_sort!", binary_insert_sort_bang, -1);
|
110
|
+
rb_define_const(sortingClass, "IS_EXT", Qtrue);
|
111
|
+
set_id_cmp(rb_intern("<=>"));
|
112
|
+
}
|