Is there an efficient way to check if a bitvector is all zeroes? (I'm using SBCL on Linux.) I've looked through the documentation but could not find a suitable function. The best I've come up with so far is:
(defun bit-zerop (array)
(equal array (make-array (length array) :element-type 'bit)))
(bit-zerop #*000)
I've also tried
(defun bit-zerop (array)
(dotimes (i (length array))
(if (eql (sbit array i) 1)
(return-from bit-zerop nil)))
t)
but it is about 100 times slower on larger bit vectors than the first version. (Which is expected, as each 64bit word is read 64 times, I guess, instead of just once). Of course, the first version is sub-optimal as well as it must allocate a new array.
EDIT: timings for mentioned solutions.
EDIT 2: timings with type declarations.
(defun bit-zerop-1 (array)
;; (declare (simple-bit-vector array))
(equal array (make-array (length array) :element-type 'bit)))
(defun bit-zerop-2 (array)
;; (declare (simple-bit-vector array))
(every #'zerop array))
(defun bit-zerop-3 (array)
;; (declare (simple-bit-vector array))
(loop
for bit across array
never (= bit 1)))
(defun bit-zerop-4 (array)
;; (declare (simple-bit-vector array))
(not (find 1 array)))
(dolist (func '(bit-zerop-1 bit-zerop-2 bit-zerop-3 bit-zerop-4))
(dolist (size '(10 100 1000))
(let ((x (make-array size :element-type 'bit)))
(format t "Testing ~a on ~a elements~%" func size)
(time
(dotimes (i 1000000)
(funcall func x))))))
gives
=============================================== method size 10 size 100 size 1000 ------------------- untyped ------------------- bit-zerop-1 0.030 s 0.030 s 0.058 s bit-zerop-2 0.112 s 1.000 s 9.324 s bit-zerop-3 0.111 s 0.935 s 8.742 s bit-zerop-4 0.047 s 0.047 s 0.063 s -------------------- typed -------------------- bit-zerop-1 0.025 s 0.023 s 0.040 s bit-zerop-2 0.036 s 0.315 s 3.005 s bit-zerop-3 0.041 s 0.348 s 3.346 s bit-zerop-4 0.010 s 0.012 s 0.026 s ===============================================
DECLARE
forms to tell the compiler that the arguments are bitvectors (and that you want your function to be optimised). – Kowalski(setf bit-vector (make-array size :element-type 'bit :initial-element 0))
is 60 (!) times quicker that setting successive bits to 0 by(loop for i from 0 below size do (setf (sbit bit-vector i) 0))
(SBCL on typical laptop). It is probably linked to a very efficient way to create bit-vector. – Degrading