1 ;;;;;;;;;;;;;;;;;;; -*- Mode: Lisp; Package: Macsyma -*- ;;;;;;;;;;;;;;;;;;;
2 ;;; (c) Copyright 1982 Massachusetts Institute of Technology ;;;
3 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
9 ;; (load-macsyma-macros Numerm)
11 ;;; 10:55 pm Sept 25, 1981 - LPH & GJC
12 ;;; added $numer and $float set to T so that quanc8(x,x,0,1/2); works. this
13 ;;; is done inside the prog for $quanc8 so that they are put back when done.
14 ;;; 3:30 pm Feb 12, 1982 - JPG, LPH, & GJC
15 ;;; removed the $numer:$float:true and replaced with mto-float which is
16 ;;; defined in maxsrc;numer > .
17 ;;; 3:45 am April 11, 1982 - LPH
18 ;;; fixed an error in estimating TOLERR due to neglect of sub-interval size
19 ;;; when abserr check is made.
21 (defmvar $quanc8_flag
0.0
22 "integer part-how many regions failed to converge. fractional part-
23 how much of the interval was left when it failed")
24 (defmvar $quanc8_errest
0.0
25 "an estimated error based on the difference between one- and two-panel
26 calculation of an interval, summed over the whole region")
27 (defmvar $quanc8_abserr
1.0e-8
28 "absolute error tolerance for reasonable single-precision answers")
29 (defmvar $quanc8_relerr
1.0e-4
30 "relative error condition for reasonable run-times")
32 ;; (DEFUN ($QUANC8 TRANSLATED-MMACRO) (F A B &OPTIONAL (C NIL C-P))
34 ;; `((CALL-QUANC8) ,F ,A ,B)
35 ;; `((CALL-QUANC8) ((LAMBDA) ((MLIST) ,A) ,F) ,B ,C)))
37 (defmspec $quanc8
(form)
38 (if (cdddr (setq form
(cdr form
)))
40 (meval `((lambda) ((mlist) ,(cadr form
)) ,(car form
)))
41 (mapcar #'meval
(cddr form
)))
42 (apply #'call-quanc8
(mapcar #'meval form
))))
44 (def%tr $quanc8
(form)
46 ,@(cdr (tr-lisp-function-call
47 (if (cdddr (setq form
(cdr form
)))
49 ((lambda) ((mlist) ,(cadr form
)) ,(car form
)) ,@(cddr form
))
50 `((call-quanc8) ,@form
)) nil
))))
52 (defvar quanc8-free-list
()
53 "For efficient calls to quanc8 keep arrays we need on a free list.")
55 (defvar quanc8-|^
]|
())
56 (defun quanc8-|^
]|
() (setq quanc8-|^
]| t
))
58 (defun call-quanc8 (fun a b
)
61 (let ((vals (if quanc8-free-list
62 (pop quanc8-free-list
)
63 (list (*array nil
'flonum
17.
)
64 (*array nil
'flonum
17.
)
65 (*array nil
'flonum
9.
31.
)
66 (*array nil
'flonum
9.
31.
)
67 (*array nil
'flonum
32.
))))
68 (user-timesofar (cons #'quanc8-|^
]| user-timesofar
)))
78 (push vals quanc8-free-list
)))))
80 (defun quanc8 (fun a b x-arr f-arr xsave-arr fsave-arr qright-arr
)
81 (declare (type (simple-array cl
:float
)
82 x-arr f-arr xsave-arr fsave-arr qright-arr
))
83 ;; local macros for typing convenience.
84 (macrolet ((x (j) `(arraycall flonum x-arr
,j
))
85 (f (j) `(arraycall flonum f-arr
,j
))
86 (xsave (j k
) `(arraycall flonum xsave-arr
,j
,k
))
87 (fsave (j k
) `(arraycall flonum fsave-arr
,j
,k
))
88 (qright (j) `(arraycall flonum qright-arr
,j
)))
89 ;; Rudimentary (non-ansi GCL compatible) error handling.
92 (prog ((levmin 1.
) (levmax 30.
) (levout 6.
) (nomax 5000.
) (nofin 0)
93 (w0 (//$
3956.0 14175.0)) (w1 (//$
23552.0 14175.0))
94 (w2 (//$ -
3712.0 14175.0)) (w3 (//$
41984.0 14175.0))
95 (w4 (//$ -
18160.0 14175.0))
96 (result 0.0) (cor11 0.0) (area 0.0)
97 (nofun 0.
) (lev 0.
) (nim 1.
) (qprev 0.0)
98 (stone (//$
(-$ b a
) 16.0))
100 (step 0.0) (qleft 0.0) (qnow 0.0) (qdiff 0.0)
101 (esterr 0.0) (tolerr 0.0) (temp 0.0)
102 ($numer t
) ($float t
))
104 (declare (cl:float w0 w1 w2 w3 w4 result cor11 area qprev stone step
105 qleft qnow qdiff esterr tolerr temp
)
106 (fixnum i levmin levmax levout nomax nofin nofun lev nim
)
107 (boolean $numer $float
))
112 nofin
(- nomax
(* 8 (+ levmax
(* -
1. levout
) (expt 2.
(1+ levout
))))))
154 (mtell "QUANC8 calculating at X= ~S" (x i
))
155 (setq quanc8-|^
]| nil
))
175 (*$
0.5 (+$
(x (1- i
))
178 (mtell "QUANC8 calculating at X= ~S" (x i
))
179 (setq quanc8-|^
]| nil
))
192 (setq nofun
(+ 8. nofun
))
194 (setq step
(//$
(-$
(x 16.
)
198 (setq qleft
(*$ step
(+$
(*$ w0
(+$
(f 0.
)
208 (setf (qright (1+ lev
))
209 (*$ step
(+$
(*$ w0
(+$
(f 8.
)
219 (setq qnow
(+$ qleft
(qright (1+ lev
))))
221 (setq qdiff
(-$ qnow qprev
))
223 (setq area
(+$ area qdiff
))
225 (setq esterr
(//$
(abs qdiff
)
237 (if (or (> lev levmax
)
244 (if (< esterr tolerr
)
273 (setf (f (+ 18.
(* -
2. i
)))
274 (f (+ 9.
(* -
1. i
))))
276 (setf (x (+ 18.
(* -
2. i
)))
277 (x (+ 9.
(* -
1. i
))))
287 (setq nofin
(* 2. nofin
))
291 (setq $quanc8_flag
(+$ $quanc8_flag
(//$
(-$ b
(x 0.
))
297 (setq $quanc8_flag
(+$ $quanc8_flag
1.0))
300 (setq result
(+$ result qnow
)
301 $quanc8_errest
(+$ $quanc8_errest esterr
)
302 cor11
(+$ cor11
(//$ qdiff
1023.0)))
305 (if (= nim
(* 2.
(// nim
2.
)))
308 (setq nim
(// nim
2.
))
321 (setq qprev
(qright lev
))
346 (setq result
(+$ result cor11
))
348 (if (= $quanc8_errest
0.0)
352 (setq temp
(+$ $quanc8_errest
(abs result
)))
354 (if (not (= temp
(abs result
)))
357 (setq $quanc8_errest
(*$
2.0 $quanc8_errest
))
361 ;; For whatever reason and with a suitable
362 ;; discrete meaning of convergence...
363 (merror "QUANC8 failed to converge.")))))