summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--math.c30
-rw-r--r--test/ruby/test_math.rb21
2 files changed, 33 insertions, 18 deletions
diff --git a/math.c b/math.c
index d099e254d9..f0237d4fa9 100644
--- a/math.c
+++ b/math.c
@@ -40,6 +40,10 @@ VALUE rb_eMathDomainError;
#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)
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)
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)
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)
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)
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)
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)
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)
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)
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 abfb980e64..73f44c6ae3 100644
--- a/test/ruby/test_math.rb
+++ b/test/ruby/test_math.rb
@@ -158,9 +158,13 @@ class TestMath < Test::Unit::TestCase
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
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
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
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
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
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
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
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
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