math.c: Complex sqrt
* math.c (rb_math_sqrt): [EXPERIMENTAL] move Complex sqrt support from mathn.rb. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@55646 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
89ed4f41a3
commit
745a2aac69
@ -1,3 +1,8 @@
|
|||||||
|
Tue Jul 12 23:13:43 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* math.c (rb_math_sqrt): [EXPERIMENTAL] move Complex sqrt support
|
||||||
|
from mathn.rb.
|
||||||
|
|
||||||
Tue Jul 12 21:59:40 2016 Martin Duerst <duerst@it.aoyama.ac.jp>
|
Tue Jul 12 21:59:40 2016 Martin Duerst <duerst@it.aoyama.ac.jp>
|
||||||
|
|
||||||
* revert r55642 (previous commit) because of test failure at
|
* revert r55642 (previous commit) because of test failure at
|
||||||
|
34
complex.c
34
complex.c
@ -535,6 +535,21 @@ m_sin(VALUE x)
|
|||||||
#if 0
|
#if 0
|
||||||
imp1(sqrt)
|
imp1(sqrt)
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_complex_sqrt(VALUE x)
|
||||||
|
{
|
||||||
|
int pos;
|
||||||
|
VALUE a, re, im;
|
||||||
|
get_dat1(x);
|
||||||
|
|
||||||
|
pos = f_positive_p(dat->imag);
|
||||||
|
a = f_abs(x);
|
||||||
|
re = m_sqrt_bang(f_div(f_add(a, dat->real), TWO));
|
||||||
|
im = m_sqrt_bang(f_div(f_sub(a, dat->real), TWO));
|
||||||
|
if (!pos) im = f_negate(im);
|
||||||
|
return f_complex_new2(rb_cComplex, re, im);
|
||||||
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
m_sqrt(VALUE x)
|
m_sqrt(VALUE x)
|
||||||
{
|
{
|
||||||
@ -543,18 +558,7 @@ m_sqrt(VALUE x)
|
|||||||
return m_sqrt_bang(x);
|
return m_sqrt_bang(x);
|
||||||
return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
|
return f_complex_new2(rb_cComplex, ZERO, m_sqrt_bang(f_negate(x)));
|
||||||
}
|
}
|
||||||
else {
|
return rb_complex_sqrt(x);
|
||||||
get_dat1(x);
|
|
||||||
|
|
||||||
if (f_negative_p(dat->imag))
|
|
||||||
return f_conj(m_sqrt(f_conj(x)));
|
|
||||||
else {
|
|
||||||
VALUE a = f_abs(x);
|
|
||||||
return f_complex_new2(rb_cComplex,
|
|
||||||
m_sqrt_bang(f_div(f_add(a, dat->real), TWO)),
|
|
||||||
m_sqrt_bang(f_div(f_sub(a, dat->real), TWO)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1415,6 +1419,12 @@ rb_complex_set_imag(VALUE cmp, VALUE i)
|
|||||||
return cmp;
|
return cmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_complex_abs(VALUE cmp)
|
||||||
|
{
|
||||||
|
return nucomp_abs(cmp);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* call-seq:
|
* call-seq:
|
||||||
* cmp.to_i -> integer
|
* cmp.to_i -> integer
|
||||||
|
@ -903,6 +903,8 @@ VALUE rb_insns_name_array(void);
|
|||||||
/* complex.c */
|
/* complex.c */
|
||||||
VALUE rb_complex_plus(VALUE, VALUE);
|
VALUE rb_complex_plus(VALUE, VALUE);
|
||||||
VALUE rb_complex_mul(VALUE, VALUE);
|
VALUE rb_complex_mul(VALUE, VALUE);
|
||||||
|
VALUE rb_complex_abs(VALUE x);
|
||||||
|
VALUE rb_complex_sqrt(VALUE x);
|
||||||
|
|
||||||
/* cont.c */
|
/* cont.c */
|
||||||
VALUE rb_obj_is_fiber(VALUE);
|
VALUE rb_obj_is_fiber(VALUE);
|
||||||
@ -1083,9 +1085,7 @@ VALUE rb_math_hypot(VALUE, VALUE);
|
|||||||
VALUE rb_math_log(int argc, const VALUE *argv);
|
VALUE rb_math_log(int argc, const VALUE *argv);
|
||||||
VALUE rb_math_sin(VALUE);
|
VALUE rb_math_sin(VALUE);
|
||||||
VALUE rb_math_sinh(VALUE);
|
VALUE rb_math_sinh(VALUE);
|
||||||
#if 0
|
|
||||||
VALUE rb_math_sqrt(VALUE);
|
VALUE rb_math_sqrt(VALUE);
|
||||||
#endif
|
|
||||||
|
|
||||||
/* newline.c */
|
/* newline.c */
|
||||||
void Init_newline(void);
|
void Init_newline(void);
|
||||||
|
@ -103,14 +103,7 @@ module Math
|
|||||||
|
|
||||||
def sqrt(a)
|
def sqrt(a)
|
||||||
if a.kind_of?(Complex)
|
if a.kind_of?(Complex)
|
||||||
abs = sqrt(a.real*a.real + a.imag*a.imag)
|
sqrt!(a)
|
||||||
x = sqrt((a.real + abs)/Rational(2))
|
|
||||||
y = sqrt((-a.real + abs)/Rational(2))
|
|
||||||
if a.imag >= 0
|
|
||||||
Complex(x, y)
|
|
||||||
else
|
|
||||||
Complex(x, -y)
|
|
||||||
end
|
|
||||||
elsif a.respond_to?(:nan?) and a.nan?
|
elsif a.respond_to?(:nan?) and a.nan?
|
||||||
a
|
a
|
||||||
elsif a >= 0
|
elsif a >= 0
|
||||||
|
15
math.c
15
math.c
@ -587,9 +587,24 @@ math_log10(VALUE obj, VALUE x)
|
|||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
math_sqrt(VALUE obj, VALUE x)
|
math_sqrt(VALUE obj, VALUE x)
|
||||||
|
{
|
||||||
|
return rb_math_sqrt(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_math_sqrt(VALUE x)
|
||||||
{
|
{
|
||||||
double d;
|
double d;
|
||||||
|
|
||||||
|
if (RB_TYPE_P(x, T_COMPLEX)) {
|
||||||
|
int neg = signbit(RCOMPLEX(x)->imag);
|
||||||
|
double re = Get_Double(RCOMPLEX(x)->real), im;
|
||||||
|
d = Get_Double(rb_complex_abs(x));
|
||||||
|
im = sqrt((d - re) / 2.0);
|
||||||
|
re = sqrt((d + re) / 2.0);
|
||||||
|
if (neg) im = -im;
|
||||||
|
return rb_complex_new(DBL2NUM(re), DBL2NUM(im));
|
||||||
|
}
|
||||||
d = Get_Double(x);
|
d = Get_Double(x);
|
||||||
/* check for domain error */
|
/* check for domain error */
|
||||||
if (d < 0.0) domain_error("sqrt");
|
if (d < 0.0) domain_error("sqrt");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user