use popcount table
This commit is contained in:
parent
139c0ca6c7
commit
a6f03ee38f
|
@ -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))
|
||||
|
|
|
@ -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))])
|
||||
|
|
Loading…
Reference in New Issue
Block a user