use popcount table

This commit is contained in:
Ryan Culpepper 2012-12-18 09:44:22 -05:00
parent 139c0ca6c7
commit a6f03ee38f
2 changed files with 17 additions and 6 deletions

View File

@ -1,8 +1,9 @@
#lang racket/base
(require (for-syntax racket/base)
(for-syntax "private/count-bits-in-fixnum.rkt")
racket/private/vector-wraps
racket/match
racket/dict
racket/dict
racket/contract/base
racket/fixnum
racket/unsafe/ops
@ -90,9 +91,20 @@
(bit-vector-copy bv start end)])])
bit-vector-copy))
(define popcount-table
(let ()
(define-syntax (make-table stx)
(with-syntax ([(elt ...)
(for/list ([i (in-range 256)])
(fxpopcount i))])
;; Literal immutable vector allocated once (?)
#'(quote #(elt ...))))
(make-table)))
(define (bit-vector-popcount bv)
(for/sum ([b (in-bytes (bit-vector-words bv))])
(unsafe-fxpopcount* b 8)))
#| (unsafe-fxpopcount* b 8) |#
(unsafe-vector-ref popcount-table b)))
(define (bit-vector->list bv)
(define len (bit-vector-size bv))

View File

@ -1,6 +1,6 @@
#lang racket/base
(require racket/unsafe/ops
(for-syntax racket/base racket/fixnum racket/vector))
(for-syntax racket/base racket/fixnum))
(provide fxpopcount
unsafe-fxpopcount*)
;; Count set bits for 30 bit number in 5 steps.
@ -43,13 +43,12 @@
(cond [(<= bits 8) lut8]
[(<= bits 30) lut30]
[(<= bits 62) lut62]
[else (raise-syntax-error "bit width too big" stx #'bits0)])]
[flut (vector-map bitwise-not lut)])
[else (raise-syntax-error "bit width too big" stx #'bits0)])])
;; Unroll the addition loop
#`(let ([n expr])
(let* #,(for/list ([m (in-vector lut)]
[f (in-vector flut)]
[b (in-naturals)])
(define f (bitwise-not m))
#`[n (unsafe-fx+ (unsafe-fxrshift (unsafe-fxand n #,m)
#,(fxlshift 1 b))
(unsafe-fxand n #,f))])