[前][次][番号順一覧][スレッド一覧]

ruby-changes:66682

From: Nobuyoshi <ko1@a...>
Date: Mon, 5 Jul 2021 10:22:41 +0900 (JST)
Subject: [ruby-changes:66682] 0a32cefabd (master): Add domain check macros

https://git.ruby-lang.org/ruby.git/commit/?id=0a32cefabd

From 0a32cefabd2fb583a9141ef9c9553994a9fb4a4a Mon Sep 17 00:00:00 2001
From: Nobuyoshi Nakada <nobu@r...>
Date: Sun, 4 Jul 2021 19:22:11 +0900
Subject: Add domain check macros

---
 math.c                 | 30 +++++++++++++-----------------
 test/ruby/test_math.rb | 21 ++++++++++++++++++++-
 2 files changed, 33 insertions(+), 18 deletions(-)

diff --git a/math.c b/math.c
index d099e25..f0237d4 100644
--- a/math.c
+++ b/math.c
@@ -40,6 +40,10 @@ VALUE rb_eMathDomainError; https://github.com/ruby/ruby/blob/trunk/math.c#L40
 
 #define domain_error(msg) \
     rb_raise(rb_eMathDomainError, "Numerical argument is out of domain - " msg)
+#define domain_check_min(val, min, msg) \
+    ((val) < (min) ? domain_error(msg) : (void)0)
+#define domain_check_range(val, min, max, msg) \
+    ((val) < (min) || (max) < (val) ? domain_error(msg) : (void)0)
 
 /*
  *  call-seq:
@@ -184,8 +188,7 @@ math_acos(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L188
     double d;
 
     d = Get_Double(x);
-    /* check for domain error */
-    if (d < -1.0 || 1.0 < d) domain_error("acos");
+    domain_check_range(d, -1.0, 1.0, "acos");
     return DBL2NUM(acos(d));
 }
 
@@ -208,8 +211,7 @@ math_asin(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L211
     double d;
 
     d = Get_Double(x);
-    /* check for domain error */
-    if (d < -1.0 || 1.0 < d) domain_error("asin");
+    domain_check_range(d, -1.0, 1.0, "asin");
     return DBL2NUM(asin(d));
 }
 
@@ -343,8 +345,7 @@ math_acosh(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L345
     double d;
 
     d = Get_Double(x);
-    /* check for domain error */
-    if (d < 1.0) domain_error("acosh");
+    domain_check_min(d, 1.0, "acosh");
     return DBL2NUM(acosh(d));
 }
 
@@ -388,8 +389,7 @@ math_atanh(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L389
     double d;
 
     d = Get_Double(x);
-    /* check for domain error */
-    if (d <  -1.0 || +1.0 <  d) domain_error("atanh");
+    domain_check_range(d, -1.0, +1.0, "atanh");
     /* check for pole error */
     if (d == -1.0) return DBL2NUM(-HUGE_VAL);
     if (d == +1.0) return DBL2NUM(+HUGE_VAL);
@@ -501,8 +501,7 @@ math_log1(VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L501
     size_t numbits;
     double d = get_double_rshift(x, &numbits);
 
-    /* check for domain error */
-    if (d < 0.0) domain_error("log");
+    domain_check_min(d, 0.0, "log");
     /* check for pole error */
     if (d == 0.0) return -HUGE_VAL;
 
@@ -544,8 +543,7 @@ math_log2(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L543
     size_t numbits;
     double d = get_double_rshift(x, &numbits);
 
-    /* check for domain error */
-    if (d < 0.0) domain_error("log2");
+    domain_check_min(d, 0.0, "log2");
     /* check for pole error */
     if (d == 0.0) return DBL2NUM(-HUGE_VAL);
 
@@ -574,8 +572,7 @@ math_log10(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L572
     size_t numbits;
     double d = get_double_rshift(x, &numbits);
 
-    /* check for domain error */
-    if (d < 0.0) domain_error("log10");
+    domain_check_min(d, 0.0, "log10");
     /* check for pole error */
     if (d == 0.0) return DBL2NUM(-HUGE_VAL);
 
@@ -656,8 +653,7 @@ rb_math_sqrt(VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L653
 	return rb_complex_new(DBL2NUM(re), DBL2NUM(im));
     }
     d = Get_Double(x);
-    /* check for domain error */
-    if (d < 0.0) domain_error("sqrt");
+    domain_check_min(d, 0.0, "sqrt");
     if (d == 0.0) return DBL2NUM(0.0);
     return DBL2NUM(sqrt(d));
 }
@@ -886,7 +882,7 @@ math_gamma(VALUE unused_obj, VALUE x) https://github.com/ruby/ruby/blob/trunk/math.c#L882
 	return signbit(d) ? DBL2NUM(-HUGE_VAL) : DBL2NUM(HUGE_VAL);
     }
     if (d == floor(d)) {
-	if (d < 0.0) domain_error("gamma");
+	domain_check_min(d, 0.0, "gamma");
 	if (1.0 <= d && d <= (double)NFACT_TABLE) {
 	    return DBL2NUM(fact_table[(int)d - 1]);
 	}
diff --git a/test/ruby/test_math.rb b/test/ruby/test_math.rb
index abfb980..73f44c6 100644
--- a/test/ruby/test_math.rb
+++ b/test/ruby/test_math.rb
@@ -158,9 +158,13 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L158
     assert_nothing_raised { assert_infinity(-Math.log(+0.0)) }
     assert_nothing_raised { assert_infinity(-Math.log(-0.0)) }
     assert_raise_with_message(Math::DomainError, /\blog\b/) { Math.log(-1.0) }
+    assert_raise_with_message(Math::DomainError, /\blog\b/) { Math.log(-Float::EPSILON) }
     assert_raise(TypeError) { Math.log(1,nil) }
-    assert_raise(Math::DomainError, '[ruby-core:62309] [ruby-Bug #9797]') { Math.log(1.0, -1.0) }
+    assert_raise_with_message(Math::DomainError, /\blog\b/, '[ruby-core:62309] [ruby-Bug #9797]') { Math.log(1.0, -1.0) }
+    assert_raise_with_message(Math::DomainError, /\blog\b/) { Math.log(1.0, -Float::EPSILON) }
     assert_nothing_raised { assert_nan(Math.log(0.0, 0.0)) }
+    assert_nothing_raised { assert_nan(Math.log(Float::NAN)) }
+    assert_nothing_raised { assert_nan(Math.log(1.0, Float::NAN)) }
   end
 
   def test_log2
@@ -173,6 +177,8 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L177
     assert_nothing_raised { assert_infinity(-Math.log2(+0.0)) }
     assert_nothing_raised { assert_infinity(-Math.log2(-0.0)) }
     assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-1.0) }
+    assert_raise_with_message(Math::DomainError, /\blog2\b/) { Math.log2(-Float::EPSILON) }
+    assert_nothing_raised { assert_nan(Math.log2(Float::NAN)) }
   end
 
   def test_log10
@@ -185,6 +191,8 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L191
     assert_nothing_raised { assert_infinity(-Math.log10(+0.0)) }
     assert_nothing_raised { assert_infinity(-Math.log10(-0.0)) }
     assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-1.0) }
+    assert_raise_with_message(Math::DomainError, /\blog10\b/) { Math.log10(-Float::EPSILON) }
+    assert_nothing_raised { assert_nan(Math.log10(Float::NAN)) }
   end
 
   def test_sqrt
@@ -194,6 +202,8 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L202
     assert_nothing_raised { assert_infinity(Math.sqrt(1.0/0)) }
     assert_equal("0.0", Math.sqrt(-0.0).to_s) # insure it is +0.0, not -0.0
     assert_raise_with_message(Math::DomainError, /\bsqrt\b/) { Math.sqrt(-1.0) }
+    assert_raise_with_message(Math::DomainError, /\bsqrt\b/) { Math.sqrt(-Float::EPSILON) }
+    assert_nothing_raised { assert_nan(Math.sqrt(Float::NAN)) }
   end
 
   def test_cbrt
@@ -204,6 +214,8 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L214
     check(0.0, Math.cbrt(0.0))
     assert_nothing_raised { assert_infinity(Math.cbrt(1.0/0)) }
     assert_operator(Math.cbrt(1.0 - Float::EPSILON), :<=, 1.0)
+    assert_nothing_raised { assert_nan(Math.sqrt(Float::NAN)) }
+    assert_nothing_raised { assert_nan(Math.cbrt(Float::NAN)) }
   end
 
   def test_frexp
@@ -212,6 +224,7 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L224
     assert_float_and_int([0.5,  1], Math.frexp(1.0))
     assert_float_and_int([0.5,  2], Math.frexp(2.0))
     assert_float_and_int([0.75, 2], Math.frexp(3.0))
+    assert_nan(Math.frexp(Float::NAN)[0])
   end
 
   def test_ldexp
@@ -229,11 +242,13 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L242
   def test_erf
     check(0, Math.erf(0))
     check(1, Math.erf(1.0 / 0.0))
+    assert_nan(Math.erf(Float::NAN))
   end
 
   def test_erfc
     check(1, Math.erfc(0))
     check(0, Math.erfc(1.0 / 0.0))
+    assert_nan(Math.erfc(Float::NAN))
   end
 
   def test_gamma
@@ -259,10 +274,12 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L274
     end
 
     assert_raise_with_message(Math::DomainError, /\bgamma\b/) { Math.gamma(-Float::INFINITY) }
+    assert_raise_with_message(Math::DomainError, /\bgamma\b/) { Math.gamma(-1.0) }
     x = Math.gamma(-0.0)
     mesg = "Math.gamma(-0.0) should be -INF"
     assert_infinity(x, mesg)
     assert_predicate(x, :negative?, mesg)
+    assert_nan(Math.gamma(Float::NAN))
   end
 
   def test_lgamma
@@ -284,6 +301,8 @@ class TestMath < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_math.rb#L301
     assert_infinity(x, mesg)
     assert_predicate(x, :positive?, mesg)
     assert_equal(-1, sign, mesg)
+    x, sign = Math.lgamma(Float::NAN)
+    assert_nan(x)
   end
 
   def test_fixnum_to_f
-- 
cgit v1.1


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]