mask.scm 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Boxed bit-masks.
  3. ; Mask-type operations
  4. ; (make-mask-type name thing? int->thing thing->int size) -> mask-type
  5. ; (mask-type? x) -> boolean
  6. ;
  7. ; Internal operations
  8. ; (mask? x)
  9. ; (mask-type mask)
  10. ; (mask-has-type? mask mask-type)
  11. ; (integer->mask mask-type integer)
  12. ; (list->mask mask-type list)
  13. ;
  14. ; Generic operations
  15. ; (mask->integer mask)
  16. ; (mask->list mask) -> things
  17. ; (mask-member? mask x)
  18. ; (mask-set mask . things)
  19. ; (mask-clear mask . things)
  20. ; (mask-union ...)
  21. ; (mask-intersection ...)
  22. ; (mask-subtract x y)
  23. ; Mask-types
  24. (define-record-type mask-type :mask-type
  25. (make-mask-type name element? integer->element element->integer size)
  26. mask-type?
  27. (name mask-type-name)
  28. (element? mask-type-element?)
  29. (integer->element mask-type-integer->element)
  30. (element->integer mask-type-element->integer)
  31. (size mask-type-size))
  32. (define-record-discloser :mask-type
  33. (lambda (mt)
  34. (list 'mask-type (mask-type-name mt))))
  35. ; Masks - the type and an integer representing the contents.
  36. (define-record-type mask :mask
  37. (make-mask type contents)
  38. mask?
  39. (type mask-type)
  40. (contents mask->integer))
  41. (define-record-discloser :mask
  42. (lambda (m)
  43. (list (mask-type-name (mask-type m))
  44. (string-append "#x"
  45. (number->string (mask->integer m) 16)))))
  46. (define (mask-has-type? mask type)
  47. (if (mask-type? type)
  48. (eq? (mask-type mask)
  49. type)
  50. (call-error "argument is not a mask" mask-has-type? mask type)))
  51. (define (integer->mask type integer)
  52. (if (and (mask-type? type)
  53. (integer? integer)
  54. (<= 0 integer)) ; no infinite masks
  55. (make-mask type integer)
  56. (call-error "argument type error" integer->mask type integer)))
  57. (define (list->mask type things)
  58. (make-mask type (list->integer type things)))
  59. (define (list->integer type things)
  60. (let ((elt->int (mask-type-element->integer type)))
  61. (do ((things things (cdr things))
  62. (m 0 (bitwise-ior m (arithmetic-shift 1 (elt->int (car things))))))
  63. ((null? things)
  64. m))))
  65. ; Return a list of the elements of the mask. This would be faster for bignums
  66. ; if we broke off fixnum-sized chunks.
  67. (define (mask->list mask)
  68. (let ((int->elt (mask-type-integer->element (mask-type mask))))
  69. (do ((mask (mask->integer mask) (arithmetic-shift mask -1))
  70. (i 0 (+ i 1))
  71. (elts '() (if (odd? mask)
  72. (cons (int->elt i) elts)
  73. elts)))
  74. ((= 0 mask)
  75. (reverse elts)))))
  76. ;----------------
  77. ; Operations on masks
  78. (define (mask-member? mask thing)
  79. (not (= 0 (bitwise-and (mask->integer mask)
  80. (arithmetic-shift 1
  81. ((mask-type-element->integer
  82. (mask-type mask))
  83. thing))))))
  84. (define (mask-set mask . things)
  85. (if (null? things)
  86. mask
  87. (make-mask (mask-type mask)
  88. (bitwise-ior (mask->integer mask)
  89. (list->integer (mask-type mask)
  90. things)))))
  91. (define (mask-clear mask . things)
  92. (if (null? things)
  93. mask
  94. (make-mask (mask-type mask)
  95. (bitwise-and (mask->integer mask)
  96. (bitwise-not (list->integer (mask-type mask)
  97. things))))))
  98. ; Union and intersection
  99. (define (mask-union mask . more-masks)
  100. (mask-binop mask more-masks bitwise-ior mask-union))
  101. (define (mask-intersection mask . more-masks)
  102. (mask-binop mask more-masks bitwise-and mask-intersection))
  103. (define (mask-binop mask more-masks bitwise-op mask-op)
  104. (if (and (mask? mask)
  105. (let ((type (mask-type mask)))
  106. (every (lambda (mask)
  107. (and (mask? mask)
  108. (eq? (mask-type mask) type)))
  109. more-masks)))
  110. (make-mask (mask-type mask)
  111. (apply bitwise-op
  112. (mask->integer mask)
  113. (map mask->integer more-masks)))
  114. (apply call-error "argument is not a mask" mask-op mask more-masks)))
  115. ; Subtraction
  116. (define (mask-subtract x y)
  117. (if (and (mask? x)
  118. (mask? y)
  119. (eq? (mask-type x)
  120. (mask-type y)))
  121. (make-mask (mask-type x)
  122. (bitwise-and (mask->integer x)
  123. (bitwise-not (mask->integer y))))
  124. (call-error mask-subtract (list x y))))
  125. ; Negation
  126. ; This is legal only for masks with a size limit.
  127. (define (mask-negate mask)
  128. (if (and (mask? mask)
  129. (mask-type-size (mask-type mask)))
  130. (let ((type (mask-type mask)))
  131. (make-mask type
  132. (bitwise-and (bitwise-not (mask->integer mask))
  133. (- (arithmetic-shift 1 (mask-type-size type))
  134. 1))))
  135. (call-error mask-negate mask)))