comparison lisp/cl-extra.el @ 5915:1af53d35dd53

Avoid allocation in #'integer-length; add #'logcount. lisp/ChangeLog addition: 2015-05-29 Aidan Kehoe <kehoea@parhasard.net> * byte-optimize.el (side-effect-free-fns): Add #'integer-length, #'logcount here. * cl-extra.el: * cl-extra.el (integer-length): Update this to avoid allocating memory. * cl-extra.el (logcount): New. Return the number of one bits in INTEGER, if non-negative. Function from Common Lisp. tests/ChangeLog addition: 2015-05-29 Aidan Kehoe <kehoea@parhasard.net> * automated/lisp-tests.el: Test #'integer-length, #'logcount in this file.
author Aidan Kehoe <kehoea@parhasard.net>
date Fri, 29 May 2015 17:06:24 +0100
parents 750fab17b299
children
comparison
equal deleted inserted replaced
5914:bd4d2c8ef9cc 5915:1af53d35dd53
838 Otherwise, return CHARACTER." 838 Otherwise, return CHARACTER."
839 (and (stringp character) (check-type character character)) 839 (and (stringp character) (check-type character character))
840 (with-case-table (standard-case-table) (downcase character))) 840 (with-case-table (standard-case-table) (downcase character)))
841 841
842 (defun integer-length (integer) 842 (defun integer-length (integer)
843 "Return the number of bits need to represent INTEGER in two's complement." 843 "Return the number of bits need to represent INTEGER in two's complement.
844 (ecase (signum integer) 844
845 (0 0) 845 Equivalent to `(ceiling (log (1+ integer) 2))' for positive integers, and
846 (-1 (1- (length (format "%b" (- integer))))) 846 `(ceiling (log (- integer) 2))' for negative integers."
847 (1 (length (format "%b" integer))))) 847 (check-type integer integer)
848 (when (< integer 0)
849 ;; Don't use #'-, which fails silently with most-negative-fixnum.
850 (setf integer (lognot integer)))
851 (let ((count 0) (last integer))
852 (while (not (eql (setq integer (/ integer 16)) 0))
853 (setf last integer
854 count (+ count 4)))
855 (+ (aref (eval-when-compile
856 (vconcat [0] (loop for fixnum from 1 below 16
857 collect (length (format "%b" fixnum)))))
858 last)
859 count)))
860
861 (defun logcount (integer)
862 "Return the number of one bits in INTEGER, if non-negative.
863
864 If INTEGER is negative, return the number of zero bits of lower order than the
865 most significant non-zero bit."
866 (let ((integer (if (>= integer 0) integer (- (1+ integer))))
867 (count 0))
868 (while (not (eql 0 integer))
869 (setf count
870 (+ count (aref
871 (eval-when-compile
872 (vconcat
873 (loop for fixnum from 0 below 16
874 collect (count ?1 (format "%b" fixnum)))))
875 (% integer 16)))
876 integer (/ integer 16)))
877 count))
848 878
849 ;; These are here because labels and symbol-macrolet are not available in 879 ;; These are here because labels and symbol-macrolet are not available in
850 ;; obsolete.el. They are, however, all marked as obsolete in that file. 880 ;; obsolete.el. They are, however, all marked as obsolete in that file.
851 (symbol-macrolet ((not-nil '#:not-nil)) 881 (symbol-macrolet ((not-nil '#:not-nil))
852 (labels ((car-or-not-nil (object) 882 (labels ((car-or-not-nil (object)