Skip to content

Commit 86450d0

Browse files
committed
Reduce type check of arguments at Complex creation
1 parent c8c1362 commit 86450d0

File tree

2 files changed

+48
-22
lines changed

2 files changed

+48
-22
lines changed

complex.c

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -421,15 +421,22 @@ f_complex_new_bang2(VALUE klass, VALUE x, VALUE y)
421421
return nucomp_s_new_internal(klass, x, y);
422422
}
423423

424-
inline static void
424+
WARN_UNUSED_RESULT(inline static VALUE nucomp_real_check(VALUE num));
425+
inline static VALUE
425426
nucomp_real_check(VALUE num)
426427
{
427428
if (!RB_INTEGER_TYPE_P(num) &&
428429
!RB_FLOAT_TYPE_P(num) &&
429430
!RB_TYPE_P(num, T_RATIONAL)) {
431+
if (RB_TYPE_P(num, T_COMPLEX) && nucomp_real_p(num)) {
432+
VALUE real = RCOMPLEX(num)->real;
433+
assert(!RB_TYPE_P(real, T_COMPLEX));
434+
return real;
435+
}
430436
if (!k_numeric_p(num) || !f_real_p(num))
431437
rb_raise(rb_eTypeError, "not a real");
432438
}
439+
return num;
433440
}
434441

435442
inline static VALUE
@@ -480,16 +487,16 @@ nucomp_s_new(int argc, VALUE *argv, VALUE klass)
480487

481488
switch (rb_scan_args(argc, argv, "11", &real, &imag)) {
482489
case 1:
483-
nucomp_real_check(real);
490+
real = nucomp_real_check(real);
484491
imag = ZERO;
485492
break;
486493
default:
487-
nucomp_real_check(real);
488-
nucomp_real_check(imag);
494+
real = nucomp_real_check(real);
495+
imag = nucomp_real_check(imag);
489496
break;
490497
}
491498

492-
return nucomp_s_canonicalize_internal(klass, real, imag);
499+
return nucomp_s_new_internal(klass, real, imag);
493500
}
494501

495502
inline static VALUE
@@ -611,16 +618,8 @@ m_sin(VALUE x)
611618
}
612619

613620
static VALUE
614-
f_complex_polar(VALUE klass, VALUE x, VALUE y)
621+
f_complex_polar_real(VALUE klass, VALUE x, VALUE y)
615622
{
616-
if (RB_TYPE_P(x, T_COMPLEX)) {
617-
get_dat1(x);
618-
x = dat->real;
619-
}
620-
if (RB_TYPE_P(y, T_COMPLEX)) {
621-
get_dat1(y);
622-
y = dat->real;
623-
}
624623
if (f_zero_p(x) || f_zero_p(y)) {
625624
return nucomp_s_new_internal(klass, x, RFLOAT_0);
626625
}
@@ -656,6 +655,14 @@ f_complex_polar(VALUE klass, VALUE x, VALUE y)
656655
f_mul(x, m_sin(y)));
657656
}
658657

658+
static VALUE
659+
f_complex_polar(VALUE klass, VALUE x, VALUE y)
660+
{
661+
x = nucomp_real_check(x);
662+
y = nucomp_real_check(y);
663+
return f_complex_polar_real(klass, x, y);
664+
}
665+
659666
#ifdef HAVE___COSPI
660667
# define cospi(x) __cospi(x)
661668
#else
@@ -705,14 +712,14 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass)
705712
VALUE abs, arg;
706713

707714
argc = rb_scan_args(argc, argv, "11", &abs, &arg);
708-
nucomp_real_check(abs);
715+
abs = nucomp_real_check(abs);
709716
if (argc == 2) {
710-
nucomp_real_check(arg);
717+
arg = nucomp_real_check(arg);
711718
}
712719
else {
713720
arg = ZERO;
714721
}
715-
return f_complex_polar(klass, abs, arg);
722+
return f_complex_polar_real(klass, abs, arg);
716723
}
717724

718725
/*

test/ruby/test_complex.rb

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1145,15 +1145,34 @@ def test_canonicalize_internal
11451145
end
11461146

11471147
def test_canonicalize_polar
1148-
obj = Class.new(Numeric) do
1149-
def initialize
1150-
@x = 2
1148+
error = "not a real"
1149+
assert_raise_with_message(TypeError, error) do
1150+
Complex.polar(1i)
1151+
end
1152+
assert_raise_with_message(TypeError, error) do
1153+
Complex.polar(1i, 0)
1154+
end
1155+
assert_raise_with_message(TypeError, error) do
1156+
Complex.polar(0, 1i)
1157+
end
1158+
n = Class.new(Numeric) do
1159+
def initialize(x = 1)
1160+
@x = x
11511161
end
11521162
def real?
11531163
(@x -= 1) > 0
11541164
end
1155-
end.new
1156-
assert_raise(TypeError) do
1165+
end
1166+
obj = n.new
1167+
assert_raise_with_message(TypeError, error) do
1168+
Complex.polar(obj)
1169+
end
1170+
obj = n.new
1171+
assert_raise_with_message(TypeError, error) do
1172+
Complex.polar(obj, 0)
1173+
end
1174+
obj = n.new
1175+
assert_raise_with_message(TypeError, error) do
11571176
Complex.polar(1, obj)
11581177
end
11591178
end

0 commit comments

Comments
 (0)