** LCM with two arguments of 0 returns 0 rather than signalling
DIVISION-BY-ZERO.
** unsigned addition of a 32-bit constant with the high bit set no
- longer causes an internal compiler error.
+ longer causes an internal compiler error on the x86.
+ ** LOGBITP accepts a non-negative bignum as its INDEX argument.
planned incompatible changes in 0.8.x:
* (not done yet, but planned:) When the profiling interface settles
"BIGNUM-COMPARE" "BIGNUM-DEPOSIT-BYTE"
"BIGNUM-ELEMENT-TYPE" "BIGNUM-GCD" "BIGNUM-INDEX"
"BIGNUM-INTEGER-LENGTH" "BIGNUM-LOAD-BYTE"
+ "BIGNUM-LOGBITP"
"BIGNUM-LOGCOUNT" "BIGNUM-LOGICAL-AND"
"BIGNUM-LOGICAL-IOR" "BIGNUM-LOGICAL-NOT"
"BIGNUM-LOGICAL-XOR" "BIGNUM-PLUS-P"
;;; bignum-logical-and bignum-logical-ior bignum-logical-xor
;;; bignum-logical-not bignum-load-byte bignum-deposit-byte
;;; bignum-truncate bignum-plus-p bignum-compare make-small-bignum
-;;; bignum-logcount
+;;; bignum-logbitp bignum-logcount
;;; These symbols define the interface to the compiler:
;;; bignum-type bignum-element-type bignum-index %allocate-bignum
;;; %bignum-length %bignum-set-length %bignum-ref %bignum-set
(t
(round-up))))))
\f
-;;;; integer length and logcount
+;;;; integer length and logbitp/logcount
(defun bignum-integer-length (bignum)
(declare (type bignum-type bignum))
(+ (integer-length (%fixnum-digit-with-correct-sign digit))
(* len-1 digit-size))))
+(defun bignum-logbitp (index bignum)
+ (declare (type bignum-type bignum))
+ (let ((len (%bignum-length bignum)))
+ (declare (type bignum-index len))
+ (multiple-value-bind (word-index bit-index)
+ (floor index digit-size)
+ (if (>= word-index len)
+ (not (bignum-plus-p bignum))
+ (not (zerop (logand (%bignum-ref bignum word-index)
+ (ash 1 bit-index))))))))
+
(defun bignum-logcount (bignum)
(declare (type bignum-type bignum))
(let* ((length (%bignum-length bignum))
if INTEGER is negative."
(etypecase integer
(fixnum
- (logcount (truly-the (integer 0 #.(max most-positive-fixnum
- (lognot most-negative-fixnum)))
+ (logcount (truly-the (integer 0
+ #.(max sb!xc:most-positive-fixnum
+ (lognot sb!xc:most-negative-fixnum)))
(if (minusp (truly-the fixnum integer))
(lognot (truly-the fixnum integer))
integer))))
(defun logbitp (index integer)
#!+sb-doc
"Predicate returns T if bit index of integer is a 1."
- (logbitp index integer))
+ (number-dispatch ((index integer) (integer integer))
+ ((fixnum fixnum) (if (> index #.(- sb!vm:n-word-bits sb!vm:n-lowtag-bits))
+ (minusp integer)
+ (not (zerop (logand integer (ash 1 index))))))
+ ((fixnum bignum) (bignum-logbitp index integer))
+ ((bignum (foreach fixnum bignum)) (minusp integer))))
(defun ash (integer count)
#!+sb-doc
(defknown lognot (integer) integer (movable foldable flushable explicit-check))
(defknown logtest (integer integer) boolean (movable foldable flushable))
-(defknown logbitp (bit-index integer) boolean (movable foldable flushable))
+(defknown logbitp (unsigned-byte integer) boolean (movable foldable flushable))
(defknown ash (integer integer) integer
(movable foldable flushable explicit-check))
(defknown (logcount integer-length) (integer) bit-index
(define-source-transform logorc1 (x y) `(logior (lognot ,x) ,y))
(define-source-transform logorc2 (x y) `(logior ,x (lognot ,y)))
(define-source-transform logtest (x y) `(not (zerop (logand ,x ,y))))
-(define-source-transform logbitp (index integer)
- `(not (zerop (logand (ash 1 ,index) ,integer))))
+
+(deftransform logbitp
+ ((index integer) (unsigned-byte (or (signed-byte #.sb!vm:n-word-bits)
+ (unsigned-byte #.sb!vm:n-word-bits))))
+ `(if (>= index #.sb!vm:n-word-bits)
+ (minusp integer)
+ (not (zerop (logand integer (ash 1 index))))))
+
(define-source-transform byte (size position)
`(cons ,size ,position))
(define-source-transform byte-size (spec) `(car ,spec))
(compile nil '(lambda (x) (declare (bit x)) (+ x #xf0000000)))
1)
#xf0000001))
+
+;;; LOGBITP on bignums:
+(dolist (x '(((1+ most-positive-fixnum) 1 nil)
+ ((1+ most-positive-fixnum) -1 t)
+ ((1+ most-positive-fixnum) (1+ most-positive-fixnum) nil)
+ ((1+ most-positive-fixnum) (1- most-negative-fixnum) t)
+ (1 (ash most-negative-fixnum 1) nil)
+ (29 most-negative-fixnum t)
+ (30 (ash most-negative-fixnum 1) t)
+ (31 (ash most-negative-fixnum 1) t)
+ (64 (ash most-negative-fixnum 36) nil)
+ (65 (ash most-negative-fixnum 36) t)))
+ (destructuring-bind (index int result) x
+ (assert (eq (eval `(logbitp ,index ,int)) result))))
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.3.52"
+"0.8.3.53"