[前][次][番号順一覧][スレッド一覧]

ruby-changes:21440

From: nobu <ko1@a...>
Date: Thu, 20 Oct 2011 11:42:39 +0900 (JST)
Subject: [ruby-changes:21440] nobu:r33489 (trunk): * util.c (mmprepare): fix for fragmental size.

nobu	2011-10-20 11:42:26 +0900 (Thu, 20 Oct 2011)

  New Revision: 33489

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=33489

  Log:
    * util.c (mmprepare): fix for fragmental size.
    * util.c (mmswap_, mmrot3_): portability improvement.

  Added files:
    trunk/ext/-test-/string/qsort.c
    trunk/test/-ext-/string/test_qsort.rb
  Modified files:
    trunk/ChangeLog
    trunk/util.c

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 33488)
+++ ChangeLog	(revision 33489)
@@ -1,3 +1,9 @@
+Thu Oct 20 11:42:23 2011  Nobuyoshi Nakada  <nobu@r...>
+
+	* util.c (mmprepare): fix for fragmental size.
+
+	* util.c (mmswap_, mmrot3_): portability improvement.
+
 Thu Oct 20 05:58:02 2011  Eric Hodel  <drbrain@s...>
 
 	* ext/openssl/ossl_ns_spki.c (Init_ossl_ns_spki):  Stub documentation
Index: util.c
===================================================================
--- util.c	(revision 33488)
+++ util.c	(revision 33489)
@@ -187,66 +187,97 @@
 
 /* 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 @@
                        ((*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 */
Index: ext/-test-/string/qsort.c
===================================================================
--- ext/-test-/string/qsort.c	(revision 0)
+++ ext/-test-/string/qsort.c	(revision 33489)
@@ -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);
+}

Property changes on: ext/-test-/string/qsort.c
___________________________________________________________________
Added: svn:eol-style
   + LF

Index: test/-ext-/string/test_qsort.rb
===================================================================
--- test/-ext-/string/test_qsort.rb	(revision 0)
+++ test/-ext-/string/test_qsort.rb	(revision 33489)
@@ -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

Property changes on: test/-ext-/string/test_qsort.rb
___________________________________________________________________
Added: svn:eol-style
   + LF


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]