aboutsummaryrefslogtreecommitdiff
path: root/src/interp/sfsfun.boot.pamphlet
diff options
context:
space:
mode:
Diffstat (limited to 'src/interp/sfsfun.boot.pamphlet')
-rw-r--r--src/interp/sfsfun.boot.pamphlet1031
1 files changed, 1031 insertions, 0 deletions
diff --git a/src/interp/sfsfun.boot.pamphlet b/src/interp/sfsfun.boot.pamphlet
new file mode 100644
index 00000000..50bd7b5b
--- /dev/null
+++ b/src/interp/sfsfun.boot.pamphlet
@@ -0,0 +1,1031 @@
+\documentclass{article}
+\usepackage{axiom}
+\begin{document}
+\title{\$SPAD/src/interp sfsfun.boot}
+\author{The Axiom Team}
+\maketitle
+\begin{abstract}
+\end{abstract}
+\eject
+\tableofcontents
+\eject
+\begin{verbatim}
+NOTEfrom TTT: at least BesselJAsymptOrder needs work
+
+1. This file contains the contents of BWC's original files:
+ floaterrors.boot
+ floatutils.boot
+ rgamma.boot
+ cgamma.boot
+ rpsi.boot
+ cpsi.boot
+ f01.boot
+ chebf01cmake.boot
+ chebevalsf.boot
+ besselIJ.boot
+
+2. All declarations have been commented out with "--@@"
+ since the boot translator is generating bad lisp code from them.
+
+3. The functions PsiAsymptotic, PsiEps and PsiAsymptoticOrder
+ had inconpatible definitions in rpsi.boot and cpsi.boot --
+ the local variables were declared float in one file and COMPLEX in
+ the other. The type declarations have been commented out and the
+ duplicate definitions have been deleted.
+
+4. BesselIJ was not compiling. I have modified the code from that
+ file to make it compile. It should be checked for correctness.
+
+SMW June 25, 1991
+
+"Fixes" to BesselJ, B. Char June 14, 1992. Needs extensive testing and
+ further fixes to BesselI and BesselJ.
+More fixes to BesselJ, T. Tsikas 24 Feb, 1995.
+
+\end{verbatim}
+\section{License}
+<<license>>=
+-- Copyright (c) 1991-2002, The Numerical ALgorithms Group Ltd.
+-- All rights reserved.
+--
+-- Redistribution and use in source and binary forms, with or without
+-- modification, are permitted provided that the following conditions are
+-- met:
+--
+-- - Redistributions of source code must retain the above copyright
+-- notice, this list of conditions and the following disclaimer.
+--
+-- - Redistributions in binary form must reproduce the above copyright
+-- notice, this list of conditions and the following disclaimer in
+-- the documentation and/or other materials provided with the
+-- distribution.
+--
+-- - Neither the name of The Numerical ALgorithms Group Ltd. nor the
+-- names of its contributors may be used to endorse or promote products
+-- derived from this software without specific prior written permission.
+--
+-- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+-- IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+-- TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+-- PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+-- OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+-- EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+-- PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+-- PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+-- LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+-- NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+-- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+@
+<<*>>=
+<<license>>
+
+-- Used to be SPECFNSF
+)package "BOOT"
+
+FloatError(formatstring,arg) ==
+-- ERROR(formatstring,arg)
+ ERROR FORMAT([],formatstring,arg)
+
+nangenericcomplex () ==
+ 1.0/COMPLEX(0.0)
+
+
+
+fracpart(x) ==
+ CADR(MULTIPLE_-VALUE_-LIST(FLOOR(x)))
+
+intpart(x) ==
+ CAR(MULTIPLE_-VALUE_-LIST(FLOOR(x)))
+
+negintp(x) ==
+ if ZEROP IMAGPART(x) and x<0.0 and ZEROP fracpart(x)
+ then
+ true
+ else
+ false
+
+--- Small float implementation of Gamma function. Valid for
+--- real arguments. Maximum error (relative) seems to be
+--- 2-4 ulps for real x 2<x<9, and up to ten ulps for larger x
+--- up to overflow. See Hart & Cheney.
+--- Bruce Char, April, 1990.
+
+horner(l,x) ==
+ result := 0
+ for el in l repeat
+ result := result *x + el
+ return result
+
+rgamma (x) ==
+ if COMPLEXP(x) then FloatError('"Gamma not implemented for complex value ~D",x)
+ ZEROP (x-1.0) => 1.0
+ if x>20 then gammaStirling(x) else gammaRatapprox(x)
+
+lnrgamma (x) ==
+ if x>20 then lnrgammaRatapprox(x) else LOG(gammaRatapprox(x))
+
+cbeta(z,w) ==
+ cgamma(z)*cgamma(w)/(cgamma(z+w))
+
+gammaStirling(x) ==
+ EXP(lnrgamma(x))
+
+lnrgammaRatapprox(x) ==
+ (x-.5)*LOG(x) - x + LOG(SQRT(2.0*PI)) + phiRatapprox(x)
+
+phiRatapprox(x) ==
+ arg := 1/(x**2)
+ p := horner([.0666629070402007526,_
+ .6450730291289920251389,_
+ .670827838343321349614617,_
+ .12398282342474941538685913],arg);
+ q := horner([1.0,7.996691123663644194772,_
+ 8.09952718948975574728214,_
+ 1.48779388109699298468156],arg);
+ result := p/(x*q)
+ result
+
+gammaRatapprox (x) ==
+ if (x>=2 and x<=3)
+ then
+ result := gammaRatkernel(x)
+ else
+ if x>3
+ then
+ n := FLOOR(x)-2
+ a := x-n-2
+ reducedarg := 2+a
+ prod := */[reducedarg+i for i in 0..n-1]
+ result := prod* gammaRatapprox(reducedarg)
+ else
+ if (2>x and x>0)
+ then
+ n := 2-FLOOR(x)
+ a := x-FLOOR(x)
+ reducedarg := 2+a
+ prod := */[x+i for i in 0..n-1]
+ result := gammaRatapprox(reducedarg)/prod
+ else
+ Pi := PI
+ lx := MULTIPLE_-VALUE_-LIST(FLOOR(x))
+ intpartx := CAR(lx)+1
+ restx := CADR(lx)
+ if ZEROP restx -- case of negative non-integer value
+ then
+ FloatError ('"Gamma undefined for non-positive integers: ~D",x)
+ result := nangenericcomplex ()
+ else
+ result := Pi/(gammaRatapprox(1.0-x)*(-1.0)**(intpartx+1)*SIN(restx*Pi))
+ result
+
+gammaRatkernel(x) ==
+ p := horner(REVERSE([3786.01050348257245475108,_
+ 2077.45979389418732098416,_
+ 893.58180452374981423868,_
+ 222.1123961680117948396,_
+ 48.95434622790993805232,_
+ 6.12606745033608429879,_
+ .778079585613300575867]),x-2)
+ q := horner(REVERSE([3786.01050348257187258861,_
+ 476.79386050368791516095,_
+ -867.23098753110299445707,_
+ 83.55005866791976957459,_
+ 50.78847532889540973716,_
+ -13.40041478578134826274,_
+ 1]),x-2.0)
+ p/q
+
+-- cgamma(z) Gamma function for complex arguments.
+-- Bruce Char April-May, 1990.
+--
+-- Our text for complex gamma is H. Kuki's paper Complex Gamma
+-- Function with Error Control", CACM vol. 15, no. 4, ppp. 262-267.
+-- (April, 1972.) It uses the reflection formula and the basic
+-- z+1 recurrence to transform the argument into something that
+-- Stirling's asymptotic formula can handle.
+--
+-- However along the way it does a few tricky things to reduce
+-- problems due to roundoff/cancellation error for particular values.
+
+-- cgammat is auxiliary "t" function (see p. 263 Kuki)
+cgammat(x) ==
+ MAX(0.1, MIN(10.0, 10.0*SQRT(2.0) - ABS(x)))
+
+cgamma (z) ==
+ z2 := IMAGPART(z)
+ z1 := REALPART(z) --- call real valued gamma if z is real
+ if ZEROP z2
+ then result := rgamma(z1)
+ else
+ result := clngamma(z1,z2,z)
+ result := EXP(result)
+ result
+
+lncgamma(z) ==
+ clngamma(REALPART z, IMAGPART z, z)
+
+clngamma(z1,z2,z) ==
+ --- conjugate of gamma is gamma of conjugate. map 2nd and 4th quads
+ --- to first and third quadrants
+ if z1<0.0
+ then if z2 > 0.0
+ then result := CONJUGATE(clngammacase1(z1,-z2,COMPLEX(z1,-z2)))
+ else result := clngammacase1(z1,z2,z)
+ else if z2 < 0.0
+ then result := CONJUGATE(clngammacase23(z1,-z2,_
+ COMPLEX(z1,-z2)))
+ else result := clngammacase23(z1,z2,z)
+ result
+
+clngammacase1(z1,z2,z) ==
+ result1 := PiMinusLogSinPi(z1,z2,z)
+ result2 := clngamma(1.0-z1,-z2,1.0-z)
+ result1-result2
+
+PiMinusLogSinPi(z1,z2,z) ==
+ cgammaG(z1,z2) - logH(z1,z2,z)
+
+cgammaG(z1,z2) ==
+ LOG(2*PI) + PI*z2 - COMPLEX(0.0,1.0)*PI*(z1-.5)
+
+logH(z1,z2,z) ==
+ z1bar := CADR(MULTIPLE_-VALUE_-LIST(FLOOR(z1))) ---frac part of z1
+ piz1bar := PI*z1bar
+ piz2 := PI*z2
+ twopiz2 := 2.0*piz2
+ i := COMPLEX(0.0,1.0)
+ part2 := EXP(twopiz2)*(2.0*SIN(piz1bar)**2 + SIN(2.0*piz1bar)*i)
+ part1 := -TANH(piz2)*(1.0+EXP(twopiz2))
+--- part1 is another way of saying 1 - exp(2*Pi*z1bar)
+ LOG(part1+part2)
+
+clngammacase23(z1,z2,z) ==
+ tz2 := cgammat(z2)
+ if (z1 < tz2)
+ then result:= clngammacase2(z1,z2,tz2,z)
+ else result:= clngammacase3(z)
+ result
+
+clngammacase2(z1,z2,tz2,z) ==
+ n := float(CEILING(tz2-z1))
+ zpn := z+n
+ (z-.5)*LOG(zpn) - (zpn) + cgammaBernsum(zpn) - cgammaAdjust(logS(z1,z2,z,n,zpn))
+
+logS(z1,z2,z,n,zpn) ==
+ sum := 0.0
+ for k in 0..(n-1) repeat
+ if z1+k < 5.0 - 0.6*z2
+ then sum := sum + LOG((z+k)/zpn)
+ else sum := sum + LOG(1.0 - (n-k)/zpn)
+ sum
+
+--- on p. 265, Kuki, logS result should have its imaginary part
+--- adjusted by 2 Pi if it is negative.
+cgammaAdjust(z) ==
+ if IMAGPART(z)<0.0
+ then result := z + COMPLEX(0.0, 2.0*PI)
+ else result := z
+ result
+
+clngammacase3(z) ==
+ (z- .5)*LOG(z) - z + cgammaBernsum(z)
+
+cgammaBernsum (z) ==
+ sum := LOG(2.0*PI)/2.0
+ zterm := z
+ zsquaredinv := 1.0/(z*z)
+ l:= [.083333333333333333333, -.0027777777777777777778,_
+ .00079365079365079365079, -.00059523809523809523810,_
+ .00084175084175084175084, -.0019175269175269175269,_
+ .0064102564102564102564]
+ for m in 1..7 for el in l repeat
+ zterm := zterm*zsquaredinv
+ sum := sum + el*zterm
+ sum
+
+
+
+
+--- nth derivatives of ln gamma for real x, n = 0,1,....
+--- requires files floatutils, rgamma
+$PsiAsymptoticBern := VECTOR(0.0, 0.1666666666666667, -0.03333333333333333, 0.02380952380952381,_
+ -0.03333333333333333, 0.07575757575757576, -0.2531135531135531, 1.166666666666667,_
+ -7.092156862745098, 54.97117794486216, -529.1242424242424, 6192.123188405797,_
+ -86580.25311355311, 1425517.166666667, -27298231.06781609, 601580873.9006424,_
+ -15116315767.09216, 429614643061.1667, -13711655205088.33, 488332318973593.2,_
+ -19296579341940070.0, 841693047573682600.0, -40338071854059460000.0)
+
+
+PsiAsymptotic(n,x) ==
+ xn := x**n
+ xnp1 := xn*x
+ xsq := x*x
+ xterm := xsq
+ factterm := rgamma(n+2)/2.0/rgamma(float(n+1))
+ --- initialize to 1/n!
+ sum := AREF($PsiAsymptoticBern,1)*factterm/xterm
+ for k in 2..22 repeat
+ xterm := xterm * xsq
+ if n=0 then factterm := 1.0/float(2*k)
+ else if n=1 then factterm := 1
+ else factterm := factterm * float(2*k+n-1)*float(2*k+n-2)/(float(2*k)*float(2*k-1))
+ sum := sum + AREF($PsiAsymptoticBern,k)*factterm/xterm
+ PsiEps(n,x) + 1.0/(2.0*xnp1) + 1.0/xn * sum
+
+
+PsiEps(n,x) ==
+ if n = 0
+ then
+ result := -LOG(x)
+ else
+ result := 1.0/(float(n)*(x**n))
+ result
+
+PsiAsymptoticOrder(n,x,nterms) ==
+ sum := 0
+ xterm := 1.0
+ np1 := n+1
+ for k in 0..nterms repeat
+ xterm := (x+float(k))**np1
+ sum := sum + 1.0/xterm
+ sum
+
+
+rPsi(n,x) ==
+ if x<=0.0
+ then
+ if ZEROP fracpart(x)
+ then FloatError('"singularity encountered at ~D",x)
+ else
+ m := MOD(n,2)
+ sign := (-1)**m
+ if fracpart(x)=.5
+ then
+ skipit := 1
+ else
+ skipit := 0
+ sign*((PI**(n+1))*cotdiffeval(n,PI*(-x),skipit) + rPsi(n,1.0-x))
+ else if n=0
+ then
+ - rPsiW(n,x)
+ else
+ rgamma(float(n+1))*rPsiW(n,x)*(-1)**MOD(n+1,2)
+
+---Amos' w function, with w(0,x) picked to be -psi(x) for x>0
+rPsiW(n,x) ==
+ if (x <=0 or n < 0)
+ then
+ HardError('"rPsiW not implemented for negative n or non-positive x")
+ nd := 6 -- magic number for number of digits in a word?
+ alpha := 3.5 + .40*nd
+ beta := 0.21 + (.008677e-3)*(nd-3) + (.0006038e-4)*(nd-3)**2
+ xmin := float(FLOOR(alpha + beta*n) + 1)
+ if n>0
+ then
+ a := MIN(0,1.0/float(n)*LOG(DOUBLE_-FLOAT_-EPSILON/MIN(1.0,x)))
+ c := EXP(a)
+ if ABS(a) >= 0.001
+ then
+ fln := x/c*(1.0-c)
+ else
+ fln := -x*a/c
+ bign := FLOOR(fln) + 1
+--- Amos says to use alternative series for large order if ordinary
+--- backwards recurrence too expensive
+ if (bign < 15) and (xmin > 7.0+x)
+ then
+ return PsiAsymptoticOrder(n,x,bign)
+ if x>= xmin
+ then
+ return PsiAsymptotic(n,x)
+---ordinary case -- use backwards recursion
+ PsiBack(n,x,xmin)
+
+PsiBack(n,x,xmin) ==
+ xintpart := PsiIntpart(x)
+ x0 := x-xintpart ---frac part of x
+ result := PsiAsymptotic(n,x0+xmin+1.0)
+ for k in xmin..xintpart by -1 repeat
+--- Why not decrement from x? See Amos p. 498
+ result := result + 1.0/((x0 + float(k))**(n+1))
+ result
+
+
+PsiIntpart(x) ==
+ if x<0
+ then
+ result := -PsiInpart(-x)
+ else
+ result := FLOOR(x)
+ return result
+
+
+---Code for computation of derivatives of cot(z), necessary for
+--- polygamma reflection formula. If you want to compute n-th derivatives of
+---cot(Pi*x), you have to multiply the result of cotdiffeval by Pi**n.
+
+-- MCD: This is defined at the Lisp Level.
+-- COT(z) ==
+-- 1.0/TAN(z)
+
+cotdiffeval(n,z,skipit) ==
+---skip=1 if arg z is known to be an exact multiple of Pi/2
+ a := MAKE_-ARRAY(n+2)
+ SETF(AREF(a,0),0.0)
+ SETF(AREF(a,1),1.0)
+ for i in 2..n repeat
+ SETF(AREF(a,i),0.0)
+ for l in 1..n repeat
+ m := MOD(l+1,2)
+ for k in m..l+1 by 2 repeat
+ if k<1
+ then
+ t1 := 0
+ else
+ t1 := -AREF(a,k-1)*(k-1)
+ if k>l
+ then
+ t2 := 0
+ else
+ t2 := -AREF(a,k+1)*(k+1)
+ SETF(AREF(a,k), t1+t2)
+ --- evaluate d^N/dX^N cot(z) via Horner-like rule
+ v := COT(z)
+ sq := v**2
+ s := AREF(a,n+1)
+ for i in (n-1)..0 by -2 repeat
+ s := s*sq + AREF(a,i)
+ m := MOD(n,2)
+ if m=0
+ then
+ s := s*v
+ if skipit=1
+ then
+ if m=0
+ then
+ return 0
+ else
+ return AREF(a,0)
+ else
+ return s
+--- nth derivatives of ln gamma for complex z, n=0,1,...
+--- requires files rpsi (and dependents), floaterrors
+--- currently defined only in right half plane until reflection formula
+--- works
+
+--- B. Char, June, 1990.
+
+cPsi(n,z) ==
+ x := REALPART(z)
+ y := IMAGPART(z)
+ if ZEROP y
+ then --- call real function if real
+ return rPsi(n,x)
+ if y<0.0
+ then -- if imagpart(z) negative, take conjugate of conjugate
+ conjresult := cPsi(n,COMPLEX(x,-y))
+ return COMPLEX(REALPART(conjresult),-IMAGPART(conjresult))
+ nterms := 22
+ bound := 10.0
+ if x<0.0 --- and ABS(z)>bound and ABS(y)<bound
+ then
+ FloatError('"Psi implementation can't compute at ~S ",[n,z])
+--- return cpsireflect(n,x,y,z)
+ else if (x>0.0 and ABS(z)>bound ) --- or (x<0.0 and ABS(y)>bound)
+ then
+ return PsiXotic(n,PsiAsymptotic(n,z))
+ else --- use recursion formula
+ m := CEILING(SQRT(bound*bound - y*y) - x + 1.0)
+ result := COMPLEX(0.0,0.0)
+ for k in 0..(m-1) repeat
+ result := result + 1.0/((z + float(k))**(n+1))
+ return PsiXotic(n,result+PsiAsymptotic(n,z+m))
+
+PsiXotic(n,result) ==
+ rgamma(float(n+1))*(-1)**MOD(n+1,2)*result
+
+cpsireflect(n,z) ==
+ m := MOD(n,2)
+ sign := (-1)**m
+ sign*PI**(n+1)*cotdiffeval(n,PI*z,0) + cPsi(n,1.0-z)
+
+--- c parameter to 0F1, possibly complex
+--- z argument to 0F1
+--- Depends on files floaterror, floatutils
+
+--- Program transcribed from Fortran,, p. 80 Luke 1977
+
+chebf01 (c,z) ==
+--- w scale factor so that 0<z/w<1
+--- n n+2 coefficients will be produced stored in an array
+--- indexed from 0 to n+1.
+--- See Luke's books for further explanation
+ n := 75 --- ad hoc decision
+--- if ABS(z)/ABS(c) > 200.0 and ABS(z)>10000.0
+--- then
+--- FloatError('"cheb0F1 not implemented for ~S < 1",[c,z])
+ w := 2.0*z
+--- arr will be used to store the Cheb. series coefficients
+ four:= 4.0
+ start := EXPT(10.0, -200)
+ n1 := n+1
+ n2 := n+2
+ a3 := 0.0
+ a2 := 0.0
+ a1 := start -- arbitrary starting value
+ z1 := four/w
+ ncount := n1
+ arr := MAKE_-ARRAY(n2)
+ SETF(AREF(arr,ncount) , start) -- start off
+ x1 := n2
+ c1 := 1.0 - c
+ for ncount in n..0 by -1 repeat
+ divfac := 1.0/x1
+ x1 := x1 -1.0
+ SETF(AREF(arr,ncount) ,_
+ x1*((divfac+z1*(x1-c1))*a1 +_
+ (1.0/x1 + z1*(x1+c1+1.0))*a2-divfac*a3))
+ a3 := a2
+ a2 := a1
+ a1 := AREF(arr,ncount)
+ SETF(AREF(arr,0),AREF(arr,0)/2.0)
+-- compute scale factor
+ rho := AREF(arr,0)
+ sum := rho
+ p := 1.0
+ for i in 1..n1 repeat
+ rho := rho - p*AREF(arr,i)
+ sum := sum+AREF(arr,i)
+ p := -p
+ for l in 0..n1 repeat
+ SETF(AREF(arr,l), AREF(arr,l)/rho)
+ sum := sum/rho
+--- Now evaluate array at argument
+ b := 0.0
+ temp := 0.0
+ for i in (n+1)..0 by -1 repeat
+ cc := b
+ b := temp
+ temp := -cc + AREF(arr,i)
+ temp
+
+
+brutef01(c,z) ==
+-- Use series definition. Won't work well if cancellation occurs
+ term := 1.0
+ sum := term
+ n := 0.0
+ oldsum := 0.0
+ maxnterms := 10000
+ for i in 0..maxnterms until oldsum=sum repeat
+ oldsum := sum
+ term := term*z/(c+n)/(n+1.0)
+ sum := sum + term
+ n := n+1.0
+ sum
+
+f01(c,z)==
+ if negintp(c)
+ then
+ FloatError('"0F1 not defined for negative integer parameter value ~S",c)
+-- conditions when we'll permit the computation
+ else if ABS(c)<1000.0 and ABS(z)<1000.0
+ then
+ brutef01(c,z)
+ else if ZEROP IMAGPART(z) and ZEROP IMAGPART(c) and z>=0.0 and c>=0.0
+ then
+ brutef01(c,z)
+--- else
+--- t := SQRT(-z)
+--- c1 := c-1.0
+--- p := PHASE(c)
+--- if ABS(c)>10.0*ABS(t) and p>=0.0 and PHASE(c)<.90*PI
+--- then BesselJAsymptOrder(c1,2*t)*cgamma(c/(t**(c1)))
+--- else if ABS(t)>10.0*ABS(c) and ABS(t)>50.0
+--- then BesselJAsympt(c1,2*t)*cgamma(c/(t**(c1)))
+--- else
+--- FloatError('"0F1 not implemented for ~S",[c,z])
+ else if (10.0*ABS(c)>ABS(z)) and ABS(c)<1.0E4 and ABS(z)<1.0E4
+ then
+ brutef01(c,z)
+ else
+ FloatError('"0F1 not implemented for ~S",[c,z])
+
+--- c parameter to 0F1
+--- w scale factor so that 0<z/w<1
+--- n n+2 coefficients will be produced stored in an array
+--- indexed from 0 to n+1.
+--- See Luke's books for further explanation
+
+--- Program transcribed from Fortran,, p. 80 Luke 1977
+chebf01coefmake (c,w,n) ==
+--- arr will be used to store the Cheb. series coefficients
+ four:= 4.0
+ start := EXPT(10.0, -200)
+ n1 := n+1
+ n2 := n+2
+ a3 := 0.0
+ a2 := 0.0
+ a1 := start -- arbitrary starting value
+ z1 := four/w
+ ncount := n1
+ arr := MAKE_-ARRAY(n2)
+ SETF(AREF(arr,ncount) , start) -- start off
+ x1 := n2
+ c1 := 1.0 - c
+ for ncount in n..0 by -1 repeat
+ divfac := 1.0/x1
+ x1 := x1 -1.0
+ SETF(AREF(arr,ncount) ,_
+ x1*((divfac+z1*(x1-c1))*a1 +_
+ (1.0/x1 + z1*(x1+c1+1.0))*a2-divfac*a3))
+ a3 := a2
+ a2 := a1
+ a1 := AREF(arr,ncount)
+ SETF(AREF(arr,0),AREF(arr,0)/2.0)
+-- compute scale factor
+ rho := AREF(arr,0)
+ sum := rho
+ p := 1.0
+ for i in 1..n1 repeat
+ rho := rho - p*AREF(arr,i)
+ sum := sum+AREF(arr,i)
+ p := -p
+ for l in 0..n1 repeat
+ SETF(AREF(arr,l), AREF(arr,l)/rho)
+ sum := sum/rho
+ return([sum,arr])
+
+
+
+
+---evaluation of Chebychev series of degree n at x, where the series's
+---coefficients are given by the list in descending order (coef. of highest
+---power first)
+
+---May be numerically unstable for certain lists of coefficients;
+--- could possibly reverse sequence of coefficients
+
+--- Cheney and Hart p. 15.
+
+--- B. Char, March 1990
+
+chebeval (coeflist,x) ==
+ b := 0;
+ temp := 0;
+ y := 2*x;
+
+ for el in coeflist repeat
+ c := b;
+ b := temp
+ temp := y*b -c + el
+ (temp -c)/2
+
+
+chebevalarr(coefarr,x,n) ==
+ b := 0;
+ temp := 0;
+ y := 2*x;
+
+ for i in 1..n repeat
+ c := b;
+ b := temp
+ temp := y*b -c + coefarr.i
+ (temp -c)/2
+
+--- If plist is a list of coefficients for the Chebychev approximation
+--- of a function f(x), then chebderiveval computes the Chebychev approximation
+--- of f'(x). See Luke, "Special Functions and their approximations, vol. 1
+--- Academic Press 1969., p. 329 (from Clenshaw and Cooper)
+
+--- < definition to be supplied>
+
+--- chebstareval(plist,n) computes a Chebychev approximation from a
+--- coefficient list, using shifted Chebychev polynomials of the first kind
+--- The defining relation is that T*(n,x) = T(n,2*x-1). Thus the interval
+--- [0,1] of T*n is the interval [-1,1] of Tn.
+
+chebstareval(coeflist,x) == -- evaluation of T*(n,x)
+ b := 0
+ temp := 0
+ y := 2*(2*x-1)
+
+ for el in coeflist repeat
+ c := b;
+ b := temp
+ temp := y*b -c + el
+ temp - y*b/2
+
+
+chebstarevalarr(coefarr,x,n) == -- evaluation of sum(C(n)*T*(n,x))
+
+ b := 0
+ temp := 0
+ y := 2*(2*x-1)
+
+ for i in (n+1)..0 by -1 repeat
+ c := b
+ b := temp
+ temp := y*b -c + AREF(coefarr,i)
+ temp - y*b/2
+
+--Float definitions for Bessel functions I and J.
+--External references: cgamma, rgamma, chebf01coefmake, chebevalstarsf
+-- floatutils
+
+---BesselJ works for complex and real values of v and z
+BesselJ(v,z) ==
+---Ad hoc boundaries for approximation
+ B1:= 10
+ B2:= 10
+ n := 50 --- number of terms in Chebychev series.
+ --- tests for negative integer order
+ (FLOATP(v) and ZEROP fracpart(v) and (v<0)) or (COMPLEXP(v) and ZEROP IMAGPART(v) and ZEROP fracpart(REALPART(v)) and REALPART(v)<0.0) =>
+ --- odd or even according to v (9.1.5 A&S)
+ --- $J_{-n}(z)=(-1)^{n} J_{n}(z)$
+ BesselJ(-v,z)*EXPT(-1.0,v)
+ (FLOATP(z) and (z<0)) or (COMPLEXP(z) and REALPART(z)<0.0) =>
+ --- negative argument (9.1.35 A&S)
+ --- $J_{\nu}(z e^{m \pi i}) = e^{m \nu \pi i} J_{\nu}(z)$
+ BesselJ(v,-z)*EXPT(-1.0,v)
+ ZEROP z and ((FLOATP(v) and (v>=0.0)) or (COMPLEXP(v) and
+ ZEROP IMAGPART(v) and REALPART(v)>=0.0)) => --- zero arg, pos. real order
+ ZEROP v => 1.0 --- J(0,0)=1
+ 0.0 --- J(v,0)=0 for real v>0
+ rv := ABS(v)
+ rz := ABS(z)
+ (rz>B1) and (rz > B2*rv) => --- asymptotic argument
+ BesselJAsympt(v,z)
+ (rv>B1) and (rv > B2*rz) => --- asymptotic order
+ BesselJAsymptOrder(v,z)
+ (rz< B1) and (rv<B1) => --- small order and argument
+ arg := -(z*z)/4.0
+ w := 2.0*arg
+ vp1 := v+1.0
+ [sum,arr] := chebf01coefmake(vp1,w,n)
+ ---if we get NaNs then half n
+ while not _=(sum,sum) repeat
+ n:=FLOOR(n/2)
+ [sum,arr] := chebf01coefmake(vp1,w,n)
+ ---now n is safe, can we increase it (we know that 2*n is bad)?
+ chebstarevalarr(arr,arg/w,n)/cgamma(vp1)*EXPT(z/2.0,v)
+ true => BesselJRecur(v,z)
+ FloatError('"BesselJ not implemented for ~S", [v,z])
+
+BesselJRecur(v,z) ==
+ -- boost order
+ --Numerical.Recipes. suggest so:=v+sqrt(n.s.f.^2*v)
+ so:=15.0*z
+ -- reduce order until non-zero
+ while ZEROP ABS(BesselJAsymptOrder(so,z)) repeat so:=so/2.0
+ if ABS(so)<ABS(z) then so:=v+18.*SQRT(v)
+ m:= FLOOR(ABS(so-v))+1
+ w:=MAKE_-ARRAY(m)
+ SETF(AREF(w,m-1),BesselJAsymptOrder(v+m-1,z))
+ SETF(AREF(w,m-2),BesselJAsymptOrder(v+m-2,z))
+ for i in m-3 .. 0 by -1 repeat
+ SETF(AREF(w,i), 2.0 * (v+i+1.0) * AREF(w,i+1) /z -AREF(w,i+2))
+ AREF(w,0)
+
+BesselI(v,z) ==
+ B1 := 15.0
+ B2 := 10.0
+ ZEROP(z) and FLOATP(v) and (v>=0.0) => --- zero arg, pos. real order
+ ZEROP(v) => 1.0 --- I(0,0)=1
+ 0.0 --- I(v,0)=0 for real v>0
+--- Transformations for negative integer orders
+ FLOATP(v) and ZEROP(fracpart(v)) and (v<0) => BesselI(-v,z)
+--- Halfplane transformations for Re(z)<0
+ REALPART(z)<0.0 => BesselI(v,-z)*EXPT(-1.0,v)
+--- Conjugation for complex order and real argument
+ REALPART(v)<0.0 and not ZEROP IMAGPART(v) and FLOATP(z) =>
+ CONJUGATE(BesselI(CONJUGATE(v),z))
+---We now know that Re(z)>= 0.0
+ ABS(z) > B1 => --- asymptotic argument case
+ FloatError('"BesselI not implemented for ~S",[v,z])
+ ABS(v) > B1 =>
+ FloatError('"BesselI not implemented for ~S",[v,z])
+--- case of small argument and order
+ REALPART(v)>= 0.0 => besselIback(v,z)
+ REALPART(v)< 0.0 =>
+ chebterms := 50
+ besselIcheb(z,v,chebterms)
+ FloatError('"BesselI not implemented for ~S",[v,z])
+
+--- Compute n terms of the chebychev series for f01
+besselIcheb(z,v,n) ==
+ arg := (z*z)/4.0
+ w := 2.0*arg;
+ vp1 := v+1.0;
+ [sum,arr] := chebf01coefmake(vp1,w,n)
+ result := chebstarevalarr(arr,arg/w,n)/cgamma(vp1)*EXPT(z/2.0,v)
+
+besselIback(v,z) ==
+ ipv := IMAGPART(v)
+ rpv := REALPART(v)
+ lm := MULTIPLE_-VALUE_-LIST(FLOOR(rpv))
+ m := CAR(lm) --- floor of real part of v
+ n := 2*MAX(20,m+10) --- how large the back recurrence should be
+ tv := CADR(lm)+(v-rpv) --- fractional part of real part of v
+ --- plus imaginary part of v
+ vp1 := tv+1.0;
+ result := BesselIBackRecur(v,m,tv,z,'"I",n)
+ result := result/cgamma(vp1)*EXPT(z/2.0,tv)
+
+--- Backward recurrence for Bessel functions. Luke (1975), p. 247.
+--- works for -Pi< arg z <= Pi and -Pi < arg v <= Pi
+BesselIBackRecur(largev,argm,v,z,type,n) ==
+--- v + m = largev
+ one := 1.0
+ two := 2.0
+ zero := 0.0
+ start := EXPT(10.0,-40)
+ z2 := two/z
+ m2 := n+3
+ w:=MAKE_-ARRAY(m2+1)
+ SETF(AREF(w,m2), zero) --- start off
+ if type = '"I"
+ then
+ val := one
+ else
+ val := -one
+ m1 := n+2
+ SETF(AREF(w,m1), start)
+ m := n+1
+ xm := float(m)
+ ct1 := z2*(xm+v)
+ --- initialize
+ for m in (n+1)..1 by -1 repeat
+ SETF(AREF(w,m), AREF(w,m+1)*ct1 + val*AREF(w,m+2))
+ ct1 := ct1 - z2
+ m := 1 + FLOOR(n/2)
+ m2 := m + m -1
+ if (v=0)
+ then
+ pn := AREF(w, m2 + 2)
+ for m2 in (2*m-1)..3 by -2 repeat
+ pn := AREF(w, m2) - val *pn
+ pn := AREF(w,1) - val*(pn+pn)
+ else
+ v1 := v-one
+ xm := float(m)
+ ct1 := v + xm + xm
+ pn := ct1*AREF(w, m2 + 2)
+ for m2 in (m+m -1)..3 by -2 repeat
+ ct1 := ct1 - two
+ pn := ct1*AREF(w,m2) - val*pn/xm*(v1+xm)
+ xm := xm - one
+ pn := AREF(w,1) - val * pn
+ m1 := n+2
+ for m in 1..m1 repeat
+ SETF(AREF(w,m), AREF(w,m)/pn)
+ AREF(w,argm+1)
+
+
+
+
+---Asymptotic functions for large values of z. See p. 204 Luke 1969 vol. 1.
+
+--- mu is 4*v**2
+--- zsqr is z**2
+--- zfth is z**4
+
+BesselasymptA(mu,zsqr,zfth) ==
+ (mu -1)/(16.0*zsqr) * (1 + (mu - 13.0)/(8.0*zsqr) + _
+ (mu**2 - 53.0*mu + 412.0)/(48.0*zfth))
+
+BesselasymptB(mu,z,zsqr,zfth) ==
+ musqr := mu*mu
+ z + (mu-1.0)/(8.0*z) *(1.0 + (mu - 25.0)/(48.0*zsqr) + _
+ (musqr - 114.0*mu + 1073.0)/(640.0*zfth) +_
+ (5.0*mu*musqr - 1535.0*musqr + 54703.0*mu - 375733.0)/(128.0*zsqr*zfth))
+
+--- Asymptotic series only works when |v| < |z|.
+
+BesselJAsympt (v,z) ==
+ pi := PI
+ mu := 4.0*v*v
+ zsqr := z*z
+ zfth := zsqr*zsqr
+ SQRT(2.0/(pi*z))*EXP(BesselasymptA(mu,zsqr,zfth))*_
+ COS(BesselasymptB(mu,z,zsqr,zfth) - pi*v/2.0 - pi/4.0)
+
+
+---Asymptotic series for I. See Whittaker, p. 373.
+--- valid for -3/2 Pi < arg z < 1/2 Pi
+
+BesselIAsympt(v,z,n) ==
+ i := COMPLEX(0.0, 1.0)
+ if (REALPART(z) = 0.0)
+ then return EXPT(i,v)*BesselJ(v,-IMAGPART(z))
+ sum1 := 0.0
+ sum2 := 0.0
+ fourvsq := 4.0*v**2
+ two := 2.0
+ eight := 8.0
+ term1 := 1.0
+--- sum1, sum2, fourvsq,two,i,eight,term1])
+ for r in 1..n repeat
+ term1 := -term1 *(fourvsq-(two*float(r)-1.0)**2)/_
+ (float(r)*eight*z)
+ sum1 := sum1 + term1
+ sum2 := sum2 + ABS(term1)
+ sqrttwopiz := SQRT(two*PI*z)
+ EXP(z)/sqrttwopiz*(1.0 + sum1 ) +_
+ EXP(-(float(n)+.5)*PI*i)*EXP(-z)/sqrttwopiz*(1.0+ sum2)
+
+
+---Asymptotic formula for BesselJ when order is large comes from
+---Debye (1909). See Olver, Asymptotics and Special Functions, p. 134.
+---Expansion good for 0<=phase(v)<Pi
+---A&S recommend "uniform expansion" with complicated coefficients and Airy function.
+---Debye's Formula is in 9.3.7,9.3.9,9.3.10 of A&S
+---AXIOM recurrence for u_{k}
+---f(0)==1::EXPR INT
+---f(n)== (t^2)*(1-t^2)*D(f(n-1),t)/2 + (1/8)*integrate( (1-5*t^2)*f(n-1),t)
+BesselJAsymptOrder(v,z) ==
+ sechalpha := z/v
+ alpha := ACOSH(1.0/sechalpha)
+ tanhalpha := SQRT(1.0-(sechalpha*sechalpha))
+ -- cothalpha := 1.0/tanhalpha
+ ca := 1.0/tanhalpha
+
+ Pi := PI
+ ca2:=ca*ca
+ ca4:=ca2*ca2
+ ca8:=ca4*ca4
+ EXP(-v*(alpha-tanhalpha))/SQRT(2.0*Pi*v*tanhalpha)*_
+ (1.0+_
+ horner([ -5.0, 3.0],_
+ ca2)*ca/(v*24.0)+_
+ horner([ 385.0, -462.0, 81.0],_
+ ca2)*ca2/(1152.0*v*v)+_
+ horner([ -425425.0, 765765.0, -369603.0, 30375.0],_
+ ca2)*ca2*ca/(414720.0*v*v*v)+_
+ horner([ 185910725.0, -446185740.0, 349922430.0, -94121676.0, 4465125.0],_
+ ca2)*ca4/(39813120.0*v*v*v*v)+_
+ horner([ -188699385875.0, 566098157625.0, -614135872350.0, 284499769554.0, -49286948607.0, 1519035525.0],_
+ ca2)*ca4*ca/(6688604160.0*v*v*v*v*v)+_
+ horner([1023694168371875.0,-3685299006138750.0,5104696716244125.0,-3369032068261860.0,1050760774457901.0,-127577298354750.0,2757049477875.0],_
+ ca2)*ca4*ca2/(4815794995200.0*v*v*v*v*v*v))
+
+
+--- See Olver, p. 376-382.
+BesselIAsymptOrder(v,vz) ==
+ z := vz/v
+ Pi := PI
+--- Use reflection formula (Atlas, p. 492) if v not in right half plane; Is this always accurate?
+ if REALPART(v)<0.0
+ then return BesselIAsymptOrder(-v,vz) + 2.0/Pi*SIN(-v*Pi)*BesselKAsymptOrder(-v,vz)
+--- Use the reflection formula (Atlas, p. 496) if z not in right half plane;
+ if REALPART(vz) < 0.0
+ then return EXPT(-1.0,v)*BesselIAsymptOrder(v,-vz)
+ vinv := 1.0/v
+ opzsqroh := SQRT(1.0+z*z)
+ eta := opzsqroh + LOG(z/(1.0+opzsqroh))
+ p := 1.0/opzsqroh
+ p2 := p*p
+ p4 := p2*p2
+ u0p := 1.
+ u1p := 1.0/8.0*p-5.0/24.0*p*p2
+ u2p := (9.0/128.0+(-77.0/192.0+385.0/1152.0*p2)*p2)*p2
+ u3p := (75.0/1024.0+(-4563.0/5120.0+(17017.0/9216.0-85085.0/82944.0*p2)_
+ *p2)*p2)*p2*p
+ u4p := (3675.0/32768.0+(-96833.0/40960.0+(144001.0/16384.0+(-7436429.0/663552.0+37182145.0/7962624.0*p2)*p2)*p2)*p2)*p4
+ u5p := (59535.0/262144.0+(-67608983.0/9175040.0+(250881631.0/5898240.0+(-108313205.0/1179648.0+(5391411025.0/63700992.0-5391411025.0/191102976.0*p2)*p2)*p2)*p2)*p2)*p4*p
+ hornerresult := horner([u5p,u4p,u3p,u2p,u1p,u0p],vinv)
+ EXP(v*eta)/(SQRT(2.0*Pi*v)*SQRT(opzsqroh))*hornerresult
+
+
+---See also Olver, pp. 376-382
+BesselKAsymptOrder (v,vz) ==
+ z := vz/v
+ vinv := 1.0/v
+ opzsqroh := SQRT(1.0+z*z)
+ eta := opzsqroh + LOG(z/(1.0+opzsqroh))
+ p := 1.0/opzsqroh
+ p2 := p**2
+ p4 := p2**2
+ u0p := 1.
+ u1p := (1.0/8.0*p-5.0/24.0*p**3)*(-1.0)
+ u2p := (9.0/128.0+(-77.0/192.0+385.0/1152.0*p2)*p2)*p2
+ u3p := ((75.0/1024.0+(-4563.0/5120.0+(17017.0/9216.0-85085.0/82944.0*p2)_
+ *p2)*p2)*p2*p)*(-1.0)
+ u4p := (3675.0/32768.0+(-96833.0/40960.0+(144001.0/16384.0+(-7436429.0/663552.0+37182145.0/7962624.0*p2)*p2)*p2)*p2)*p4
+ u5p := ((59535.0/262144.0+(-67608983.0/9175040.0+(250881631.0/5898240.0+(-108313205.0/1179648.0+(5391411025.0/63700992.0-5391411025.0/191102976.0*p2)*p2)*p2)*p2)*p2)*p4*p)*(-1.0)
+ hornerresult := horner([u5p,u4p,u3p,u2p,u1p,u0p],vinv)
+ SQRT(PI/(2.0*v))*EXP(-v*eta)/(SQRT(opzsqroh))*hornerresult
+
+
+
+
+
+
+
+@
+\eject
+\begin{thebibliography}{99}
+\bibitem{1} nothing
+\end{thebibliography}
+\end{document}