xnum.scm 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361
  1. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  2. ; This is file xnum.scm.
  3. ;;;; Extended number support
  4. (define-simple-type :extended-number (:number) extended-number?)
  5. (define-record-type extended-number-type :extended-number-type
  6. (really-make-extended-number-type field-names supers priority predicate id)
  7. extended-number-type?
  8. (field-names extended-number-type-field-names)
  9. (supers extended-number-type-supers)
  10. (priority extended-number-type-priority)
  11. (predicate extended-number-predicate)
  12. (id extended-number-type-identity))
  13. (define-record-discloser :extended-number-type
  14. (lambda (e-n-t)
  15. (list 'extended-number-type (extended-number-type-identity e-n-t))))
  16. (define (make-extended-number-type field-names supers id)
  17. (letrec ((t (really-make-extended-number-type
  18. field-names
  19. supers
  20. (+ (apply max
  21. (map type-priority
  22. (cons :extended-number supers)))
  23. 10)
  24. (lambda (x)
  25. (and (extended-number? x)
  26. (eq? (extended-number-type x) t)))
  27. id)))
  28. t))
  29. (define (extended-number-type x) (extended-number-ref x 0))
  30. ; DEFINE-EXTENDED-NUMBER-TYPE macro
  31. (define-syntax define-extended-number-type
  32. (syntax-rules ()
  33. ((define-extended-number-type ?type (?super ...)
  34. (?constructor ?arg1 ?arg ...)
  35. ?predicate
  36. (?field ?accessor)
  37. ...)
  38. (begin (define ?type
  39. (make-extended-number-type '(?field ...)
  40. (list ?super ...)
  41. '?type))
  42. (define ?constructor
  43. (let ((args '(?arg1 ?arg ...)))
  44. (if (equal? args
  45. (extended-number-type-field-names ?type))
  46. (let ((k (+ (length args) 1)))
  47. (lambda (?arg1 ?arg ...)
  48. (let ((n (make-extended-number k #f))
  49. (i 1))
  50. (extended-number-set! n 0 ?type)
  51. (extended-number-set! n 1 ?arg1)
  52. (begin (set! i (+ i 1))
  53. (extended-number-set! n i ?arg))
  54. ...
  55. n)))
  56. (error "ill-formed DEFINE-EXTENDED-NUMBER-TYPE" '?type))))
  57. (define (?predicate x)
  58. (and (extended-number? x)
  59. (eq? (extended-number-type x) ?type)))
  60. (define-extended-number-accessors ?accessor ...)))))
  61. (define-syntax define-extended-number-accessors
  62. (syntax-rules ()
  63. ((define-extended-number-accessors ?accessor)
  64. (define (?accessor n) (extended-number-ref n 1)))
  65. ((define-extended-number-accessors ?accessor1 ?accessor2)
  66. (begin (define (?accessor1 n) (extended-number-ref n 1))
  67. (define (?accessor2 n) (extended-number-ref n 2))))
  68. ((define-extended-number-accessors ?accessor1 ?accessor2 ?accessor3)
  69. (begin (define (?accessor1 n) (extended-number-ref n 1))
  70. (define (?accessor2 n) (extended-number-ref n 2))
  71. (define (?accessor3 n) (extended-number-ref n 3))))))
  72. (define-method &type-priority ((t :extended-number-type))
  73. (extended-number-type-priority t))
  74. (define-method &type-predicate ((t :extended-number-type))
  75. (extended-number-predicate t))
  76. ; Make all the numeric instructions be extensible.
  77. (define (make-opcode-generic! opcode mtable)
  78. (let ((perform (method-table-get-perform mtable)))
  79. (extend-opcode! opcode
  80. (lambda (lose)
  81. (set-final-method! mtable
  82. (lambda (next-method . args)
  83. (apply lose args)))
  84. (lambda args
  85. ((perform) args))))))
  86. (define-syntax define-opcode-extension
  87. (syntax-rules ()
  88. ((define-opcode-extension ?name ?table-name)
  89. (begin (define ?table-name (make-method-table '?name))
  90. (make-opcode-generic! (enum op ?name) ?table-name)))))
  91. (define-opcode-extension + &+)
  92. (define-opcode-extension - &-)
  93. (define-opcode-extension * &*)
  94. (define-opcode-extension / &/)
  95. (define-opcode-extension = &=)
  96. (define-opcode-extension < &<)
  97. (define-opcode-extension quotient &quotient)
  98. (define-opcode-extension remainder &remainder)
  99. (define-opcode-extension integer? &integer?)
  100. (define-opcode-extension rational? &rational?)
  101. (define-opcode-extension real? &real?)
  102. (define-opcode-extension complex? &complex?)
  103. (define-opcode-extension number? &number?)
  104. (define-opcode-extension exact? &exact?)
  105. (define-opcode-extension exact->inexact &exact->inexact)
  106. (define-opcode-extension inexact->exact &inexact->exact)
  107. (define-opcode-extension real-part &real-part)
  108. (define-opcode-extension imag-part &imag-part)
  109. (define-opcode-extension angle &angle)
  110. (define-opcode-extension magnitude &magnitude)
  111. (define-opcode-extension floor &floor)
  112. (define-opcode-extension numerator &numerator)
  113. (define-opcode-extension denominator &denominator)
  114. (define-opcode-extension make-rectangular &make-rectangular)
  115. (define-opcode-extension exp &exp)
  116. (define-opcode-extension log &log)
  117. (define-opcode-extension sin &sin)
  118. (define-opcode-extension cos &cos)
  119. (define-opcode-extension tan &tan)
  120. (define-opcode-extension asin &asin)
  121. (define-opcode-extension acos &acos)
  122. (define-opcode-extension atan1 &atan1)
  123. (define-opcode-extension atan2 &atan2)
  124. (define-opcode-extension sqrt &sqrt)
  125. ; >, <=, and >= are all extended using the table for <.
  126. (let ((perform (method-table-get-perform &<)))
  127. (extend-opcode! (enum op >)
  128. (lambda (lose)
  129. (lambda (x y)
  130. ((perform) (list y x)))))
  131. (extend-opcode! (enum op <=)
  132. (lambda (lose)
  133. (lambda (x y)
  134. (not ((perform) (list y x))))))
  135. (extend-opcode! (enum op >=)
  136. (lambda (lose)
  137. (lambda (x y)
  138. (not ((perform) (list x y)))))))
  139. ; Default methods.
  140. (define-method &integer? (x) #f)
  141. (define-method &rational? (x) (integer? x))
  142. (define-method &real? (x) (rational? x))
  143. (define-method &complex? (x) (real? x))
  144. (define-method &number? (x) (complex? x))
  145. (define-method &real-part ((x :real)) x)
  146. (define-method &imag-part ((x :real))
  147. (if (exact? x) 0 (exact->inexact 0)))
  148. (define-method &magnitude ((x :real))
  149. (abs x))
  150. (define pi (delay (* 2 (asin 1)))) ; can't compute at build time
  151. (define-method &angle ((x :real))
  152. (cond
  153. ((positive? x)
  154. (if (exact? x)
  155. 0
  156. (exact->inexact 0)))
  157. ((negative? x) (force pi))
  158. ((exact? x) (call-error "invalid argument to angle" angle x))
  159. (else x)))
  160. (define-method &floor ((n :integer)) n)
  161. (define-method &numerator ((n :integer)) n)
  162. (define-method &denominator ((n :integer))
  163. (if (exact? n) 1 (exact->inexact 1)))
  164. ; Make sure this has very low priority, so that it's only tried as a
  165. ; last resort.
  166. (define-method &/ (m n)
  167. (if (and (integer? m) (integer? n))
  168. (if (= 0 (remainder m n))
  169. (quotient m n)
  170. (let ((z (abs (quotient n 2))))
  171. (set-exactness (quotient (if (< m 0)
  172. (- m z)
  173. (+ m z))
  174. n)
  175. #f)))
  176. (next-method)))
  177. (define-method &sqrt (n)
  178. (if (and (integer? n)
  179. (>= n 0))
  180. (non-negative-integer-sqrt n)
  181. (next-method)))
  182. (define (non-negative-integer-sqrt n)
  183. (cond ((<= n 1) ; for both 0 and 1
  184. n)
  185. ;; ((< n 0)
  186. ;; (make-rectangular 0 (integer-sqrt (- 0 n))))
  187. (else
  188. (let loop ((m (quotient n 2)))
  189. (let ((m1 (quotient n m)))
  190. (cond ((< m1 m)
  191. (loop (quotient (+ m m1) 2)))
  192. ((= n (* m m))
  193. m)
  194. ((exact? m)
  195. (exact->inexact m))
  196. (else m)))))))
  197. (define-simple-type :exact (:number)
  198. (lambda (n) (and (number? n) (exact? n))))
  199. (define-method &inexact->exact ((n :exact)) n)
  200. (define-simple-type :inexact (:number)
  201. (lambda (n) (and (number? n) (inexact? n))))
  202. (define-method &exact->inexact ((n :inexact)) n)
  203. ; Whattakludge.
  204. ; Replace the default method (which in the initial image always returns #f).
  205. (define-method &really-string->number (s radix xact?)
  206. (let ((len (string-length s)))
  207. (cond ((<= len 1) #f)
  208. ((char=? (string-ref s (- len 1)) #\i)
  209. (parse-rectangular s radix xact?))
  210. ((string-position #\@ s)
  211. => (lambda (at)
  212. (let ((r (really-string->number (substring s 0 at)
  213. radix xact?))
  214. (theta (really-string->number (substring s (+ at 1) len)
  215. radix xact?)))
  216. (if (and (real? r) (real? theta))
  217. (make-polar r theta)))))
  218. ((string-position #\/ s)
  219. => (lambda (slash)
  220. (let ((m (string->integer (substring s 0 slash) radix))
  221. (n (string->integer (substring s (+ slash 1) len)
  222. radix)))
  223. (if (and m n (not (zero? n)))
  224. (set-exactness (/ m n) xact?)
  225. #f))))
  226. ((string-position #\# s)
  227. (if xact?
  228. #f
  229. (really-string->number
  230. (list->string (map (lambda (c) (if (char=? c #\#) #\5 c))
  231. (string->list s)))
  232. radix
  233. xact?)))
  234. ((and (= radix 10)
  235. (string-position #\e s))
  236. => (lambda (e)
  237. (parse-with-exponent s xact? e)))
  238. ((string-position #\. s)
  239. => (lambda (dot)
  240. (parse-decimal s radix xact? dot)))
  241. (else #f))))
  242. (define (parse-decimal s radix xact? dot)
  243. ;; Talk about kludges. This is REALLY kludgey.
  244. (let* ((len (string-length s))
  245. (j (if (or (char=? (string-ref s 0) #\+)
  246. (char=? (string-ref s 0) #\-))
  247. 1
  248. 0))
  249. (m (if (= dot j)
  250. 0
  251. (string->integer (substring s j dot)
  252. radix)))
  253. (n (if (= dot (- len 1))
  254. 0
  255. (string->integer (substring s (+ dot 1) len)
  256. radix))))
  257. (if (and m n)
  258. (let ((n (+ m (/ n (expt radix
  259. (- len (+ dot 1)))))))
  260. (set-exactness (if (char=? (string-ref s 0) #\-)
  261. (- 0 n)
  262. n)
  263. xact?))
  264. #f)))
  265. (define (parse-with-exponent s xact? e)
  266. (let ((len (string-length s)))
  267. (cond
  268. ((string->integer (substring s (+ e 1) len) 10)
  269. => (lambda (exp)
  270. (cond
  271. ((really-string->number (substring s 0 e) 10 xact?)
  272. => (lambda (significand)
  273. (* significand
  274. (expt 10 exp))))
  275. (else #f))))
  276. (else #f))))
  277. (define (parse-rectangular s radix xact?)
  278. (let ((len (string-length s)))
  279. (let loop ((i (- len 2)))
  280. (if (< i 0)
  281. #f
  282. (let ((c (string-ref s i)))
  283. (if (or (char=? c #\+)
  284. (char=? c #\-))
  285. (let ((x (if (= i 0)
  286. 0
  287. (really-string->number (substring s 0 i)
  288. radix xact?)))
  289. (y (if (= i (- len 2))
  290. (if (char=? c #\+) 1 -1)
  291. (really-string->number (substring s i (- len 1))
  292. radix xact?))))
  293. (if (and (real? x) (real? y))
  294. (make-rectangular x y)
  295. #f))
  296. (loop (- i 1))))))))
  297. (define (set-exactness n xact?)
  298. (if (exact? n)
  299. (if xact? n (exact->inexact n))
  300. ;; ?what to do? (if xact? (inexact->exact n) n)
  301. n))
  302. ; Utility
  303. (define (string-position c s)
  304. (let loop ((i 0))
  305. (if (>= i (string-length s))
  306. #f
  307. (if (char=? c (string-ref s i))
  308. i
  309. (loop (+ i 1))))))