From: jurgen_defurne
Subject: Converting between different unsigned-byte results
Date: 
Message-ID: <1157118784.762767.278510@i3g2000cwc.googlegroups.com>
I am using the contents of an (unsigned-byte 32) field to set the value
of an (unsigned-byte 7) field.

While this seems dangerous, I know that at that moment the
(unsigned-byte 32) field will always be between 0 and 127.

It seems I can suppress warnings about unsigned word to integer
coercion by doing

        (setf f1 (logand '#x7F f2))

Doing

        (setf f1 (the (unsigned-byte 7) f2))

does not work.

Are there any other ways of doing this conversion that are maybe
perhaps better defined ?

Regards,

Jurgen

From: ··············@hotmail.com
Subject: Re: Converting between different unsigned-byte results
Date: 
Message-ID: <1157122040.438539.75410@m73g2000cwd.googlegroups.com>
jurgen_defurne wrote:
> I am using the contents of an (unsigned-byte 32) field to set the value
> of an (unsigned-byte 7) field.
>
> While this seems dangerous, I know that at that moment the
> (unsigned-byte 32) field will always be between 0 and 127.
>
> It seems I can suppress warnings about unsigned word to integer
> coercion by doing
>
>         (setf f1 (logand '#x7F f2))
>
> Doing
>
>         (setf f1 (the (unsigned-byte 7) f2))
>
> does not work.
>
> Are there any other ways of doing this conversion that are maybe
> perhaps better defined ?
>
> Regards,
>
> Jurgen

Have you met the functions LDB, (SETF LDB), and DPB?
and their cousins DEPOSIT-FIELD, MASK-FIELD, and (SETF MASK-FIELD)?

http://www.lispworks.com/documentation/HyperSpec/Body/f_ldb.htm
http://www.lispworks.com/documentation/HyperSpec/Body/f_dpb.htm#dpb

http://www.lispworks.com/documentation/HyperSpec/Body/f_deposi.htm#deposit-field
http://www.lispworks.com/documentation/HyperSpec/Body/f_mask_f.htm#mask-field
From: Thomas A. Russ
Subject: Re: Converting between different unsigned-byte results
Date: 
Message-ID: <ymiu03rza8g.fsf@blackcat.isi.edu>
"jurgen_defurne" <··············@pandora.be> writes:

> I am using the contents of an (unsigned-byte 32) field to set the value
> of an (unsigned-byte 7) field.
...
> Doing
> 
>         (setf f1 (the (unsigned-byte 7) f2))
> 
> does not work.

And it shouldn't.  The Common Lisp THE operation is an assertion
(promise) about the type of the expression.  It is NOT a coercion
operator.  That would mean, for example that the following code is in
error: 

   (setf i (the fixnum 3.0))

since the value 3.0 is, in fact, not a fixnum.  THE will not coerce
values.  Instead it just instructs the compiler to trust the
programmer's assertion about the type of the data.  If you lie, then
undefined consequence can rear their ugly head.

--
Thomas A. Russ,  USC/Information Sciences Institute
From: Barry Margolin
Subject: Re: Converting between different unsigned-byte results
Date: 
Message-ID: <barmar-E14D9F.21462801092006@comcast.dca.giganews.com>
In article <···············@blackcat.isi.edu>,
 ···@sevak.isi.edu (Thomas A. Russ) wrote:

> "jurgen_defurne" <··············@pandora.be> writes:
> 
> > I am using the contents of an (unsigned-byte 32) field to set the value
> > of an (unsigned-byte 7) field.
> ...
> > Doing
> > 
> >         (setf f1 (the (unsigned-byte 7) f2))
> > 
> > does not work.
> 
> And it shouldn't.

But since he said that he knows a priori that f2's value is between 0 
and 127, it SHOULD work.  As you said, the declaration is a promise, and 
in this case he keeps the promise.  No coercion is required, because f2 
is already of the desired type.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Thomas A. Russ
Subject: Re: Converting between different unsigned-byte results
Date: 
Message-ID: <ymipsea9k2v.fsf@sevak.isi.edu>
Barry Margolin <······@alum.mit.edu> writes:

> In article <···············@blackcat.isi.edu>,
>  ···@sevak.isi.edu (Thomas A. Russ) wrote:
> 
> > "jurgen_defurne" <··············@pandora.be> writes:
> > 
> > > I am using the contents of an (unsigned-byte 32) field to set the value
> > > of an (unsigned-byte 7) field.
> > ...
> > > Doing
> > > 
> > >         (setf f1 (the (unsigned-byte 7) f2))
> > > 
> > > does not work.
> > 
> > And it shouldn't.
> 
> But since he said that he knows a priori that f2's value is between 0 
> and 127, it SHOULD work.  As you said, the declaration is a promise, and 
> in this case he keeps the promise.  No coercion is required, because f2 
> is already of the desired type.

Actually it probably isn't, and coercion may or may not be required,
depending on what sorts of special values the lisp implementation
supports.

Although the numeric RANGE of the integer value fits inside the
(unsigned byte 7) type, that doesn't mean that the actual storage
implementation (and thus type as far as the compiler is concerned) is
the same in both cases.

Take just the simple case of a 32-bit integer and an 8-bit integer, and
assume that the lisp implementation in question supports some optimized
data structure for each of these.  Further assume that the value in
question is the number 12.  One of them will be four bytes long with the
top three bytes 0 and the lower byte 12.  The other will be a single
byte with the value 12.  A pointer to one of these data structures is
different than a pointer to the other.  A coercion step would be
required to transform them, and thus one can't use THE larger range type
to actually be of the smaller range.  [Or even vice-versa].


-- 
Thomas A. Russ,  USC/Information Sciences Institute
From: Barry Margolin
Subject: Re: Converting between different unsigned-byte results
Date: 
Message-ID: <barmar-E3DE60.03385506092006@comcast.dca.giganews.com>
In article <···············@sevak.isi.edu>,
 ···@sevak.isi.edu (Thomas A. Russ) wrote:

> Barry Margolin <······@alum.mit.edu> writes:
> 
> > In article <···············@blackcat.isi.edu>,
> >  ···@sevak.isi.edu (Thomas A. Russ) wrote:
> > 
> > > "jurgen_defurne" <··············@pandora.be> writes:
> > > 
> > > > I am using the contents of an (unsigned-byte 32) field to set the value
> > > > of an (unsigned-byte 7) field.
> > > ...
> > > > Doing
> > > > 
> > > >         (setf f1 (the (unsigned-byte 7) f2))
> > > > 
> > > > does not work.
> > > 
> > > And it shouldn't.
> > 
> > But since he said that he knows a priori that f2's value is between 0 
> > and 127, it SHOULD work.  As you said, the declaration is a promise, and 
> > in this case he keeps the promise.  No coercion is required, because f2 
> > is already of the desired type.
> 
> Actually it probably isn't, and coercion may or may not be required,
> depending on what sorts of special values the lisp implementation
> supports.
> 
> Although the numeric RANGE of the integer value fits inside the
> (unsigned byte 7) type, that doesn't mean that the actual storage
> implementation (and thus type as far as the compiler is concerned) is
> the same in both cases.

(unsigned-byte 7) doesn't imply a particular storage implementation.  
It's equivalent to (integer 0 127) -- it just specifies the range of 
values.

The compiler can use the declaration to use particular instructions to 
extract the value and operate on it, for optimization.  E.g. if you write

(+ (the (unsigned-byte 7) x) (the (unsigned-byte 7) y))

it can extract the values from the variables using a single-byte load 
instruction, and compute the sum using an integer addition without 
having to check for overflow.

-- 
Barry Margolin, ······@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
*** PLEASE don't copy me on replies, I'll read them in the group ***
From: Frode Vatvedt Fjeld
Subject: Re: Converting between different unsigned-byte results
Date: 
Message-ID: <2hmz9jftqf.fsf@vserver.cs.uit.no>
"jurgen_defurne" <··············@pandora.be> writes:

> It seems I can suppress warnings about unsigned word to integer
> coercion by doing
> 
>         (setf f1 (logand '#x7F f2))

That's the first time I've seen anyone quote a literal number, but
this should work just fine and is very clearly defined.

>         (setf f1 (the (unsigned-byte 7) f2))
> 
> does not work.

The semantics of this is that you are making a promise to the compiler
that the value of f2 will always be an integer in the range 0 to 127.

> Are there any other ways of doing this conversion that are maybe
> perhaps better defined?

Again, there's nothing ill-defined about the logand form above, but a
more fluent way is, as someone else suggested already,

  (setf f1 (ldb (byte 7 0) f2))

-- 
Frode Vatvedt Fjeld