Commit 8136df6a authored by Paul Eggert's avatar Paul Eggert

Make logcount act like CL on negative arg

Behaving like Common Lisp is less likely to lead to surprises,
as it yields the same answers on 32- vs 64-bit machines.
* doc/lispref/numbers.texi (Bitwise Operations):
Document behavior on negative integers.
* src/data.c (Flogcount):
Behave like Common Lisp for negative arguments.
* test/src/data-tests.el (data-tests-popcnt)
(data-tests-logcount): Test negative args too.
parent d247e1d3
......@@ -1113,9 +1113,14 @@ bit is one in the result if, and only if, the @var{n}th bit is zero in
@defun logcount integer
This function returns the @dfn{Hamming weight} of @var{integer}: the
number of ones in the binary representation of @var{integer}.
If @var{integer} is negative, it returns the number of zero bits in
its two's complement binary representation. The result is always
nonnegative.
@example
(logcount 42) ; 42 = #b101010
(logcount 43) ; 43 = #b101011
@result{} 4
(logcount -43) ; -43 = #b111...1010101
@result{} 3
@end example
@end defun
......
......@@ -3071,11 +3071,13 @@ usage: (logxor &rest INTS-OR-MARKERS) */)
DEFUN ("logcount", Flogcount, Slogcount, 1, 1, 0,
doc: /* Return population count of VALUE.
If VALUE is negative, the count is of its two's complement representation. */)
This is the number of one bits in the two's complement representation
of VALUE. If VALUE is negative, return the number of zero bits in the
representation. */)
(Lisp_Object value)
{
CHECK_NUMBER (value);
EMACS_UINT v = XUINT (value);
EMACS_INT v = XINT (value) < 0 ? -1 - XINT (value) : XINT (value);
return make_number (EMACS_UINT_WIDTH <= UINT_WIDTH
? count_one_bits (v)
: EMACS_UINT_WIDTH <= ULONG_WIDTH
......
......@@ -109,12 +109,14 @@
(defun data-tests-popcnt (byte)
"Calculate the Hamming weight of BYTE."
(if (< byte 0)
(setq byte (lognot byte)))
(setq byte (- byte (logand (lsh byte -1) #x55555555)))
(setq byte (+ (logand byte #x33333333) (logand (lsh byte -2) #x33333333)))
(lsh (* (logand (+ byte (lsh byte -4)) #x0f0f0f0f) #x01010101) -24))
(ert-deftest data-tests-logcount ()
(should (cl-loop for n in (number-sequence 0 255)
(should (cl-loop for n in (number-sequence -255 255)
always (= (logcount n) (data-tests-popcnt n))))
;; https://oeis.org/A000120
(should (= 11 (logcount 9727)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment