zbrent.scm 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  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. ;;;; Finds roots of function f in domain from x1 to x2.
  21. ;;; From Numerical Recipes, 2nd Edition, Press, et.al.
  22. (declare (usual-integrations))
  23. ;;; Given a real continuous function f of one real variable, two
  24. ;;; distinct argument values x1 and x2 satisfying f(x1) X f(x2) <= 0,
  25. ;;; a positive tolerance tol, and a maximum number of iterations,
  26. ;;; itmax.
  27. ;;; To produce a list. The first element is true if the algorithm
  28. ;;; converged to a root, the second is the root, and the third is the
  29. ;;; number of iterations required. The number of function evaluations
  30. ;;; is always two more than the number of iterations.
  31. (define* (zbrent f x1 x2 #:optional tol itmax)
  32. (if (default-object? tol) (set! tol 0))
  33. (if (default-object? itmax) (set! itmax 100))
  34. (let ((fa (f x1)) (fb (f x2)))
  35. (if (or (and (> fa 0) (> fb 0)) (and (< fa 0) (< fb 0)))
  36. (error "Root must be bracketed in zbrent" x1 x2))
  37. (let lp ((iter 0) (a x1) (fa fa)
  38. (b x2) (fb fb)
  39. (c x1) (fc fa)
  40. (d (- x2 x1)) (e (- x2 x1)))
  41. (cond ((fix:= iter itmax)
  42. (list #f b iter))
  43. ((or (and (> fb 0) (> fc 0))
  44. (and (< fb 0) (< fc 0)))
  45. (let ((u (- b a)))
  46. (lp iter a fa b fb a fa u u)))
  47. ((< (abs fc) (abs fb))
  48. (lp iter b fb c fc a fa d e))
  49. (else
  50. (let ((tol1
  51. (+ (* *machine-epsilon* (abs b))
  52. (/ tol 2.0)))
  53. (xm (/ (- c b) 2.0)))
  54. (define (next1 p q)
  55. (let ((p (abs p))
  56. (q (if (> p 0.0) (- q) q)))
  57. (let ((min1 (- (* 3.0 xm q) (abs (* tol1 q))))
  58. (min2 (abs (* e q))))
  59. (if (< (* 2.0 p) (min min1 min2))
  60. (next2 d (/ p q))
  61. (next2 d xm)))))
  62. (define (next2 e d)
  63. (let ((nb
  64. (if (> (abs d) tol1)
  65. (+ b d)
  66. (+ b
  67. (if (> xm 0.0)
  68. (abs tol1)
  69. (- (abs tol1)))))))
  70. (lp (fix:+ iter 1) b fb nb (f nb) c fc d e)))
  71. (cond ((or (<= (abs xm) tol1) (= fb 0.0))
  72. (list #t b iter))
  73. ((and (>= (abs e) tol1) (> (abs fa) (abs fb)))
  74. (let ((s (/ fb fa)))
  75. (if (= a c)
  76. (next1 (* 2.0 xm s) (- 1.0 s))
  77. (let ((q (/ fa fc)) (r (/ fb fc)))
  78. (next1 (* s
  79. (- (* 2.0 xm q (- q r))
  80. (* (- b a) (- r 1.0))))
  81. (* (- q 1.0)
  82. (- r 1.0)
  83. (- s 1.0)))))))
  84. (else
  85. (next2 d xm)))))))))
  86. #|
  87. (define *machine-epsilon*
  88. (let loop ((e 1.0))
  89. (if (= 1.0 (+ e 1.0))
  90. (* 2 e)
  91. (loop (/ e 2)))))
  92. |#
  93. #|
  94. (begin
  95. (define numval 0)
  96. (let ((v
  97. (zbrent (lambda (x)
  98. (set! numval (+ numval 1))
  99. (- (sin x) 0.5))
  100. 0. 1.5
  101. 1e-15
  102. 100)))
  103. (append v (list numval))))
  104. ;Value 10: (#t .5235987755982988 8 10)
  105. (begin
  106. (define n 3)
  107. (define numval 0)
  108. (let ((v
  109. (zbrent (lambda (x)
  110. (set! numval (+ numval 1))
  111. (+ (* 2 x (exp (- n))) 1 (* -2 (exp (* -1 n x)))))
  112. 0. 1.
  113. 1e-15
  114. 100)))
  115. (append v (list numval))))
  116. ;Value 11: (#t .22370545765466293 7 9)
  117. (begin
  118. (define n 10)
  119. (define numval 0)
  120. (let ((v
  121. (zbrent (lambda (x)
  122. (set! numval (+ numval 1))
  123. (- (* (+ 1 (expt (- 1 n) 2)) x) (expt (- 1 (* n x)) 2)))
  124. 0. 1.
  125. 1e-15
  126. 100)))
  127. (append v (list numval))))
  128. ;Value 12: (#t 9.900009998000501e-3 8 10)
  129. (begin
  130. (define n 5)
  131. (define numval 0)
  132. (let ((v
  133. (zbrent (lambda (x)
  134. (set! numval (+ numval 1))
  135. (- (* x x) (expt (- 1 x) n)))
  136. 0. 1.
  137. 1e-15
  138. 100)))
  139. (append v (list numval))))
  140. ;Value 14: (#t .34595481584824217 7 9)
  141. (begin
  142. (define n 19)
  143. (define a 0)
  144. (define b 1e-4)
  145. (define numval 0)
  146. (let ((v
  147. (zbrent (lambda (x)
  148. (set! numval (+ numval 1))
  149. (+ (expt x n) (* a x) b))
  150. -3. 5.
  151. 1e-15
  152. 100)))
  153. (append v (list numval))))
  154. ;Value 15: (#t -.6158482110660264 23 25)
  155. (begin
  156. (define n 3)
  157. (define numval 0)
  158. (let ((v
  159. (zbrent (lambda (x)
  160. (set! numval (+ numval 1))
  161. (expt x n))
  162. -1. 10.
  163. 1e-15
  164. 200)))
  165. (append v (list numval))))
  166. ;Value 17: (#t -1.4076287793739637e-16 158 160)
  167. (begin
  168. (define n 9)
  169. (define numval 0)
  170. (let ((v
  171. (zbrent (lambda (x)
  172. (set! numval (+ numval 1))
  173. (expt x n))
  174. -1. 10.
  175. 1e-15
  176. 200)))
  177. (append v (list numval))))
  178. ;Value 18: (#t -1.1555192900497495e-17 147 149)
  179. (begin
  180. (define n 19)
  181. (define numval 0)
  182. (let ((v
  183. (zbrent (lambda (x)
  184. (set! numval (+ numval 1))
  185. (expt x n))
  186. -1. 10.
  187. 1e-15
  188. 200)))
  189. (append v (list numval))))
  190. ;Value 19: (#t 1.4548841231758658e-16 152 154)
  191. (define (kepler ecc m)
  192. (define 2pi (* 8 (atan 1 1)))
  193. (zbrent
  194. (lambda (e)
  195. (write-line e)
  196. (- e (* ecc (sin e)) m))
  197. 0.0
  198. 2pi
  199. 1e-15
  200. 100))
  201. ;Value: kepler
  202. (kepler .99 .01)
  203. 6.283185307179586
  204. 0.
  205. 9.999999999999998e-3
  206. .9967954452700871
  207. .06907877394105355
  208. .5329371096055704
  209. .2160603559873964
  210. .4415169261644992
  211. .3111033353177872
  212. .3466110470491019
  213. .3419230916206179
  214. .34226662531904334
  215. .34227031654601936
  216. .34227031649177464
  217. .3422703164917755
  218. ;Value 20: (#t .3422703164917755 13)
  219. |#