fixnums.scm 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. ;;; fixnums.scm --- The R6RS fixnums arithmetic library
  2. ;; Copyright (C) 2010, 2011, 2013 Free Software Foundation, Inc.
  3. ;;
  4. ;; This library is free software; you can redistribute it and/or
  5. ;; modify it under the terms of the GNU Lesser General Public
  6. ;; License as published by the Free Software Foundation; either
  7. ;; version 3 of the License, or (at your option) any later version.
  8. ;;
  9. ;; This library is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;; Lesser General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU Lesser General Public
  15. ;; License along with this library; if not, write to the Free Software
  16. ;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. (library (rnrs arithmetic fixnums (6))
  18. (export fixnum?
  19. fixnum-width
  20. least-fixnum
  21. greatest-fixnum
  22. fx=?
  23. fx>?
  24. fx<?
  25. fx>=?
  26. fx<=?
  27. fxzero?
  28. fxpositive?
  29. fxnegative?
  30. fxodd?
  31. fxeven?
  32. fxmax
  33. fxmin
  34. fx+
  35. fx*
  36. fx-
  37. fxdiv-and-mod
  38. fxdiv
  39. fxmod
  40. fxdiv0-and-mod0
  41. fxdiv0
  42. fxmod0
  43. fx+/carry
  44. fx-/carry
  45. fx*/carry
  46. fxnot
  47. fxand
  48. fxior
  49. fxxor
  50. fxif
  51. fxbit-count
  52. fxlength
  53. fxfirst-bit-set
  54. fxbit-set?
  55. fxcopy-bit
  56. fxbit-field
  57. fxcopy-bit-field
  58. fxarithmetic-shift
  59. fxarithmetic-shift-left
  60. fxarithmetic-shift-right
  61. fxrotate-bit-field
  62. fxreverse-bit-field)
  63. (import (only (guile) ash
  64. cons*
  65. define-inlinable
  66. inexact->exact
  67. logand
  68. logbit?
  69. logcount
  70. logior
  71. lognot
  72. logxor
  73. most-positive-fixnum
  74. most-negative-fixnum
  75. object-address)
  76. (ice-9 optargs)
  77. (rnrs base (6))
  78. (rnrs control (6))
  79. (rnrs arithmetic bitwise (6))
  80. (rnrs conditions (6))
  81. (rnrs exceptions (6))
  82. (rnrs lists (6)))
  83. (define fixnum-width
  84. (let ((w (do ((i 0 (+ 1 i))
  85. (n 1 (* 2 n)))
  86. ((> n most-positive-fixnum)
  87. (+ 1 i)))))
  88. (lambda () w)))
  89. (define (greatest-fixnum) most-positive-fixnum)
  90. (define (least-fixnum) most-negative-fixnum)
  91. (define (fixnum? obj)
  92. (not (= 0 (logand 2 (object-address obj)))))
  93. (define-inlinable (inline-fixnum? obj)
  94. (not (= 0 (logand 2 (object-address obj)))))
  95. (define-syntax assert-fixnum
  96. (syntax-rules ()
  97. ((_ arg ...)
  98. (or (and (inline-fixnum? arg) ...)
  99. (raise (make-assertion-violation))))))
  100. (define (assert-fixnums args)
  101. (or (for-all inline-fixnum? args) (raise (make-assertion-violation))))
  102. (define-syntax define-fxop*
  103. (syntax-rules ()
  104. ((_ name op)
  105. (define name
  106. (case-lambda
  107. ((x y)
  108. (assert-fixnum x y)
  109. (op x y))
  110. (args
  111. (assert-fixnums args)
  112. (apply op args)))))))
  113. ;; All these predicates don't check their arguments for fixnum-ness,
  114. ;; as this doesn't seem to be strictly required by R6RS.
  115. (define fx=? =)
  116. (define fx>? >)
  117. (define fx<? <)
  118. (define fx>=? >=)
  119. (define fx<=? <=)
  120. (define fxzero? zero?)
  121. (define fxpositive? positive?)
  122. (define fxnegative? negative?)
  123. (define fxodd? odd?)
  124. (define fxeven? even?)
  125. (define-fxop* fxmax max)
  126. (define-fxop* fxmin min)
  127. (define (fx+ fx1 fx2)
  128. (assert-fixnum fx1 fx2)
  129. (let ((r (+ fx1 fx2)))
  130. (or (inline-fixnum? r)
  131. (raise (make-implementation-restriction-violation)))
  132. r))
  133. (define (fx* fx1 fx2)
  134. (assert-fixnum fx1 fx2)
  135. (let ((r (* fx1 fx2)))
  136. (or (inline-fixnum? r)
  137. (raise (make-implementation-restriction-violation)))
  138. r))
  139. (define* (fx- fx1 #:optional fx2)
  140. (assert-fixnum fx1)
  141. (if fx2
  142. (begin
  143. (assert-fixnum fx2)
  144. (let ((r (- fx1 fx2)))
  145. (or (inline-fixnum? r) (raise (make-assertion-violation)))
  146. r))
  147. (let ((r (- fx1)))
  148. (or (inline-fixnum? r) (raise (make-assertion-violation)))
  149. r)))
  150. (define (fxdiv fx1 fx2)
  151. (assert-fixnum fx1 fx2)
  152. (div fx1 fx2))
  153. (define (fxmod fx1 fx2)
  154. (assert-fixnum fx1 fx2)
  155. (mod fx1 fx2))
  156. (define (fxdiv-and-mod fx1 fx2)
  157. (assert-fixnum fx1 fx2)
  158. (div-and-mod fx1 fx2))
  159. (define (fxdiv0 fx1 fx2)
  160. (assert-fixnum fx1 fx2)
  161. (div0 fx1 fx2))
  162. (define (fxmod0 fx1 fx2)
  163. (assert-fixnum fx1 fx2)
  164. (mod0 fx1 fx2))
  165. (define (fxdiv0-and-mod0 fx1 fx2)
  166. (assert-fixnum fx1 fx2)
  167. (div0-and-mod0 fx1 fx2))
  168. (define (fx+/carry fx1 fx2 fx3)
  169. (assert-fixnum fx1 fx2 fx3)
  170. (let* ((s (+ fx1 fx2 fx3))
  171. (s0 (mod0 s (expt 2 (fixnum-width))))
  172. (s1 (div0 s (expt 2 (fixnum-width)))))
  173. (values s0 s1)))
  174. (define (fx-/carry fx1 fx2 fx3)
  175. (assert-fixnum fx1 fx2 fx3)
  176. (let* ((d (- fx1 fx2 fx3))
  177. (d0 (mod0 d (expt 2 (fixnum-width))))
  178. (d1 (div0 d (expt 2 (fixnum-width)))))
  179. (values d0 d1)))
  180. (define (fx*/carry fx1 fx2 fx3)
  181. (assert-fixnum fx1 fx2 fx3)
  182. (let* ((s (+ (* fx1 fx2) fx3))
  183. (s0 (mod0 s (expt 2 (fixnum-width))))
  184. (s1 (div0 s (expt 2 (fixnum-width)))))
  185. (values s0 s1)))
  186. (define (fxnot fx) (assert-fixnum fx) (lognot fx))
  187. (define-fxop* fxand logand)
  188. (define-fxop* fxior logior)
  189. (define-fxop* fxxor logxor)
  190. (define (fxif fx1 fx2 fx3)
  191. (assert-fixnum fx1 fx2 fx3)
  192. (bitwise-if fx1 fx2 fx3))
  193. (define (fxbit-count fx)
  194. (assert-fixnum fx)
  195. (if (negative? fx)
  196. (bitwise-not (logcount fx))
  197. (logcount fx)))
  198. (define (fxlength fx) (assert-fixnum fx) (bitwise-length fx))
  199. (define (fxfirst-bit-set fx) (assert-fixnum fx) (bitwise-first-bit-set fx))
  200. (define (fxbit-set? fx1 fx2) (assert-fixnum fx1 fx2) (logbit? fx2 fx1))
  201. (define (fxcopy-bit fx1 fx2 fx3)
  202. (assert-fixnum fx1 fx2 fx3)
  203. (bitwise-copy-bit fx1 fx2 fx3))
  204. (define (fxbit-field fx1 fx2 fx3)
  205. (assert-fixnum fx1 fx2 fx3)
  206. (bitwise-bit-field fx1 fx2 fx3))
  207. (define (fxcopy-bit-field fx1 fx2 fx3 fx4)
  208. (assert-fixnum fx1 fx2 fx3 fx4)
  209. (bitwise-copy-bit-field fx1 fx2 fx3 fx4))
  210. (define (fxarithmetic-shift fx1 fx2) (assert-fixnum fx1 fx2) (ash fx1 fx2))
  211. (define fxarithmetic-shift-left fxarithmetic-shift)
  212. (define (fxarithmetic-shift-right fx1 fx2)
  213. (assert-fixnum fx1 fx2) (ash fx1 (- fx2)))
  214. (define (fxrotate-bit-field fx1 fx2 fx3 fx4)
  215. (assert-fixnum fx1 fx2 fx3 fx4)
  216. (bitwise-rotate-bit-field fx1 fx2 fx3 fx4))
  217. (define (fxreverse-bit-field fx1 fx2 fx3)
  218. (assert-fixnum fx1 fx2 fx3)
  219. (bitwise-reverse-bit-field fx1 fx2 fx3))
  220. )