183 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Scheme
		
	
	
	
			
		
		
	
	
			183 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			Scheme
		
	
	
	
| (define-library (srfi 60)
 | |
|   (import (scheme base)
 | |
|           (srfi 1))
 | |
| 
 | |
|   ;; # Bitwise Operations
 | |
|   (define (logand . args)
 | |
|     (letrec ((lgand
 | |
|               (lambda (x y)
 | |
|                 (if (or (zero? x) (zero? y))
 | |
|                     0
 | |
|                     (+ (* (lgand (floor/ x 2) (floor/ y 2)) 2)
 | |
|                        (if (or (even? x) (even? y)) 0 1))))))
 | |
|       (fold lgand -1 args)))
 | |
| 
 | |
|   (define bitwise-and logand)
 | |
| 
 | |
|   (define (logior . args)
 | |
|     (letrec ((lgior
 | |
|               (lambda (x y)
 | |
|                 (cond
 | |
|                  ((= x y) x)
 | |
|                  ((zero? x) y)
 | |
|                  ((zero? y) x)
 | |
|                  (else
 | |
|                   (+ (* (lgior (truncate-quotient x 2)
 | |
|                                (truncate-quotient y 2))
 | |
|                         2)
 | |
|                      (if (and (even? x) (even? y)) 0 1)))))))
 | |
|       (fold lgior 0 args)))
 | |
| 
 | |
|   (define bitwise-ior logior)
 | |
| 
 | |
|   (define (logxor . args)
 | |
|     (letrec ((lgxor
 | |
|               (lambda (x y)
 | |
|                 (cond
 | |
|                  ((zero? x) y)
 | |
|                  ((zero? y) x)
 | |
|                  (else
 | |
|                   (+ (* (lgxor (floor/ x 2) (floor/ y 2)) 2)
 | |
|                      (if (even? x)
 | |
|                          (if (even? y) 0 1)
 | |
|                          (if (even? y) 1 0))))))))
 | |
|       (fold lgxor 0 args)))
 | |
| 
 | |
|   (define bitwise-xor logxor)
 | |
| 
 | |
|   (define (lognot n)
 | |
|     (- -1 n))
 | |
| 
 | |
|   (define bitwise-not lognot)
 | |
| 
 | |
|   (define (bitwise-if mask n0 n1)
 | |
|     (logior (logand mask n0)
 | |
|             (logand (lognot mask) n1)))
 | |
| 
 | |
|   (define bitwise-merge bitwise-if)
 | |
| 
 | |
|   (define (logtest j k)
 | |
|     (not (zero? (logand j k))))
 | |
| 
 | |
|   (define any-bits-set? logtest)
 | |
| 
 | |
|   ;; # Integer Properties
 | |
|   (define (logcount n)
 | |
|     (letrec ((lgcnt
 | |
|               (lambda (n)
 | |
|                 (if (zero? n) 0
 | |
|                     (+ (lgcnt (floor/ n 2))
 | |
|                        (if (even? n) 0 1))))))
 | |
|       (if (negative? n)
 | |
|           (lgcnt (lognot n))
 | |
|           (lgcnt n))))
 | |
| 
 | |
|   (define bit-count logcount)
 | |
| 
 | |
|   (define (integer-length n)
 | |
|     (let loop ((n n) (count 0))
 | |
|       (if (zero? n)
 | |
|           count
 | |
|           (loop (floor/ n 2) (+ count 1)))))
 | |
| 
 | |
|   (define (log2-binary-factors n)
 | |
|     (+ -1 (integer-length (logand n (- n)))))
 | |
| 
 | |
|   (define first-set-bit log2-binary-factors)
 | |
|   
 | |
|   ;; # Bit Within Word
 | |
|   (define (logbit? index n)
 | |
|     (logtest (expt 2 index) n))
 | |
| 
 | |
|   (define bit-set? logbit?)
 | |
| 
 | |
|   (define (copy-bit index from bit)
 | |
|     (if bit
 | |
|         (logior from (expt 2 index))
 | |
|         (logand from (lognot (expt 2 index)))))
 | |
| 
 | |
| 
 | |
|   ;; # Field of Bits
 | |
|   (define (ash n count)
 | |
|     (if (negative? count)
 | |
|         (let ((k (expt 2 (- count))))
 | |
|           (if (negative? n)
 | |
|               (+ -1 (truncate-quotient (+ 1 n) k))
 | |
|               (truncate-quotient n k)))
 | |
|         (* (expt 2 count) n)))
 | |
| 
 | |
|   (define arithmetic-shift ash)
 | |
| 
 | |
|   (define (bit-field n start end)
 | |
|     (logand (lognot (ash -1 (- end start)))
 | |
|             (ash n (- start))))
 | |
| 
 | |
|   (define (copy-bit-field to from start end)
 | |
|     (bitwise-if (ash (lognot (ash -1 (- end start))) start)
 | |
|                 (ash from start)
 | |
|                 to))
 | |
| 
 | |
|   (define (rotate-bit-field n count start end)
 | |
|     (let* ((width (- start end))
 | |
|            (count (floor-remainder count width))
 | |
|            (mask (lognot (ash -1 width)))
 | |
|            (zn (logand mask (ash n (- start)))))
 | |
|       (logior (ash (logior (logand mask (ash zn count))
 | |
|                            (ash zn (- count width)))
 | |
|                    start)
 | |
|               (logand (lognot (ash mask start)) n))))
 | |
| 
 | |
|   (define (reverse-bit-field n start end)
 | |
|     (letrec ((bit-reverse
 | |
|               (lambda (k n)
 | |
|                 (let loop ((m (if (negative? n) (lognot n) n))
 | |
|                            (k (- k 1))
 | |
|                            (rvs 0))
 | |
|                   (if (negative? k)
 | |
|                       (if (negative? n) (lognot rvs) rvs)
 | |
|                       (loop (ash m -1)
 | |
|                             (- k 1)
 | |
|                             (logior (ash rvs 1) (logand 1 m))))))))
 | |
|       (let* ((width (- start end))
 | |
|              (mask (lognot (ash -1 width)))
 | |
|              (zn (logand mask (ash n (- start)))))
 | |
|         (logior (ash (bit-reverse width zn) start)
 | |
|                 (logand (lognot (ash mask start)) n)))))
 | |
| 
 | |
|   ;; Bits as Booleans
 | |
|   (define (integer->list k . len)
 | |
|     (let ((len (if (null? len) (integer-length k) len)))
 | |
|       (let loop ((k k) (len len) (acc '()))
 | |
|         (if (or (zero? k) (zero? len))
 | |
|             acc
 | |
|             (loop (floor/ k 2) (- len 1) (cons (if (even? k) #f #t) acc))))))
 | |
| 
 | |
|   (define (list->integer lst)
 | |
|     (let loop ((lst lst) (acc 0))
 | |
|       (if (null? lst)
 | |
|           acc
 | |
|           (loop (cdr lst) (+ (* acc 2) (if (car lst) 1 0))))))
 | |
| 
 | |
|   (define (booleans->integer . args)
 | |
|     (list->integer args))
 | |
| 
 | |
|   (export logand bitwise-and
 | |
|           logior bitwise-ior
 | |
|           logxor bitwise-xor
 | |
|           lognot bitwise-not
 | |
|           bitwise-if bitwise-merge
 | |
|           logtest any-bits-set?
 | |
|           logcount bit-count
 | |
|           integer-length
 | |
|           log2-binary-factors first-set-bit
 | |
|           logbit? bit-set?
 | |
|           copy-bit
 | |
|           bit-field
 | |
|           copy-bit-field
 | |
|           ash arithmetic-shift
 | |
|           rotate-bit-field
 | |
|           reverse-bit-field
 | |
|           integer->list
 | |
|           list->integer
 | |
|           booleans->integer))
 |