mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* util.c (mmprepare): fix for fragmental size.
* util.c (mmswap_, mmrot3_): portability improvement. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@33489 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
2e32ad8163
commit
72cbec3f6d
4 changed files with 139 additions and 22 deletions
|
@ -1,3 +1,9 @@
|
|||
Thu Oct 20 11:42:23 2011 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||
|
||||
* util.c (mmprepare): fix for fragmental size.
|
||||
|
||||
* util.c (mmswap_, mmrot3_): portability improvement.
|
||||
|
||||
Thu Oct 20 05:58:02 2011 Eric Hodel <drbrain@segment7.net>
|
||||
|
||||
* ext/openssl/ossl_ns_spki.c (Init_ossl_ns_spki): Stub documentation
|
||||
|
|
61
ext/-test-/string/qsort.c
Normal file
61
ext/-test-/string/qsort.c
Normal file
|
@ -0,0 +1,61 @@
|
|||
#include "ruby.h"
|
||||
#include "ruby/util.h"
|
||||
#include "ruby/encoding.h"
|
||||
|
||||
struct sort_data {
|
||||
rb_encoding *enc;
|
||||
long elsize;
|
||||
};
|
||||
|
||||
static int
|
||||
cmp_1(const void *ap, const void *bp, void *dummy)
|
||||
{
|
||||
struct sort_data *d = dummy;
|
||||
VALUE a = rb_enc_str_new(ap, d->elsize, d->enc);
|
||||
VALUE b = rb_enc_str_new(bp, d->elsize, d->enc);
|
||||
VALUE retval = rb_yield_values(2, a, b);
|
||||
return rb_cmpint(retval, a, b);
|
||||
}
|
||||
|
||||
static int
|
||||
cmp_2(const void *ap, const void *bp, void *dummy)
|
||||
{
|
||||
int a = *(const unsigned char *)ap;
|
||||
int b = *(const unsigned char *)bp;
|
||||
return a - b;
|
||||
}
|
||||
|
||||
static VALUE
|
||||
bug_str_qsort_bang(int argc, VALUE *argv, VALUE str)
|
||||
{
|
||||
VALUE beg, len, size;
|
||||
long l, b = 0, n, s = 1;
|
||||
struct sort_data d;
|
||||
|
||||
rb_scan_args(argc, argv, "03", &beg, &len, &size);
|
||||
l = RSTRING_LEN(str);
|
||||
if (!NIL_P(beg) && (b = NUM2INT(beg)) < 0 && (b += l) < 0) {
|
||||
rb_raise(rb_eArgError, "out of bounds");
|
||||
}
|
||||
if (!NIL_P(size) && (s = NUM2INT(size)) < 0) {
|
||||
rb_raise(rb_eArgError, "negative size");
|
||||
}
|
||||
if (NIL_P(len) ||
|
||||
(((n = NUM2INT(len)) < 0) ?
|
||||
(rb_raise(rb_eArgError, "negative length"), 0) :
|
||||
(b + n * s > l))) {
|
||||
n = (l - b) / s;
|
||||
}
|
||||
rb_str_modify(str);
|
||||
d.enc = rb_enc_get(str);
|
||||
d.elsize = s;
|
||||
ruby_qsort(RSTRING_PTR(str) + b, n, s,
|
||||
rb_block_given_p() ? cmp_1 : cmp_2, &d);
|
||||
return str;
|
||||
}
|
||||
|
||||
void
|
||||
Init_qsort(VALUE klass)
|
||||
{
|
||||
rb_define_method(klass, "qsort!", bug_str_qsort_bang, -1);
|
||||
}
|
19
test/-ext-/string/test_qsort.rb
Normal file
19
test/-ext-/string/test_qsort.rb
Normal file
|
@ -0,0 +1,19 @@
|
|||
require 'test/unit'
|
||||
require "-test-/string/string"
|
||||
|
||||
class Test_StringQSort < Test::Unit::TestCase
|
||||
def test_qsort
|
||||
s = Bug::String.new("xxozfxx")
|
||||
s.qsort!
|
||||
assert_equal("foxxxxz", s)
|
||||
end
|
||||
|
||||
def test_qsort_slice
|
||||
s = Bug::String.new("xxofzx1")
|
||||
s.qsort!(nil, nil, 3)
|
||||
assert_equal("fzxxxo1", s)
|
||||
s = Bug::String.new("xxofzx231")
|
||||
s.qsort!(nil, nil, 3)
|
||||
assert_equal("231fzxxxo", s)
|
||||
end
|
||||
end
|
75
util.c
75
util.c
|
@ -187,66 +187,97 @@ ruby_strtoul(const char *str, char **endptr, int base)
|
|||
|
||||
/* mm.c */
|
||||
|
||||
#define A ((int*)a)
|
||||
#define B ((int*)b)
|
||||
#define C ((int*)c)
|
||||
#define D ((int*)d)
|
||||
#define mmtype long
|
||||
#define mmcount (16 / SIZEOF_LONG)
|
||||
#define A ((mmtype*)a)
|
||||
#define B ((mmtype*)b)
|
||||
#define C ((mmtype*)c)
|
||||
#define D ((mmtype*)d)
|
||||
|
||||
#define mmstep (sizeof(mmtype) * mmcount)
|
||||
#define mmprepare(base, size) do {\
|
||||
if (((VALUE)(base) & (0x3)) == 0)\
|
||||
if ((size) >= 16) mmkind = 1;\
|
||||
if (((VALUE)(base) % sizeof(mmtype)) == 0 && ((size) % sizeof(mmtype)) == 0) \
|
||||
if ((size) >= mmstep) mmkind = 1;\
|
||||
else mmkind = 0;\
|
||||
else mmkind = -1;\
|
||||
high = ((size) & (~0xf));\
|
||||
low = ((size) & 0x0c);\
|
||||
high = ((size) / mmstep) * mmstep;\
|
||||
low = ((size) % mmstep);\
|
||||
} while (0)\
|
||||
|
||||
#define mmarg mmkind, size, high, low
|
||||
#define mmargdecl int mmkind, size_t size, size_t high, size_t low
|
||||
|
||||
static void mmswap_(register char *a, register char *b, int mmkind, size_t size, size_t high, size_t low)
|
||||
static void mmswap_(register char *a, register char *b, mmargdecl)
|
||||
{
|
||||
register int s;
|
||||
if (a == b) return;
|
||||
if (mmkind >= 0) {
|
||||
register mmtype s;
|
||||
#if mmcount > 1
|
||||
if (mmkind > 0) {
|
||||
register char *t = a + high;
|
||||
do {
|
||||
s = A[0]; A[0] = B[0]; B[0] = s;
|
||||
s = A[1]; A[1] = B[1]; B[1] = s;
|
||||
#if mmcount > 2
|
||||
s = A[2]; A[2] = B[2]; B[2] = s;
|
||||
s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16;
|
||||
#if mmcount > 3
|
||||
s = A[3]; A[3] = B[3]; B[3] = s;
|
||||
#endif
|
||||
#endif
|
||||
a += mmstep; b += mmstep;
|
||||
} while (a < t);
|
||||
}
|
||||
#endif
|
||||
if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s;
|
||||
if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s;
|
||||
if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}}
|
||||
#if mmcount > 2
|
||||
if (low >= 2 * sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = s;
|
||||
#if mmcount > 3
|
||||
if (low >= 3 * sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = s;}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
register char *t = a + size;
|
||||
register char *t = a + size, s;
|
||||
do {s = *a; *a++ = *b; *b++ = s;} while (a < t);
|
||||
}
|
||||
}
|
||||
#define mmswap(a,b) mmswap_((a),(b),mmarg)
|
||||
|
||||
static void mmrot3_(register char *a, register char *b, register char *c, int mmkind, size_t size, size_t high, size_t low)
|
||||
/* a, b, c = b, c, a */
|
||||
static void mmrot3_(register char *a, register char *b, register char *c, mmargdecl)
|
||||
{
|
||||
register int s;
|
||||
if (mmkind >= 0) {
|
||||
register mmtype s;
|
||||
#if mmcount > 1
|
||||
if (mmkind > 0) {
|
||||
register char *t = a + high;
|
||||
do {
|
||||
s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
|
||||
s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
|
||||
#if mmcount > 2
|
||||
s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;
|
||||
s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16;
|
||||
#if mmcount > 3
|
||||
s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s;
|
||||
#endif
|
||||
#endif
|
||||
a += mmstep; b += mmstep; c += mmstep;
|
||||
} while (a < t);
|
||||
}
|
||||
#endif
|
||||
if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s;
|
||||
if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
|
||||
if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}}
|
||||
#if mmcount > 2
|
||||
if (low >= 2 * sizeof(mmtype)) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s;
|
||||
#if mmcount > 3
|
||||
if (low == 3 * sizeof(mmtype)) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
register char *t = a + size;
|
||||
register char *t = a + size, s;
|
||||
do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t);
|
||||
}
|
||||
}
|
||||
|
@ -269,9 +300,9 @@ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */
|
|||
((*cmp)((b),(c),d)<0 ? (b) : ((*cmp)((a),(c),d)<0 ? (c) : (a))) : \
|
||||
((*cmp)((b),(c),d)>0 ? (b) : ((*cmp)((a),(c),d)<0 ? (a) : (c))))
|
||||
|
||||
typedef int (cmpfunc_t)(const void*, const void*, void*);
|
||||
void
|
||||
ruby_qsort(void* base, const size_t nel, const size_t size,
|
||||
int (*cmp)(const void*, const void*, void*), void *d)
|
||||
ruby_qsort(void* base, const size_t nel, const size_t size, cmpfunc_t *cmp, void *d)
|
||||
{
|
||||
register char *l, *r, *m; /* l,r:left,right group m:median point */
|
||||
register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */
|
||||
|
|
Loading…
Reference in a new issue