Fix bug with equal? on small bit-vectors.

This commit is contained in:
Greg Hendershott 2014-08-19 23:05:51 -04:00 committed by Sam Tobin-Hochstadt
parent c389bfab3b
commit 9de70551dc
2 changed files with 47 additions and 7 deletions

View File

@ -87,6 +87,36 @@
(eq-hash-code (bit-vector #t #f #t #f #t)))
#f))
(test-case "bit-vector, equal-proc (via equal?)"
;; Zero length bit-vectors are equal...
(equal? (make-bit-vector 0 #t)
(make-bit-vector 0 #t))
;; ...even if fill value differed, because it's N/A
(equal? (make-bit-vector 0 #t)
(make-bit-vector 0 #f))
;; Check a range of bit lengths spanning a few 8-bit bytes:
(for ([len (in-range 1 24)])
(check-equal?
(equal? (make-bit-vector len #t)
(make-bit-vector len #t))
#t)
(check-equal?
(equal? (make-bit-vector len #t)
(make-bit-vector len #f))
#f))
;; Attempt to flush out potential bugs wrt to unused bits
;; that might be set by a "fill" value (implementation
;; detail we don't know for sure here), but should
;; definitely be ignored by equal?.
(let ([x (make-bit-vector 1 #t)] ;#t fill value
[y (make-bit-vector 1 #f)]) ;#f fill value
;; Set the only bit to #t in both
(bit-vector-set! x 0 #t)
(bit-vector-set! y 0 #t)
;; Should be equal, regardless of different fill values
;; in make-bit-vector:
(check-equal? (equal? x y) #t)))
(test-case "for/bit-vector"
(check-equal? (for/bit-vector ([i 5]) (odd? i))
(bit-vector #f #t #f #t #f))

View File

@ -148,8 +148,7 @@
bit-vector-copy
#f)
; A bit vector is represented as a vector of words.
; Each word contains 30 or 62 bits depending on the size of a fixnum.
;; A bit vector is represented as bytes.
(serializable-struct bit-vector (words size)
; words is the bytes of words
; size is the number of bits in bitvector
@ -187,11 +186,22 @@
[nx (bit-vector-size x)]
[ny (bit-vector-size y)])
(and (= nx ny)
(for/and ([index (in-range (- (bytes-length vx) 1))])
(eq? (bytes-ref vx index)
(bytes-ref vy index)))
; TODO: check last word
)))
(or (zero? nx) ;zero-length bit-vectors are equal
(let ([last-index (sub1 (bytes-length vx))])
(and
;; Check all but last byte.
;; These use all bits, therefore simple eq?.
(for/and ([index (in-range (sub1 last-index))])
(eq? (bytes-ref vx index)
(bytes-ref vy index)))
;; Check the used bits of the last byte.
(let ([used-bits (min 8 (remainder nx 256))])
(eq? (bitwise-bit-field (bytes-ref vx last-index)
0
used-bits)
(bitwise-bit-field (bytes-ref vy last-index)
0
used-bits)))))))))
(define (hash-code x hc)
(let ([v (bit-vector-words x)]
[n (bit-vector-size x)])