From: Matt Emerson
Subject: bit shift operations
Date: 
Message-ID: <slrn689fld.q0q.rme@foil.apk.net>
not long ago in this newsgroup, it was suggested that an
implementation of gzip in common lisp would be useful.  so, as a
wannabe lisp hacker, i decided to give that a go.  however, in
the process of writing code to compute CRCs, i ran across the
need to do bit shifting.  the ash function was all i could
find,  but since it preserves the sign, i needed to write a
function to extract the part i wanted:

(defun lsr (i n)
  "logically shift i n bits to the right"
  (let* ((len (integer-length i))
	 (b (byte (- len n) 0))
	 (x (ash i (- n))))
    (ldb b x)))

now, the performance of this function most probably will not be
a tremendous issue but i can't help wondering if there isn't some
more "efficient" way to do this.

From: Hrvoje Niksic
Subject: Re: bit shift operations
Date: 
Message-ID: <kig1zzv2l4s.fsf@jagor.srce.hr>
···@foil.apk.net (Matt Emerson) writes:

> not long ago in this newsgroup, it was suggested that an
> implementation of gzip in common lisp would be useful.  so, as a
> wannabe lisp hacker, i decided to give that a go.
[...]

As a side issue (irrelevant to the question): have you considered
using the existing code in libz?  Building a Lisp interface to the
appropriate C primitives should not be very hard, and should provide a 
fast and reliable streamed `gzip' implementation.  Portability may be
a problem, though.

-- 
Hrvoje Niksic <·······@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
* Q: What is an experienced Emacs user?
* A: A person who wishes that the terminal had pedals.
From: Andreas Eder
Subject: Re: bit shift operations
Date: 
Message-ID: <m390u220vn.fsf@laphroig.mch.sni.de>
Hrvoje Niksic <·······@srce.hr> writes:

> ···@foil.apk.net (Matt Emerson) writes:
> 
> > not long ago in this newsgroup, it was suggested that an
> > implementation of gzip in common lisp would be useful.  so, as a
> > wannabe lisp hacker, i decided to give that a go.
> [...]
> 
> As a side issue (irrelevant to the question): have you considered
> using the existing code in libz?  Building a Lisp interface to the
> appropriate C primitives should not be very hard, and should provide a 
> fast and reliable streamed `gzip' implementation.  Portability may be
> a problem, though.
> 
> -- 
> Hrvoje Niksic <·······@srce.hr> | Student at FER Zagreb, Croatia
> --------------------------------+--------------------------------
> * Q: What is an experienced Emacs user?
> * A: A person who wishes that the terminal had pedals.
I think that this ( using code from libz ) just is against the spirit of 
the issue. The whole meaning of it, as I see it, is doing the whole thing 
in Lisp, from the ground up.

Andreas
From: Hrvoje Niksic
Subject: Re: bit shift operations
Date: 
Message-ID: <kig4t4qz696.fsf@jagor.srce.hr>
Andreas Eder <···@laphroig.mch.sni.de> writes:

> > As a side issue (irrelevant to the question): have you considered
> > using the existing code in libz?  Building a Lisp interface to the
> > appropriate C primitives should not be very hard, and should provide a 
> > fast and reliable streamed `gzip' implementation.  Portability may be
> > a problem, though.
[...]
> I think that this ( using code from libz ) just is against the spirit of 
> the issue. The whole meaning of it, as I see it, is doing the whole thing 
> in Lisp, from the ground up.

I was not talking about spirit -- it was just an idea to reuse the
existing code.  I still think it's a good idea, when Lisp
implementations allow it?

I know this doesn't answer the original question, which is why I
called it a "side issue."

-- 
Hrvoje Niksic <·······@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
Oh lord won't you buy me a color TV...
From: Hrvoje Niksic
Subject: Re: bit shift operations
Date: 
Message-ID: <kigoh2yxq2m.fsf@jagor.srce.hr>
Andreas Eder <···@laphroig.mch.sni.de> writes:

> > As a side issue (irrelevant to the question): have you considered
> > using the existing code in libz?  Building a Lisp interface to the
> > appropriate C primitives should not be very hard, and should provide a 
> > fast and reliable streamed `gzip' implementation.  Portability may be
> > a problem, though.
[...]
> I think that this ( using code from libz ) just is against the spirit of 
> the issue. The whole meaning of it, as I see it, is doing the whole thing 
> in Lisp, from the ground up.

I was not talking about spirit -- it was just an idea to reuse the
existing code.  I still think it's a good idea, for Lisp
implementations that allow it.

I know this doesn't answer the original question, which is why I
called it a "side issue."

-- 
Hrvoje Niksic <·······@srce.hr> | Student at FER Zagreb, Croatia
--------------------------------+--------------------------------
Oh lord won't you buy me a color TV...
From: Kelly Murray
Subject: Re: bit shift operations
Date: 
Message-ID: <66482v$kre$1@news2.franz.com>
In article <··················@foil.apk.net>, ···@foil.apk.net (Matt Emerson) writes:
>> not long ago in this newsgroup, it was suggested that an
>> implementation of gzip in common lisp would be useful.  so, as a
>> wannabe lisp hacker, i decided to give that a go.  

Super. Will Hartung (······@netcom.com) mentioned he's working on this also.
You might want to coordinate.

>> however, in
>> the process of writing code to compute CRCs, i ran across the
>> need to do bit shifting.  the ash function was all i could
>> find,  but since it preserves the sign, i needed to write a
>> function to extract the part i wanted:
>> 
>> (defun lsr (i n)
>>   "logically shift i n bits to the right"
>>   (let* ((len (integer-length i))
>> 	 (b (byte (- len n) 0))
>> 	 (x (ash i (- n))))
>>     (ldb b x)))
>> 
>> now, the performance of this function most probably will not be
>> a tremendous issue but i can't help wondering if there isn't some
>> more "efficient" way to do this.
>> 

(ash i (- n))  is sufficient for a positive number.  
In a CRC application I would expect all the numbers to be positive.
If not, test it first

(defun lsr (i n) (if (>= i 0) (ash i (- n)) (error "lsr got negative number"))

BTW, using the return value of #'byte is generally to be avoided 
when efficiency is important, for CL programs.
It will cons since it must be able to
represent bytes for infinite integers, and thus needs two fixnums
for the width and start.  The LispM implementation coded
the value into a fixnum, which is "buggy" on huge massive integers,
but makes the function actually useful for efficient use.

Any efficient compiler special cases its typical use
and breaks out the two argument, so it doesn't cons

 (ldb (byte 8 8) x)  ==> (low-level-ldb 8 8 x)

It can't do this if you use a byte-spec as a first-class object.

-kelly murray   ···@franz.com
From: Pierpaolo Bernardi
Subject: Re: bit shift operations
Date: 
Message-ID: <66ro6b$edj$1@croci.unipi.it>
Some time ago I wrote the following code for parsing a gzip file.
It may be useful to the people writing the lisp gzip.

The code is incomplete and probably full of bugs, but maybe something
useful may be extracted.  Good luck.

Pierpaolo.


;;; ====(Fri Dec 12 06:15:24 1997)==================================
;;; $Id: read-unsigned.lisp,v 1.2 1997/03/23 15:06:16 pierpa Exp pierpa $

(in-package :JVM)

(file-description
 "Macros for generating functions for reading arbitrary length unsigned
integers, both from little and big endian, 8-bit bytes, binary streams.")


(eval-when (eval compile)
  #+(or (and :CLISP :PC386)
	(and :CMU :X86))
  (pushnew :LITTLE-ENDIAN *features*))

(eval-when (eval compile)
  #-(or :LITTLE-ENDIAN :BIG-ENDIAN)
  (error "GLEP! Should specify endiannes!"))

(deftype nonneg ()
  `(integer 0 ,most-positive-fixnum))

(defun build-unsigned-reader (n endiannes)
  (check-type n nonneg)
  (check-type endiannes (member :little :big))
  (let ((nvars (loop repeat n collecting (gensym))))
    `(lambda (stream)
       (declare (stream stream))
       (let ,(mapcar (lambda (v)
		       `(,v (read-byte stream)))
	      nvars)
	 (declare (type (unsigned-byte 8) ,@nvars))
	 (logior ,@(do* ((vars (ecase endiannes
				 (:little nvars)
				 (:big (reverse nvars)))
			       (cdr vars))
			 (shift 0 (+ shift 8))
			 (acc `(,(car vars)) (cons `(ash ,(car vars) ,shift) acc)))
		       ((null (cdr vars)) (nreverse acc))))))))

(defmacro make-unsigned-reader (n &key (endiannes
					#+LITTLE-ENDIAN :little
					#+BIG-ENDIAN :big))
  (build-unsigned-reader n endiannes))

(defmacro def-read-unsigned-n (name n &key (endiannes
					    #+LITTLE-ENDIAN :little
					    #+BIG-ENDIAN :big)
					   (inline nil))
  `(progn
     (declaim ,@(if inline
		    `((inline ,name))
		    `())
	      (ftype (function (stream) (unsigned-byte ,(* 8 n))) ,name))
     (defun ,name ,@(cdr (build-unsigned-reader n endiannes)))))

(defun read-unsigned-n-be (n input-stream)
  (declare (type nonneg n)
	   (type stream input-stream))
  (do ((n n (- n 1))
       (acc 0 (+ (* acc 256) (read-byte input-stream))))
      ((zerop n) acc)
    (declare (type nonneg n))))


;;; ====(Fri Dec 12 06:00:30 1997)==================================
;;; $Id: gzip.lisp,v 1.1 1997/12/12 04:51:01 pierpa Exp pierpa $

;;; Code for parsing a gzip file  (see RFC-1952, also relevant RFC-1950, RFC-1951)


(defconstant identification-1 31)
(defconstant identification-2 139)

(defconstant deflate 8)


(defun decode-flags (flags names)
  (do ((flags flags (truncate flags 2))
       (flag-names names (cdr flag-names))
       (acc '() (if (oddp flags)
		    (cons (car flag-names) acc)
		    acc)))
      ((zerop flags) acc)))

(defconstant *flag-names* '(:FTEXT :FHCRC :FEXTRA :FNAME :FCOMMENT))

(jvm::def-read-unsigned-n read-unsigned-4-le 4 :endiannes :little :inline t)
(jvm::def-read-unsigned-n read-unsigned-2-le 2 :endiannes :little :inline t)

(defconstant jan-1-1970 (encode-universal-time 0 0 0 1 1 1970 0))

(defun unix-time-to-universal-time (unix-time)
  (+ unix-time jan-1-1970))

(defun os-to-string (os)
  (ecase os
    (0 "FAT filesystem (MS-DOS, OS/2, NT/Win32)")
    (1 "Amiga")
    (2 "VMS (or OpenVMS)")
    (3 "Unix")
    (4 "VM/CMS")
    (5 "Atari TOS")
    (6 "HPFS filesystem (OS/2, NT)")
    (7 "Macintosh")
    (8 "Z-System")
    (9 "CP/M")
    (10 "TOPS-20")
    (11 "NTFS filesystem (NT)")
    (12 "QDOS")
    (13 "Acorn RISCOS")
    (255 "unknown")))

(defun read-null-terminated-string (dadove)
  (let ((acc (make-array 30 :adjustable t :fill-pointer 0 :element-type 'character)))
    (loop
	for char-code = (read-byte dadove)
	until (zerop char-code)
	do (vector-push-extend (code-char char-code) acc))
    (copy-seq acc)))

(defun read-gzip (name)
  (with-open-file (dadove name
		   :direction :input
		   :element-type '(mod 256))
    (let ((id1 (read-byte dadove))
	  (id2 (read-byte dadove)))
      
      (assert (and (= id1 identification-1)
		   (= id2 identification-2)))
      
      (format t "Identification ok~%")
      
      (let ((compression-method (read-byte dadove)))
	(format t "Compression method = ~A~%" compression-method))
      
      (let ((flags (decode-flags (read-byte dadove) *flag-names*)))
	(format t "Flags = ~A~%" flags)
	
	(let ((mtime (read-unsigned-4-le dadove)))
	  (format t "Mtime = ~A~%" (ut:format-universal-time nil (unix-time-to-universal-time mtime))))
	
	(let ((xfl (read-byte dadove)))
	  (format t "XFL = ~A~%" xfl))
	
	(let ((os (read-byte dadove)))
	  (format t "OS = ~A~%" (os-to-string os)))
	
	(when (member :fextra flags)
	  (let* ((xlen (read-unsigned-2-le dadove)))
	    (format t "There is an extra field ~A bytes long~%" xlen)
	    (jvm::discard-bytes dadove xlen)))
	
	(when (member :fname flags)
	  (format t "The original file name is: ~A~%" (read-null-terminated-string dadove)))
	
	(when (member :fcomment flags)
	  (format t "Comment: ~A~%" (read-null-terminated-string dadove)))
	
	(when (member :fhcrc flags)
	  (format t "There is a CRC = ~A~%" (read-unsigned-2-le dadove)))
	
	))))


;;; ====(Tue Jun 10 05:43:22 1997)==================================
;;; The naive implementation of Adler-32, as per rfc1950

(defconstant base 65521)

(defun update-adler32 (adler buf)
  (let ((s1 (logand adler #xFFFF))
	(s2 (logand (ash adler -16) #xFFFF)))
    
    (loop for c across buf
	do (setf s1 (mod (+ s1 c) base))
	   (setf s2 (mod (+ s1 s2) base)))
    
    (+ (ash s2 16) s1)))

;;; ====(Tue Jun 10 05:56:14 1997)==================================
;;; CRC as per rfc1952

(deftype u32 ()
  '(unsigned-byte 32))

(deftype u8 ()
  '(unsigned-byte 8))


(declaim (type (simple-array t 256) crc-table))

(defconstant crc-table
    (make-array
     256
     ;;:element-type 'u32
     :initial-contents
     '(#x00000000 #x77073096 #xEE0E612C #x990951BA #x076DC419 #x706AF48F #xE963A535 #x9E6495A3
       #x0EDB8832 #x79DCB8A4 #xE0D5E91E #x97D2D988 #x09B64C2B #x7EB17CBD #xE7B82D07 #x90BF1D91
       #x1DB71064 #x6AB020F2 #xF3B97148 #x84BE41DE #x1ADAD47D #x6DDDE4EB #xF4D4B551 #x83D385C7
       #x136C9856 #x646BA8C0 #xFD62F97A #x8A65C9EC #x14015C4F #x63066CD9 #xFA0F3D63 #x8D080DF5
       #x3B6E20C8 #x4C69105E #xD56041E4 #xA2677172 #x3C03E4D1 #x4B04D447 #xD20D85FD #xA50AB56B
       #x35B5A8FA #x42B2986C #xDBBBC9D6 #xACBCF940 #x32D86CE3 #x45DF5C75 #xDCD60DCF #xABD13D59
       #x26D930AC #x51DE003A #xC8D75180 #xBFD06116 #x21B4F4B5 #x56B3C423 #xCFBA9599 #xB8BDA50F
       #x2802B89E #x5F058808 #xC60CD9B2 #xB10BE924 #x2F6F7C87 #x58684C11 #xC1611DAB #xB6662D3D
       #x76DC4190 #x01DB7106 #x98D220BC #xEFD5102A #x71B18589 #x06B6B51F #x9FBFE4A5 #xE8B8D433
       #x7807C9A2 #x0F00F934 #x9609A88E #xE10E9818 #x7F6A0DBB #x086D3D2D #x91646C97 #xE6635C01
       #x6B6B51F4 #x1C6C6162 #x856530D8 #xF262004E #x6C0695ED #x1B01A57B #x8208F4C1 #xF50FC457
       #x65B0D9C6 #x12B7E950 #x8BBEB8EA #xFCB9887C #x62DD1DDF #x15DA2D49 #x8CD37CF3 #xFBD44C65
       #x4DB26158 #x3AB551CE #xA3BC0074 #xD4BB30E2 #x4ADFA541 #x3DD895D7 #xA4D1C46D #xD3D6F4FB
       #x4369E96A #x346ED9FC #xAD678846 #xDA60B8D0 #x44042D73 #x33031DE5 #xAA0A4C5F #xDD0D7CC9
       #x5005713C #x270241AA #xBE0B1010 #xC90C2086 #x5768B525 #x206F85B3 #xB966D409 #xCE61E49F
       #x5EDEF90E #x29D9C998 #xB0D09822 #xC7D7A8B4 #x59B33D17 #x2EB40D81 #xB7BD5C3B #xC0BA6CAD
       #xEDB88320 #x9ABFB3B6 #x03B6E20C #x74B1D29A #xEAD54739 #x9DD277AF #x04DB2615 #x73DC1683
       #xE3630B12 #x94643B84 #x0D6D6A3E #x7A6A5AA8 #xE40ECF0B #x9309FF9D #x0A00AE27 #x7D079EB1
       #xF00F9344 #x8708A3D2 #x1E01F268 #x6906C2FE #xF762575D #x806567CB #x196C3671 #x6E6B06E7
       #xFED41B76 #x89D32BE0 #x10DA7A5A #x67DD4ACC #xF9B9DF6F #x8EBEEFF9 #x17B7BE43 #x60B08ED5
       #xD6D6A3E8 #xA1D1937E #x38D8C2C4 #x4FDFF252 #xD1BB67F1 #xA6BC5767 #x3FB506DD #x48B2364B
       #xD80D2BDA #xAF0A1B4C #x36034AF6 #x41047A60 #xDF60EFC3 #xA867DF55 #x316E8EEF #x4669BE79
       #xCB61B38C #xBC66831A #x256FD2A0 #x5268E236 #xCC0C7795 #xBB0B4703 #x220216B9 #x5505262F
       #xC5BA3BBE #xB2BD0B28 #x2BB45A92 #x5CB36A04 #xC2D7FFA7 #xB5D0CF31 #x2CD99E8B #x5BDEAE1D
       #x9B64C2B0 #xEC63F226 #x756AA39C #x026D930A #x9C0906A9 #xEB0E363F #x72076785 #x05005713
       #x95BF4A82 #xE2B87A14 #x7BB12BAE #x0CB61B38 #x92D28E9B #xE5D5BE0D #x7CDCEFB7 #x0BDBDF21
       #x86D3D2D4 #xF1D4E242 #x68DDB3F8 #x1FDA836E #x81BE16CD #xF6B9265B #x6FB077E1 #x18B74777
       #x88085AE6 #xFF0F6A70 #x66063BCA #x11010B5C #x8F659EFF #xF862AE69 #x616BFFD3 #x166CCF45
       #xA00AE278 #xD70DD2EE #x4E048354 #x3903B3C2 #xA7672661 #xD06016F7 #x4969474D #x3E6E77DB
       #xAED16A4A #xD9D65ADC #x40DF0B66 #x37D83BF0 #xA9BCAE53 #xDEBB9EC5 #x47B2CF7F #x30B5FFE9
       #xBDBDF21C #xCABAC28A #x53B39330 #x24B4A3A6 #xBAD03605 #xCDD70693 #x54DE5729 #x23D967BF
       #xB3667A2E #xC4614AB8 #x5D681B02 #x2A6F2B94 #xB40BBE37 #xC30C8EA1 #x5A05DF1B #x2D02EF8D)))


;;;         Update a running crc with the bytes buf[0..len-1] and return
;;;       the updated crc. The crc should be initialized to zero. Pre- and
;;;       post-conditioning (one's complement) is performed within this
;;;       function so it shouldn't be done by the caller. Usage example:
;;;
;;;         unsigned long crc = 0L;
;;;
;;;         while (read_buffer(buffer, length) != EOF) {
;;;           crc = update_crc(crc, buffer, length);
;;;         }
;;;         if (crc != original_crc) error();


(defun update-crc (crc buf)
  (declare (optimize speed (safety 0)))
  (declare (type u32 crc))
  (loop for n fixnum from 0 below (length buf)
      do (setf crc 
	   (the u32 (logxor (the u32 (svref crc-table
					   (the u8 (logand (the u32 (logxor crc
									    (the u8 (svref buf n))))
							   #xFF))))
			    (ash crc -8)))))
  (logxor crc #xFFFFFFFF))


;; Return the CRC of the bytes buf[0..len-1].
(defun crc (buf)
  (update-crc 0 buf))

;;; ====(Fri Jun 20 02:51:16 1997)==================================

(defstruct node
  len
  code)

(defconstant MAX-BITS 20)

(defun codes-as-integers (tree)
  (let ((bl-count (make-array 30 :initial-element 0))
	(next-code (make-array 30 :initial-element 0)))
    
    (loop for node across tree
	do (incf (aref bl-count (node-len node))))
    
    (format t "bl-count = ~A~%" bl-count)
    (format t "next-code = ~A~%" next-code)
    (format t "----------~%")
    
    (let ((code 0))
      (setf (aref bl-count 0) 0)
      (loop for bits from 1 to MAX-BITS
	  do (setf code (ash (+ code (aref bl-count (- bits 1))) 1))
	     (setf (aref next-code bits) code)))
    
    (format t "next-code = ~A~%" next-code)
    (format t "----------~%")
    
    (loop for n from 0 to (- (length tree) 1)
	do (let ((len (node-len (aref tree n))))
	     (when (not (zerop len))
	       (setf (node-code (aref tree n)) (aref next-code len))
	       (incf (aref next-code len)))))

    tree))

;;; ====(Fri Dec 12 06:25:37 1997)==================================

;; $Id: utilities.lisp,v 1.1 1997/06/19 07:41:37 pierpa Exp pierpa $

(defpackage :Utilities
  (:nicknames :Ut)
  (:use :CL))

(in-package :Utilities)

;;; ====(Thu Jun 19 09:39:31 1997)==================================

(export '(decode-flags encode-flags))

(defun decode-flags (flags names)
  (do ((flags flags (truncate flags 2))
       (flag-names names (cdr flag-names))
       (acc '() (if (oddp flags)
		    (cons (car flag-names) acc)
		    acc)))
      ((zerop flags) (nreverse acc))))

(defun encode-flags (afs names)
  (let ((acc 0))
    (dolist (af afs acc)
      (incf acc (ash 1 (position af names :test #'eq))))))

;;; ====(Thu Jun 19 09:39:48 1997)==================================

(export 'format-universal-time)

(defun format-universal-time (&optional (stream *standard-output*)
					(universal-time (get-universal-time)))
  (multiple-value-bind (second minute hour date month year day dst tz)
      (decode-universal-time universal-time)
    (format stream "~A ~A/~A/~A Ore: ~2,'0D:~2,'0D:~2,'0D ····@D ~A"
	    (svref #("Luned�" "Marted�" "Mercoled�" "Gioved�"
		     "Venerd�" "Sabato" "Domenica")
		   day)
	    date month year hour minute second
	    (- tz)
	    (if dst "Ora legale" ""))))

;;; ====(Thu Jun 19 09:40:20 1997)==================================

(export 'same-type-p)

(defun same-type-p (t1 t2)
  (multiple-value-bind (s12 c12) (subtypep t1 t2)
    (multiple-value-bind (s21 c21) (subtypep t2 t1)
      (values (and s12 s21)
	      (and c12 c21)))))

;;; ====(Thu Jun 19 09:40:33 1997)==================================








Kelly Murray (···@math.ufl.edu) wrote:
: In article <··················@foil.apk.net>, ···@foil.apk.net (Matt Emerson) writes:
: >> not long ago in this newsgroup, it was suggested that an
: >> implementation of gzip in common lisp would be useful.  so, as a
: >> wannabe lisp hacker, i decided to give that a go.  

: Super. Will Hartung (······@netcom.com) mentioned he's working on this also.
: You might want to coordinate.

: >> however, in
: >> the process of writing code to compute CRCs, i ran across the
: >> need to do bit shifting.  the ash function was all i could
: >> find,  but since it preserves the sign, i needed to write a
: >> function to extract the part i wanted:
: >> 
: >> (defun lsr (i n)
: >>   "logically shift i n bits to the right"
: >>   (let* ((len (integer-length i))
: >> 	 (b (byte (- len n) 0))
: >> 	 (x (ash i (- n))))
: >>     (ldb b x)))
: >> 
: >> now, the performance of this function most probably will not be
: >> a tremendous issue but i can't help wondering if there isn't some
: >> more "efficient" way to do this.
: >> 

: (ash i (- n))  is sufficient for a positive number.  
: In a CRC application I would expect all the numbers to be positive.
: If not, test it first

: (defun lsr (i n) (if (>= i 0) (ash i (- n)) (error "lsr got negative number"))

: BTW, using the return value of #'byte is generally to be avoided 
: when efficiency is important, for CL programs.
: It will cons since it must be able to
: represent bytes for infinite integers, and thus needs two fixnums
: for the width and start.  The LispM implementation coded
: the value into a fixnum, which is "buggy" on huge massive integers,
: but makes the function actually useful for efficient use.

: Any efficient compiler special cases its typical use
: and breaks out the two argument, so it doesn't cons

:  (ldb (byte 8 8) x)  ==> (low-level-ldb 8 8 x)

: It can't do this if you use a byte-spec as a first-class object.

: -kelly murray   ···@franz.com
From: Barry Margolin
Subject: Re: bit shift operations
Date: 
Message-ID: <664gng$rm@tools.bbnplanet.com>
In article <··················@foil.apk.net>,
Matt Emerson <···@foil.apk.net> wrote:
>(defun lsr (i n)
>  "logically shift i n bits to the right"
>  (let* ((len (integer-length i))
>	 (b (byte (- len n) 0))
>	 (x (ash i (- n))))
>    (ldb b x)))

Why do you use LDB *and* ASH, instead of simply specifying the position in
the byte specifier?  E.g.

(defun lsr (i n)
  (ldb (byte (- (integer-length i) n)
             n)
       i))

I wonder why Common Lisp has no logical shift operator?  Didn't MacLisp
have LSH?

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
Support the anti-spam movement; see <http://www.cauce.org/>
Please don't send technical questions directly to me, post them to newsgroups.