Subject: Re: packing multiple datapoints into a single fixnum
From: rpw3@rpw3.org (Rob Warnock)
Date: Sat, 10 Mar 2007 05:14:34 -0600
Newsgroups: comp.lang.lisp
Message-ID: <0dqdnaf738OHDm_YnZ2dnUVZ_qWvnZ2d@speakeasy.net>
Alan Crowe  <alan@cawtech.freeserve.co.uk> wrote:
+---------------
| nallen05@gmail.com writes:
| > I have values A, B, C, and D (all fixnum integers). I want to
| > be able to combine them to create integer E and later pull
| > A, B, C, or D out of E
| > 
| > I know it's simple but I'm sure I'll do it naively if left
| > to my own ways...
| 
| Not a wizard but an ex-assembler programmer. I'd go for
| 
| CL-USER> (defun pack (b01 b234 b5678)
|            (logior b01 (ash b234 2) (ash b5678 5)))
| PACK
| 
| CL-USER> (write (pack 1 5 10) :base 2)
| 101010101
| 341
+---------------

As an ex-*PDP-10*[1] assembler programmer,  ;-}
I'd probably go for this:

    > (defun pack (b01 b234 b5678)
	(dpb b5678 (byte 5 5)     
	  (dpb b234 (byte 3 2)
	    b01)))
    PACK
    > (write (pack 1 5 10) :base 2)
    101010101
    341
    > 

Or the more-imperative equivalent:

      (defun pack (b01 b234 b5678)
	(setf (ldb (byte 3 2) b01) b234)
	(setf (ldb (byte 5 5) b01) b5678)
	b01)

[I'm not sure which one is faster.]

+---------------
| CL-USER> (defun unpack (i)
|            (values (ldb (byte 2 0) i)
|                    (ldb (byte 3 2) i)
|                    (ldb (byte 4 5) i)))
| UNPACK
+---------------

Yup, just so!


-Rob

[1] See CLHS LBD & DPB:

      Historically, the name ``ldb'' comes from a DEC PDP-10
        assembly language instruction meaning ``load byte.''
      ...
      Historically, the name ``dpb'' comes from a DEC PDP-10
        assembly language instruction meaning ``deposit byte.''

-----
Rob Warnock			<rpw3@rpw3.org>
627 26th Avenue			<URL:http://rpw3.org/>
San Mateo, CA 94403		(650)572-2607