mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
Add domain check macros
This commit is contained in:
parent
2488589b2f
commit
0a32cefabd
2 changed files with 33 additions and 18 deletions
30
math.c
30
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]);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue