1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

* complex.c (nucomp_addsub): new

* complex.c (nucomp_{add,sub}): use nucomp_addsub.

	* complex.c (nucomp_divide): changed the algorithm.

	* complex.c (nucomp_abs): added shortcuts.



git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@23872 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
tadf 2009-06-27 10:12:04 +00:00
parent f94228c8bd
commit 7cf1d66848
2 changed files with 82 additions and 45 deletions

View file

@ -1,3 +1,13 @@
Sat Jun 27 19:06:22 2009 Tadayoshi Funaba <tadf@dotrb.org>
* complex.c (nucomp_addsub): new
* complex.c (nucomp_{add,sub}): use nucomp_addsub.
* complex.c (nucomp_divide): changed the algorithm.
* complex.c (nucomp_abs): added shortcuts.
Sat Jun 27 16:56:33 2009 Tadayoshi Funaba <tadf@dotrb.org>
* rational.c (nurat_cmp): use rb_num_coerce_cmp.

115
complex.c
View file

@ -585,6 +585,29 @@ nucomp_negate(VALUE self)
f_negate(dat->real), f_negate(dat->imag));
}
static VALUE
nucomp_addsub(VALUE self, VALUE other,
VALUE (*func)(VALUE, VALUE), ID id)
{
if (k_complex_p(other)) {
VALUE real, imag;
get_dat2(self, other);
real = (*func)(adat->real, bdat->real);
imag = (*func)(adat->imag, bdat->imag);
return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
(*func)(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, id);
}
/*
* call-seq:
* cmp + numeric -> complex
@ -594,23 +617,7 @@ nucomp_negate(VALUE self)
static VALUE
nucomp_add(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
VALUE real, imag;
get_dat2(self, other);
real = f_add(adat->real, bdat->real);
imag = f_add(adat->imag, bdat->imag);
return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_add(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '+');
return nucomp_addsub(self, other, f_add, '+');
}
/*
@ -622,23 +629,7 @@ nucomp_add(VALUE self, VALUE other)
static VALUE
nucomp_sub(VALUE self, VALUE other)
{
if (k_complex_p(other)) {
VALUE real, imag;
get_dat2(self, other);
real = f_sub(adat->real, bdat->real);
imag = f_sub(adat->imag, bdat->imag);
return f_complex_new2(CLASS_OF(self), real, imag);
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
return f_complex_new2(CLASS_OF(self),
f_sub(dat->real, other), dat->imag);
}
return rb_num_coerce_bin(self, other, '-');
return nucomp_addsub(self, other, f_sub, '-');
}
/*
@ -677,19 +668,42 @@ nucomp_divide(VALUE self, VALUE other,
VALUE (*func)(VALUE, VALUE), ID id)
{
if (k_complex_p(other)) {
int flo;
get_dat2(self, other);
if (TYPE(adat->real) == T_FLOAT ||
TYPE(adat->imag) == T_FLOAT ||
TYPE(bdat->real) == T_FLOAT ||
TYPE(bdat->imag) == T_FLOAT) {
VALUE magn = m_hypot(bdat->real, bdat->imag);
VALUE tmp = f_complex_new_bang2(CLASS_OF(self),
(*func)(bdat->real, magn),
(*func)(bdat->imag, magn));
return (*func)(f_mul(self, f_conj(tmp)), magn);
flo = (k_float_p(adat->real) || k_float_p(adat->imag) ||
k_float_p(bdat->real) || k_float_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));
}
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));
}
return (*func)(f_mul(self, f_conj(other)), f_abs2(other));
}
if (k_numeric_p(other) && f_real_p(other)) {
get_dat1(self);
@ -858,6 +872,19 @@ static VALUE
nucomp_abs(VALUE self)
{
get_dat1(self);
if (f_zero_p(dat->real)) {
VALUE a = f_abs(dat->imag);
if (k_float_p(dat->real) && !k_float_p(dat->imag))
a = f_to_f(a);
return a;
}
if (f_zero_p(dat->imag)) {
VALUE a = f_abs(dat->real);
if (!k_float_p(dat->real) && k_float_p(dat->imag))
a = f_to_f(a);
return a;
}
return m_hypot(dat->real, dat->imag);
}