rational.scm 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876
  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. ;;; JW
  21. (declare (usual-integrations))
  22. ;;; To find the limit of (f x) as x goes to zero, rationally extrapolated
  23. ;;; from the given x-list.
  24. (define (extrapolate-function-to-zero f x-list eps)
  25. (build-tableau-f '() '() f x-list eps 666.0)) ; a beastly estimate.
  26. (define (build-tableau-f dt dx-list f x-list eps estimate)
  27. (if (null? x-list)
  28. (error "RATIONAL-FUNCTIONS: INACCURATE" estimate)
  29. (let ((dx-new (car x-list)))
  30. (let ((c (f dx-new)))
  31. (let ((new-dt
  32. (cons c (rational-interpolation dt c dx-list dx-new eps))))
  33. (let ((new-estimate (sum-list-flo new-dt)))
  34. (if (and (close-enuf? new-estimate estimate eps)
  35. (> (length new-dt) 2))
  36. (list new-estimate (length dt))
  37. (build-tableau-f new-dt (cons dx-new dx-list)
  38. f (cdr x-list) eps new-estimate))))))))
  39. ;;;----------------------------------------------------------------
  40. ;;; Rational interpolation on a pair of lists
  41. (define* ((rational-function-interpolation x-list y-list eps) x)
  42. (let ((data (map (lambda (xl y) (cons (- x xl) y)) x-list y-list)))
  43. (let ((sdata (sort data (lambda (a b) (< (abs (car a)) (abs (car b)))))))
  44. (let ((cd (car sdata)))
  45. (let ((sdx (map car sdata))
  46. (sdy (map cdr sdata)))
  47. (if (= (car cd) 0.0)
  48. (cdr cd)
  49. (build-tableau-lists '() '() sdx sdy eps (cdr cd))))))))
  50. (define (build-tableau-lists dt dx-list x-list y-list eps estimate)
  51. (if (null? x-list)
  52. (error "RATIONAL-FUNCTIONS: INACCURATE" estimate)
  53. (let ((dx-new (car x-list))
  54. (c (car y-list)))
  55. (let ((new-dt
  56. (cons c (rational-interpolation dt c dx-list dx-new eps))))
  57. (let ((new-estimate (sum-list-flo new-dt)))
  58. (if (and (close-enuf? new-estimate estimate eps)
  59. (> (length new-dt) 2))
  60. new-estimate
  61. (build-tableau-lists new-dt
  62. (cons dx-new dx-list)
  63. (cdr x-list) (cdr y-list)
  64. eps
  65. new-estimate)))))))
  66. (define (sum-list-flo l) ; from small end up
  67. (if (null? (cdr l))
  68. (car l)
  69. (flo:+ (car l) (sum-list-flo (cdr l)))))
  70. ;;;----------------------------------------------------------------
  71. ;;; The following is the core of the rational interpolation,
  72. ;;; with the zero denominator fix used by BS and Henon.
  73. ;;; Original version
  74. (define (rational-interpolation dt c dx-list dx-new eps)
  75. (if (null? dt)
  76. '()
  77. (let* ((dt1 (car dt))
  78. (w (flo:- c dt1))
  79. (b1 (flo:* (flo:/ (car dx-list) dx-new) dt1))
  80. (den (flo:- b1 c)))
  81. (if (flo:= den 0.0)
  82. (begin (if zd-wallp? (display "zd "))
  83. (cons dt1
  84. (rational-interpolation (cdr dt)
  85. c
  86. (cdr dx-list)
  87. dx-new
  88. eps)))
  89. (let* ((b (flo:/ w den))
  90. (new-d (flo:* c b)))
  91. (cons new-d
  92. (rational-interpolation (cdr dt)
  93. (flo:* b1 b)
  94. (cdr dx-list)
  95. dx-new
  96. eps)))))))
  97. (define zd-wallp? #f)
  98. #|
  99. Date: Sun, 30 Nov 2008 16:47:59 -0500
  100. From: Jack Wisdom <wisdom@MIT.EDU>
  101. To: gjs@mit.edu
  102. Subject: quadrature
  103. The problem seems to occur when the rational-interpolation
  104. gets a zero denominator. Try setting zd-wallp? to #t.
  105. I do not yet fully understand it, but if we quit the
  106. rational-interpolation instead of using the "zero denominator fix of
  107. BS and Henon", then the quadrature seems to work, in this case.
  108. So replace rational-interpolation with
  109. (define (rational-interpolation dt c dx-list dx-new eps)
  110. (if (null? dt)
  111. '()
  112. (let* ((dt1 (car dt))
  113. (w (flo:- c dt1))
  114. (b1 (flo:* (flo:/ (car dx-list) dx-new) dt1))
  115. (den (flo:- b1 c)))
  116. (if (flo:= den 0.0)
  117. '()
  118. (let* ((b (flo:/ w den))
  119. (new-d (flo:* c b)))
  120. (cons new-d
  121. (rational-interpolation (cdr dt)
  122. (flo:* b1 b)
  123. (cdr dx-list)
  124. dx-new
  125. eps)))))))
  126. I'll keep looking at it.
  127. |#
  128. ;;; Utilities
  129. #|
  130. (define (sigma-flo f low high)
  131. (let lp ((i low) (sum 0.0))
  132. (if (fix:> i high)
  133. sum
  134. (lp (fix:+ i 1) (flo:+ sum (f i))))))
  135. ;;; The following uses Kahan's compensated summation trick.
  136. |#
  137. (define (sigma-flo f low high)
  138. (let lp ((i low) (sum 0.0) (c 0.0))
  139. (if (fix:> i high)
  140. sum
  141. (let* ((y (flo:- (f i) c)) (t (flo:+ sum y)))
  142. (lp (fix:+ i 1) t (flo:- (flo:- t sum) y))))))
  143. (define (rat-square x)
  144. (let ((fx (exact->inexact x)))
  145. (flo:* fx fx)))
  146. #|
  147. (define *new-bs-steps*
  148. (merge-streams (stream-of-iterates (lambda (x) (* 2 x)) 2)
  149. (stream-of-iterates (lambda (x) (* 2 x)) 3)))
  150. |#
  151. (define *new-bs-steps*
  152. (merge-streams (stream-of-iterates (lambda (x) (* 2 x)) 4)
  153. (stream-of-iterates (lambda (x) (* 2 x)) 6)))
  154. (define (make-bs-intervals a b)
  155. (map-stream (lambda (x) (rat-square (/ (- b a) x)))
  156. *new-bs-steps*))
  157. ;;;; Quadrature Routines
  158. ;;; Rational interpolation on streams is used in the quadrature code below.
  159. (define (extrapolate-streams-to-zero x-stream y-stream eps)
  160. (build-tableau-streams '() '() x-stream y-stream eps (stream-car y-stream)))
  161. ;;; FBE start
  162. (define (build-tableau-streams dt dx-list x-stream y-stream eps estimate)
  163. (if (empty-stream? x-stream)
  164. '()
  165. ;;(null? x-stream)
  166. ;;'()
  167. (let ((dx-new (stream-car x-stream))
  168. (c (stream-car y-stream)))
  169. (let ((new-dt
  170. (cons c (rational-interpolation dt c dx-list dx-new eps))))
  171. (let ((new-estimate (sum-list-flo new-dt)))
  172. (if (and (close-enuf? new-estimate estimate eps)
  173. (> (length new-dt) 2))
  174. new-estimate
  175. (build-tableau-streams new-dt (cons dx-new dx-list)
  176. (stream-cdr x-stream)
  177. (stream-cdr y-stream)
  178. eps
  179. new-estimate)))))))
  180. ;;; To make quadrature deterministic, but sensitive to special choices
  181. ;;; make the choice: (define *quadrature-neighborhood-width* #f)
  182. ;;; FBE: make it a parameter. Also used in quadrature/defint.scm and
  183. ;;; mechanics/action.scm
  184. (define *quadrature-neighborhood-width* (make-parameter 0.05))
  185. (define (from-neighborhood a b)
  186. (if (*quadrature-neighborhood-width*)
  187. (+ a
  188. (* (+ 0.5
  189. (* (- (* 2.0 (uniform-random)) 1.0)
  190. (*quadrature-neighborhood-width*)))
  191. (- b a)))
  192. (* 0.5 (+ a b))))
  193. #|
  194. ;;; Produces a uniformly distributed x such that 0 <= x < 1.
  195. ;;; Defined in statistics/gauss.scm
  196. (define (uniform-random) (random 1.))
  197. |#
  198. ;;; *INTEGRATE-N* is the number of step sizes used before aborting
  199. ;;; to smaller intervals. n = 10 seems to work well.
  200. (define *INTEGRATE-N* 10)
  201. (define (integrate-closed-closed f a b eps)
  202. (let ((m (from-neighborhood a b)))
  203. (+ (integrate-closed-closed-1 f a m eps)
  204. (integrate-closed-closed-1 f m b eps))))
  205. (define (integrate-closed-closed-1 f a b eps)
  206. (let ((ans
  207. (integrate-closed-finite f a b *INTEGRATE-N* eps)))
  208. (if (null? ans)
  209. (integrate-closed-closed f a b eps)
  210. ans)))
  211. (define (integrate-open-closed f a b eps)
  212. (let ((m (from-neighborhood a b)))
  213. (+ (integrate-open-closed-1 f a m eps)
  214. (integrate-closed-closed-1 f m b eps))))
  215. (define (integrate-open-closed-1 f a b eps)
  216. (let ((ans
  217. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  218. (if (null? ans)
  219. (integrate-open-closed f a b eps)
  220. ans)))
  221. (define (integrate-closed-open f a b eps)
  222. (let ((m (from-neighborhood a b)))
  223. (+ (integrate-closed-closed-1 f a m eps)
  224. (integrate-closed-open-1 f m b eps))))
  225. (define (integrate-closed-open-1 f a b eps)
  226. (let ((ans
  227. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  228. (if (null? ans)
  229. (integrate-closed-open f a b eps)
  230. ans)))
  231. (define (integrate-open-open f a b eps)
  232. (let* ((m (from-neighborhood a b)))
  233. (+ (integrate-open-closed-1 f a m eps)
  234. (integrate-closed-open-1 f m b eps))))
  235. (define (integrate-open-open-1 f a b eps)
  236. (let ((ans
  237. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  238. (if (null? ans)
  239. (integrate-open-open f a b eps)
  240. ans)))
  241. (define integrate-open integrate-open-open-1)
  242. (define *roundoff-cutoff* 1e-14)
  243. ;;; Set this to true, if you want to see the cases where roundoff cutoff occurs.
  244. (define integrate-roundoff-wallp? #f)
  245. (define (integrate-closed-finite f a b n eps)
  246. (if (<= (abs (- b a))
  247. (* *roundoff-cutoff*
  248. (+ (abs b) (abs a))))
  249. (begin (if integrate-roundoff-wallp?
  250. (write-line `(roundoff-cutoff ,a ,b)))
  251. (* (/ (+ (f a) (f b)) 2.0) (- b a)))
  252. (extrapolate-streams-to-zero
  253. (shorten-stream n (make-bs-intervals a b))
  254. (merge-streams (trapezoid-stream f a b 2)
  255. (trapezoid-stream f a b 3))
  256. eps)))
  257. (define (integrate-open-finite f a b n eps)
  258. (if (<= (abs (- b a))
  259. (* *roundoff-cutoff*
  260. (+ (abs b) (abs a))))
  261. (begin (if integrate-roundoff-wallp?
  262. (write-line `(roundoff-cutoff ,a ,b)))
  263. (* (f (/ (+ a b) 2.0)) (- b a)))
  264. (extrapolate-streams-to-zero
  265. (shorten-stream n (make-bs-intervals a b))
  266. (map-stream (second-euler-maclaurin f a b)
  267. *new-bs-steps*)
  268. eps)))
  269. (define (trapezoid-stream f a b n0)
  270. (let ((steps (stream-of-iterates (lambda (x) (* 2 x)) n0))
  271. (first-S ((rat-trapezoid f a b) n0)))
  272. (let loop ((steps (stream-cdr steps)) (Sn/2 first-S))
  273. (let ((S (trapezoid-using-previous-sum f a b Sn/2 (stream-car steps))))
  274. (cons-stream S (loop (stream-cdr steps) S))))))
  275. (define* ((rat-trapezoid f a b) n)
  276. (let ((h (flo:/ (flo:- b a) (exact->inexact n))))
  277. (let ((fx (lambda (i)
  278. (exact->inexact (f (flo:+ a (flo:* (exact->inexact i) h)))))))
  279. (flo:* h (flo:+ (flo:/ (flo:+ (exact->inexact (f a))
  280. (exact->inexact (f b)))
  281. 2.0)
  282. (sigma-flo fx 1 (fix:- n 1)))))))
  283. (define (trapezoid-using-previous-sum f a b Sn/2 n)
  284. (let ((h (flo:/ (flo:- b a) (exact->inexact n))))
  285. (let ((fx
  286. (lambda (i)
  287. (exact->inexact
  288. (f (flo:+ a (flo:* (exact->inexact (fix:- (fix:+ i i) 1)) h)))))))
  289. (flo:+ (flo:/ Sn/2 2.0)
  290. (flo:* h (sigma-flo fx 1 (quotient n 2)))))))
  291. (define* ((second-euler-maclaurin f a b) n)
  292. (let ((h (flo:/ (flo:- b a) (exact->inexact n))))
  293. (let ((h/2 (flo:/ h 2.0)))
  294. (let ((fx
  295. (lambda (i)
  296. (exact->inexact
  297. (f (flo:+ a (flo:+ h/2 (flo:* (exact->inexact i) h))))))))
  298. (flo:* h (sigma-flo fx 0 (fix:- n 1)))))))
  299. #|
  300. ;;; ************ All text below this point is comments ************
  301. ;;; Other plans
  302. ;;; same as Romberg, but with rational extrapolation.
  303. (define (integrate-rtrap f a b eps steps)
  304. (extrapolate-streams-to-zero
  305. (map-stream (lambda (x) (rat-square (/ (- b a) x))) steps)
  306. (trapezoid-stream f a b (stream-car steps))
  307. eps))
  308. (define (general-integrate method steps f a b eps)
  309. (extrapolate-streams-to-zero
  310. (map-stream (lambda (x) (rat-square (/ (- b a) x)))
  311. steps)
  312. (map-stream (method f a b) steps)
  313. eps))
  314. (define (integrate-inf f a b eps)
  315. (extrapolate-streams-to-zero
  316. (map-stream (lambda (x) (rat-square (/ (- b a) x)))
  317. *new-bs-steps*)
  318. (merge-streams (trapezoid-stream f a b 2)
  319. (trapezoid-stream f a b 3))
  320. eps))
  321. (define (integrate-open-inf f a b eps)
  322. (extrapolate-streams-to-zero
  323. (map-stream (lambda (x) (rat-square (/ (- b a) x)))
  324. *new-bs-steps*)
  325. (map-stream (second-euler-maclaurin f a b)
  326. *new-bs-steps*)
  327. eps))
  328. |#
  329. #|
  330. ;;;;quadrature samples
  331. (define count)
  332. (set! count 0)
  333. (define (fc x)
  334. (set! count (+ count 1))
  335. (if (= x 0.0) 1.0 (/ (sin x) x)))
  336. (integrate-open-open fc 0.0 pi 1.0e-15)
  337. ;Value: 1.8519370519824663
  338. (set! count 0)
  339. ;Value: 70
  340. (define (xx x)
  341. (set! count (fix:+ count 1))
  342. (if (flo:= x 0.0) 0.0 (flo:expt x x)))
  343. (integrate-closed-closed xx 0.0 1.0 1.0e-10)
  344. ;Value: .7834305105286976
  345. (set! count 0)
  346. ;Value: 7792
  347. (integrate-open-open xx 0.0 1.0 1.0e-10)
  348. ;Value: .7834305106529134
  349. (set! count 0)
  350. ;Value: 1897
  351. (define (xsin1/x x)
  352. (set! count (+ count 1))
  353. (if (= x 0.0)
  354. 0.0
  355. (* x (sin (/ 1 x)))))
  356. (integrate-closed-closed xsin1/x 0.1 1.0 1.0e-10)
  357. ;Value: .3794280654186952
  358. (set! count 0)
  359. ;Value: 568
  360. (integrate-open-open xsin1/x 0.1 1.0 1.0e-10)
  361. ;Value: .3794280654199685
  362. (set! count 0)
  363. ;Value: 680
  364. (romberg-quadrature xsin1/x 0.1 1.0 1.0e-10)
  365. ;Value: .3794280654204438
  366. (set! count 0)
  367. ;Value: 1025
  368. (integrate-open-closed xsin1/x 0.05 1.0 1.0e-10)
  369. ;Value: .3784640968911057
  370. (set! count 0)
  371. ;Value: 980
  372. (integrate-closed-closed xsin1/x 0.05 1.0 1.0e-10)
  373. ;Value: .3784640968910794
  374. (set! count 0)
  375. ;Value: 932
  376. (romberg-quadrature xsin1/x 0.05 1.0 1.0e-10)
  377. ;Value: .37846409689114535
  378. (set! count 0)
  379. ;Value: 4097
  380. |#
  381. #|
  382. ;;;; bulirsch-stoer integrator
  383. ;;; modified midpoint takes vector state -> vector state
  384. (define-integrable (modified-midpoint n f state htot)
  385. (lambda (nsteps)
  386. (let ((2*nsteps (fix:* 2 nsteps)))
  387. (let ((h (flo:/ htot (exact->inexact 2*nsteps))))
  388. (let ((2h (flo:* 2.0 h))
  389. (f0 (f state)))
  390. (let loop
  391. ((m (fix:- 2*nsteps 1))
  392. (zm-1 state)
  393. (zm (make-initialized-vector n
  394. (lambda (i)
  395. (flo:+ (vector-ref state i)
  396. (flo:* h (vector-ref f0 i)))))))
  397. (let ((fn (f zm)))
  398. (if (fix:= m 0)
  399. (make-initialized-vector
  400. n
  401. (lambda (i)
  402. (flo:* 0.5
  403. (flo:+ (vector-ref zm i)
  404. (flo:+ (vector-ref zm-1 i)
  405. (flo:* h
  406. (vector-ref fn i)))))))
  407. (loop (fix:-1+ m)
  408. zm
  409. (make-initialized-vector
  410. n
  411. (lambda (i)
  412. (flo:+ (vector-ref zm-1 i)
  413. (flo:* 2h (vector-ref fn i))))))))))))))
  414. #|
  415. (define (kepler s)
  416. (let ((x (vector-ref s 0))
  417. (y (vector-ref s 1)))
  418. (let ((radius^3 (flo:expt (flo:+ (flo:* x x) (flo:* y y)) 1.5)))
  419. (vector
  420. (vector-ref s 2)
  421. (vector-ref s 3)
  422. (flo:negate (flo:/ x radius^3))
  423. (flo:negate (flo:/ y radius^3))))))
  424. |#
  425. #| this one uses continuations rather than vectors
  426. about as fast as following one 24 sec compared to 23 for the
  427. next inline coded one
  428. generic vector routine with define-integrable is about 30 sec
  429. C code is about 10 sec
  430. (define-integrable (modified-midpoint n f state htot)
  431. (if (not (fix:= n 4)) (error "only n=4 for this midpoint integrator"))
  432. (let ((s.0 (vector-ref state 0))
  433. (s.1 (vector-ref state 1))
  434. (s.2 (vector-ref state 2))
  435. (s.3 (vector-ref state 3)))
  436. (lambda (nsteps)
  437. (let ((2*nsteps (fix:* 2 nsteps)))
  438. (let ((h (flo:/ htot (exact->inexact 2*nsteps))))
  439. (let ((2h (flo:* 2.0 h)))
  440. (f (lambda (d.0 d.1 d.2 d.3)
  441. (midpoint-steps (fix:- 2*nsteps 1)
  442. f h 2h
  443. s.0 s.1 s.2 s.3
  444. (flo:+ s.0 (flo:* h d.0)) ; first half step
  445. (flo:+ s.1 (flo:* h d.1))
  446. (flo:+ s.2 (flo:* h d.2))
  447. (flo:+ s.3 (flo:* h d.3))))
  448. s.0 s.1 s.2 s.3)))))))
  449. (define (midpoint-steps m f h 2h zm-1.0 zm-1.1 zm-1.2 zm-1.3 zm.0 zm.1 zm.2 zm.3)
  450. (if (fix:= m 0)
  451. (f (lambda (d.0 d.1 d.2 d.3)
  452. (vector
  453. (flo:* 0.5 (flo:+ zm.0 (flo:+ zm-1.0 (flo:* h d.0)))) ; last half step
  454. (flo:* 0.5 (flo:+ zm.1 (flo:+ zm-1.1 (flo:* h d.1))))
  455. (flo:* 0.5 (flo:+ zm.2 (flo:+ zm-1.2 (flo:* h d.2))))
  456. (flo:* 0.5 (flo:+ zm.3 (flo:+ zm-1.3 (flo:* h d.3))))))
  457. zm.0 zm.1 zm.2 zm.3)
  458. (f (lambda (d.0 d.1 d.2 d.3)
  459. (midpoint-steps (fix:- m 1) f h 2h
  460. zm.0 zm.1 zm.2 zm.3
  461. (flo:+ zm-1.0 (flo:* 2h d.0)) ; middle steps
  462. (flo:+ zm-1.1 (flo:* 2h d.1))
  463. (flo:+ zm-1.2 (flo:* 2h d.2))
  464. (flo:+ zm-1.3 (flo:* 2h d.3))))
  465. zm.0 zm.1 zm.2 zm.3)))
  466. (define (f-kepler c s.0 s.1 s.2 s.3)
  467. (let ((radius^3 (flo:expt (flo:+ (flo:* s.0 s.0) (flo:* s.1 s.1)) 1.5)))
  468. (c s.2
  469. s.3
  470. (flo:negate (flo:/ s.0 radius^3))
  471. (flo:negate (flo:/ s.1 radius^3)))))
  472. ;;; this is the fastest so far
  473. (define (modified-midpoint-kepler n f state htot)
  474. (let ((s.0 (vector-ref state 0))
  475. (s.1 (vector-ref state 1))
  476. (s.2 (vector-ref state 2))
  477. (s.3 (vector-ref state 3)))
  478. (let ((radius^3 (flo:expt (flo:+ (flo:* s.0 s.0) (flo:* s.1 s.1)) 1.5)))
  479. (lambda (nsteps)
  480. (let ((2*nsteps (fix:* 2 nsteps)))
  481. (let ((h (flo:/ htot (exact->inexact 2*nsteps))))
  482. (let ((2h (flo:* 2.0 h)))
  483. (let loop
  484. ((m (fix:- 2*nsteps 1))
  485. (zm-1.0 s.0)
  486. (zm-1.1 s.1)
  487. (zm-1.2 s.2)
  488. (zm-1.3 s.3)
  489. (zm.0 (flo:+ s.0 (flo:* h s.2)))
  490. (zm.1 (flo:+ s.1 (flo:* h s.3)))
  491. (zm.2 (flo:+ s.2 (flo:* h (flo:negate (flo:/ s.0 radius^3)))))
  492. (zm.3 (flo:+ s.3 (flo:* h (flo:negate (flo:/ s.1 radius^3))))))
  493. (let ((radius^3
  494. (flo:expt (flo:+ (flo:* zm.0 zm.0) (flo:* zm.1 zm.1)) 1.5)))
  495. (if (fix:= m 0)
  496. (vector
  497. (flo:* 0.5 (flo:+ zm.0 (flo:+ zm-1.0 (flo:* h zm.2))))
  498. (flo:* 0.5 (flo:+ zm.1 (flo:+ zm-1.1 (flo:* h zm.3))))
  499. (flo:* 0.5
  500. (flo:+ zm.2
  501. (flo:+ zm-1.2
  502. (flo:* h
  503. (flo:negate (flo:/ zm.0
  504. radius^3))))))
  505. (flo:* 0.5
  506. (flo:+ zm.3
  507. (flo:+ zm-1.3
  508. (flo:* h
  509. (flo:negate (flo:/ zm.1
  510. radius^3)))))))
  511. (loop (fix:-1+ m)
  512. zm.0 zm.1 zm.2 zm.3
  513. (flo:+ zm-1.0 (flo:* 2h zm.2))
  514. (flo:+ zm-1.1 (flo:* 2h zm.3))
  515. (flo:+ zm-1.2
  516. (flo:* 2h
  517. (flo:negate (flo:/ zm.0
  518. radius^3))))
  519. (flo:+ zm-1.3
  520. (flo:* 2h
  521. (flo:negate (flo:/ zm.1
  522. radius^3)))))))))))))))
  523. |#
  524. ;;; (define (rat-next-h h m)
  525. ;;; (* h 1.5 (if (< m 7) 1 (expt 0.6 (- m 6)))))
  526. ;;; STEP-SIZE-N is related to the desired level of rational tableau (equal?)
  527. (define STEP-SIZE-N 9)
  528. (define (rat-next-h h m)
  529. (if bs-print? (write-line (list h m)))
  530. (if (not (fix:> m STEP-SIZE-N))
  531. (flo:* h 1.5)
  532. (flo:* h (flo:* 1.5 (flo:expt 0.6 (exact->inexact (- m STEP-SIZE-N)))))))
  533. (define (bulirsch-stoer-step n f eps t.htot.state)
  534. (let ((t (car t.htot.state))
  535. (htot (cadr t.htot.state))
  536. (state (caddr t.htot.state)))
  537. (if bs-print? (begin (write-line 'state) (write-line t.htot.state)))
  538. (let ((m (modified-midpoint n f state htot))
  539. (x-list (list 1 2 3 4 6 8 12 16 24 32 48 64)))
  540. (let ((ans (extrapolate-vector-function-to-zero-2 n m x-list eps)))
  541. (let ((ms (map tableau-data->table-length ans)))
  542. (if (null? ans)
  543. (bulirsch-stoer-step n f eps (list t (flo:/ htot 2.0) state))
  544. (list (flo:+ t htot)
  545. (rat-next-h htot (apply max ms))
  546. (list->vector (map tableau-data->estimate ans)))))))))
  547. (define (advance-state n f t.dt.state target eps monitor)
  548. (let loop ((t.dt.s t.dt.state))
  549. (monitor t.dt.s)
  550. (let ((t (car t.dt.s)))
  551. (if (flo:< (flo:abs (flo:- target t)) eps)
  552. t.dt.s
  553. (let ((dt (cadr t.dt.s))
  554. (state (caddr t.dt.s)))
  555. (if (< (apply + (map abs (cdr (vector->list state))))
  556. 1.0e-3)
  557. (bkpt "foo"))
  558. (loop
  559. (bulirsch-stoer-step
  560. n f eps
  561. (list t
  562. (flo:* dt
  563. (min 1.0
  564. (flo:/ (flo:- target t)
  565. dt)))
  566. state))))))))
  567. ;;;; extrapolation of vector valued functions (elementwise unfortunately)
  568. (define *huge* 1.0e30)
  569. (define bs-print? false)
  570. ;;; tableau-data is a list of estimate error table-length dt
  571. (define make-tableau-data list)
  572. (define tableau-data->estimate car)
  573. (define tableau-data->error cadr)
  574. (define tableau-data->table-length caddr)
  575. (define tableau-data->tableau cadddr)
  576. (define (extrapolate-vector-function-to-zero n f x-list eps)
  577. (let ((tableaus
  578. (make-list n (make-tableau-data *huge* *huge* false '())))
  579. (step->dx (lambda (x) (exact->inexact x))))
  580. (build-tableau-vector-f step->dx tableaus '() f x-list eps)))
  581. ;;; assumes f(x) = g(1/x^2)
  582. (define (extrapolate-vector-function-to-zero-2 n f step-list eps)
  583. (let ((tableaus
  584. (make-list n (make-tableau-data *huge* *huge* false '())))
  585. (step->dx (lambda (x)
  586. (let ((xf (exact->inexact x)))
  587. (flo:/ 1.0 (flo:* xf xf))))))
  588. (build-tableau-vector-f step->dx tableaus '() f step-list eps)))
  589. (define (build-tableau-vector-f step->dx tableaus dx-list f step-list eps)
  590. (if (null? step-list)
  591. '()
  592. (let ((step-new (car step-list)))
  593. (let ((c (vector->list (f step-new))))
  594. (let ((dx-new (step->dx step-new)))
  595. (let ((new-tableaus
  596. (map (individual-extrapolation dx-list dx-new eps)
  597. c
  598. tableaus)))
  599. (if bs-print? (write-line (list 'new-tableaus new-tableaus)))
  600. (cond ((all-done? new-tableaus) new-tableaus)
  601. ((diverging? tableaus new-tableaus) '())
  602. (else
  603. (build-tableau-vector-f
  604. step->dx new-tableaus (cons dx-new dx-list)
  605. f (cdr step-list) eps)))))))))
  606. (define (individual-extrapolation dx-list dx-new eps)
  607. (lambda (c tableau-data)
  608. (if (tableau-data->table-length tableau-data)
  609. tableau-data
  610. (let ((estimate (tableau-data->estimate tableau-data))
  611. (dt (tableau-data->tableau tableau-data)))
  612. (let ((new-dt
  613. (cons c (rational-interpolation dt c dx-list dx-new eps))))
  614. (let ((new-estimate (sum-list-flo new-dt)))
  615. (let ((new-error
  616. (abs (/ (* 2.0 (- estimate new-estimate))
  617. (+ 2.0 (abs estimate) (abs new-estimate))))))
  618. (make-tableau-data new-estimate new-error
  619. (if (< new-error eps) (length new-dt) false)
  620. new-dt))))))))
  621. (define (diverging? tableaus new-tableaus)
  622. (let ((max-error (apply max (map tableau-data->error tableaus)))
  623. (new-max-error (apply max (map tableau-data->error new-tableaus))))
  624. (> new-max-error max-error)))
  625. (define (all-done? tableaus)
  626. (reduce (lambda (a b) (and a b))
  627. true
  628. (map tableau-data->table-length tableaus)))
  629. |#
  630. #|----------------------------------------------------------------
  631. ;;;;numerical integration examples
  632. ;;; use compiled diffeq in test-difeq!!
  633. (define harmonic
  634. (lambda (s) ; (set! count (+ count 1))
  635. (vector (vector-ref s 1) (flo:negate (vector-ref s 0)))))
  636. (show-time
  637. (lambda ()
  638. (advance-state 2 harmonic
  639. (list 0.0 1.0 (vector 0.0 1.0))
  640. (* 100.0 2pi) 1.0e-13
  641. (lambda args '()))))
  642. process time: 10140; real time: 12186
  643. ;Value: (628.3185307179587
  644. 2.0149000002514867
  645. #(-5.71774615501508e-14 .9999999999999801))
  646. (define (stiff x)
  647. (let ((u (vector-ref x 0)) (v (vector-ref x 1)))
  648. (vector (flo:+ (flo:* 998.0 u) (flo:* 1998.0 v))
  649. (flo:+ (flo:* -999.0 u) (flo:* -1999.0 v)))))
  650. (define (stiff-answer x)
  651. (vector (- (* 2 (exp (- x))) (exp (* -1000 x)))
  652. (+ (- (exp (- x))) (exp (* -1000 x)))
  653. x))
  654. (define (stiff-hamiltonian x)
  655. (let ((u (vector-ref x 0)) (v (vector-ref x 1)))
  656. (vector (flo:+ (flo:* 500.5 u) v)
  657. (flo:+ (flo:* 998.0 u) (flo:* -500.5 v)))))
  658. (show-time
  659. (lambda ()
  660. (advance-state 2 stiff
  661. (list 0.0 0.01 (vector 1.0 0.0)) 0.01 1.0e-12
  662. (lambda args (write-line args)))))
  663. (show-time
  664. (lambda ()
  665. (advance-state 2 stiff-vec
  666. (list 0.0 0.01 (vector 1.0 0.0)) 1.0 1.0e-12
  667. (lambda args '()))))
  668. process time: 9380; real time: 10762
  669. ;Value: (1. 1.3233357542007995e-2 #(.7357588824655332 -.36787944124663186))
  670. (define (kepler s)
  671. (let ((x (vector-ref s 0)) (y (vector-ref s 1)))
  672. (let ((radius^3
  673. (flonum-expt
  674. (flonum-add (flonum-multiply x x) (flonum-multiply y y))
  675. 1.5)))
  676. (vector (vector-ref s 2)
  677. (vector-ref s 3)
  678. (flonum-negate (flonum-divide x radius^3))
  679. (flonum-negate (flonum-divide y radius^3))))))
  680. (show-time
  681. (lambda ()
  682. (advance-state 4 kepler
  683. (list 0.0 1.0 (vector 1.0 0.0 0.0 1.1))
  684. (* 100.0 2pi) 1.0e-13
  685. (lambda args '()))))
  686. process time: 79200; real time: 93153
  687. ;Value: (628.3185307179587
  688. .9771894138036714
  689. #(-.2670827485008997
  690. 1.2375960779353004
  691. -.8886332522158626
  692. -8.647969066388888e-4))
  693. |#
  694. #|;;; Got caught on trick cases, such as 1-cos32t, from 0 to 2pi.
  695. ;;; *INTEGRATE-N* is the number of step sizes used before aborting
  696. ;;; to smaller intervals. n = 10 seems to work well.
  697. (define *INTEGRATE-N* 10)
  698. (define (integrate-closed-closed f a b eps)
  699. (let ((ans
  700. (integrate-closed-finite f a b *INTEGRATE-N* eps)))
  701. (if (null? ans)
  702. (let ((m (/ (+ a b) 2)))
  703. (+ (integrate-closed-closed f a m eps)
  704. (integrate-closed-closed f m b eps)))
  705. ans)))
  706. (define (integrate-open-closed f a b eps)
  707. (let ((ans
  708. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  709. (if (null? ans)
  710. (let ((m (/ (+ a b) 2)))
  711. (+ (integrate-open-closed f a m eps)
  712. (integrate-closed-closed f m b eps)))
  713. ans)))
  714. (define (integrate-closed-open f a b eps)
  715. (let ((ans
  716. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  717. (if (null? ans)
  718. (let ((m (/ (+ a b) 2)))
  719. (+ (integrate-closed-closed f a m eps)
  720. (integrate-closed-open f m b eps)))
  721. ans)))
  722. (define (integrate-open-open f a b eps)
  723. (let ((ans
  724. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  725. (if (null? ans)
  726. (let* ((s (+ a b))
  727. (m1 (/ s 3))
  728. (m2 (/ (* 2 s) 3)))
  729. (+ (integrate-open-closed f a m1 eps)
  730. (integrate-closed-closed f m1 m2 eps)
  731. (integrate-closed-open f m2 b eps)))
  732. ans)))
  733. (define (integrate-open f a b eps)
  734. (let ((ans
  735. (integrate-open-finite f a b *INTEGRATE-N* eps)))
  736. (if (null? ans)
  737. (let ((m (/ (+ a b) 2)))
  738. (+ (integrate-open f a m eps)
  739. (integrate-open f m b eps)))
  740. ans)))
  741. |#