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

ruby-changes:74211

From: Nobuyoshi <ko1@a...>
Date: Sun, 23 Oct 2022 16:45:10 +0900 (JST)
Subject: [ruby-changes:74211] 86450d03a8 (master): Reduce type check of arguments at Complex creation

https://git.ruby-lang.org/ruby.git/commit/?id=86450d03a8

From 86450d03a8c1570571c20452578cb923060e1d1f Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Sun, 23 Oct 2022 13:42:36 +0900
Subject: Reduce type check of arguments at Complex creation

---
 complex.c                 | 41 ++++++++++++++++++++++++-----------------
 test/ruby/test_complex.rb | 29 ++++++++++++++++++++++++-----
 2 files changed, 48 insertions(+), 22 deletions(-)

diff --git a/complex.c b/complex.c
index c4f0f5e8c9..db114cd914 100644
--- a/complex.c
+++ b/complex.c
@@ -421,15 +421,22 @@ f_complex_new_bang2(VALUE klass, VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/complex.c#L421
     return nucomp_s_new_internal(klass, x, y);
 }
 
-inline static void
+WARN_UNUSED_RESULT(inline static VALUE nucomp_real_check(VALUE num));
+inline static VALUE
 nucomp_real_check(VALUE num)
 {
     if (!RB_INTEGER_TYPE_P(num) &&
         !RB_FLOAT_TYPE_P(num) &&
         !RB_TYPE_P(num, T_RATIONAL)) {
+        if (RB_TYPE_P(num, T_COMPLEX) && nucomp_real_p(num)) {
+            VALUE real = RCOMPLEX(num)->real;
+            assert(!RB_TYPE_P(real, T_COMPLEX));
+            return real;
+        }
         if (!k_numeric_p(num) || !f_real_p(num))
             rb_raise(rb_eTypeError, "not a real");
     }
+    return num;
 }
 
 inline static VALUE
@@ -480,16 +487,16 @@ nucomp_s_new(int argc, VALUE *argv, VALUE klass) https://github.com/ruby/ruby/blob/trunk/complex.c#L487
 
     switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
       case 1:
-        nucomp_real_check(real);
+        real = nucomp_real_check(real);
         imag = ZERO;
         break;
       default:
-        nucomp_real_check(real);
-        nucomp_real_check(imag);
+        real = nucomp_real_check(real);
+        imag = nucomp_real_check(imag);
         break;
     }
 
-    return nucomp_s_canonicalize_internal(klass, real, imag);
+    return nucomp_s_new_internal(klass, real, imag);
 }
 
 inline static VALUE
@@ -611,16 +618,8 @@ m_sin(VALUE x) https://github.com/ruby/ruby/blob/trunk/complex.c#L618
 }
 
 static VALUE
-f_complex_polar(VALUE klass, VALUE x, VALUE y)
+f_complex_polar_real(VALUE klass, VALUE x, VALUE y)
 {
-    if (RB_TYPE_P(x, T_COMPLEX)) {
-        get_dat1(x);
-        x = dat->real;
-    }
-    if (RB_TYPE_P(y, T_COMPLEX)) {
-        get_dat1(y);
-        y = dat->real;
-    }
     if (f_zero_p(x) || f_zero_p(y)) {
         return nucomp_s_new_internal(klass, x, RFLOAT_0);
     }
@@ -656,6 +655,14 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y) https://github.com/ruby/ruby/blob/trunk/complex.c#L655
                                           f_mul(x, m_sin(y)));
 }
 
+static VALUE
+f_complex_polar(VALUE klass, VALUE x, VALUE y)
+{
+    x = nucomp_real_check(x);
+    y = nucomp_real_check(y);
+    return f_complex_polar_real(klass, x, y);
+}
+
 #ifdef HAVE___COSPI
 # define cospi(x) __cospi(x)
 #else
@@ -705,14 +712,14 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass) https://github.com/ruby/ruby/blob/trunk/complex.c#L712
     VALUE abs, arg;
 
     argc = rb_scan_args(argc, argv, "11", &abs, &arg);
-    nucomp_real_check(abs);
+    abs = nucomp_real_check(abs);
     if (argc == 2) {
-        nucomp_real_check(arg);
+        arg = nucomp_real_check(arg);
     }
     else {
         arg = ZERO;
     }
-    return f_complex_polar(klass, abs, arg);
+    return f_complex_polar_real(klass, abs, arg);
 }
 
 /*
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index 5b63b03acf..b35aedb6b0 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -1145,15 +1145,34 @@ class Complex_Test < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_complex.rb#L1145
   end
 
   def test_canonicalize_polar
-    obj = Class.new(Numeric) do
-      def initialize
-        @x = 2
+    error = "not a real"
+    assert_raise_with_message(TypeError, error) do
+      Complex.polar(1i)
+    end
+    assert_raise_with_message(TypeError, error) do
+      Complex.polar(1i, 0)
+    end
+    assert_raise_with_message(TypeError, error) do
+      Complex.polar(0, 1i)
+    end
+    n = Class.new(Numeric) do
+      def initialize(x = 1)
+        @x = x
       end
       def real?
         (@x -= 1) > 0
       end
-    end.new
-    assert_raise(TypeError) do
+    end
+    obj = n.new
+    assert_raise_with_message(TypeError, error) do
+      Complex.polar(obj)
+    end
+    obj = n.new
+    assert_raise_with_message(TypeError, error) do
+      Complex.polar(obj, 0)
+    end
+    obj = n.new
+    assert_raise_with_message(TypeError, error) do
       Complex.polar(1, obj)
     end
   end
-- 
cgit v1.2.3


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

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