1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

math.c: check domain of base argument

* math.c (math_log): check domain of base argument too.  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.  [ruby-core:62309] [Bug #9797]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@45795 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2014-05-03 05:28:46 +00:00
parent 1fd4c7f1f5
commit 38656e24be
3 changed files with 26 additions and 8 deletions

7
NEWS
View file

@ -48,6 +48,13 @@ with all sufficient information, see the ChangeLog file.
* When flushing file IO, you cannot assume that the metadata of the file * When flushing file IO, you cannot assume that the metadata of the file
is updated immediately. On some platforms (especially Windows), it is is updated immediately. On some platforms (especially Windows), it is
delayed until the filesystem load is decreased. delayed until the filesystem load is decreased.
* Math
* incompatible changes:
* 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.
* Proc * Proc
* incompatible changes: * incompatible changes:
* ArgumentError is no longer raised when lambda Proc is passed as a * ArgumentError is no longer raised when lambda Proc is passed as a

25
math.c
View file

@ -416,6 +416,8 @@ math_exp(VALUE obj, VALUE x)
# define log10(x) ((x) < 0.0 ? nan("") : log10(x)) # define log10(x) ((x) < 0.0 ? nan("") : log10(x))
#endif #endif
static double math_log1(VALUE x);
/* /*
* call-seq: * call-seq:
* Math.log(x) -> Float * Math.log(x) -> Float
@ -441,10 +443,21 @@ static VALUE
math_log(int argc, VALUE *argv, VALUE obj) math_log(int argc, VALUE *argv, VALUE obj)
{ {
VALUE x, base; VALUE x, base;
double d0, d; double d;
size_t numbits;
rb_scan_args(argc, argv, "11", &x, &base); rb_scan_args(argc, argv, "11", &x, &base);
d = math_log1(x);
if (argc == 2) {
d /= math_log1(base);
}
return DBL2NUM(d);
}
static double
math_log1(VALUE x)
{
double d0, d;
size_t numbits;
if (RB_BIGNUM_TYPE_P(x) && BIGNUM_POSITIVE_P(x) && if (RB_BIGNUM_TYPE_P(x) && BIGNUM_POSITIVE_P(x) &&
DBL_MAX_EXP <= (numbits = rb_absint_numwords(x, 1, NULL))) { DBL_MAX_EXP <= (numbits = rb_absint_numwords(x, 1, NULL))) {
@ -460,15 +473,11 @@ math_log(int argc, VALUE *argv, VALUE obj)
/* check for domain error */ /* check for domain error */
if (d0 < 0.0) domain_error("log"); if (d0 < 0.0) domain_error("log");
/* check for pole error */ /* check for pole error */
if (d0 == 0.0) return DBL2NUM(-INFINITY); if (d0 == 0.0) return -INFINITY;
d = log(d0); d = log(d0);
if (numbits) if (numbits)
d += numbits * log(2); /* log(2**numbits) */ d += numbits * log(2); /* log(2**numbits) */
if (argc == 2) { return d;
Need_Float(base);
d /= log(RFLOAT_VALUE(base));
}
return DBL2NUM(d);
} }
#ifndef log2 #ifndef log2

View file

@ -142,6 +142,8 @@ 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(Math::DomainError) { Math.log(-1.0) } assert_raise(Math::DomainError) { Math.log(-1.0) }
assert_raise(TypeError) { Math.log(1,nil) } assert_raise(TypeError) { Math.log(1,nil) }
assert_raise(Math::DomainError, '[ruby-core:62309] [ruby-Bug #9797]') { Math.log(1.0, -1.0) }
assert_nothing_raised { assert_nan(Math.log(0.0, 0.0)) }
end end
def test_log2 def test_log2