]> git.eshelyaron.com Git - emacs.git/commitdiff
Make logcount act like CL on negative arg
authorPaul Eggert <eggert@cs.ucla.edu>
Sat, 30 Sep 2017 22:36:52 +0000 (15:36 -0700)
committerPaul Eggert <eggert@cs.ucla.edu>
Sat, 30 Sep 2017 22:38:14 +0000 (15:38 -0700)
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.

doc/lispref/numbers.texi
src/data.c
test/src/data-tests.el

index 5058063af4d261b781de7b5dc11edd8a725468fb..be74b0c61115aa748574138ee43043eb0b40fb16 100644 (file)
@@ -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
index fd8cdd19aa2173fa992821e9bfa0669b2a1e6028..2e7f3e017be9d8371a1fca75dcaf9d199782fe07 100644 (file)
@@ -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
index d1154cc5c4472e3a1243382dc5a442a00f01f98d..374d1689b9e7764c3aa99a1f86da4032457a68c2 100644 (file)
 
 (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)))