summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-09-01 07:34:31 +0000
committernobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-09-01 07:34:31 +0000
commit929e9713bbfd76140bced29c6f398904ae9d4a85 (patch)
treeabb04468573060b8a2ee3a5c56cbd717d0cfbb1a
parent9563db5eb18eae0e59da22f000ef21ed7516c179 (diff)
complex.c: simplify division result
* complex.c (f_divide): canonicalize rationals to simplify integer complex results. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64610 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--complex.c22
-rw-r--r--internal.h1
-rw-r--r--rational.c9
-rw-r--r--test/ruby/test_complex.rb7
4 files changed, 25 insertions, 14 deletions
diff --git a/complex.c b/complex.c
index 71c24a0024..ff6e3e038e 100644
--- a/complex.c
+++ b/complex.c
@@ -774,6 +774,7 @@ f_divide(VALUE self, VALUE other,
VALUE (*func)(VALUE, VALUE), ID id)
{
if (RB_TYPE_P(other, T_COMPLEX)) {
+ VALUE r, n, x, y;
int flo;
get_dat2(self, other);
@@ -781,35 +782,28 @@ f_divide(VALUE self, VALUE other,
RB_FLOAT_TYPE_P(bdat->real) || RB_FLOAT_TYPE_P(bdat->imag));
if (f_gt_p(f_abs(bdat->real), f_abs(bdat->imag))) {
- VALUE r, n;
-
r = (*func)(bdat->imag, bdat->real);
n = f_mul(bdat->real, f_add(ONE, f_mul(r, r)));
if (flo)
return f_complex_new2(CLASS_OF(self),
(*func)(self, n),
(*func)(f_negate(f_mul(self, r)), n));
- return f_complex_new2(CLASS_OF(self),
- (*func)(f_add(adat->real,
- f_mul(adat->imag, r)), n),
- (*func)(f_sub(adat->imag,
- f_mul(adat->real, r)), n));
+ x = (*func)(f_add(adat->real, f_mul(adat->imag, r)), n);
+ y = (*func)(f_sub(adat->imag, f_mul(adat->real, r)), n);
}
else {
- VALUE r, n;
-
r = (*func)(bdat->real, bdat->imag);
n = f_mul(bdat->imag, f_add(ONE, f_mul(r, r)));
if (flo)
return f_complex_new2(CLASS_OF(self),
(*func)(f_mul(self, r), n),
(*func)(f_negate(self), n));
- return f_complex_new2(CLASS_OF(self),
- (*func)(f_add(f_mul(adat->real, r),
- adat->imag), n),
- (*func)(f_sub(f_mul(adat->imag, r),
- adat->real), n));
+ x = (*func)(f_add(f_mul(adat->real, r), adat->imag), n);
+ y = (*func)(f_sub(f_mul(adat->imag, r), adat->real), n);
}
+ x = rb_rational_canonicalize(x);
+ y = rb_rational_canonicalize(y);
+ return f_complex_new2(CLASS_OF(self), x, y);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
diff --git a/internal.h b/internal.h
index ea1b926de8..bfeffabffd 100644
--- a/internal.h
+++ b/internal.h
@@ -1729,6 +1729,7 @@ rb_pid_t rb_fork_ruby(int *status);
void rb_last_status_clear(void);
/* rational.c */
+VALUE rb_rational_canonicalize(VALUE x);
VALUE rb_rational_uminus(VALUE self);
VALUE rb_rational_plus(VALUE self, VALUE other);
VALUE rb_lcm(VALUE x, VALUE y);
diff --git a/rational.c b/rational.c
index d88f50f886..64fc10ce47 100644
--- a/rational.c
+++ b/rational.c
@@ -1991,6 +1991,15 @@ rb_numeric_quo(VALUE x, VALUE y)
return nurat_div(x, y);
}
+VALUE
+rb_rational_canonicalize(VALUE x)
+{
+ if (RB_TYPE_P(x, T_RATIONAL)) {
+ get_dat1(x);
+ if (f_one_p(dat->den)) return dat->num;
+ }
+ return x;
+}
/*
* call-seq:
diff --git a/test/ruby/test_complex.rb b/test/ruby/test_complex.rb
index d8d8fb9cd6..10289226fe 100644
--- a/test/ruby/test_complex.rb
+++ b/test/ruby/test_complex.rb
@@ -323,6 +323,13 @@ class Complex_Test < Test::Unit::TestCase
assert_equal(Complex(Rational(1,2),Rational(1)), c / Rational(2))
assert_equal(Complex(Rational(3,2),Rational(3)), c / Rational(2,3))
+
+ c = Complex(1)
+ r = c / c
+ assert_instance_of(Complex, r)
+ assert_equal(1, r)
+ assert_predicate(r.real, :integer?)
+ assert_predicate(r.imag, :integer?)
end
def test_quo