diff options
-rw-r--r-- | doc/lispref/numbers.texi | 8 | ||||
-rw-r--r-- | etc/NEWS | 4 | ||||
-rw-r--r-- | src/floatfns.c | 27 |
3 files changed, 21 insertions, 18 deletions
diff --git a/doc/lispref/numbers.texi b/doc/lispref/numbers.texi index cffc634169f..fbdd83fa86e 100644 --- a/doc/lispref/numbers.texi +++ b/doc/lispref/numbers.texi @@ -313,14 +313,18 @@ and returns the result. @var{x1} and @var{x2} must be floating point. @defun logb x This function returns the binary exponent of @var{x}. More -precisely, the value is the logarithm base 2 of @math{|x|}, rounded -down to an integer. +precisely, if @var{x} is finite and nonzero, the value is the +logarithm base 2 of @math{|x|}, rounded down to an integer. +If @var{x} is zero, infinite, or a NaN, the value is minus infinity, +plus infinity, or a NaN respectively. @example (logb 10) @result{} 3 (logb 10.0e20) @result{} 69 +(logb 0) + @result{} -1.0e+INF @end example @end defun @@ -1112,6 +1112,10 @@ old-style backquotes as new-style, bind the new variable integer, Emacs now signals an error if the number is too large for the implementation to format. +** logb now returns infinity when given an infinite or zero argument, +and returns a NaN when given a NaN. Formerly, it returned an extreme +fixnum for such arguments. + --- ** Some functions and variables obsolete since Emacs 22 have been removed: archive-mouse-extract, assoc-ignore-case, assoc-ignore-representation, diff --git a/src/floatfns.c b/src/floatfns.c index 2d76b97eec7..a913aad5aac 100644 --- a/src/floatfns.c +++ b/src/floatfns.c @@ -306,27 +306,22 @@ This is the same as the exponent of a float. */) if (FLOATP (arg)) { double f = XFLOAT_DATA (arg); - if (f == 0) - value = MOST_NEGATIVE_FIXNUM; - else if (isfinite (f)) - { - int ivalue; - frexp (f, &ivalue); - value = ivalue - 1; - } - else - value = MOST_POSITIVE_FIXNUM; + return make_float (-HUGE_VAL); + if (!isfinite (f)) + return f < 0 ? make_float (-f) : arg; + int ivalue; + frexp (f, &ivalue); + value = ivalue - 1; } - else if (BIGNUMP (arg)) + else if (!FIXNUMP (arg)) value = mpz_sizeinbase (XBIGNUM (arg)->value, 2) - 1; else { - eassert (FIXNUMP (arg)); - EMACS_INT i = eabs (XFIXNUM (arg)); - value = (i == 0 - ? MOST_NEGATIVE_FIXNUM - : EMACS_UINT_WIDTH - 1 - ecount_leading_zeros (i)); + EMACS_INT i = XFIXNUM (arg); + if (i == 0) + return make_float (-HUGE_VAL); + value = EMACS_UINT_WIDTH - 1 - ecount_leading_zeros (eabs (i)); } return make_fixnum (value); |