* Added bitwise-bit-count
This commit is contained in:
parent
a0ba3d3d4f
commit
a3f1feefb9
|
@ -2837,43 +2837,80 @@
|
|||
(error 'fldiv0-and-mod0 "not a flonum" n))))
|
||||
|
||||
(library (ikarus bitwise misc)
|
||||
(export bitwise-first-bit-set)
|
||||
(export bitwise-first-bit-set
|
||||
bitwise-bit-count)
|
||||
(import
|
||||
(ikarus system $fx)
|
||||
(ikarus system $bignums)
|
||||
(except (ikarus) bitwise-first-bit-set))
|
||||
(except (ikarus)
|
||||
bitwise-first-bit-set
|
||||
bitwise-bit-count))
|
||||
|
||||
(module (bitwise-first-bit-set)
|
||||
(define (bitwise-first-bit-set x)
|
||||
(define (byte-first-bit-set x i)
|
||||
(case ($fxlogand x #b11)
|
||||
[(0) (byte-first-bit-set ($fxsra x 2) ($fx+ i 2))]
|
||||
[(2) ($fx+ i 1)]
|
||||
[else i]))
|
||||
|
||||
(define (fx-first-bit-set x i)
|
||||
(let ([y ($fxlogand x 255)])
|
||||
(if ($fx= y 0)
|
||||
(fx-first-bit-set ($fxsra x 8) ($fx+ i 8))
|
||||
(byte-first-bit-set y i))))
|
||||
|
||||
(define (bn-first-bit-set x i idx)
|
||||
(let ([b ($bignum-byte-ref x idx)])
|
||||
(if ($fxzero? b)
|
||||
(bn-first-bit-set x ($fx+ i 8) ($fx+ idx 1))
|
||||
(byte-first-bit-set b i))))
|
||||
|
||||
(define (bitwise-first-bit-set x)
|
||||
(cond
|
||||
[(fixnum? x)
|
||||
(if ($fx> x 0)
|
||||
(fx-first-bit-set x 0)
|
||||
(if ($fx= x 0)
|
||||
-1
|
||||
(if ($fx> x (least-fixnum))
|
||||
(fx-first-bit-set ($fx- 0 x) 0)
|
||||
(bn-first-bit-set (- x) 0 0))))]
|
||||
[(bignum? x) (bn-first-bit-set x 0 0)]
|
||||
[else (error 'bitwise-first-bit-set "not an exact integer" x)])))
|
||||
(cond
|
||||
[(fixnum? x)
|
||||
(if ($fx> x 0)
|
||||
(fx-first-bit-set x 0)
|
||||
(if ($fx= x 0)
|
||||
-1
|
||||
(if ($fx> x (least-fixnum))
|
||||
(fx-first-bit-set ($fx- 0 x) 0)
|
||||
(bn-first-bit-set (- x) 0 0))))]
|
||||
[(bignum? x) (bn-first-bit-set x 0 0)]
|
||||
[else (error 'bitwise-first-bit-set "not an exact integer" x)]))
|
||||
|
||||
(define (bitwise-bit-count n)
|
||||
(define (pos-fxbitcount n)
|
||||
;;; nifty parrallel count from:
|
||||
;;; http://infolab.stanford.edu/~manku/bitcount/bitcount.html
|
||||
(let ([m0 #x15555555]
|
||||
[m1 #x13333333]
|
||||
[m2 #x0f0f0f0f])
|
||||
(let* ([n ($fx+ ($fxlogand n m0) ($fxlogand ($fxsra n 1) m0))]
|
||||
[n ($fx+ ($fxlogand n m1) ($fxlogand ($fxsra n 2) m1))]
|
||||
[n ($fx+ ($fxlogand n m2) ($fxlogand ($fxsra n 4) m2))])
|
||||
($fxmodulo n 255))))
|
||||
(define (fxbitcount n)
|
||||
(if ($fx< n 0)
|
||||
(fxlognot (pos-fxbitcount (fxlognot n)))
|
||||
(pos-fxbitcount n)))
|
||||
(define (bnbitcount n)
|
||||
(define (poscount x idx c)
|
||||
(let ([c (+ c
|
||||
($fx+ (pos-fxbitcount
|
||||
($fxlogor
|
||||
($fxsll ($bignum-byte-ref x ($fx+ idx 3)) 8)
|
||||
($bignum-byte-ref x ($fx+ idx 2))))
|
||||
(pos-fxbitcount
|
||||
($fxlogor
|
||||
($fxsll ($bignum-byte-ref x ($fxadd1 idx)) 8)
|
||||
($bignum-byte-ref x idx)))))])
|
||||
(if ($fx= idx 0)
|
||||
c
|
||||
(poscount x ($fx- idx 4) c))))
|
||||
(if ($bignum-positive? n)
|
||||
(poscount n ($fx- ($bignum-size n) 4) 0)
|
||||
(let ([n (bitwise-not n)])
|
||||
(bitwise-not (poscount n ($fx- ($bignum-size n) 4) 0)))))
|
||||
(cond
|
||||
[(fixnum? n) (fxbitcount n)]
|
||||
[(bignum? n) (bnbitcount n)]
|
||||
[else (error 'bitwise-bit-count "not an exact integer" n)]))
|
||||
|
||||
)
|
||||
|
||||
|
|
|
@ -756,7 +756,7 @@
|
|||
[bitwise-and i r bw]
|
||||
[bitwise-ior r bw]
|
||||
[bitwise-xor r bw]
|
||||
[bitwise-bit-count r bw]
|
||||
[bitwise-bit-count i r bw]
|
||||
[bitwise-bit-field r bw]
|
||||
[bitwise-bit-set? r bw]
|
||||
[bitwise-copy-bit r bw]
|
||||
|
|
|
@ -63,4 +63,5 @@
|
|||
(test-fldiv0-and-mod0)
|
||||
(test-fxdiv-and-mod)
|
||||
(test-fxdiv0-and-mod0)
|
||||
(test-bitwise-bit-count)
|
||||
(printf "Happy Happy Joy Joy\n")
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
(library (tests bignums)
|
||||
(export test-bignums test-bignum-conversion)
|
||||
(export test-bignums test-bignum-conversion test-bitwise-bit-count)
|
||||
(import (ikarus) (tests framework))
|
||||
|
||||
(define (test-bignum-conversion)
|
||||
|
@ -19,6 +19,30 @@
|
|||
(test -39487932748923498234))
|
||||
|
||||
|
||||
(define (test-bitwise-bit-count)
|
||||
(define (test n)
|
||||
(define (pos-count-bits n)
|
||||
(if (zero? n)
|
||||
0
|
||||
(let ([c (count-bits (bitwise-arithmetic-shift-right n 1))])
|
||||
(if (even? n) c (+ c 1)))))
|
||||
(define (count-bits n)
|
||||
(if (>= n 0)
|
||||
(pos-count-bits n)
|
||||
(bitwise-not (pos-count-bits (bitwise-not n)))))
|
||||
(let ([bc0 (bitwise-bit-count n)]
|
||||
[bc1 (count-bits n)])
|
||||
(unless (= bc0 bc1)
|
||||
(error 'test-bitcount "failed/expected/got" n bc1 bc0))))
|
||||
(define (test-fx n)
|
||||
(when (fixnum? n)
|
||||
(when (zero? (fxlogand n #x7FFFFFF))
|
||||
(printf "bitwise-bit-count ~s\n" n))
|
||||
(test n)
|
||||
(test-fx (+ n 512))))
|
||||
(test-fx (least-fixnum))
|
||||
(test 28472347823493290482390849023840928390482309480923840923840983)
|
||||
(test -847234234903290482390849023840928390482309480923840923840983))
|
||||
|
||||
(define-tests test-bignums
|
||||
; first, some simple quotients
|
||||
|
|
|
@ -258,7 +258,7 @@
|
|||
[bitwise-and C bw]
|
||||
[bitwise-ior S bw]
|
||||
[bitwise-xor S bw]
|
||||
[bitwise-bit-count S bw]
|
||||
[bitwise-bit-count C bw]
|
||||
[bitwise-bit-field S bw]
|
||||
[bitwise-bit-set? S bw]
|
||||
[bitwise-copy-bit S bw]
|
||||
|
|
Loading…
Reference in New Issue