;;; simple.
(deftransform sxhash ((x) (fixnum))
'(logand most-positive-fixnum
- (logxor x
- (ash x -3) ; to get sign bit into hash
+ (logxor (ash (logand x (ash most-positive-fixnum -4)) 4)
+ (ash x -1) ; to get sign bit into hash
361475658)))
+;;; SXHASH of SIMPLE-BIT-VECTOR values is defined as a DEFTRANSFORM
+;;; because it is endian-dependent.
+(deftransform sxhash ((x) (simple-bit-vector))
+ `(let ((result 410823708))
+ (declare (type fixnum result))
+ (mixf result (sxhash (length x)))
+ (do* ((i sb!vm:vector-data-offset (+ i 1))
+ ;; FIXME: should we respect DEPTHOID? SXHASH on strings
+ ;; doesn't seem to...
+ (end (+ sb!vm:vector-data-offset
+ (ceiling (length x) sb!vm:n-word-bits))))
+ ((= i end) result)
+ (declare (type index i end))
+ (let ((num
+ (if (= i (1- end))
+ (logand
+ (ash (1- (ash 1 (mod (length x) sb!vm:n-word-bits)))
+ ,(ecase sb!c:*backend-byte-order*
+ (:little-endian 0)
+ (:big-endian
+ '(- sb!vm:n-word-bits
+ (mod (length x) sb!vm:n-word-bits)))))
+ (%raw-bits x i))
+ (%raw-bits x i))))
+ (declare (type (unsigned-byte 32) num))
+ (mixf result ,(ecase sb!c:*backend-byte-order*
+ (:little-endian '(logand num most-positive-fixnum))
+ ;; FIXME: I'm not certain that N-LOWTAG-BITS
+ ;; is the clearest way of expressing this:
+ ;; it's essentially the difference between
+ ;; `(UNSIGNED-BYTE ,SB!VM:N-WORD-BITS) and
+ ;; (AND FIXNUM UNSIGNED-BYTE).
+ (:big-endian '(ash num (- sb!vm:n-lowtag-bits)))))))))
+
;;; Some other common SXHASH cases are defined as DEFTRANSFORMs in
;;; order to avoid having to do TYPECASE at runtime.
;;;
(if #+sb-xc-host nil #-sb-xc-host (constant-continuation-p x)
(sxhash (continuation-value x))
'(%sxhash-simple-string (symbol-name x))))
+
+