srfi-60.scm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. ;; Implementation of SRFI 60 "Integers as Bits" for Scheme 48, based on
  2. ;; reference implementation.
  3. ;; Copyright (C) 2005 David Van Horn
  4. ;; Released under the same terms as the SRFI reference implementation
  5. ;; included below.
  6. ;; SRFI 60 defines several procedures which are already provided
  7. ;; by Scheme48's bitwise structure, namely bit-count,
  8. ;; bitwise-{ior,xor,and,not}, and arithmetic-shift, which are used
  9. ;; for the implementation of this library, and exported by this
  10. ;; structure.
  11. (define logior bitwise-ior)
  12. (define logxor bitwise-xor)
  13. (define logand bitwise-and)
  14. (define lognot bitwise-not)
  15. (define logcount bit-count)
  16. ;; The reference implementation follows below and has been changed only
  17. ;; by adding S-expression comments to definitions which are not needed,
  18. ;; such as definitions implemented as Scheme 48 exact integer primitives.
  19. ;;;; "logical.scm", bit access and operations for integers for Scheme
  20. ;;; Copyright (C) 1991, 1993, 2001, 2003, 2005 Aubrey Jaffer
  21. ;
  22. ;Permission to copy this software, to modify it, to redistribute it,
  23. ;to distribute modified versions, and to use it for any purpose is
  24. ;granted, subject to the following restrictions and understandings.
  25. ;
  26. ;1. Any copy made of this software must include this copyright notice
  27. ;in full.
  28. ;
  29. ;2. I have made no warranty or representation that the operation of
  30. ;this software will be error-free, and I am under no obligation to
  31. ;provide any services, by way of maintenance, update, or otherwise.
  32. ;
  33. ;3. In conjunction with products arising from the use of this
  34. ;material, there shall be no use of my name in any advertising,
  35. ;promotional, or sales literature without prior written consent in
  36. ;each case.
  37. ; (define logical:boole-xor
  38. ; '#(#(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)
  39. ; #(1 0 3 2 5 4 7 6 9 8 11 10 13 12 15 14)
  40. ; #(2 3 0 1 6 7 4 5 10 11 8 9 14 15 12 13)
  41. ; #(3 2 1 0 7 6 5 4 11 10 9 8 15 14 13 12)
  42. ; #(4 5 6 7 0 1 2 3 12 13 14 15 8 9 10 11)
  43. ; #(5 4 7 6 1 0 3 2 13 12 15 14 9 8 11 10)
  44. ; #(6 7 4 5 2 3 0 1 14 15 12 13 10 11 8 9)
  45. ; #(7 6 5 4 3 2 1 0 15 14 13 12 11 10 9 8)
  46. ; #(8 9 10 11 12 13 14 15 0 1 2 3 4 5 6 7)
  47. ; #(9 8 11 10 13 12 15 14 1 0 3 2 5 4 7 6)
  48. ; #(10 11 8 9 14 15 12 13 2 3 0 1 6 7 4 5)
  49. ; #(11 10 9 8 15 14 13 12 3 2 1 0 7 6 5 4)
  50. ; #(12 13 14 15 8 9 10 11 4 5 6 7 0 1 2 3)
  51. ; #(13 12 15 14 9 8 11 10 5 4 7 6 1 0 3 2)
  52. ; #(14 15 12 13 10 11 8 9 6 7 4 5 2 3 0 1)
  53. ; #(15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0)))
  54. ;
  55. ; (define logical:boole-and
  56. ; '#(#(0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0)
  57. ; #(0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1)
  58. ; #(0 0 2 2 0 0 2 2 0 0 2 2 0 0 2 2)
  59. ; #(0 1 2 3 0 1 2 3 0 1 2 3 0 1 2 3)
  60. ; #(0 0 0 0 4 4 4 4 0 0 0 0 4 4 4 4)
  61. ; #(0 1 0 1 4 5 4 5 0 1 0 1 4 5 4 5)
  62. ; #(0 0 2 2 4 4 6 6 0 0 2 2 4 4 6 6)
  63. ; #(0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7)
  64. ; #(0 0 0 0 0 0 0 0 8 8 8 8 8 8 8 8)
  65. ; #(0 1 0 1 0 1 0 1 8 9 8 9 8 9 8 9)
  66. ; #(0 0 2 2 0 0 2 2 8 8 10 10 8 8 10 10)
  67. ; #(0 1 2 3 0 1 2 3 8 9 10 11 8 9 10 11)
  68. ; #(0 0 0 0 4 4 4 4 8 8 8 8 12 12 12 12)
  69. ; #(0 1 0 1 4 5 4 5 8 9 8 9 12 13 12 13)
  70. ; #(0 0 2 2 4 4 6 6 8 8 10 10 12 12 14 14)
  71. ; #(0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15)))
  72. (define (logical:ash-4 x)
  73. (if (negative? x)
  74. (+ -1 (quotient (+ 1 x) 16))
  75. (quotient x 16)))
  76. ; (define (logical:reduce op4 ident)
  77. ; (lambda args
  78. ; (do ((res ident (op4 res (car rgs) 1 0))
  79. ; (rgs args (cdr rgs)))
  80. ; ((null? rgs) res))))
  81. ;
  82. ; (define logand
  83. ; (letrec
  84. ; ((lgand
  85. ; (lambda (n2 n1 scl acc)
  86. ; (cond ((= n1 n2) (+ acc (* scl n1)))
  87. ; ((zero? n2) acc)
  88. ; ((zero? n1) acc)
  89. ; (else (lgand (logical:ash-4 n2)
  90. ; (logical:ash-4 n1)
  91. ; (* 16 scl)
  92. ; (+ (* (vector-ref (vector-ref logical:boole-and
  93. ; (modulo n1 16))
  94. ; (modulo n2 16))
  95. ; scl)
  96. ; acc)))))))
  97. ; (logical:reduce lgand -1)))
  98. ;
  99. ; (define logior
  100. ; (letrec
  101. ; ((lgior
  102. ; (lambda (n2 n1 scl acc)
  103. ; (cond ((= n1 n2) (+ acc (* scl n1)))
  104. ; ((zero? n2) (+ acc (* scl n1)))
  105. ; ((zero? n1) (+ acc (* scl n2)))
  106. ; (else (lgior (logical:ash-4 n2)
  107. ; (logical:ash-4 n1)
  108. ; (* 16 scl)
  109. ; (+ (* (- 15 (vector-ref
  110. ; (vector-ref logical:boole-and
  111. ; (- 15 (modulo n1 16)))
  112. ; (- 15 (modulo n2 16))))
  113. ; scl)
  114. ; acc)))))))
  115. ; (logical:reduce lgior 0)))
  116. ;
  117. ; (define logxor
  118. ; (letrec
  119. ; ((lgxor
  120. ; (lambda (n2 n1 scl acc)
  121. ; (cond ((= n1 n2) acc)
  122. ; ((zero? n2) (+ acc (* scl n1)))
  123. ; ((zero? n1) (+ acc (* scl n2)))
  124. ; (else (lgxor (logical:ash-4 n2)
  125. ; (logical:ash-4 n1)
  126. ; (* 16 scl)
  127. ; (+ (* (vector-ref (vector-ref logical:boole-xor
  128. ; (modulo n1 16))
  129. ; (modulo n2 16))
  130. ; scl)
  131. ; acc)))))))
  132. ; (logical:reduce lgxor 0)))
  133. ;
  134. ; (define (lognot n) (- -1 n))
  135. (define (logtest n1 n2)
  136. (not (zero? (logand n1 n2))))
  137. (define (logbit? index n)
  138. (logtest (expt 2 index) n))
  139. (define (copy-bit index to bool)
  140. (if bool
  141. (logior to (arithmetic-shift 1 index))
  142. (logand to (lognot (arithmetic-shift 1 index)))))
  143. (define (bitwise-if mask n0 n1)
  144. (logior (logand mask n0)
  145. (logand (lognot mask) n1)))
  146. (define (bit-field n start end)
  147. (logand (lognot (ash -1 (- end start)))
  148. (arithmetic-shift n (- start))))
  149. (define (copy-bit-field to from start end)
  150. (bitwise-if (arithmetic-shift (lognot (ash -1 (- end start))) start)
  151. (arithmetic-shift from start)
  152. to))
  153. (define (rotate-bit-field n count start end)
  154. (define width (- end start))
  155. (set! count (modulo count width))
  156. (let ((mask (lognot (ash -1 width))))
  157. (define zn (logand mask (arithmetic-shift n (- start))))
  158. (logior (arithmetic-shift
  159. (logior (logand mask (arithmetic-shift zn count))
  160. (arithmetic-shift zn (- count width)))
  161. start)
  162. (logand (lognot (ash mask start)) n))))
  163. ; (define (arithmetic-shift n count)
  164. ; (if (negative? count)
  165. ; (let ((k (expt 2 (- count))))
  166. ; (if (negative? n)
  167. ; (+ -1 (quotient (+ 1 n) k))
  168. ; (quotient n k)))
  169. ; (* (expt 2 count) n)))
  170. (define integer-length
  171. (letrec ((intlen (lambda (n tot)
  172. (case n
  173. ((0 -1) (+ 0 tot))
  174. ((1 -2) (+ 1 tot))
  175. ((2 3 -3 -4) (+ 2 tot))
  176. ((4 5 6 7 -5 -6 -7 -8) (+ 3 tot))
  177. (else (intlen (logical:ash-4 n) (+ 4 tot)))))))
  178. (lambda (n) (intlen n 0))))
  179. ; (define logcount
  180. ; (letrec ((logcnt (lambda (n tot)
  181. ; (if (zero? n)
  182. ; tot
  183. ; (logcnt (quotient n 16)
  184. ; (+ (vector-ref
  185. ; '#(0 1 1 2 1 2 2 3 1 2 2 3 2 3 3 4)
  186. ; (modulo n 16))
  187. ; tot))))))
  188. ; (lambda (n)
  189. ; (cond ((negative? n) (logcnt (lognot n) 0))
  190. ; ((positive? n) (logcnt n 0))
  191. ; (else 0)))))
  192. (define (log2-binary-factors n)
  193. (+ -1 (integer-length (logand n (- n)))))
  194. (define (bit-reverse k n)
  195. (do ((m (if (negative? n) (lognot n) n) (arithmetic-shift m -1))
  196. (k (+ -1 k) (+ -1 k))
  197. (rvs 0 (logior (arithmetic-shift rvs 1) (logand 1 m))))
  198. ((negative? k) (if (negative? n) (lognot rvs) rvs))))
  199. (define (reverse-bit-field n start end)
  200. (define width (- end start))
  201. (let ((mask (lognot (ash -1 width))))
  202. (define zn (logand mask (arithmetic-shift n (- start))))
  203. (logior (arithmetic-shift (bit-reverse width zn) start)
  204. (logand (lognot (ash mask start)) n))))
  205. (define (integer->list k . len)
  206. (if (null? len)
  207. (do ((k k (arithmetic-shift k -1))
  208. (lst '() (cons (odd? k) lst)))
  209. ((<= k 0) lst))
  210. (do ((idx (+ -1 (car len)) (+ -1 idx))
  211. (k k (arithmetic-shift k -1))
  212. (lst '() (cons (odd? k) lst)))
  213. ((negative? idx) lst))))
  214. (define (list->integer bools)
  215. (do ((bs bools (cdr bs))
  216. (acc 0 (+ acc acc (if (car bs) 1 0))))
  217. ((null? bs) acc)))
  218. (define (booleans->integer . bools)
  219. (list->integer bools))
  220. ;;;; SRFI-60 aliases
  221. (define ash arithmetic-shift)
  222. ; (define bitwise-ior logior)
  223. ; (define bitwise-xor logxor)
  224. ; (define bitwise-and logand)
  225. ; (define bitwise-not lognot)
  226. ; (define bit-count logcount)
  227. (define bit-set? logbit?)
  228. (define any-bits-set? logtest)
  229. (define first-set-bit log2-binary-factors)
  230. (define bitwise-merge bitwise-if)
  231. ;;; Legacy
  232. ;;(define (logical:rotate k count len) (rotate-bit-field k count 0 len))
  233. ;;(define (logical:ones deg) (lognot (ash -1 deg)))
  234. ;;(define integer-expt expt) ; legacy name