(defun read-ui16 (stream)
(let ((ui16 0))
(setf (ldb (byte 8 8) ui16) (read-byte stream))
(setf (ldb (byte 8 0) ui16) (read-byte stream))
ui16))
So far, so good. How would a Lisp expert read a signed 16-bit thing?
One might, for example, write (sign-ui16 (read-ui16 stream)), where
sign-ui16 is defined as follows:
(defun sign-ui16 (n)
(if (zerop (ldb (byte 1 15) n))
n
(- (1+ (logxor #xffff n)))))
If the sign-bit is zero, return the number. If it's set, return -(~n +
1). (Note: lognot doesn't work - it has to be logxor).
Any suggestions on a better way to do this?
| (defun sign-ui16 (n)
| (if (zerop (ldb (byte 1 15) n))
| n
| (- (1+ (logxor #xffff n)))))
|
| If the sign-bit is zero, return the number. If it's set, return -(~n +
| 1). (Note: lognot doesn't work - it has to be logxor).
|
| Any suggestions on a better way to do this?
Here is general code from Pascal Bourguignon
(defun unsigned-to-signed/2-complement (x width)
(declare (integer x width))
(let ((maxpos+1 (expt 2 (1- width))))
(if (< x maxpos+1) x (- x (* 2 maxpos+1)))))
Most of the code I've seen which reads signed 16bit words is along these
lines: declare the variable to be an unsigned-byte 16, check and
subtract 65536, or just return n.
This does not address how n was read from the external file, endianness
in which the file was stored. For parsing binary files I've been using
frodef's excellent
<URL:http://www.cs.uit.no/~frodef/sw/binary-types/>
(from even before PCL came out.) There you'd do
(read-binary 's16 stream)
--
Madhu
> So far, so good. How would a Lisp expert read a signed 16-bit thing?
>
> One might, for example, write (sign-ui16 (read-ui16 stream)), where
> sign-ui16 is defined as follows:
>
> (defun sign-ui16 (n)
> (if (zerop (ldb (byte 1 15) n))
> n
> (- (1+ (logxor #xffff n)))))
>
> If the sign-bit is zero, return the number. If it's set, return -(~n +
> 1). (Note: lognot doesn't work - it has to be logxor).
>
> Any suggestions on a better way to do this?
Christophe Rhodes showed me this general idea:
(defun sign-sized (n size)
(if (logbitp (1- size) n)
(dpb n (byte size 0) -1)
n))
So:
(defun sign-ui16 (n)
(sign-sized n 16))
Zach