From: Craig Sauer
Subject: Foreign types in Allegro CL
Date: 
Message-ID: <93cc0047.0411241414.29fd87de@posting.google.com>
I'm fairly new to Lisp, and this is my first posting here.  I'd
appreciate any advice on this problem I'm having:

I'm passing data back and forth between two applications (currently
both on the same computer) via UDP.

The Lisp program needs to receive a packet of 16 bytes, consisting of
an integer, a double, and another integer.  I am receiving the packet
just fine, and I can print out each byte's value individually.  


I'm using Allegro CL's foreign types facility, with commands like:

(setf int1test (ff:fslot-value-typed :int :lisp (subseq data 0 4)))
(setf doubletest (ff:fslot-value-typed :double :lisp (subseq data 4
12)))
(setf int2test (ff:fslot-value-typed :int :lisp (subseq data 12)))

to convert the 16 bytes in "data" into the int, double, int, that I'm
expecting.

When I print out these 3 values, using code like:

(format t "~D " int1test)
(format t "~F " doubletest)
(format t "~D~%" int2test)

The integers print out fine, but the double is unrecognizable. I've
tried swapping the bytes in case there is an endian issue at work (but
I doubt it because the integers are ok).

An example:

I send 5, 7.0, 10 ten times

the Lisp program responds:  (the third line of every set is the 16
bytes)

Packet 1 ->16 bytes from 2130706433
5 5.31405562d-315 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 2 ->16 bytes from 2130706433
5 -1.6958247478583448d+216 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 3 ->16 bytes from 2130706433
5 5.31405562d-315 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 4 ->16 bytes from 2130706433
5 5.31405562d-315 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 5 ->16 bytes from 2130706433
5 5.31405562d-315 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 6 ->16 bytes from 2130706433
5 1.5069781534728802d-154 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 7 ->16 bytes from 2130706433
5 -6.591781867590727d-213 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 8 ->16 bytes from 2130706433
5 1.4951352948556237d-154 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 9 ->16 bytes from 2130706433
5 5.31405562d-315 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

Packet 10 ->16 bytes from 2130706433
5 -5.880343017059636d-39 10
5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0 

I can see that the 16 bytes are the same on each cycle, but I'm
getting a different (incorrect) double on every cycle.

I would appreciate any help on this problem.

Sincerely,

Craig Sauer

From: Kenny Tilton
Subject: Re: Foreign types in Allegro CL
Date: 
Message-ID: <41A83B8D.4090809@nyc.rr.com>
[also on c.l.l]

Craig Sauer wrote:

 > I'm fairly new to Lisp, and this is my first posting here.  I'd
 > appreciate any advice on this problem I'm having:
 >
 > I'm passing data back and forth between two applications (currently
 > both on the same computer) via UDP.
 >
 > The Lisp program needs to receive a packet of 16 bytes, consisting of
 > an integer, a double, and another integer.  I am receiving the packet
 > just fine, and I can print out each byte's value individually.
 >
 >
 > I'm using Allegro CL's foreign types facility, with commands like:
 >
 > (setf int1test (ff:fslot-value-typed :int :lisp (subseq data 0 4)))
 > (setf doubletest (ff:fslot-value-typed :double :lisp (subseq data 4
 > 12)))
 > (setf int2test (ff:fslot-value-typed :int :lisp (subseq data 12)))
 >
 > to convert the 16 bytes in "data" into the int, double, int, that I'm
 > expecting.
 >
 > When I print out these 3 values, using code like:
 >
 > (format t "~D " int1test)
 > (format t "~F " doubletest)
 > (format t "~D~%" int2test)
 >
 > The integers print out fine, but the double is unrecognizable. I've
 > tried swapping the bytes in case there is an endian issue at work (but
 > I doubt it because the integers are ok).
 >
 > An example:
 >
 > I send 5, 7.0, 10 ten times
 >
 > the Lisp program responds:  (the third line of every set is the 16
 > bytes)
 >
 > Packet 1 ->16 bytes from 2130706433
 > 5 5.31405562d-315 10
 > 5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0

I do not know if this helps, but maybe you can work backwards from it to 
figure out what is going on:

(defparameter data (make-array 16
                      :element-type 'byte
                      :initial-contents '(5 0 0 0
             #| reordered --> |#          0 0 0 0 0 0 #x1c #x40
                                          #x0a 0 0 0)))

(let ((mem (ff:allocate-fobject :double :c)))
   (loop for b across (subseq data 0 4)
         for n upfrom 0
         do (setf (ff:fslot-value-typed
                    '(:array :unsigned-char) :c mem n) b))
   (print `(int1 ,(ff:fslot-value-typed :int :c mem)))

   (loop for b across (subseq data 4 12)
         for n upfrom 0
         do (setf (ff:fslot-value-typed
                    '(:array :unsigned-char) :c mem n) b))
   (print `(double ,(ff:fslot-value-typed :double :c mem)))

   (loop for b across (subseq data 12)
         for n upfrom 0
         do (setf (ff:fslot-value-typed
                    '(:array :unsigned-char) :c mem n) b))
   (print `(int2 ,(ff:fslot-value-typed :int :c mem)))
   (values))

=>


(INT1 5)
(DOUBLE 7.0d0)
(INT2 10)


There may be a simpler way to get the same effect, but I was learning, 
too, as I managed to get this much.

Note that I had to re-order the bytes, and I worked out the new order 
(since you are new to lisp) by inspecting 7.0d0 and the various 
erroneous doubles I got from other orderings of the bytes. Just:

  The AllegroCL sneakily shows the hex form of values down along the 
bottom of the inspector. If I had not found that I would have used 
format or print-radix or (hand-waving) something to get at the hex rep 
of the doubles. Oops, just thought of this:

(describe 7.0d0) =>
7.0d0 is a DOUBLE-FLOAT.
  It is a writable box.
  The hex representation is [#x401c0000 00000000].


Once I saw #x40 and #x1c in the erroneous doubles (describe them) but in 
the wrong places, I just shuffled the array until I got 7.0d0.

I realize this does not help you read the data as is, but maybe it 
suggests how to swap bytes if you know what data is expected.

kt
From: Craig Sauer
Subject: Re: Foreign types in Allegro CL
Date: 
Message-ID: <93cc0047.0411291326.4ccd1ea0@posting.google.com>
Kenny Tilton <·······@nyc.rr.com> wrote in message news:<················@nyc.rr.com>...
> [also on c.l.l]
> 
> Craig Sauer wrote:
>  > The integers print out fine, but the double is unrecognizable. I've
>  > tried swapping the bytes in case there is an endian issue at work (but
>  > I doubt it because the integers are ok).
>  >
>  > An example:
>  >
>  > I send 5, 7.0, 10 ten times
>  >
>  > the Lisp program responds:  (the third line of every set is the 16
>  > bytes)
>  >
>  > Packet 1 ->16 bytes from 2130706433
>  > 5 5.31405562d-315 10
>  > 5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0
> 
> I do not know if this helps, but maybe you can work backwards from it to 
> figure out what is going on:
> 
> (defparameter data (make-array 16
>                       :element-type 'byte
>                       :initial-contents '(5 0 0 0
>              #| reordered --> |#          0 0 0 0 0 0 #x1c #x40
>                                           #x0a 0 0 0)))
> [snip]
> Once I saw #x40 and #x1c in the erroneous doubles (describe them) but in 
> the wrong places, I just shuffled the array until I got 7.0d0.

I'm confused by your response.  It looks to me like the bytes in your
string are in the same order as in my string.  I ran your code
successfully and got the same output you did, but I don't see how
you've shuffled the bytes.  The last two bytes in the double are 1c
and 40 in both our sequences, right?

In any case, thanks for your help.  Your sample code is very helpful
for me to have, to see ways of doing this stuff in Lisp.  I find
reading Lisp loops sort of confusing, so having some clear examples is
really helpful.

-Craig
From: Kenny Tilton
Subject: Re: Foreign types in Allegro CL
Date: 
Message-ID: <41AB9A44.2050208@nyc.rr.com>
Craig Sauer wrote:

> Kenny Tilton <·······@nyc.rr.com> wrote in message news:<················@nyc.rr.com>...
> 
>>[also on c.l.l]
>>
>>Craig Sauer wrote:
>> > The integers print out fine, but the double is unrecognizable. I've
>> > tried swapping the bytes in case there is an endian issue at work (but
>> > I doubt it because the integers are ok).
>> >
>> > An example:
>> >
>> > I send 5, 7.0, 10 ten times
>> >
>> > the Lisp program responds:  (the third line of every set is the 16
>> > bytes)
>> >
>> > Packet 1 ->16 bytes from 2130706433
>> > 5 5.31405562d-315 10
>> > 5 0 0 0 0 0 0 0 0 0 1c 40 a 0 0 0
>>
>>I do not know if this helps, but maybe you can work backwards from it to 
>>figure out what is going on:
>>
>>(defparameter data (make-array 16
>>                      :element-type 'byte
>>                      :initial-contents '(5 0 0 0
>>             #| reordered --> |#          0 0 0 0 0 0 #x1c #x40
>>                                          #x0a 0 0 0)))
>>[snip]
>>Once I saw #x40 and #x1c in the erroneous doubles (describe them) but in 
>>the wrong places, I just shuffled the array until I got 7.0d0.
> 
> 
> I'm confused by your response.  It looks to me like the bytes in your
> string are in the same order as in my string.

Oops, I could have sworn I had to reverse those. maybe while goofing 
around I reversed it once and forgot I had done so.

So I guess the difference was in packing a byte at a time instead of 
using SUBSEQ?

As I said, I did not know anything about the issues, I just worked 
backwards from inspecting the hex values of desired and erroneous 
floats. Bit of a blind leading the blind here until some floating-point 
guru checks in to explain what is happening.

kenny

-- 
Cells? Cello? Celtik?: http://www.common-lisp.net/project/cells/
Why Lisp? http://alu.cliki.net/RtL%20Highlight%20Film