From: Stas B. <sta...@gm...> - 2014-06-27 17:29:33
|
Jeff Cunningham <je...@jk...> writes: > On 06/27/2014 12:32 AM, Stas Boukarev wrote: >> (defun read-u2le (s) >> (let ((u 0)) >> (setf (ldb (byte 8 0) u) >> (the (unsigned-byte 8) (read-byte s))) >> (setf (ldb (byte 8 8) u) >> (the (unsigned-byte 8) (read-byte s))) >> u)) >>> > > That cut the time down to about 40% of what it was. That's a good > trick, Stas. > I applied it to some of the larger word sized read functions but ran > into this warning on 64-bit integers: > > (declaim (inline read-u8le)) > (defun read-u8le (s) > (let ((u 0)) > (declare (type (unsigned-byte 64) u)) > (setf (ldb (byte 8 0) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 8) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 16) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 24) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 32) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 40) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 48) u) > (the (unsigned-byte 8) (read-byte s))) > (setf (ldb (byte 8 56) u) > (the (unsigned-byte 8) (read-byte s))) > u)) > > (declaim (inline read-i8le)) > (defun read-i8le (s) > (let ((v (read-u8le s))) > (if (/= 0 (logand v #x8000000000000000)) > (- v #x10000000000000000) > v))) > > ; in: DEFUN READ-U8LE > ; (SETF (LDB (BYTE 8 56) BINDATA::U) > ; (THE (UNSIGNED-BYTE 8) (READ-BYTE BINDATA::S))) > ; --> LET* MULTIPLE-VALUE-BIND LET LET > ; ==> > ; (SETQ BINDATA::U #:NEW35) > ; > ; note: doing unsigned word to integer coercion (cost 20) to U > ; > ; compilation unit finished > ; printed 1 note > > ; file: /tmp/fileiJYXnF > ; in: DEFUN READ-I8LE > ; (BINDATA:READ-U8LE BINDATA::S) > ; --> BLOCK LET SETF LET* MULTIPLE-VALUE-BIND LET LET > ; ==> > ; (SETQ BINDATA::U #:NEW35) > ; > ; note: doing unsigned word to integer coercion (cost 20) to U > ; > > I don't understand why it thinks it could overflow (unsigned-byte 64). > Am I doing something wrong here? It can't overflow ub64, but it can overflow fixnum. But it wouldn't matter when it's inlined. And a better way to sign-extend is (logior n (- (mask-field (byte 1 63) n))), except that SBCL currently fails to optimize it properly. I'll look into it for the next release. For now, if you are not afraid to use internals, you can use (sb-c::mask-signed-field 64 n) -- With best regards, Stas. |