use popcount table
This commit is contained in:
parent
139c0ca6c7
commit
a6f03ee38f
|
@ -1,8 +1,9 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require (for-syntax racket/base)
|
(require (for-syntax racket/base)
|
||||||
|
(for-syntax "private/count-bits-in-fixnum.rkt")
|
||||||
racket/private/vector-wraps
|
racket/private/vector-wraps
|
||||||
racket/match
|
racket/match
|
||||||
racket/dict
|
racket/dict
|
||||||
racket/contract/base
|
racket/contract/base
|
||||||
racket/fixnum
|
racket/fixnum
|
||||||
racket/unsafe/ops
|
racket/unsafe/ops
|
||||||
|
@ -90,9 +91,20 @@
|
||||||
(bit-vector-copy bv start end)])])
|
(bit-vector-copy bv start end)])])
|
||||||
bit-vector-copy))
|
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)
|
(define (bit-vector-popcount bv)
|
||||||
(for/sum ([b (in-bytes (bit-vector-words 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 (bit-vector->list bv)
|
||||||
(define len (bit-vector-size bv))
|
(define len (bit-vector-size bv))
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#lang racket/base
|
#lang racket/base
|
||||||
(require racket/unsafe/ops
|
(require racket/unsafe/ops
|
||||||
(for-syntax racket/base racket/fixnum racket/vector))
|
(for-syntax racket/base racket/fixnum))
|
||||||
(provide fxpopcount
|
(provide fxpopcount
|
||||||
unsafe-fxpopcount*)
|
unsafe-fxpopcount*)
|
||||||
;; Count set bits for 30 bit number in 5 steps.
|
;; Count set bits for 30 bit number in 5 steps.
|
||||||
|
@ -43,13 +43,12 @@
|
||||||
(cond [(<= bits 8) lut8]
|
(cond [(<= bits 8) lut8]
|
||||||
[(<= bits 30) lut30]
|
[(<= bits 30) lut30]
|
||||||
[(<= bits 62) lut62]
|
[(<= bits 62) lut62]
|
||||||
[else (raise-syntax-error "bit width too big" stx #'bits0)])]
|
[else (raise-syntax-error "bit width too big" stx #'bits0)])])
|
||||||
[flut (vector-map bitwise-not lut)])
|
|
||||||
;; Unroll the addition loop
|
;; Unroll the addition loop
|
||||||
#`(let ([n expr])
|
#`(let ([n expr])
|
||||||
(let* #,(for/list ([m (in-vector lut)]
|
(let* #,(for/list ([m (in-vector lut)]
|
||||||
[f (in-vector flut)]
|
|
||||||
[b (in-naturals)])
|
[b (in-naturals)])
|
||||||
|
(define f (bitwise-not m))
|
||||||
#`[n (unsafe-fx+ (unsafe-fxrshift (unsafe-fxand n #,m)
|
#`[n (unsafe-fx+ (unsafe-fxrshift (unsafe-fxand n #,m)
|
||||||
#,(fxlshift 1 b))
|
#,(fxlshift 1 b))
|
||||||
(unsafe-fxand n #,f))])
|
(unsafe-fxand n #,f))])
|
||||||
|
|
Loading…
Reference in New Issue
Block a user