Logical LISP

In March 1999 in the AutoCAD forum on Compuserve the following discussion took place. During this I explained how the bitwise logical functions in AutoLISP/Visual LISP work. Maybe someone else needs this as well:

Q: Can someone explain what Logior and Logiand do? I've been trying to figure this one out for a while.

A: Logior and logand assume that the integer you pass as an
argument is in fact a list of bits. Here's a routine from my book
on LISP programming, which prints an integer as a list of bits:

(defun print-bits (Bits / Bit-list Max-bit) (if (minusp Bits) (setq Max-bit 1 Bits (- Bits 2147483648)) (setq Max-bit 0) ) (repeat 31 (setq Bit-list (cons (rem Bits 2) Bit-list) Bits (/ Bits 2)) ) (cons Max-bit Bit-list) )

Here are some examples of the functions working on bit-coded integers:

Command: (print-bits 53) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1) Command: (print-bits (~ 53)) ; Bit-wise complement (1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 1 0 1 0) Command: (print-bits (lsh 53 4)) ; left shift by four bits (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1 0 1 0 0 0 0) Command: (print-bits 24) (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 0) Command: (print-bits (logand 53 24)) ; bit-wise and (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0) Command: (print-bits (logior 53 24)) ; bit-wise or (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 1 1 0 1) Command: (print-bits (boole 6 53 24)) ; bit-wise xor (0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 1)

Q: In my brief and torrid involvement with Assembly Language, I remember something about bit shifting emulating division, but seems it usually only involved a one-bit shift. So, was wondering how a shift of more than one bit was useful, and, generally what is the difference in shifting left or right? Also, when it's stated in the manual that "zero bits are shifted in, and the bits shifted out are discarded", what is "in" and "out"? Does "in"=right and "out"=left? Guess the real question is the purpose of the (lsh num bits) function?

A: LSH shifts all bits to the left. Where 'left' is as in the print-bits output. You see that (lsh 4 53) creates the same output as 53, only with every bit shifted four places to the left. Bits that fell off the left edge (32 bits maximum in an AutoLISP integer) get lost. The empty places at the right edge will be filled with zero bits.

If you shift the bits by a negative number of places, they shift right. In this case some bits fall off the right edge while zero bits are padded in the now empty (left) places.

If you convert the bit-list back to an integer, you'll see that (lsh num bits) is the same as (* bits (exp 2 num)). Each left shift by one place equals multiplying the integer by two. Each right shift by one place equals a division by two.

Typical uses for bit functions in AutoCAD are the evaluation of bit-coded fields you get from (entget), e.g. the 70 group of attributes or the OSMODE variable. You can use logand with a bit pattern to check if all the bits you're interested in are set.

You can use the lsh function to create recursive functions working on bit-coded integers. Thus the print-bits function could also be written as

(defun print-bits (Bits) (reverse (cond ((zerop Bits) '()) (t (cons (logand Bits 1) (reverse (print-bits (lsh Bits -1)))) ) ) ) )

This variant of the print-bits function however does not display the zero bits at the left end (beginning) of the list.

Dietmar Rudolph

This is a shareware document. What is a shareware document? Did this article help you earn some money? Then give something back! Help creating shareware documents by donating something to the author:

© 2000-2011 by CR/LF GmbH, Essen/Germany. All rights reserved.

No part of this document may be reproduced or published without written consent by CR/LF GmbH.

Last modification: 31.03.2011