Anyone want to port?

-------- Original Message --------
Subject: Re: Array#flatten works quadratic time on length of resulting array. It could be linear
Date: Fri, 07 Dec 2007 11:34:37 +0900
From: Nobuyoshi Nakada <[EMAIL PROTECTED]>
Reply-To: [EMAIL PROTECTED]
To: [EMAIL PROTECTED]
References: <[EMAIL PROTECTED]> <[EMAIL PROTECTED]> <[EMAIL PROTECTED]>

Hi,

At Fri, 7 Dec 2007 10:14:02 +0900,
Artem Voroztsov wrote in [ruby-core:13898]:
Method Array#join has the same drawback.
It joins recursively, checks for recursive arrays,  and works quadratic time.

HTH.


Index: thread.c
===================================================================
--- thread.c    (revision 14122)
+++ thread.c    (working copy)
@@ -2584,8 +2573,6 @@ static ID recursive_key;

 static VALUE
-recursive_check(VALUE obj)
+recursive_check(VALUE hash, VALUE obj)
 {
-    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
-
     if (NIL_P(hash) || TYPE(hash) != T_HASH) {
        return Qfalse;
@@ -2594,14 +2581,15 @@ recursive_check(VALUE obj)
        VALUE list = rb_hash_aref(hash, ID2SYM(rb_frame_this_func()));

-       if (NIL_P(list) || TYPE(list) != T_ARRAY)
+       if (NIL_P(list) || TYPE(list) != T_HASH)
+           return Qfalse;
+       if (NIL_P(rb_hash_lookup(list, rb_obj_id(obj))))
            return Qfalse;
-       return rb_ary_includes(list, rb_obj_id(obj));
+       return Qtrue;
     }
 }

-static void
-recursive_push(VALUE obj)
+static VALUE
+recursive_push(VALUE hash, VALUE obj)
 {
-    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
     VALUE list, sym;

@@ -2615,15 +2603,15 @@ recursive_push(VALUE obj)
        list = rb_hash_aref(hash, sym);
     }
-    if (NIL_P(list) || TYPE(list) != T_ARRAY) {
-       list = rb_ary_new();
+    if (NIL_P(list) || TYPE(list) != T_HASH) {
+       list = rb_hash_new();
        rb_hash_aset(hash, sym, list);
     }
-    rb_ary_push(list, rb_obj_id(obj));
+    rb_hash_aset(list, rb_obj_id(obj), Qtrue);
+    return hash;
 }

 static void
-recursive_pop(void)
+recursive_pop(VALUE hash, VALUE obj)
 {
-    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
     VALUE list, sym;

@@ -2639,5 +2627,5 @@ recursive_pop(void)
     }
     list = rb_hash_aref(hash, sym);
-    if (NIL_P(list) || TYPE(list) != T_ARRAY) {
+    if (NIL_P(list) || TYPE(list) != T_HASH) {
        VALUE symname = rb_inspect(sym);
        VALUE thrname = rb_inspect(rb_thread_current());
@@ -2645,5 +2633,5 @@ recursive_pop(void)
                 StringValuePtr(symname), StringValuePtr(thrname));
     }
-    rb_ary_pop(list);
+    rb_hash_delete(list, obj);
 }

@@ -2651,5 +2639,7 @@ VALUE
 rb_exec_recursive(VALUE (*func) (VALUE, VALUE, int), VALUE obj, VALUE arg)
 {
-    if (recursive_check(obj)) {
+    VALUE hash = rb_thread_local_aref(rb_thread_current(), recursive_key);
+
+    if (recursive_check(hash, obj)) {
        return (*func) (obj, arg, Qtrue);
     }
@@ -2658,5 +2648,5 @@ rb_exec_recursive(VALUE (*func) (VALUE,
        int state;

-       recursive_push(obj);
+       hash = recursive_push(hash, obj);
        PUSH_TAG();
        if ((state = EXEC_TAG()) == 0) {
@@ -2664,5 +2654,5 @@ rb_exec_recursive(VALUE (*func) (VALUE,
        }
        POP_TAG();
-       recursive_pop();
+       recursive_pop(hash, obj);
        if (state)
            JUMP_TAG(state);


--
Nobu Nakada


---------------------------------------------------------------------
To unsubscribe from this list please visit:

   http://xircles.codehaus.org/manage_email

Reply via email to