defint.scm 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. ;;;; Numerical definite integration system interface.
  21. ;;; The integrand is a procedure that computes a function.
  22. ;;; Use: (definite-integral <integrand> <from> <to> [compile? #t/#f])
  23. #|
  24. (definite-integral (lambda (x) (* (exp (- x)) (log x))) 0.0 :+infinity)
  25. ;Value: -.5772156647120303
  26. (define (foo n)
  27. (definite-integral (lambda (x) (expt (log (/ 1 x)) n)) 0.0 1.0))
  28. (foo 1)
  29. ;Value: .9999999998053075
  30. (foo 2)
  31. ;Value: 1.9999999997719113
  32. (foo 3)
  33. ;Value: 5.999999999805274
  34. (foo 4)
  35. ;Value: 23.999999999815316
  36. (foo 5)
  37. ;Value: 119.99999999980271
  38. (foo 6)
  39. ;Value: 719.9999999997759
  40. |#
  41. (declare (usual-integrations))
  42. ;;; Default compile integrand
  43. (define *compile-integrand? #t)
  44. ;;; Default error specification
  45. (define *definite-integral-allowable-error* 1.0e-11)
  46. ;;; Default ditherer off (see rational.scm)
  47. (define %numerics-quadrature-defint-dummy-1
  48. (*quadrature-neighborhood-width* #f))
  49. ;;; Interface to quadrature.scm
  50. (define (definite-integral-with-tolerance f x1 x2 tolerance)
  51. ((make-definite-integrator f x1 x2 tolerance)
  52. 'integral))
  53. ;;; Assumes f is purely numerical, and no units on t1, t2
  54. (define (definite-integral-numerical f t1 t2 tolerance compile?)
  55. (cond ((and (number? t1) (number? t2) (= t1 t2)) 0)
  56. ((not compile?)
  57. (definite-integral-with-tolerance f t1 t2 tolerance))
  58. (else
  59. (definite-integral-with-tolerance (compile-procedure f)
  60. t1 t2 tolerance))))
  61. (define* (definite-integral f t1 t2 #:optional tolerance compile?)
  62. (if (default-object? tolerance)
  63. (set! tolerance *definite-integral-allowable-error*))
  64. (if (default-object? compile?)
  65. (set! compile? *compile-integrand?))
  66. (let ((fx (f (choose-interior-point t1 t2))))
  67. (if (with-units? fx) ;Must extract numerical procedure
  68. (let* ((input-value (generate-uninterned-symbol))
  69. (input-units (u:units t1))
  70. (input (with-units input-value input-units))
  71. (output (f input))
  72. (output-units (u:units output))
  73. (output-value (u:value output))
  74. (integral-units (*units output-units input-units))
  75. (lexp
  76. (text/cselim
  77. `(lambda (,input-value)
  78. ,((*compiler-simplifier*) output-value))))
  79. (nf (eval lexp scmutils-base-environment)))
  80. (with-units
  81. (definite-integral-numerical nf (u:value t1) (u:value t2)
  82. tolerance compile?)
  83. integral-units))
  84. (definite-integral-numerical f (u:value t1) (u:value t2)
  85. tolerance compile?))))
  86. (define (choose-interior-point x1 x2)
  87. (assert (units:= x1 x2)
  88. "Limits of integration must have same units.")
  89. (let ((u (u:units x1))
  90. (t1 (u:value x1))
  91. (t2 (u:value x2)))
  92. (cond ((and (number? t1) (number? t2))
  93. (with-units (/ (+ t1 t2) 2.0) u))
  94. ((and (eq? t1 :-infinity) (number? t2))
  95. (with-units (- t2 1.0) u))
  96. ((and (number? t1) (eq? t2 :+infinity))
  97. (with-units (+ t1 1.0) u))
  98. ((and (eq? t1 :+infinity) (number? t2))
  99. (with-units (+ t2 1.0) u))
  100. ((and (number? t1) (eq? t2 :-infinity))
  101. (with-units (- t1 1.0) u))
  102. ((and (eq? t1 :-infinity) (eq? t2 :+infinity))
  103. (with-units 0 u))
  104. ((and (eq? t1 :+infinity) (eq? t2 :-infinity))
  105. (with-units 0 u))
  106. (else
  107. (error "No interior point: CHOOSE-INTERIOR-POINT")))))
  108. #|
  109. (define* (definite-integral f t1 t2 #:optional epsilon compile?)
  110. (if (default-object? epsilon)
  111. (set! epsilon *definite-integral-allowable-error*))
  112. (if (default-object? compile?)
  113. (set! compile? *compile-integrand?))
  114. (cond ((and (number? t1) (number? t2) (= t1 t2)) 0)
  115. ((not compile?)
  116. ((make-definite-integrator f t1 t2 epsilon)
  117. 'integral))
  118. (else
  119. ((make-definite-integrator (compile-procedure f) t1 t2 epsilon)
  120. 'integral))))
  121. |#