elliptic.scm 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. #| -*-Scheme-*-
  2. Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994,
  3. 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
  4. 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Massachusetts
  5. Institute of Technology
  6. This file is part of MIT/GNU Scheme.
  7. MIT/GNU Scheme is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or (at
  10. your option) any later version.
  11. MIT/GNU Scheme is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with MIT/GNU Scheme; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301,
  18. USA.
  19. |#
  20. ;;; Elliptic functions from Press
  21. (declare (usual-integrations))
  22. (define Carlson-elliptic-1
  23. (let ((eps (expt *machine-epsilon* 1/6))
  24. (C1 (/ 1. 24.))
  25. (C2 0.1)
  26. (C3 (/ 3. 44.))
  27. (C4 (/ 1. 14.)))
  28. (define (rf x y z)
  29. (let loop ((x x) (y y) (z z))
  30. (let ((sqrtx (sqrt x))
  31. (sqrty (sqrt y))
  32. (sqrtz (sqrt z)))
  33. (let ((alamb (+ (* sqrtx (+ sqrty sqrtz)) (* sqrty sqrtz))))
  34. (let ((xp (* 0.25 (+ x alamb)))
  35. (yp (* 0.25 (+ y alamb)))
  36. (zp (* 0.25 (+ z alamb))))
  37. (let ((ave (/ (+ xp yp zp) 3.)))
  38. (let ((delx (/ (- ave xp) ave))
  39. (dely (/ (- ave yp) ave))
  40. (delz (/ (- ave zp) ave)))
  41. (let ((error (max (abs delx) (abs dely) (abs delz))))
  42. (if (> error eps)
  43. (loop xp yp zp)
  44. (let ((e2 (- (* delx dely) (* delz delz)))
  45. (e3 (* delx dely delz)))
  46. (/ (+ 1.
  47. (* (- (* C1 e2)
  48. (+ C2 (* C3 e3))) e2)
  49. (* C4 e3))
  50. (sqrt ave))))))))))))
  51. rf))
  52. (define Carlson-elliptic-1-simple
  53. (let ((eps (sqrt *machine-epsilon*)))
  54. (define (rf1 x y z)
  55. (let ((av (/ (+ x y z) 3.0)))
  56. (if (< (max (abs (/ (- x av) av))
  57. (abs (/ (- y av) av))
  58. (abs (/ (- z av) av)))
  59. eps)
  60. (/ 1.0 (sqrt av))
  61. (let ((lamb
  62. (+ (sqrt (* x y))
  63. (sqrt (* x z))
  64. (sqrt (* y z)))))
  65. (rf1 (/ (+ x lamb) 4.0)
  66. (/ (+ y lamb) 4.0)
  67. (/ (+ z lamb) 4.0))))))
  68. rf1))
  69. (define Carlson-elliptic-2
  70. (let* ((eps (sqrt *machine-epsilon*))
  71. (C1 (/ -3. 14.)) ; opposite Press
  72. (C2 (/ 1. 6.))
  73. (C3 (/ -9. 22.)) ; opposite Press
  74. (C4 (/ 3. 26.))
  75. (C5 (* 0.25 C3))
  76. (C6 (* -1.5 C4)) ; opposite Press
  77. )
  78. (define (rd x y z)
  79. (let loop ((x x) (y y) (z z) (sum 0.) (fac 1.))
  80. (let ((sqrtx (sqrt x))
  81. (sqrty (sqrt y))
  82. (sqrtz (sqrt z)))
  83. (let ((alamb (+ (* sqrtx (+ sqrty sqrtz)) (* sqrty sqrtz))))
  84. (let ((sump (+ sum (/ fac (* sqrtz (+ z alamb)))))
  85. (facp (* 0.25 fac)))
  86. (let ((xp (* 0.25 (+ x alamb)))
  87. (yp (* 0.25 (+ y alamb)))
  88. (zp (* 0.25 (+ z alamb))))
  89. (let ((ave (* 0.2 (+ xp yp (* 3. zp)))))
  90. (let ((delx (/ (- ave xp) ave))
  91. (dely (/ (- ave yp) ave))
  92. (delz (/ (- ave zp) ave)))
  93. (if (> (max (abs delx) (abs dely) (abs delz)) eps)
  94. (loop xp yp zp sump facp)
  95. (let* ((ea (* delx dely))
  96. (eb (* delz delz))
  97. (ec (- ea eb))
  98. (ed (- ea (* 6. eb)))
  99. (ee (+ ed ec ec)))
  100. (+ (* 3. sump)
  101. (/ (* facp
  102. (+ (+ 1. (* ed (+ C1 (* C5 ed) (* C6 delz ee))))
  103. (* delz (+ (* C2 ee) (* delz (+ (* C3 ec) (* delz C4 ea)))))))
  104. (* ave (sqrt ave))))))))))))))
  105. rd))
  106. (define (elliptic-integral-F phi k)
  107. (let ((s (sin phi)))
  108. (* s (Carlson-elliptic-1 (square (cos phi))
  109. (* (- 1. (* s k)) (+ 1. (* s k)))
  110. 1.))))
  111. (define (complete-elliptic-integral-K k)
  112. (elliptic-integral-F pi/2 k))
  113. (define (elliptic-integral-E phi k)
  114. (let ((s (sin phi))
  115. (cc (square (cos phi))))
  116. (let ((q (* (- 1. (* s k)) (+ 1. (* s k)))))
  117. (* s (- (Carlson-elliptic-1 cc q 1.)
  118. (* (square (* s k))
  119. (/ (Carlson-elliptic-2 cc q 1.) 3.)))))))
  120. (define (complete-elliptic-integral-E k)
  121. (elliptic-integral-E pi/2 k))
  122. ;;; older definition of the complete elliptic integrals
  123. ;;; probably from A&Stegun
  124. (define (elliptic-integrals k continue) ; (continue K E)
  125. (if (= k 1)
  126. (continue :+infinity 1.)
  127. (let loop ((a 1.0)
  128. (b (sqrt (- 1.0 (square k))))
  129. (c k)
  130. (d 0.0)
  131. (powers-2 1.0))
  132. (if (< (abs c) *machine-epsilon*)
  133. (let ((first-elliptic-integral (/ pi/2 a)))
  134. (continue first-elliptic-integral
  135. (* first-elliptic-integral
  136. (- 1.0 (/ d 2.0)))))
  137. (loop (/ (+ a b) 2.0)
  138. (sqrt (* a b))
  139. (/ (- a b) 2.0)
  140. (+ d (* (square c) powers-2))
  141. (* powers-2 2.0))))))
  142. ;;; K
  143. (define (first-elliptic-integral k)
  144. (elliptic-integrals k (lambda (K E) K)))
  145. ;;; E
  146. (define (second-elliptic-integral k)
  147. (elliptic-integrals k (lambda (K E) E)))
  148. (define (first-elliptic-integral&derivative k cont) ; (cont K dK/dk)
  149. (if (= k 0.0)
  150. (cons pi/2 0.0)
  151. (elliptic-integrals k
  152. (lambda (Kk Ek)
  153. (cont Kk
  154. (/ (- (/ Ek (- 1 (* k k))) Kk) k))))))
  155. #|
  156. (define (elliptic-integral-F-check phi k)
  157. (definite-integral
  158. (lambda (theta) (/ 1. (sqrt (- 1. (square (* k (sin theta)))))))
  159. 0. phi 1.e-13))
  160. ;(elliptic-integral-F-check 1. .9)
  161. ;Value: 1.159661070732225
  162. ; (elliptic-integral-F 1. .9)
  163. ;Value: 1.159661070732199
  164. ; (elliptic-integral-F pi/2 .9)
  165. ;Value: 2.2805491384227703
  166. ;(first-elliptic-integral .9)
  167. ;Value: 2.2805491384227703
  168. (define (elliptic-integral-E-check phi k)
  169. (definite-integral
  170. (lambda (theta) (sqrt (- 1. (square (* k (sin theta))))))
  171. 0. phi 1.e-13))
  172. (elliptic-integral-E 1. .9)
  173. ;Value: .8762622199915486
  174. (elliptic-integral-E-check 1. .9)
  175. ;Value: .876262219991453
  176. (complete-elliptic-integral-E .9)
  177. ;Value: 1.1716970527816144
  178. (second-elliptic-integral .9)
  179. ;Value: 1.171697052781614
  180. |#
  181. ;;; sn cn dn
  182. ;;; lisptran of Press
  183. (define Jacobi-elliptic-functions
  184. (let ((eps (sqrt *machine-epsilon*)))
  185. (lambda (uu k cont)
  186. ;; (cont sn cn dn)
  187. (let ((emc (- 1. (square k)))
  188. (u uu)
  189. (d 1.0))
  190. (if (= emc 0.)
  191. (let ((cn (/ 1. (cosh u))))
  192. (cont (tanh u) cn cn))
  193. (let ((bo (< emc 0.)))
  194. (if bo
  195. (begin
  196. (set! d (- 1. emc))
  197. (set! emc (- (/ emc d)))
  198. (set! d (sqrt d))
  199. (set! u (* u d))))
  200. (let ((dn 1.))
  201. (let loop ((a 1.) (emc emc) (i 1) (em '()) (en '()))
  202. (let ((emc (sqrt emc)))
  203. (let ((c (* 0.5 (+ a emc))))
  204. (if (and (> (abs (- a emc)) (* eps a))
  205. (fix:< i 13))
  206. (loop c (* a emc) (fix:+ i 1) (cons a em) (cons emc en))
  207. ;; label 1
  208. (let* ((u (* c u))
  209. (sn (sin u))
  210. (cn (cos u)))
  211. (if (not (= sn 0.))
  212. (let* ((a (/ cn sn))
  213. (c (* a c)))
  214. (let loop2 ((em em) (en en))
  215. (if (and (not (null? em)) (not (null? en)))
  216. (let ((b (car em)))
  217. (set! a (* c a))
  218. (set! c (* dn c))
  219. (set! dn (/ (+ (car en) a) (+ a b)))
  220. (set! a (/ c b))
  221. (loop2 (cdr em) (cdr en)))
  222. (let ((a (/ 1. (sqrt (+ 1. (square c))))))
  223. (if (< sn 0.)
  224. (set! sn (- a))
  225. (set! sn a))
  226. (set! cn (* c sn)))))))
  227. (if bo
  228. (cont (/ sn d) a cn)
  229. (cont sn cn dn))))))))))))))
  230. #|
  231. (Jacobi-elliptic-functions 1.3369113189159216 0. list)
  232. ;Value 12: (.9727733548546672 .231758495172875 1.)
  233. (sin 1.3369113189159216)
  234. ;Value: .9727733548546673
  235. (elliptic-integral-F 1.1 .92)
  236. ;Value: 1.3369113189159216
  237. (Jacobi-elliptic-functions 1.3369113189159216 0.92 list)
  238. ;Value 13: (.8912073600614343 .45359612142557926 .5724913337139167)
  239. (sin 1.1)
  240. ;Value: .8912073600614354
  241. (+ (square .8912073600614343) (square .45359612142557926))
  242. ;Value: .9999999999999999 ok cn
  243. (sqrt (- 1 (* (square 0.92) (square .8912073600614343))))
  244. ;Value: .5724913337139168 ok dn
  245. (define (check-elliptic-1 phi k)
  246. (let ((u (elliptic-integral-F phi k)))
  247. (Jacobi-elliptic-functions
  248. u k
  249. (lambda (sn cn dc)
  250. (- phi (asin sn))))))
  251. ;;; seems to work for -pi/2 < phi < pi/2 and k<1
  252. ;;; why does the Jacobi program have a branch for k>1?
  253. ;;; (elliptic-integral-F (* 40 (/ pi 180)) (sin (* 50 (/ pi 180))))
  254. ;;; (elliptic-integral-E (* 40 (/ pi 180)) (sin (* 50 (/ pi 180))))
  255. |#