summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/lispref/numbers.texi8
-rw-r--r--etc/NEWS4
-rw-r--r--src/floatfns.c27
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
diff --git a/etc/NEWS b/etc/NEWS
index b316aecbfa4..3670ab5bf44 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -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);