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

ruby-changes:27965

From: akr <ko1@a...>
Date: Sun, 31 Mar 2013 13:51:39 +0900 (JST)
Subject: [ruby-changes:27965] akr:r40017 (trunk): * numeric.c (rb_num2ulong_internal): New function similart to

akr	2013-03-31 13:51:29 +0900 (Sun, 31 Mar 2013)

  New Revision: 40017

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

  Log:
    * numeric.c (rb_num2ulong_internal): New function similart to
      rb_num2ulong but integer wrap around flag is also returned.
      (rb_num2ulong): Use rb_num2ulong_internal.
      (rb_num2uint): Use rb_num2ulong_internal and the wrap around flag is
      used instead of negative_int_p(val).
      (rb_num2ushort): ditto.

  Modified files:
    trunk/ChangeLog
    trunk/numeric.c
    trunk/test/-ext-/num2int/test_num2int.rb

Index: ChangeLog
===================================================================
--- ChangeLog	(revision 40016)
+++ ChangeLog	(revision 40017)
@@ -1,3 +1,12 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1
+Sun Mar 31 13:47:04 2013  Tanaka Akira  <akr@f...>
+
+	* numeric.c (rb_num2ulong_internal): New function similart to
+	  rb_num2ulong but integer wrap around flag is also returned.
+	  (rb_num2ulong): Use rb_num2ulong_internal.
+	  (rb_num2uint): Use rb_num2ulong_internal and the wrap around flag is
+	  used instead of negative_int_p(val).
+	  (rb_num2ushort): ditto.
+
 Sun Mar 31 06:27:17 2013  Nobuyoshi Nakada  <nobu@r...>
 
 	* class.c (HAVE_METACLASS_P): should check FL_SINGLTON flag before get
Index: numeric.c
===================================================================
--- numeric.c	(revision 40016)
+++ numeric.c	(revision 40017)
@@ -1979,21 +1979,29 @@ rb_num2long(VALUE val) https://github.com/ruby/ruby/blob/trunk/numeric.c#L1979
     }
 }
 
-VALUE
-rb_num2ulong(VALUE val)
+static unsigned long
+rb_num2ulong_internal(VALUE val, int *wrap_p)
 {
   again:
     if (NIL_P(val)) {
        rb_raise(rb_eTypeError, "no implicit conversion from nil to integer");
     }
 
-    if (FIXNUM_P(val)) return FIX2LONG(val); /* this is FIX2LONG, inteneded */
+    if (FIXNUM_P(val)) {
+        long l = FIX2LONG(val); /* this is FIX2LONG, inteneded */
+        if (wrap_p)
+            *wrap_p = l < 0;
+        return l;
+    }
 
     switch (TYPE(val)) {
       case T_FLOAT:
        if (RFLOAT_VALUE(val) < ULONG_MAX_PLUS_ONE
            && LONG_MIN_MINUS_ONE_IS_LESS_THAN(RFLOAT_VALUE(val))) {
-           return (VALUE)RFLOAT_VALUE(val);
+           double d = RFLOAT_VALUE(val);
+           if (wrap_p)
+               *wrap_p = d <= -1.0; /* NUM2ULONG(v) uses v.to_int conceptually.  */
+           return (unsigned long)d;
        }
        else {
            char buf[24];
@@ -2005,7 +2013,12 @@ rb_num2ulong(VALUE val) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2013
        }
 
       case T_BIGNUM:
-	return rb_big2ulong(val);
+        {
+            unsigned long ul = rb_big2ulong(val);
+            if (wrap_p)
+                *wrap_p = RBIGNUM_NEGATIVE_P(val);
+            return ul;
+        }
 
       default:
        val = rb_to_int(val);
@@ -2013,6 +2026,12 @@ rb_num2ulong(VALUE val) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2026
     }
 }
 
+VALUE
+rb_num2ulong(VALUE val)
+{
+    return rb_num2ulong_internal(val, NULL);
+}
+
 #if SIZEOF_INT < SIZEOF_VALUE
 void
 rb_out_of_int(SIGNED_VALUE num)
@@ -2068,10 +2087,11 @@ rb_fix2int(VALUE val) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2087
 unsigned long
 rb_num2uint(VALUE val)
 {
-    VALUE num = rb_num2ulong(val);
+    int wrap;
+    unsigned long num = rb_num2ulong_internal(val, &wrap);
 
-    check_uint(num, negative_int_p(val));
-    return (unsigned long)num;
+    check_uint(num, wrap);
+    return num;
 }
 
 unsigned long
@@ -2155,10 +2175,11 @@ rb_fix2short(VALUE val) https://github.com/ruby/ruby/blob/trunk/numeric.c#L2175
 unsigned short
 rb_num2ushort(VALUE val)
 {
-    VALUE num = rb_num2ulong(val);
+    int wrap;
+    unsigned long num = rb_num2ulong_internal(val, &wrap);
 
-    check_ushort(num, negative_int_p(val));
-    return (unsigned long)num;
+    check_ushort(num, wrap);
+    return num;
 }
 
 unsigned short
Index: test/-ext-/num2int/test_num2int.rb
===================================================================
--- test/-ext-/num2int/test_num2int.rb	(revision 40016)
+++ test/-ext-/num2int/test_num2int.rb	(revision 40017)
@@ -48,6 +48,17 @@ class TestNum2int < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/-ext-/num2int/test_num2int.rb#L48
     if num.to_f.to_i == num
       assert_num2i_success_internal(result.to_s, func, num.to_f)
     end
+    if num == result
+      # The conversion functions such as NUM2INT uses to_int (conceptually).
+      arg = num.to_f + 0.5
+      if arg != num.to_f && arg.to_int == num
+        assert_num2i_success_internal(result.to_s, func, arg)
+      end
+      arg = num.to_f - 0.5
+      if arg != num.to_f && arg.to_int == num
+        assert_num2i_success_internal(result.to_s, func, arg)
+      end
+    end
   end
 
   def assert_num2i_error_internal(func, arg)

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

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