integer-op.scm 9.8 KB

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