From: Gisle Sælensminde
Subject: Converting bytes to an integer
Date: 
Message-ID: <slrnao0c14.r3o.gisle@apal.ii.uib.no>
I need to convert a byte array representing an integer into a CL
integer type, but I can not find an elegant way of doing it. I can
always make a function like the one below, that converts the bytes 
in the given range.

(defun bytes-to-int (bytearr start end)
  "Convert the bits of a byte array to an integer"
  (let ((intval 0))
    (loop for i downfrom end to start
          and j from 0 to (- end start)  
          sum (* (aref bytearr i)
                 (expt 2 (* j  8)))
          into intval
          finally return intval)))

Are there any better way?

-- 
--
Gisle S�lensminde ( ·····@ii.uib.no )   

With sufficient thrust, pigs fly just fine. However, this is not
necessarily a good idea. It is hard to be sure where they are going
to land, and it could be dangerous sitting under them as they fly
overhead. (from RFC 1925)

From: Espen Vestre
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <kwfzwfwsj2.fsf@merced.netfonds.no>
Gisle S�lensminde <·····@apal.ii.uib.no> writes:

> I need to convert a byte array representing an integer into a CL
> integer type, but I can not find an elegant way of doing it. I can
> always make a function like the one below, that converts the bytes 
> in the given range.
> 
> (defun bytes-to-int (bytearr start end)
>   "Convert the bits of a byte array to an integer"
>   (let ((intval 0))
>     (loop for i downfrom end to start
>           and j from 0 to (- end start)  
>           sum (* (aref bytearr i)
>                  (expt 2 (* j  8)))
>           into intval
>           finally return intval)))

Two comments:

1) Your loop can be made more compact by noting that sum has an
   implicit "finally":

(defun bytes-to-int (bytearr start end)
  "Convert the bits of a byte array to an integer"
    (loop for i downfrom end to start
          and j from 0 to (- end start)  
          sum (* (aref bytearr i)
                 (expt 2 (* j  8)))))

2) You can speed up significantly by using (setf (ldb ...)) instead
   of summing:

(defun bytes-to-int2 (bytearr start end)
  "Convert the bits of a byte array to an integer"
  (loop with intval = 0
        with k = (* (- end start) 8)
        for i downfrom end to start
        and j from 0 to k by 8
        do (setf (ldb (byte 8 j) intval)
                 (aref bytearr i))
        finally return intval))

-- 
  (espen)
From: Espen Vestre
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <kw3csfwrip.fsf@merced.netfonds.no>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> (defun bytes-to-int2 (bytearr start end)
>   "Convert the bits of a byte array to an integer"
>   (loop with intval = 0
>         with k = (* (- end start) 8)
>         for i downfrom end to start
>         and j from 0 to k by 8
>         do (setf (ldb (byte 8 j) intval)
>                  (aref bytearr i))
>         finally return intval))

the limit check on j is unnecessary, as I noted in Raymonds code, so 
this is cleaner:

(defun bytes-to-int2 (bytearr start end)
   "Convert the bits of a byte array to an integer"
   (loop with intval = 0
         for i downfrom end to start
         and j from 0 by 8
         do (setf (ldb (byte 8 j) intval)
                  (aref bytearr i))
         finally return intval))

I noted that your version (or the reduce-version) is faster
(at least in my implementation) if you're summing small arrays
(e.g. result is a fixnum). However, for a 1000-element array,
the ldb-version is about 4x faster and uses half the memory.

-- 
  (espen)
From: Espen Vestre
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <kwy9a7vcpk.fsf@merced.netfonds.no>
Espen Vestre <·····@*do-not-spam-me*.vestre.net> writes:

> I noted that your version (or the reduce-version) is faster
> (at least in my implementation) if you're summing small arrays
> (e.g. result is a fixnum). However, for a 1000-element array,
> the ldb-version is about 4x faster and uses half the memory.

Or maybe not. The reduce-version is actually the fastest for
both small and large numbers. 

So I think Lars B. found both the most beautiful (*) _and_ the
fastest solution!

(*) nice applications of reduce are _always_ beuatiful ;-)
-- 
  (espen)
From: Raymond Wiker
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <86hegv4q90.fsf@raw.grenland.fast.no>
Gisle S�lensminde <·····@apal.ii.uib.no> writes:

> I need to convert a byte array representing an integer into a CL
> integer type, but I can not find an elegant way of doing it. I can
> always make a function like the one below, that converts the bytes 
> in the given range.
> 
> (defun bytes-to-int (bytearr start end)
>   "Convert the bits of a byte array to an integer"
>   (let ((intval 0))
>     (loop for i downfrom end to start
>           and j from 0 to (- end start)  
>           sum (* (aref bytearr i)
>                  (expt 2 (* j  8)))
>           into intval
>           finally return intval)))
> 
> Are there any better way?

        You could use "dpb" for depositing bytes directly into the
destination:  

(defun bytes-to-int2 (bytearr start end)
  (let ((res 0))
    (loop for i downfrom end to start
          and j from 0 by 8
          do (setf res (dpb (aref bytearr i)
                            (byte 8 j)
                            res)))
    res))


-- 
Raymond Wiker                        Mail:  ·············@fast.no
Senior Software Engineer             Web:   http://www.fast.no/
Fast Search & Transfer ASA           Phone: +47 23 01 11 60
P.O. Box 1677 Vika                   Fax:   +47 35 54 87 99
NO-0120 Oslo, NORWAY                 Mob:   +47 48 01 11 60

Try FAST Search: http://alltheweb.com/
From: Lars Brinkhoff
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <85admn7hxr.fsf@junk.nocrew.org>
Gisle S�lensminde <·····@apal.ii.uib.no> writes:
> I need to convert a byte array representing an integer into a CL
> integer type, but I can not find an elegant way of doing it. I can
> always make a function like the one below, that converts the bytes 
> in the given range.
> 
> (defun bytes-to-int (bytearr start end)
>   "Convert the bits of a byte array to an integer"
>   (let ((intval 0))
>     (loop for i downfrom end to start
>           and j from 0 to (- end start)  
>           sum (* (aref bytearr i)
>                  (expt 2 (* j  8)))
>           into intval
>           finally return intval)))
> 
> Are there any better way?

I'm a novice, but this seems to work:

(defun bytes-to-int (bytearr start end)
  "Convert the bits of a byte array to an integer"
  (reduce (lambda (x y) (+ (* 256 x) y)) subseq :start start :end end))

-- 
Lars Brinkhoff          http://lars.nocrew.org/     Linux, GCC, PDP-10,
Brinkhoff Consulting    http://www.brinkhoff.se/    HTTP programming
From: Lars Brinkhoff
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <8565xb7hm1.fsf@junk.nocrew.org>
Lars Brinkhoff <·········@nocrew.org> writes:
> (defun bytes-to-int (bytearr start end)
>   "Convert the bits of a byte array to an integer"
>   (reduce (lambda (x y) (+ (* 256 x) y)) subseq :start start :end end))

Typo, new try:

(defun bytes-to-int (bytearr start end)
  "Convert the bits of a byte array to an integer"
  (reduce (lambda (x y) (+ (* 256 x) y)) bytearr :start start :end end))

-- 
Lars Brinkhoff          http://lars.nocrew.org/     Linux, GCC, PDP-10,
Brinkhoff Consulting    http://www.brinkhoff.se/    HTTP programming
From: Frode Vatvedt Fjeld
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <2hhegvjzc9.fsf@vserver.cs.uit.no>
Lars Brinkhoff <·········@nocrew.org> writes:

> (defun bytes-to-int (bytearr start end)
>   "Convert the bits of a byte array to an integer"
>   (reduce (lambda (x y) (+ (* 256 x) y)) bytearr :start start :end end))

This looks good to me, but I'd prefer something like this:

 (defun bytes-to-int (bytes start end)
   "Convert the bits of a little-endian 8-bit byte array to an integer."
   (reduce (lambda (x y) (+ (* 256 x) y)) bytes :start start :end end))

-- 
Frode Vatvedt Fjeld
From: Barry Margolin
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <HO0g9.2$i66.147@paloalto-snr1.gtei.net>
In article <··············@vserver.cs.uit.no>,
Frode Vatvedt Fjeld  <······@acm.org> wrote:
>Lars Brinkhoff <·········@nocrew.org> writes:
>
>> (defun bytes-to-int (bytearr start end)
>>   "Convert the bits of a byte array to an integer"
>>   (reduce (lambda (x y) (+ (* 256 x) y)) bytearr :start start :end end))
>
>This looks good to me, but I'd prefer something like this:
>
> (defun bytes-to-int (bytes start end)
>   "Convert the bits of a little-endian 8-bit byte array to an integer."
>   (reduce (lambda (x y) (+ (* 256 x) y)) bytes :start start :end end))

I don't see any significant differences.  Just the name of a variable and
rewording of the documentation string.

-- 
Barry Margolin, ······@genuity.net
Genuity, Woburn, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
Please DON'T copy followups to me -- I'll assume it wasn't posted to the group.
From: Thomas F. Burdick
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <xcvu1kvulv6.fsf@hurricane.OCF.Berkeley.EDU>
Barry Margolin <······@genuity.net> writes:

> In article <··············@vserver.cs.uit.no>,
> Frode Vatvedt Fjeld  <······@acm.org> wrote:
> >Lars Brinkhoff <·········@nocrew.org> writes:
> >
> >> (defun bytes-to-int (bytearr start end)
> >>   "Convert the bits of a byte array to an integer"
> >>   (reduce (lambda (x y) (+ (* 256 x) y)) bytearr :start start :end end))
> >
> >This looks good to me, but I'd prefer something like this:
> >
> > (defun bytes-to-int (bytes start end)
> >   "Convert the bits of a little-endian 8-bit byte array to an integer."
> >   (reduce (lambda (x y) (+ (* 256 x) y)) bytes :start start :end end))
> 
> I don't see any significant differences.  Just the name of a variable and
> rewording of the documentation string.

As someone who works almost exclusively on big-endian systems, I think
it's a pretty important change.  In fact, I'd rewrite it like this:

  (defun byteseq-integer (byteseq &key (byte-size 8) (start 0)
                                  (end (length byteseq)) from-end)
     "Convert the bits of an array of bytes to an integer.
      Defaults to 8-bit bytes in little-endian order."
     (let ((shift (expt 2 byte-size)))
       (reduce (lambda (x y) (+ (* shift x) y))
               byteseq :start start :end end :from-end from-end)))

or even

  (defvar *default-endianness* :big-endian)

  (defun byteseq-integer (byteseq &key (byte-size 8) (start 0)
                                  (end (length byteseq))
                                  (from-end (ecase *default-endianness*
                                              (:big-endian t)
                                              (:little-endian nil))))
     "Convert the bits of an array of bytes to an integer.
      Defaults to 8-bit bytes in the order specified by *default-endianness*"
     (let ((shift (expt 2 byte-size)))
       (reduce (lambda (x y) (+ (* shift x) y))
               byteseq :start start :end end :from-end from-end)))

-- 
           /|_     .-----------------------.                        
         ,'  .\  / | No to Imperialist war |                        
     ,--'    _,'   | Wage class war!       |                        
    /       /      `-----------------------'                        
   (   -.  |                               
   |     ) |                               
  (`-.  '--.)                              
   `. )----'                               
From: Raymond Toy
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <4nhegvw6gw.fsf@rtp.ericsson.se>
>>>>> "Barry" == Barry Margolin <······@genuity.net> writes:

    Barry> In article <··············@vserver.cs.uit.no>,
    Barry> Frode Vatvedt Fjeld  <······@acm.org> wrote:
    >> Lars Brinkhoff <·········@nocrew.org> writes:
    >> 
    >>> (defun bytes-to-int (bytearr start end)
    >>> "Convert the bits of a byte array to an integer"
    >>> (reduce (lambda (x y) (+ (* 256 x) y)) bytearr :start start :end end))
    >> 
    >> This looks good to me, but I'd prefer something like this:
    >> 
    >> (defun bytes-to-int (bytes start end)
    >> "Convert the bits of a little-endian 8-bit byte array to an integer."
    >> (reduce (lambda (x y) (+ (* 256 x) y)) bytes :start start :end end))

    Barry> I don't see any significant differences.  Just the name of a variable and
    Barry> rewording of the documentation string.

I think the fact that he says "little-endian" is significant, having
been bitten lately by not knowing which endian some code was.

Ray
From: Frode Vatvedt Fjeld
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <2h4rcvjieg.fsf@vserver.cs.uit.no>
Barry Margolin <······@genuity.net> writes:

> I don't see any significant differences.  Just the name of a
> variable and rewording of the documentation string.

It was just a comment on coding style. I happen to believe that
documentation strings and variable names _are_ significant :)
Specifically I find the combination of hungarian notation and
abbreviated names in lisp code to be tasteless.

Come to think about it, function names are important too: I'd prefer
the function to either be named such that it's reasonably clear how
the byte-vector is interpreted, or that it accepts endianness and/or
byte-size as parameters, explicitly or implicitly via special
variables.

-- 
Frode Vatvedt Fjeld
From: Erik Naggum
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <3240840763579547@naggum.no>
* Frode Vatvedt Fjeld <······@acm.org>
| This looks good to me, but I'd prefer something like this:
| 
|  (defun bytes-to-int (bytes start end)
|    "Convert the bits of a little-endian 8-bit byte array to an integer."
|    (reduce (lambda (x y) (+ (* 256 x) y)) bytes :start start :end end))

  I would much prefer

(reduce (lambda (x y) (logior (ash x 8) y)) bytes :start start :end end)

  This is not a job for multiplication and addition.

-- 
Erik Naggum, Oslo, Norway

Act from reason, and failure makes you rethink and study harder.
Act from faith, and failure makes you blame someone and push harder.
From: Vassil Nikolov
Subject: Re: Converting bytes to an integer
Date: 
Message-ID: <f34a0f4f.0209130418.2c3e103d@posting.google.com>
Erik Naggum <····@naggum.no> wrote in message news:<················@naggum.no>...
> * Frode Vatvedt Fjeld <······@acm.org>
> | This looks good to me, but I'd prefer something like this:
> | 
> |  (defun bytes-to-int (bytes start end)
> |    "Convert the bits of a little-endian 8-bit byte array to an integer."
> |    (reduce (lambda (x y) (+ (* 256 x) y)) bytes :start start :end end))
> 
>   I would much prefer
> 
> (reduce (lambda (x y) (logior (ash x 8) y)) bytes :start start :end end)
> 
>   This is not a job for multiplication and addition.

I would say there is a tradeoff here between solving the
specific problem at hand (bytes into integer), for which
LOGIOR�ASH is the way to go, and being general, that is,
able to compute the polynomial for an arbitrary argument
by using the composition of + and * and `parameterizing'
the constant 256.

---Vassil.