diff --git a/collects/data/bit-vector.rkt b/collects/data/bit-vector.rkt index 3c4a69b14a..b535c3d277 100644 --- a/collects/data/bit-vector.rkt +++ b/collects/data/bit-vector.rkt @@ -6,26 +6,21 @@ racket/contract/base racket/fixnum racket/unsafe/ops + racket/serialize "private/count-bits-in-fixnum.rkt") -(define bits-in-a-word - (if (fixnum? (expt 2 61)) - ; 32 or 64-bit fixnums? - 62 30)) +(define bits-in-a-word 8) -(define largest-fixnum +(define largest-word (- (expt 2 bits-in-a-word) 1)) -(define ((bad-index-error who index)) - (raise-mismatch-error who "index out of range: " index)) - (define (make-bit-vector size [fill #f]) (define-values (q r) (quotient/remainder size bits-in-a-word)) (define word-size (+ q (if (zero? r) 0 1))) - (define words (make-fxvector word-size (if fill largest-fixnum 0))) + (define words (make-bytes word-size (if fill largest-word 0))) (when (and fill (not (zero? r))) - (fxvector-set! words q (- (expt 2 r) 1))) - (bit-vector words size word-size)) + (bytes-set! words q (- (expt 2 r) 1))) + (bit-vector words size)) (define bit-vector* (let ([bit-vector @@ -52,8 +47,8 @@ (define (unsafe-bit-vector-ref bv n) (define-values (wi bi) (quotient/remainder n bits-in-a-word)) (match bv - [(struct bit-vector (words size word-size)) - (define word (fxvector-ref words wi)) + [(struct bit-vector (words size)) + (define word (bytes-ref words wi)) (define bit (bitwise-bit-set? word bi)) bit])) @@ -74,11 +69,11 @@ (define (bit-vector-set! bv n b) (define-values (wi bi) (quotient/remainder n bits-in-a-word)) (match bv - [(struct bit-vector (words size word-size)) - (define word (fxvector-ref words wi)) + [(struct bit-vector (words size)) + (define word (bytes-ref words wi)) (define bit (bitwise-bit-set? word bi)) (unless (eq? bit b) - (fxvector-set! words wi (bitwise-xor word (expt 2 bi))))])) + (bytes-set! words wi (bitwise-xor word (expt 2 bi))))])) (define (bit-vector-length bv) (bit-vector-size bv)) @@ -87,9 +82,8 @@ (let ([bit-vector-copy (case-lambda [(bv) - (bit-vector (fxvector-copy (bit-vector-words bv)) - (bit-vector-size bv) - (bit-vector-word-size bv))] + (bit-vector (bytes-copy (bit-vector-words bv)) + (bit-vector-size bv))] [(bv start) (bit-vector-copy bv start)] [(bv start end) @@ -97,7 +91,7 @@ bit-vector-copy)) (define (bit-vector-popcount bv) - (for/sum ([fx (in-fxvector (bit-vector-words bv))]) + (for/sum ([fx (in-bytes (bit-vector-words bv))]) (fxpopcount fx))) (define (bit-vector->list bv) @@ -143,10 +137,21 @@ ; A bit vector is represented as a vector of words. ; Each word contains 30 or 62 bits depending on the size of a fixnum. -(struct bit-vector (words size word-size) - ; words is the fxvector of words +(serializable-struct bit-vector (words size) + ; words is the bytes of words ; size is the number of bits in bitvector - ; word-size is the number of words in words + #:guard ;; needed because deserialization doesn't go through contracts + (lambda (words size _name) + (unless (bytes? words) + (raise-argument-error 'bit-vector "bytes?" words)) + (unless (exact-nonnegative-integer? size) + (raise-argument-error 'bit-vector "exact-nonnegative-integer?" size)) + (let-values ([(q r) (quotient/remainder size bits-in-a-word)]) + (unless (and (= (bytes-length words) (+ q (if (zero? r) 0 1))) + ;; make sure "unreachable" bits are unset + (or (zero? r) (< (bytes-ref words q) (expt 2 r)))) + (error 'bit-vector "bit vector data contains wrong number of bits"))) + (values words size)) #:property prop:dict/contract (list (vector-immutable bit-vector-ref bit-vector-set! @@ -167,23 +172,20 @@ (let ([vx (bit-vector-words x)] [vy (bit-vector-words y)] [nx (bit-vector-size x)] - [ny (bit-vector-size y)] - [wsx (bit-vector-word-size x)] - [wsy (bit-vector-word-size y)]) - (and (= nx ny) (= wsx wsy) - (for/and ([index (in-range (- (fxvector-length vx) 1))]) - (eq? (fxvector-ref vx index) - (fxvector-ref vy index))) + [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 ))) (define (hash-code x hc) (let ([v (bit-vector-words x)] - [n (bit-vector-size x)] - [ws (bit-vector-word-size x)]) + [n (bit-vector-size x)]) (bitwise-xor - (hc ws) (hc n) - (for/fold ([h 1]) ([i (in-range (fxvector-length v))]) - (bitwise-xor h (hc (fxvector-ref v i))))))) + (hc n) + (for/fold ([h 1]) ([i (in-range (bytes-length v))]) + (bitwise-xor h (hc (bytes-ref v i))))))) (define hash-proc hash-code) (define hash2-proc hash-code)] #:property prop:sequence in-bit-vector)