Skip to content

Commit 43a31d6

Browse files
committed
Fix gausslaguerre(2,α) return type
1 parent ada3e7d commit 43a31d6

File tree

2 files changed

+44
-41
lines changed

2 files changed

+44
-41
lines changed

src/gausslaguerre.jl

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,48 @@
11
# (x,w) = gausslaguerre(n) returns n Gauss-Laguerre nodes and weights.
22
# (x,w) = gausslaguerre(n,alpha) allows generalized Gauss-Laguerre quadrature.
33
# (x,w) = gausslaguerre(n,alpha,method) allows the user to select which method to use.
4-
# METHOD = "GW" will use the traditional Golub-Welsch eigenvalue method, which is best for when N is small.
4+
# METHOD = "GW" will use the traditional Golub-Welsch eigenvalue method, which is best for when N is small.
55
# METHOD = "RH" will use asymptotics of Laguerre polynomials, and METHOD = "RHW" is O(sqrt(n)) as it stops when the weights are below realmin. gausslaguerre(round(Int64, (n/17)^2), "RHW") returns about n nodes and weights above realmin(Float64) for large n.
66
# METHOD = "gen" can generate an arbitrary number of terms of the asymptotic expansion of Laguerre-type polynomials, orthogonal with respect to x^alpha*exp(-qm*x^m). "genW" does the same, but stops as the weights underflow.
77
# METHOD = "default" uses "gen" when m or qm are not one, "GW" when 2 < n < 128 and else "RH".
88
function gausslaguerre( n::Int64, alpha::Float64=0.0, method::AbstractString="default", qm::Float64=1.0, m::Int64=1 )
9+
if ( imag(alpha) != 0 ) || ( alpha < -1 )
10+
error(string("alpha = ", alpha, " is not allowed.") )
11+
elseif ( (m != 1) || (qm != 1) ) && ( (method != "gen") && (method != "genW") && (method != "default") )
12+
error(string("Method ", method, " is not implemented for generalised weights.") )
13+
end
914

10-
if ( imag(alpha) != 0 ) || ( alpha < -1 )
11-
error(string("alpha = ", alpha, " is not allowed.") )
12-
elseif ( (m != 1) || (qm != 1) ) && ( (method != "gen") && (method != "genW") && (method != "default") )
13-
error(string("Method ", method, " is not implemented for generalised weights.") )
14-
end
15-
16-
if ( (method == "default") && ( (m != 1) || (qm != 1.0) ) ) || (method == "gen") || (method == "genW")
17-
(x,w) = asyRHgen(n, method == "genW", alpha, m, qm)
18-
w = w/sum(w)*gamma((alpha+1)/m)*qm^(-(alpha+1)/m)/m # We left out a constant factor while computing w in case we use finite differences
19-
(x,w)
20-
elseif (method == "default") && (n == 0)
21-
Float64[], Float64[]
22-
elseif (method == "default") && (n == 1)
23-
[1.0+alpha], [1.0]
24-
elseif (method == "default") && (n == 2)
25-
[alpha+2.-sqrt(alpha+2.) alpha+2.+sqrt(alpha+2.)], [((alpha-sqrt(alpha+2)+2)*gamma(alpha+2))/(2*(alpha+2)*(sqrt(alpha+2)-1)^2) ((alpha+sqrt(alpha+2)+2)*gamma(alpha+2))/(2*(alpha+2)*(sqrt(alpha+2)+1)^2)]
26-
elseif method == "RHW"
27-
laguerreRH( n, true, alpha )   # Use RH and only compute the representable weights
28-
elseif ( (method == "default") && (n < 128 ) ) || (method == "GW")
29-
laguerreGW( n, alpha ) # Use Golub-Welsch
30-
elseif (method == "RH") || ( (method == "default") && (n >= 128) )
31-
laguerreRH( n, false, alpha ) # Use RH
32-
else
33-
error(string("Wrong method string, got ", method) )
34-
end
35-
15+
if ( (method == "default") && ( (m != 1) || (qm != 1.0) ) ) || (method == "gen") || (method == "genW")
16+
(x,w) = asyRHgen(n, method == "genW", alpha, m, qm)
17+
w = w/sum(w)*gamma((alpha+1)/m)*qm^(-(alpha+1)/m)/m # We left out a constant factor while computing w in case we use finite differences
18+
(x,w)
19+
elseif (method == "default") && (n == 0)
20+
Float64[], Float64[]
21+
elseif (method == "default") && (n == 1)
22+
[1.0+alpha], [1.0]
23+
elseif (method == "default") && (n == 2)
24+
[alpha+2.-sqrt(alpha+2.),alpha+2.+sqrt(alpha+2.)], [((alpha-sqrt(alpha+2)+2)*gamma(alpha+2))/(2*(alpha+2)*(sqrt(alpha+2)-1)^2),((alpha+sqrt(alpha+2)+2)*gamma(alpha+2))/(2*(alpha+2)*(sqrt(alpha+2)+1)^2)]
25+
elseif method == "RHW"
26+
laguerreRH( n, true, alpha )   # Use RH and only compute the representable weights
27+
elseif ( (method == "default") && (n < 128 ) ) || (method == "GW")
28+
laguerreGW( n, alpha ) # Use Golub-Welsch
29+
elseif (method == "RH") || ( (method == "default") && (n >= 128) )
30+
laguerreRH( n, false, alpha ) # Use RH
31+
else
32+
error(string("Wrong method string, got ", method) )
33+
end
3634
end
3735

3836
function laguerreGW( n::Int64, alpha::Float64 )
39-
# Calculate Gauss-Laguerre nodes and weights based on Golub-Welsch
40-
37+
# Calculate Gauss-Laguerre nodes and weights based on Golub-Welsch
38+
4139
alph = 2*(1:n)-1+alpha # 3-term recurrence coeffs
4240
beta = sqrt( (1:n-1).*(alpha + (1:n-1) ) )
4341
T = diagm(beta,1) + diagm(alph) + diagm(beta,-1) # Jacobi matrix
4442
x, V = eig( T ) # eigenvalue decomposition
4543
w = gamma(alpha+1)*V[1,:].^2 # Quadrature weights
4644
x, vec(w)
47-
45+
4846
end
4947

5048
########################## Routines for the RH algorithm ##########################
@@ -313,7 +311,7 @@ function asyBulk(np, y, alpha, T)
313311
R1 = R1 + (-7/10485760*alpha^12 + 77/6291456*alpha^11 - 8023/94371840*alpha^10 + 194831/754974720*alpha^9)*d^(-1)/np^6
314312
R1 = R1 + (-1697501/9059696640*alpha^8 - 3268067/4529848320*alpha^7 + 232121/169869312*alpha^6 + 708119/2548039680*alpha^5)*d^(-1)/np^6
315313
R1 = R1 + (-578367767/326149079040*alpha^4 + 7120279/21743271936*alpha^3 +4384859317/6849130659840*alpha^2 - 464353573/5218385264640*alpha - 6115336781/87668872445952)*d^(-1)/np^6
316-
R2 = R2 + (-1/368640*alpha^12 + 3101/94371840*alpha^11 - 4729/37748736*alpha^10 + 387539/6794772480*alpha^9)*d^(-1)/np^6
314+
R2 = R2 + (-1/368640*alpha^12 + 3101/94371840*alpha^11 - 4729/37748736*alpha^10 + 387539/6794772480*alpha^9)*d^(-1)/np^6
317315
R2 = R2 + (698591/1132462080*alpha^8 - 610643/704643072*alpha^7 - 1822295/1811939328*alpha^6 + 154675561/81537269760*alpha^5)*d^(-1)/np^6
318316
R2 = R2 + (212982187/326149079040*alpha^4 - 1334636401/978447237120*alpha^3 -789100727/4566087106560*alpha^2 + 25497378911/109586090557440*alpha + 69110929651/4931374075084800)*d^(-1)/np^6
319317
R1 = R1 + (-13/37748736*alpha^12 + 49/23592960*alpha^11 + 2197/188743680*alpha^10 - 405053/3397386240*alpha^9)*d^(-2)/np^6
@@ -1105,7 +1103,7 @@ function asyRHgen(n, compRepr, alpha, m, qm)
11051103
T = ceil(Int64, 34/log(n) ) # Heuristic for number of terms, should be scaled by the logarithm of eps(Float64) over the machine precision.
11061104
UQ0 = getUQ(alpha, qm ,m, T)
11071105
if compRepr
1108-
mn = min(n,ceil(Int64, exp(exp(1/m)*1.05)*n^(1-1/2/m) ))
1106+
mn = min(n,ceil(Int64, exp(exp(1/m)*1.05)*n^(1-1/2/m) ))
11091107
else
11101108
mn = n
11111109
end
@@ -1124,7 +1122,7 @@ function asyRHgen(n, compRepr, alpha, m, qm)
11241122
w = zeros(mn)
11251123
if useFinDiff
11261124
x = [bes*(2*m-1)^2/16/m^2/n^2*softEdge ; zeros(mn-itric) ]
1127-
else
1125+
else
11281126
ak = [-13.69148903521072; -12.828776752865757; -11.93601556323626; -11.00852430373326; -10.04017434155809; -9.02265085340981; -7.944133587120853; -6.786708090071759; -5.520559828095551; -4.08794944413097; -2.338107410459767]
11291127
t = 3*pi/2*( (igatt:-1:12)-0.25) # [DLMF (9.9.6)]
11301128
ak = [-t.^(2/3).*(1 + 5/48./t.^2 - 5/36./t.^4 + 77125/82944./t.^6 -10856875/6967296./t.^8); ak[max(1,12-igatt):11] ]
@@ -1159,7 +1157,7 @@ function asyRHgen(n, compRepr, alpha, m, qm)
11591157
while ( ( abs(step) > eps(Float64)*40*x[k] ) && ( l < 20) )
11601158
l = l + 1
11611159
pe = polyAsyRHgen(n, x[k], alpha, T, qm, m, UQ0)
1162-
if (abs(pe) >= abs(ov)*(1-35*eps(Float64)) )
1160+
if (abs(pe) >= abs(ov)*(1-35*eps(Float64)) )
11631161
# The function values do not decrease enough any more due to roundoff errors.
11641162
x[k] = ox # Set to the previous value and quit.
11651163
break
@@ -1428,7 +1426,7 @@ function getV(alpha,qm,m::Int64,maxOrder::Int64,r)
14281426
end
14291427
end
14301428
OmOdd = (1+1im)*zeros(mo+1); OmEven = (1+1im)*zeros(mo+1)
1431-
XiOdd = (1+1im)*zeros(mo+1); XiEven = (1+1im)*zeros(mo+1)
1429+
XiOdd = (1+1im)*zeros(mo+1); XiEven = (1+1im)*zeros(mo+1)
14321430
ThOdd = (1+1im)*zeros(mo+1); ThEven = (1+1im)*zeros(mo+1)
14331431
OmO = (1+1im)*zeros(mo+1); OmE = (1+1im)*zeros(mo+1)
14341432
XiO = (1+1im)*zeros(mo+1); XiE = (1+1im)*zeros(mo+1)
@@ -1453,7 +1451,7 @@ function getV(alpha,qm,m::Int64,maxOrder::Int64,r)
14531451
end
14541452
end
14551453
Ts = (1+1im)*zeros(2,2,mo+1) # = G_{k,n}^{odd/even} depending on k, overwritten on each new k
1456-
WV = (1+1im)*zeros(2,2,maxOrder-1,mo+1)
1454+
WV = (1+1im)*zeros(2,2,maxOrder-1,mo+1)
14571455
for k = 1:(maxOrder-1)
14581456
Ts[:,:,:] = 0
14591457
if r == 1
@@ -1471,7 +1469,7 @@ function getV(alpha,qm,m::Int64,maxOrder::Int64,r)
14711469
else
14721470
if mod(k,2) == 1
14731471
for n = 0:mo
1474-
Ts[:,:,n+1] = -(alpha^2+k/2-1/4)/k*[-(-1)^n*(2*binom(-1/2,n-1)*(n>0)+binom(-1/2,n))*2 -1im*4^(-alpha)*2*(-1)^n*binom(-1/2,n) ; -1im*4^(alpha)*2*(-1)^n*binom(-1/2,n) ( (-1)^n*(2*binom(-1/2,n-1)*(n>0) +binom(-1/2,n))*2)] - (k-1/2)*[2*OmO[n+1] 4^(-alpha)*2im*XiO[n+1] ; 4^(alpha)*2im*ThO[n+1] -2*OmO[n+1]] # binom(-1/2,-1) should be zero
1472+
Ts[:,:,n+1] = -(alpha^2+k/2-1/4)/k*[-(-1)^n*(2*binom(-1/2,n-1)*(n>0)+binom(-1/2,n))*2 -1im*4^(-alpha)*2*(-1)^n*binom(-1/2,n) ; -1im*4^(alpha)*2*(-1)^n*binom(-1/2,n) ( (-1)^n*(2*binom(-1/2,n-1)*(n>0) +binom(-1/2,n))*2)] - (k-1/2)*[2*OmO[n+1] 4^(-alpha)*2im*XiO[n+1] ; 4^(alpha)*2im*ThO[n+1] -2*OmO[n+1]] # binom(-1/2,-1) should be zero
14751473
WV[:,:,k,n+1] = -(-1)^(ceil(Int64, k/2)+1)*(1im*sqrt(2))^k*(-2+0im)^(-k/2)/4^(k+1)*brac(k-1,alpha)*sum(repeat(reshape(g[k,1:(n+1) ], (1,1,n+1) ), outer=[2,2,1]).*Ts[:,:,(n+1):-1:1],3)
14761474
end
14771475
else
@@ -1495,7 +1493,7 @@ function getUQ(alpha, qm, m::Int64, maxOrder::Int64)
14951493
Vr = getV(alpha, qm, m, maxOrder, 1)
14961494
Vl = getV(alpha, qm, m, maxOrder, -1)
14971495
UQ = (1+1im)*zeros(2,2,maxOrder-1,ceil(Int64,3*maxOrder/2)+2, 4)
1498-
for kt = 0:(maxOrder-2)
1496+
for kt = 0:(maxOrder-2)
14991497
# Uright(:,:,(maxOrder-1)+1,:) will not be used later on because first term in expansions is without U's
15001498
for mt = 0:(ceil(Int64,3*(kt+1)/2)-1)
15011499
UQ[:,:,kt+1,mt+1,1] = Vr[:,:,kt+1,ceil(Int64,3*(kt+1)/2)-mt]
@@ -1534,6 +1532,3 @@ function getUQ(alpha, qm, m::Int64, maxOrder::Int64)
15341532
end
15351533
UQ
15361534
end
1537-
1538-
1539-

test/test_gausslaguerre.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,3 +144,11 @@ for alpha = [0.0; 4.15]
144144
end
145145
end
146146
end
147+
148+
149+
## Test type is correct
150+
151+
152+
x,w=gausslaguerre(2,0.0)
153+
@test isa(x,Vector{Float64})
154+
@test isa(w,Vector{Float64})

0 commit comments

Comments
 (0)