bit32.lisp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. (import lua/basic (_G require xpcall))
  2. (import compiler (flag?))
  3. ;;; Sorry for this NIH silliness, the lua/bit32 and luajit/bit
  4. ;;; functions compile into for example bit32.arshift and require('bit').arshift
  5. ;;; which both error if the libraries don't exist.
  6. (define bit32 :hidden (.> _G :bit32))
  7. (define bit :hidden (with ((status ret) (pcall (cut require "bit")))
  8. (when status ret)))
  9. (define u-32 :hidden (expt 2 32))
  10. (defmacro defbitop (name lua-native luajit-native software-docs software-args &software-impl) :hidden
  11. `(define ,name
  12. ,software-docs
  13. (cond
  14. [bit32 (.> bit32 ,lua-native)]
  15. [(and bit (neq? ,luajit-native nil)) (wrap-luajit-bitop (.> bit ,luajit-native))]
  16. [else ,(if (flag? "bit32-no-soft")
  17. `nil
  18. `(lambda ,software-args ,@software-impl))])))
  19. ;;; LuaJIT bitops return 32-bit signed integers, so make them unsigned.
  20. (defun wrap-luajit-bitop (fn) :hidden
  21. (lambda (&args)
  22. (with (result (fn (splice args)))
  23. (if (< result 0)
  24. (+ u-32 result)
  25. result))))
  26. (defun valid-u-32 (n)
  27. "Returns whether the number N is a valid u32 integer.
  28. A number is considered valid when it's an integer between 0 and 2^32-1."
  29. (and (= (math/floor n) n)
  30. (>= n 0)
  31. (< n u-32)))
  32. (defun accumulating-bitop (bit-fn args) :hidden
  33. (desire (all valid-u-32 args) "One or more numbers provided is not a valid u32 integer.")
  34. (with (result (nth args 1))
  35. (for i 2 (n args) 1
  36. (with (new-result 0)
  37. (for j 0 31 1
  38. (let* [(a-bit (math/floor (mod (/ result (expt 2 j)) 2)))
  39. (b-bit (math/floor (mod (/ (nth args i) (expt 2 j)) 2)))
  40. (r-bit (if (bit-fn (= a-bit 1) (= b-bit 1)) 1 0))]
  41. (set! new-result (+ new-result (* r-bit (expt 2 j))))))
  42. (set! result new-result)))
  43. (mod result u-32)))
  44. (defbitop ashr :arshift :arshift
  45. "Returns the arithmetic right shift of X shifted right by DISP.
  46. If DISP is greater than 0 and the leftmost bit is 1, the void gets
  47. filled by 1, otherwise 0."
  48. (x disp)
  49. (desire (valid-u-32 x) "Number must be a valid u32 integer.")
  50. (with (result (shr x disp))
  51. (when (>= disp 0)
  52. (when (> disp 32)
  53. (set! disp 32))
  54. (when (>= (mod x u-32) (expt 2 31))
  55. (for i 1 disp 1
  56. (set! result (+ result (expt 2 (- 32 i)))))))
  57. result))
  58. (defbitop bit-and :band :band
  59. "Returns the bitwise AND of its arguments."
  60. (&args)
  61. (accumulating-bitop -and args))
  62. (defbitop bit-not :bnot :bnot
  63. "Returns the bitwise NOT of X."
  64. (x)
  65. (desire (valid-u-32 x) "Number must be a valid u32 integer.")
  66. (- u-32 (mod x u-32) 1))
  67. (defbitop bit-or :bor :bor
  68. "Returns the bitwise OR of its arguments."
  69. (&args)
  70. (accumulating-bitop -or args))
  71. (defbitop bit-test :btest nil
  72. "Returns true if the bitwise AND of its arguments is not 0."
  73. (&args)
  74. (/= (bit-and (splice args)) 0))
  75. (defbitop bit-xor :bxor :bxor
  76. "Returns the bitwise XOR of its arguments."
  77. (&args)
  78. (accumulating-bitop /= args))
  79. (defbitop bit-extract :extract nil
  80. "Returns the unsigned number formed by splicing the bits FIELD to
  81. FIELD + WIDTH - 1 from X.
  82. Bit 0 is the least significant bit, bit 31 the most.
  83. The default for WIDTH is 1."
  84. (n field (width 1))
  85. (desire (valid-u-32 n) "Number must be a valid u32 integer.")
  86. (math/floor (mod (/ n (expt 2 field)) (expt 2 width))))
  87. (defbitop bit-replace :replace nil
  88. "Returns X with the bits FIELD to FIELD + WIDTH - 1 replaced with
  89. the unsigned number value of V.
  90. Bit 0 is the least significant bit, bit 31 the most.
  91. The default for WIDTH is 1."
  92. (n v field (width 1))
  93. (desire (and (valid-u-32 n) (valid-u-32 v)) "Numbers must be valid u32 integers.")
  94. (let* [(pre (shr (shl n (- 32 field)) (- 32 field)))
  95. (val (shl (mod v (expt 2 width)) field))
  96. (post (shl (shr n (+ field width)) (+ field width)))]
  97. (mod (+ pre val post) u-32)))
  98. (defbitop bit-rotl :lrotate :rol
  99. "Returns X rotated left by DISP."
  100. (x disp)
  101. (desire (valid-u-32 x) "Number must be a valid u32 integer.")
  102. (with (disp-32 (mod disp 32))
  103. (+ (shl x disp-32) (shr x (- 32 disp-32)))))
  104. (defbitop bit-rotr :rrotate :ror
  105. "Returns X rotated right by DISP."
  106. (x disp)
  107. (bit-rotl x (- 0 disp)))
  108. (defbitop shl :lshift :lshift
  109. "Returns X shifted left by DISP."
  110. (x disp)
  111. (desire (valid-u-32 x) "Number must be a valid u32 integer.")
  112. (if (>= disp 0)
  113. (mod (* x (expt 2 disp)) u-32)
  114. (mod (math/floor (* x (expt 2 disp))) u-32)))
  115. (defbitop shr :rshift :rshift
  116. "Returns X shifted right by DISP."
  117. (x disp)
  118. (shl x (- 0 disp)))