xnum.scm 11 KB

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