recnum.scm 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Mike Sperber
  3. ; Rectangular complex arithmetic built on real arithmetic.
  4. (define-extended-number-type <recnum> (<complex>)
  5. (make-recnum real imag)
  6. recnum?
  7. (real recnum-real-part)
  8. (imag recnum-imag-part))
  9. (define (rectangulate x y) ; Assumes (eq? (exact? x) (exact? y))
  10. (if (= y 0)
  11. x
  12. (make-recnum x y)))
  13. (define (rectangular-real-part z)
  14. (if (recnum? z)
  15. (recnum-real-part z)
  16. (real-part z)))
  17. (define (rectangular-imag-part z)
  18. (if (recnum? z)
  19. (recnum-imag-part z)
  20. (imag-part z)))
  21. (define (rectangular+ a b)
  22. (rectangulate (+ (rectangular-real-part a) (rectangular-real-part b))
  23. (+ (rectangular-imag-part a) (rectangular-imag-part b))))
  24. (define (rectangular- a b)
  25. (rectangulate (- (rectangular-real-part a) (rectangular-real-part b))
  26. (- (rectangular-imag-part a) (rectangular-imag-part b))))
  27. (define (rectangular* a b)
  28. (let ((a1 (rectangular-real-part a))
  29. (a2 (rectangular-imag-part a))
  30. (b1 (rectangular-real-part b))
  31. (b2 (rectangular-imag-part b)))
  32. (rectangulate (- (* a1 b1) (* a2 b2))
  33. (+ (* a1 b2) (* a2 b1)))))
  34. (define (rectangular/ a b)
  35. (let ((a1 (rectangular-real-part a))
  36. (a2 (rectangular-imag-part a))
  37. (b1 (rectangular-real-part b))
  38. (b2 (rectangular-imag-part b)))
  39. (let ((d (+ (* b1 b1) (* b2 b2))))
  40. (rectangulate (/ (+ (* a1 b1) (* a2 b2)) d)
  41. (/ (- (* a2 b1) (* a1 b2)) d)))))
  42. (define (rectangular= a b)
  43. (let ((a1 (rectangular-real-part a))
  44. (a2 (rectangular-imag-part a))
  45. (b1 (rectangular-real-part b))
  46. (b2 (rectangular-imag-part b)))
  47. (and (= a1 b1) (= a2 b2))))
  48. ; Methods
  49. (define-method &complex? ((z <recnum>)) #t)
  50. (define-method &real-part ((z <recnum>)) (recnum-real-part z))
  51. (define-method &imag-part ((z <recnum>)) (recnum-imag-part z))
  52. (define-method &magnitude ((z <recnum>))
  53. (let ((r (recnum-real-part z))
  54. (i (recnum-imag-part z)))
  55. (sqrt (+ (* r r) (* i i)))))
  56. (define-method &angle ((z <recnum>))
  57. (atan (recnum-imag-part z)
  58. (recnum-real-part z)))
  59. ; Methods on complexes in terms of real-part and imag-part
  60. (define-method &exact? ((z <recnum>))
  61. (exact? (recnum-real-part z)))
  62. (define-method &inexact->exact ((z <recnum>))
  63. (make-recnum (inexact->exact (recnum-real-part z))
  64. (inexact->exact (recnum-imag-part z))))
  65. (define-method &exact->inexact ((z <recnum>))
  66. (make-recnum (exact->inexact (recnum-real-part z))
  67. (exact->inexact (recnum-imag-part z))))
  68. (define (define-recnum-method mtable proc)
  69. (define-method mtable ((m <recnum>) (n <complex>)) (proc m n))
  70. (define-method mtable ((m <complex>) (n <recnum>)) (proc m n)))
  71. (define-recnum-method &+ rectangular+)
  72. (define-recnum-method &- rectangular-)
  73. (define-recnum-method &* rectangular*)
  74. (define-recnum-method &/ rectangular/)
  75. (define-recnum-method &= rectangular=)
  76. (define-method &sqrt ((n <real>))
  77. (if (< n 0)
  78. (make-rectangular 0 (sqrt (- 0 n)))
  79. (next-method))) ; not that we have to
  80. (define-method &sqrt ((z <recnum>))
  81. (exp (/ (log z) 2)))
  82. (define plus-i (make-recnum 0 1)) ; we can't read +i yet
  83. (define minus-i (make-recnum 0 -1))
  84. (define-method &exp ((z <recnum>))
  85. (let ((i (imag-part z)))
  86. (* (exp (real-part z))
  87. (+ (cos i) (* plus-i (sin i))))))
  88. (define-method &log ((z <recnum>))
  89. (+ (log (magnitude z)) (* plus-i (angle z))))
  90. (define pi (delay (* 2 (asin 1)))) ; can't compute at build time
  91. (define-method &log ((n <real>))
  92. (if (< n 0)
  93. (make-rectangular (log (- 0 n)) (force pi))
  94. (next-method)))
  95. (define-method &sin ((c <recnum>))
  96. (let ((i-c (* c plus-i)))
  97. (/ (- (exp i-c)
  98. (exp (- 0 i-c)))
  99. (* 2 plus-i))))
  100. (define-method &cos ((c <recnum>))
  101. (let ((i-c (* c plus-i)))
  102. (/ (+ (exp i-c)
  103. (exp (- 0 i-c)))
  104. 2)))
  105. (define-method &tan ((c <recnum>))
  106. (/ (sin c) (cos c)))
  107. (define-method &asin ((c <recnum>))
  108. (* minus-i
  109. (log (+ (* c plus-i)
  110. (sqrt (- 1 (* c c)))))))
  111. (define-method &acos ((c <recnum>))
  112. (* minus-i
  113. (log (+ c
  114. (* plus-i (sqrt (- 1 (* c c))))))))
  115. ; kludge; we can't read floating point yet
  116. (define infinity (delay (expt (exact->inexact 2) (exact->inexact 1500))))
  117. (define-method &atan1 ((c <recnum>))
  118. (if (or (= c plus-i)
  119. (= c minus-i))
  120. (- 0 (force infinity))
  121. (* plus-i
  122. (/ (log (/ (+ plus-i c)
  123. (+ plus-i (- 0 c))))
  124. 2))))
  125. ; Gleep! Can we do quotient and remainder on Gaussian integers?
  126. ; Can we do numerator and denominator on complex rationals?
  127. (define-method &number->string ((z <recnum>) radix)
  128. (let ((x (real-part z))
  129. (y (imag-part z)))
  130. (let ((r (number->string x radix))
  131. (i (number->string (abs y) radix))
  132. (& (if (< y 0) "-" "+")))
  133. (if (and (inexact? y) ;gross
  134. (char=? (string-ref i 0) #\#))
  135. (string-append (if (char=? (string-ref r 0) #\#)
  136. ""
  137. "#i")
  138. r &
  139. (substring i 2 (string-length i))
  140. "i")
  141. (string-append r & i "i")))))
  142. (define-method &make-rectangular ((x <real>) (y <real>))
  143. (if (eq? (exact? x) (exact? y))
  144. (rectangulate x y)
  145. (rectangulate (exact->inexact x) (exact->inexact y))))
  146. (define-method &make-polar ((x <real>) (y <real>))
  147. (rectangulate (* x (cos y)) (* x (sin y))))