ruby-changes:33724
From: nobu <ko1@a...>
Date: Sun, 4 May 2014 10:23:09 +0900 (JST)
Subject: [ruby-changes:33724] nobu:r45805 (trunk): math.c: C99-like atan2
nobu 2014-05-04 10:23:01 +0900 (Sun, 04 May 2014) New Revision: 45805 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=45805 Log: math.c: C99-like atan2 * math.c (math_atan2): return values like as expected by C99 if both two arguments are infinity. based on the patch by cremno phobia <cremno AT mail.ru> in [ruby-core:62310]. [Feature #9799] Modified files: trunk/ChangeLog trunk/NEWS trunk/configure.in trunk/math.c trunk/test/ruby/test_math.rb Index: math.c =================================================================== --- math.c (revision 45804) +++ math.c (revision 45805) @@ -55,6 +55,10 @@ VALUE rb_eMathDomainError; https://github.com/ruby/ruby/blob/trunk/math.c#L55 * Math.atan2(1.0, 0.0) #=> 1.5707963267948966 * Math.atan2(1.0, -1.0) #=> 2.356194490192345 * Math.atan2(0.0, -1.0) #=> 3.141592653589793 + * Math.atan2(INFINITY, INFINITY) #=> 0.7853981633974483 + * Math.atan2(INFINITY, -INFINITY) #=> 2.356194490192345 + * Math.atan2(-INFINITY, INFINITY) #=> -0.7853981633974483 + * Math.atan2(-INFINITY, -INFINITY) #=> -2.356194490192345 * */ @@ -75,7 +79,20 @@ math_atan2(VALUE obj, VALUE y, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L79 return DBL2NUM(M_PI); return DBL2NUM(-M_PI); } - if (isinf(dx) && isinf(dy)) domain_error("atan2"); +#if !(defined(HAVE_ATAN2L) && defined(HAVE_ATAN2F)) || 1 + /* assume atan2() doesn't handle Inf as C99 */ + if (isinf(dx) && isinf(dy)) { + /* optimization for FLONUM */ + if (dx < 0.0) { + const double dz = (3.0 * M_PI / 4.0); + return (dy < 0.0) ? DBL2NUM(-dz) : DBL2NUM(dz); + } + else { + const double dz = (M_PI / 4.0); + return (dy < 0.0) ? DBL2NUM(-dz) : DBL2NUM(dz); + } + } +#endif return DBL2NUM(atan2(dy, dx)); } Index: configure.in =================================================================== --- configure.in (revision 45804) +++ configure.in (revision 45805) @@ -1941,6 +1941,7 @@ AC_CHECK_FUNCS(__syscall) https://github.com/ruby/ruby/blob/trunk/configure.in#L1941 AC_CHECK_FUNCS(_longjmp) # used for AC_ARG_WITH(setjmp-type) AC_CHECK_FUNCS(_setjmp) # used for AC_ARG_WITH(setjmp-type) AC_CHECK_FUNCS(_setjmpex) # used for AC_ARG_WITH(setjmp-type) +AC_CHECK_FUNCS(atan2l atan2f) AC_CHECK_FUNCS(chroot) AC_CHECK_FUNCS(chsize) AC_CHECK_FUNCS(clock_gettime) Index: ChangeLog =================================================================== --- ChangeLog (revision 45804) +++ ChangeLog (revision 45805) @@ -1,3 +1,9 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Sun May 4 10:22:59 2014 Nobuyoshi Nakada <nobu@r...> + + * math.c (math_atan2): return values like as expected by C99 if + both two arguments are infinity. based on the patch by cremno + phobia <cremno AT mail.ru> in [ruby-core:62310]. [Feature #9799] + Sun May 4 03:46:42 2014 Tanaka Akira <akr@f...> * lib/time.rb (Time.httpdate): Always return a UTC Time object. Index: NEWS =================================================================== --- NEWS (revision 45804) +++ NEWS (revision 45805) @@ -54,6 +54,8 @@ with all sufficient information, see the https://github.com/ruby/ruby/blob/trunk/NEWS#L54 * Math.log now raises Math::DomainError instead of returning NaN if the base is less than 0, and returns NaN instead of -infinity if both of two arguments are 0. + * Math.atan2 now returns values like as expected by C99 if both two + arguments are infinity. * Proc * incompatible changes: Index: test/ruby/test_math.rb =================================================================== --- test/ruby/test_math.rb (revision 45804) +++ test/ruby/test_math.rb (revision 45805) @@ -22,10 +22,15 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L22 check(-0.0, Math.atan2(-0.0, +0.0)) check(+Math::PI, Math.atan2(+0.0, -0.0)) check(-Math::PI, Math.atan2(-0.0, -0.0)) - assert_raise(Math::DomainError) { Math.atan2(Float::INFINITY, Float::INFINITY) } - assert_raise(Math::DomainError) { Math.atan2(Float::INFINITY, -Float::INFINITY) } - assert_raise(Math::DomainError) { Math.atan2(-Float::INFINITY, Float::INFINITY) } - assert_raise(Math::DomainError) { Math.atan2(-Float::INFINITY, -Float::INFINITY) } + + inf = Float::INFINITY + expected = 3.0 * Math::PI / 4.0 + assert_nothing_raised { check(+expected, Math.atan2(+inf, -inf)) } + assert_nothing_raised { check(-expected, Math.atan2(-inf, -inf)) } + expected = Math::PI / 4.0 + assert_nothing_raised { check(+expected, Math.atan2(+inf, +inf)) } + assert_nothing_raised { check(-expected, Math.atan2(-inf, +inf)) } + check(0, Math.atan2(0, 1)) check(Math::PI / 4, Math.atan2(1, 1)) check(Math::PI / 2, Math.atan2(1, 0)) -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/