From: Fabricio Chalub
Subject: Converting INTEGER to a BYTE array, LISP style
Date: 
Message-ID: <6caba068.0207311742.6521b2ea@posting.google.com>
Hello,

I need a function to convert an INTEGER to an UNSIGNED-BYTE array for
a network protocol I'm working with.  I wrote this:

(defun int->bytes (i)
  (let ((d i) (r 0))
    (loop until (= d 0) do
          (setf d (ash i -8))
          (setf r (rem i 256))
          (setf i d)
          collect r)))

which works, but looks like there may be something more concise and/or
elegant.

Any suggestions?

fc

From: Wade Humeniuk
Subject: Re: Converting INTEGER to a BYTE array, LISP style
Date: 
Message-ID: <b9129.672$%6.35809@news2.telusplanet.net>
Since the integer you need to write is of fixed size (isn't it?), you could use something
like

(defun write-long-to-byte-array (array integer &optional (offset 0))
  (setf  (aref array offset) (ldb (byte 8 0) integer)
  (aref array (+ offset 1))(ldb (byte 8 8) integer)
  (aref array (+ offset 2))(ldb (byte 8 16) integer)
  (aref array (+ offset 3))(ldb (byte 8 24) integer)))

This writes an integer into an array (little endian), you are going to have to decide your
byte order.

The corresponding read function

(defun read-long (byte-array offset)
  (let ((long 0))
    (setf (ldb (byte 8 0) long) (aref byte-array offset)
          (ldb (byte 8 8) long) (aref byte-array (+ offset 1))
          (ldb (byte 8 16) long) (aref byte-array (+ offset 2))
          (ldb (byte 8 24) long) (aref byte-array (+ offset 3)))
    long))

GDI 13 > (setf *array* (make-array 8 :element-type '(unsigned-byte 8) :initial-element 0))
#(0 0 0 0 0 0 0 0)

GDI 14 > (write-long-to-byte-array *array* #xffeeddcc)
255

GDI 15 > *array*
#(204 221 238 255 0 0 0 0)

GDI 20 > (format t "#x~X" (read-long *array* 0))
#xFFEEDDCC
NIL

Wade

"Fabricio Chalub" <·········@gnu.org> wrote in message
·································@posting.google.com...
> Hello,
>
> I need a function to convert an INTEGER to an UNSIGNED-BYTE array for
> a network protocol I'm working with.  I wrote this:
>
> (defun int->bytes (i)
>   (let ((d i) (r 0))
>     (loop until (= d 0) do
>           (setf d (ash i -8))
>           (setf r (rem i 256))
>           (setf i d)
>           collect r)))
>
> which works, but looks like there may be something more concise and/or
> elegant.
>
> Any suggestions?
>
> fc
From: Kent M Pitman
Subject: Re: Converting INTEGER to a BYTE array, LISP style
Date: 
Message-ID: <sfwptx39tqw.fsf@shell01.TheWorld.com>
·········@gnu.org (Fabricio Chalub) writes:

> Hello,
> 
> I need a function to convert an INTEGER to an UNSIGNED-BYTE array for
> a network protocol I'm working with.  I wrote this:
> 
> (defun int->bytes (i)
>   (let ((d i) (r 0))
>     (loop until (= d 0) do
>           (setf d (ash i -8))
>           (setf r (rem i 256))
>           (setf i d)
>           collect r)))
> 
> which works, but looks like there may be something more concise and/or
> elegant.
> 
> Any suggestions?

Don't have a lot of time to look at this, but ...

If it's really for a network protocol, I suggest you might want to
create a buffer that you recycle rather than allocate and gc
repetitively.  Especially don't use collect, which is going to allocate a
set of conses, probably overkill.  You only need a byte vector.  Look into
byte vectors with fill-pointers, so you can change the size.  Start with
fill pointer as 0 and use VECTOR-PUSH-EXTEND.  Your target should maybe be
a (copy-int-to-byte-vector i v).

And personally, I don't trust REM not to use division, which can be slow.
Maybe the compiler will recognize the case of constant power of 2 division
and do something clever, but I'd just as soon use LDB directly...

Overall, though, probably not worth fussing over a lot, though.  Just
see if it runs adequately fast in the given implementation and tune it
if not--each implementation will likely be different, and you really
should not fuss microoptimization like this anyway until you have a
working product and what stands between you and commercial (or
"deployed") success is making the thing faster...
From: Fabricio Chalub
Subject: Re: Converting INTEGER to a BYTE array, LISP style
Date: 
Message-ID: <6caba068.0208010527.5603863a@posting.google.com>
Kent M Pitman <······@world.std.com> wrote in message news:<···············@shell01.TheWorld.com>...

> Overall, though, probably not worth fussing over a lot, though.  Just
> see if it runs adequately fast in the given implementation and tune it
> if not--each implementation will likely be different, and you really
> should not fuss microoptimization like this anyway until you have a
> working product and what stands between you and commercial (or
> "deployed") success is making the thing faster...

Well, this just an application I'm building in order to improve my
LISP knowledge.  I'm not actually seeking to optimize this function to
the extreme, just trying to see if there's a more LISP-y way of doing
it (whatever that means).

The function, as it stands, looks too much like a C function to me. ;)
Your comments and Wade's already made things a bit clearer.

fc
From: Frode Vatvedt Fjeld
Subject: Re: Converting INTEGER to a BYTE array, LISP style
Date: 
Message-ID: <2h4reeu1zc.fsf@vserver.cs.uit.no>
·········@gnu.org (Fabricio Chalub) writes:

> [..] I'm not actually seeking to optimize this function to the
> extreme, just trying to see if there's a more LISP-y way of doing it
> (whatever that means).

I suppose my binary-types library could be used for this purpose, it's
a library for declaring two-way mappings between lisp objects and any
octet-based binary format, which would be suitable for wire transfer,
although the library's focus is file I/O.

  <URL:http://www.cs.uit.no/~frodef/sw/binary-types/>

-- 
Frode Vatvedt Fjeld
From: Fabricio Chalub
Subject: Re: Converting INTEGER to a BYTE array, LISP style
Date: 
Message-ID: <6caba068.0208021558.658a873a@posting.google.com>
Frode Vatvedt Fjeld <······@acm.org> wrote in message news:<··············@vserver.cs.uit.no>...
> 
> I suppose my binary-types library could be used for this purpose, it's
> a library for declaring two-way mappings between lisp objects and any
> octet-based binary format, which would be suitable for wire transfer,
> although the library's focus is file I/O.
> 

Thanks!  It will help me a lot!

fc