integer-op.scm 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; Integer-only primitive operations
  3. ; These predicates are used to characterize the numeric representations that
  4. ; are implemented in the VM.
  5. (define (unary-lose x)
  6. (raise-exception wrong-type-argument 0 x))
  7. (define (binary-lose x y)
  8. (raise-exception wrong-type-argument 0 x y))
  9. ; They're all numbers, even if we can't handle them.
  10. (define-primitive number? (any->)
  11. (lambda (x)
  12. (or (fixnum? x)
  13. (bignum? x)
  14. (ratnum? x)
  15. (double? x)
  16. (extended-number? x)))
  17. return-boolean)
  18. (define (integer? n)
  19. (or (fixnum? n)
  20. (bignum? n)))
  21. (define (vm-integer? n)
  22. (cond ((integer? n)
  23. (goto return-boolean #t))
  24. ((extended-number? n)
  25. (unary-lose n))
  26. (else
  27. (goto return-boolean #f))))
  28. (define-primitive integer? (any->)
  29. (lambda (n)
  30. (cond ((or (fixnum? n)
  31. (bignum? n))
  32. (goto return-boolean #t))
  33. ((or (extended-number? n)
  34. (double? n))
  35. (unary-lose n))
  36. (else
  37. (goto return-boolean #f)))))
  38. (define vm-number-predicate
  39. (lambda (n)
  40. (cond ((or (fixnum? n)
  41. (bignum? n)
  42. (ratnum? n)
  43. (double? n))
  44. (goto return-boolean #t))
  45. ((extended-number? n)
  46. (unary-lose n))
  47. (else
  48. (goto return-boolean #f)))))
  49. (define-primitive rational? (any->) vm-number-predicate)
  50. (define-primitive real? (any->) vm-number-predicate)
  51. (define-primitive complex? (any->) vm-number-predicate)
  52. ; These assume that ratnums and doubles aren't being used.
  53. ;(define-primitive integer? (any->) vm-integer?)
  54. ;(define-primitive rational? (any->) vm-integer?)
  55. ;(define-primitive real? (any->) vm-integer?)
  56. ;(define-primitive complex? (any->) vm-integer?)
  57. ;----------------
  58. ; A macro for defining primitives that only operate on integers.
  59. (define-syntax define-integer-only
  60. (syntax-rules ()
  61. ((define-integer-only (opcode arg) value)
  62. (define-integer-only (opcode arg) (any->) value))
  63. ((define-integer-only (opcode arg0 arg1) value)
  64. (define-integer-only (opcode arg0 arg1) (any-> any->) value))
  65. ((define-integer-only (opcode arg ...) specs value)
  66. (define-primitive opcode specs
  67. (lambda (arg ...)
  68. (if (and (integer? arg) ...)
  69. (goto return value)
  70. (raise-exception wrong-type-argument 0 arg ...)))))))
  71. ; These primitives have a simple answer in the case of integers; for all others
  72. ; they punt to the run-time system.
  73. (define-integer-only (exact? n) true)
  74. (define-integer-only (real-part n) n)
  75. (define-integer-only (imag-part n) (enter-fixnum 0))
  76. (define-integer-only (floor n) n)
  77. (define-integer-only (numerator n) n)
  78. (define-integer-only (denominator n) (enter-fixnum 1))
  79. (define-primitive angle (vm-integer->)
  80. (lambda (n)
  81. (if (if (fixnum? n)
  82. (fixnum> n (enter-fixnum 0))
  83. (bignum-nonnegative? n))
  84. (goto return (enter-fixnum 0))
  85. (unary-lose n))))
  86. (define-primitive magnitude (vm-integer->)
  87. (lambda (x)
  88. (if (fixnum? x)
  89. (goto return-integer (abs (extract-fixnum x)))
  90. (goto return (integer-abs x)))))
  91. ; These all just raise an exception and let the run-time system do the work.
  92. (define-syntax define-punter
  93. (syntax-rules ()
  94. ((define-punter opcode)
  95. (define-primitive opcode (any->) unary-lose))))
  96. (define-punter exact->inexact)
  97. (define-punter inexact->exact)
  98. (define-punter exp)
  99. (define-punter log)
  100. (define-punter sin)
  101. (define-punter cos)
  102. (define-punter tan)
  103. (define-punter asin)
  104. (define-punter acos)
  105. (define-punter sqrt)
  106. (define-syntax define-punter2
  107. (syntax-rules ()
  108. ((define-punter2 opcode)
  109. (define-primitive opcode (any-> any->) binary-lose))))
  110. (define-punter atan1)
  111. (define-punter2 atan2)
  112. (define-punter2 make-polar)
  113. (define-punter2 make-rectangular)
  114. (define-syntax define-fixnum-or-integer
  115. (syntax-rules ()
  116. ((define-fixnum-or-integer (opcode arg) fixnum-val integer-val)
  117. (define-fixnum-or-integer (opcode arg)
  118. (any->)
  119. fixnum-val integer-val))
  120. ((define-fixnum-or-integer (opcode arg0 arg1) fixnum-val integer-val)
  121. (define-fixnum-or-integer (opcode arg0 arg1)
  122. (any-> any->)
  123. fixnum-val integer-val))
  124. ((define-fixnum-or-integer (opcode arg ...) specs fixnum-val integer-val)
  125. (define-primitive opcode specs
  126. (lambda (arg ...)
  127. (if (and (fixnum? arg) ...)
  128. (goto return fixnum-val)
  129. (if (and (integer? arg) ...)
  130. (goto return integer-val)
  131. (raise-exception wrong-type-argument 0 arg ...))))))))
  132. (define-syntax define-fixnum-or-integer-or-float
  133. (syntax-rules ()
  134. ((define-fixnum-or-integer (opcode arg) fixnum-val integer-val float-val)
  135. (define-fixnum-or-integer (opcode arg) (any->)
  136. fixnum-val integer-val float-val))
  137. ((define-fixnum-or-integer-or-float (opcode arg0 arg1)
  138. fixnum-val integer-val float-val)
  139. (define-fixnum-or-integer-or-float (opcode arg0 arg1)
  140. (any-> any->)
  141. fixnum-val integer-val float-val))
  142. ((define-fixnum-or-integer-or-float (opcode arg ...) specs
  143. fixnum-val integer-val float-val)
  144. (define-primitive opcode specs
  145. (lambda (arg ...)
  146. (cond ((and (fixnum? arg) ...)
  147. (goto return fixnum-val))
  148. ((and (integer? arg) ...)
  149. (goto return integer-val))
  150. ((and (double? arg) ...)
  151. (goto return float-val))
  152. (else
  153. (raise-exception wrong-type-argument 0 arg ...))))))))
  154. (define-fixnum-or-integer-or-float (+ x y)
  155. (enter-integer (+ (extract-fixnum x)
  156. (extract-fixnum y))
  157. (ensure-space long-as-integer-size))
  158. (integer-add x y)
  159. (flonum-add x y))
  160. (define-fixnum-or-integer-or-float (- x y)
  161. (enter-integer (- (extract-fixnum x)
  162. (extract-fixnum y))
  163. (ensure-space long-as-integer-size))
  164. (integer-subtract x y)
  165. (flonum-subtract x y))
  166. (define (return-integer x)
  167. (goto return (enter-integer x (ensure-space long-as-integer-size))))
  168. (define-primitive * (any-> any->)
  169. (lambda (x y)
  170. (cond ((and (fixnum? x) (fixnum? y))
  171. (goto multiply-carefully x y
  172. return-integer
  173. (lambda (x y)
  174. (goto return (integer-multiply x y)))))
  175. ((and (integer? x) (integer? y))
  176. (goto return (integer-multiply x y)))
  177. ((and (double? x) (double? y))
  178. (goto return (flonum-multiply x y)))
  179. (else
  180. (binary-lose x y)))))
  181. ;----------------------------------------------------------------
  182. ; division and friends
  183. (define-primitive / (any-> any->)
  184. (lambda (x y)
  185. (cond ((= y (enter-fixnum 0))
  186. (binary-lose x y))
  187. ((and (fixnum? x)
  188. (fixnum? y))
  189. (divide-carefully x y return-integer
  190. binary-lose))
  191. ((and (integer? x)
  192. (integer? y))
  193. (call-with-values
  194. (lambda ()
  195. (integer-divide x y))
  196. (lambda (div-by-zero? quot rem x y)
  197. (if (and (not div-by-zero?)
  198. (fixnum? rem)
  199. (= (enter-fixnum 0) rem))
  200. (goto return quot)
  201. (binary-lose x y)))))
  202. ((and (double? x) (double? y))
  203. (goto return (flonum-divide x y)))
  204. (else
  205. (binary-lose x y)))))
  206. (define (divide-action fixnum-op integer-op)
  207. (lambda (x y)
  208. (cond ((= y (enter-fixnum 0))
  209. (binary-lose x y))
  210. ((and (fixnum? x)
  211. (fixnum? y))
  212. (fixnum-op x
  213. y
  214. return
  215. (lambda (x y)
  216. (goto return (integer-op x y)))))
  217. ((and (integer? x)
  218. (integer? y))
  219. (goto return
  220. (integer-op x y)))
  221. (else
  222. (binary-lose x y)))))
  223. (let ((action (divide-action quotient-carefully integer-quotient)))
  224. (define-primitive quotient (any-> any->) action))
  225. (let ((action (divide-action remainder-carefully integer-remainder)))
  226. (define-primitive remainder (any-> any->) action))
  227. ;----------------------------------------------------------------
  228. ; comparisons
  229. (define-syntax define-comparison
  230. (syntax-rules ()
  231. ((define-comparison op fixnum integer float)
  232. (define-fixnum-or-integer-or-float (op x y)
  233. (enter-boolean (fixnum x y))
  234. (enter-boolean (integer x y))
  235. (enter-boolean (float x y))))))
  236. (define-comparison = fixnum= integer= flonum=)
  237. (define-comparison < fixnum< integer< flonum<)
  238. (define-comparison > fixnum> integer> flonum>)
  239. (define-comparison <= fixnum<= integer<= flonum<=)
  240. (define-comparison >= fixnum>= integer>= flonum>=)
  241. ;----------------------------------------------------------------
  242. ; bitwise operations
  243. ; Shifting left by a bignum number of bits loses; shifting right gives 0 or
  244. ; -1 depending on the sign of the first argument.
  245. (define-primitive arithmetic-shift (any-> any->)
  246. (lambda (x y)
  247. (cond ((bignum? y)
  248. (goto shift-by-bignum x y))
  249. ((not (fixnum? y))
  250. (binary-lose x y))
  251. ((fixnum? x)
  252. (goto shift-carefully x y return-integer
  253. (lambda (x y)
  254. (goto return (integer-arithmetic-shift x y)))))
  255. ((bignum? x)
  256. (goto return (integer-arithmetic-shift x y)))
  257. (else
  258. (binary-lose x y)))))
  259. (define (shift-by-bignum x y)
  260. (cond ((bignum-positive? y)
  261. (raise-exception arithmetic-overflow 0 x y))
  262. ((fixnum? x)
  263. (goto return
  264. (if (fixnum<= (enter-fixnum 0)
  265. x)
  266. (enter-fixnum 0)
  267. (enter-fixnum -1))))
  268. ((bignum? x)
  269. (goto return
  270. (if (bignum-positive? x)
  271. (enter-fixnum 0)
  272. (enter-fixnum -1))))
  273. (else
  274. (raise-exception arithmetic-overflow 0 x y))))
  275. (define-fixnum-or-integer (bitwise-not x)
  276. (fixnum-bitwise-not x)
  277. (integer-bitwise-not x))
  278. (define-fixnum-or-integer (bit-count x)
  279. (fixnum-bit-count x)
  280. (integer-bit-count x))
  281. (define-fixnum-or-integer (bitwise-and x y)
  282. (fixnum-bitwise-and x y)
  283. (integer-bitwise-and x y))
  284. (define-fixnum-or-integer (bitwise-ior x y)
  285. (fixnum-bitwise-ior x y)
  286. (integer-bitwise-ior x y))
  287. (define-fixnum-or-integer (bitwise-xor x y)
  288. (fixnum-bitwise-xor x y)
  289. (integer-bitwise-xor x y))