Skip to content

Commit e06d88a

Browse files
authored
Cholesky instead of Lanczos (#131)
* Cholesky instead of Lanczos * Remove Lanczos * Get more tests passing * more tests pass * cleanup test * v0.6 * Update runtests.jl * Update runtests.jl * Update SemiclassicalOrthogonalPolynomials.jl * fix whitespace
1 parent b3e4cb3 commit e06d88a

5 files changed

+266
-266
lines changed

Project.toml

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "SemiclassicalOrthogonalPolynomials"
22
uuid = "291c01f3-23f6-4eb6-aeb0-063a639b53f2"
33
authors = ["Sheehan Olver <[email protected]>"]
4-
version = "0.5.11"
4+
version = "0.6"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -20,13 +20,13 @@ SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b"
2020
[compat]
2121
ArrayLayouts = "1"
2222
BandedMatrices = "0.17, 1"
23-
ClassicalOrthogonalPolynomials = "0.13, 0.14"
23+
ClassicalOrthogonalPolynomials = "0.14.3"
2424
ContinuumArrays = "0.18"
2525
FillArrays = "1"
2626
HypergeometricFunctions = "0.3.4"
2727
InfiniteArrays = "0.14, 0.15"
28-
InfiniteLinearAlgebra = "0.8, 0.9"
29-
LazyArrays = "2"
28+
InfiniteLinearAlgebra = "0.9.1"
29+
LazyArrays = "2.4"
3030
QuasiArrays = "0.11"
3131
SpecialFunctions = "1.0, 2"
3232
julia = "1.10"

src/SemiclassicalOrthogonalPolynomials.jl

+46-46
Original file line numberDiff line numberDiff line change
@@ -8,19 +8,19 @@ import Base: getindex, axes, size, \, /, *, +, -, summary, show, ==, copy, sum,
88
import ArrayLayouts: MemoryLayout, ldiv, diagonaldata, subdiagonaldata, supdiagonaldata
99
import BandedMatrices: bandwidths, AbstractBandedMatrix, BandedLayout, _BandedMatrix
1010
import LazyArrays: resizedata!, paddeddata, CachedVector, CachedMatrix, CachedAbstractVector, LazyMatrix, LazyVector, arguments, ApplyLayout, colsupport, AbstractCachedVector, ApplyArray,
11-
AccumulateAbstractVector, LazyVector, AbstractCachedMatrix, BroadcastLayout
11+
AccumulateAbstractVector, LazyVector, AbstractCachedMatrix, BroadcastLayout, simplifiable
1212
import ClassicalOrthogonalPolynomials: OrthogonalPolynomial, recurrencecoefficients, jacobimatrix, normalize, _p0, UnitInterval, orthogonalityweight, NormalizedOPLayout, MappedOPLayout,
1313
Bidiagonal, Tridiagonal, SymTridiagonal, symtridiagonalize, normalizationconstant, LanczosPolynomial,
1414
OrthogonalPolynomialRatio, Weighted, AbstractWeightLayout, UnionDomain, oneto, WeightedBasis, HalfWeighted,
15-
golubwelsch, AbstractOPLayout, weight, cholesky_jacobimatrix, qr_jacobimatrix, isnormalized
15+
golubwelsch, AbstractOPLayout, weight, cholesky_jacobimatrix, qr_jacobimatrix, isnormalized, ConvertedOrthogonalPolynomial, AbstractNormalizedOPLayout
1616

1717
import InfiniteArrays: OneToInf, InfUnitRange
1818
import ContinuumArrays: basis, Weight, @simplify, AbstractBasisLayout, BasisLayout, MappedBasisLayout, grid, plotgrid, equals_layout, ExpansionLayout
1919
import FillArrays: SquareEye
2020
import HypergeometricFunctions: _₂F₁general2, _₂F₁
2121
import SpecialFunctions: beta
2222

23-
export LanczosPolynomial, Legendre, Normalized, normalize, SemiclassicalJacobi, SemiclassicalJacobiWeight, WeightedSemiclassicalJacobi, OrthogonalPolynomialRatio
23+
export Legendre, Normalized, normalize, SemiclassicalJacobi, SemiclassicalJacobiWeight, WeightedSemiclassicalJacobi, OrthogonalPolynomialRatio
2424

2525
""""
2626
SemiclassicalJacobiWeight(t, a, b, c)
@@ -131,7 +131,7 @@ WeightedSemiclassicalJacobi{T}(t, a, b, c, P...) where T = SemiclassicalJacobiWe
131131

132132
# Returns α, β such that P1(x) = β(x-α)
133133
function _linear_coefficients(t, a, b, c)
134-
# beta(a + 1, b + 1) * t^c * _₂F₁(a + 1, -c, a + b + 2, 1/t) is the integral ∫₀¹ wᵗ⁽ᵃᵇᶜ⁾(x) dx
134+
# beta(a + 1, b + 1) * t^c * _₂F₁(a + 1, -c, a + b + 2, 1/t) is the integral ∫₀¹ wᵗ⁽ᵃᵇᶜ⁾(x) dx
135135
Γᵃ = beta(a + 1, b + 1) * _₂F₁(a + 1, -c, a + b + 2, 1/t)
136136
Γᵃ⁺¹ = beta(a + 2, b + 1) * _₂F₁(a + 2, -c, a + b + 3, 1/t)
137137
Γᵃ⁺² = beta(a + 3, b + 1) * _₂F₁(a + 3, -c, a + b + 4, 1/t)
@@ -150,7 +150,7 @@ function semiclassical_jacobimatrix(t, a, b, c)
150150
C = -(N)./(N.*4 .- 2)
151151
B = Vcat((α[1]^2*3-α[1]*α[2]*2-1)/6 , -(N)./(N.*4 .+ 2).*α[2:end]./α)
152152
return SymTridiagonal(A, sqrt.(B.*C)) # if J is Tridiagonal(c,a,b) then for norm. OPs it becomes SymTridiagonal(a, sqrt.( b.* c))
153-
elseif b == -one(T)
153+
elseif b == -one(T)
154154
J′ = semiclassical_jacobimatrix(t, a, one(b), c)
155155
J′a, J′b = diagonaldata(J′), supdiagonaldata(J′)
156156
A = Vcat(one(T), J′a[1:end])
@@ -168,7 +168,7 @@ function semiclassical_jacobimatrix(t, a, b, c)
168168
return SemiclassicalJacobi.(t, a, b, 0:Int(c))[end].X
169169
else # if c is not an integer, use Lanczos
170170
x = axes(P,1)
171-
return jacobimatrix(LanczosPolynomial(@.(x^a * (1-x)^b * (t-x)^c), jacobi(b, a, UnitInterval{T}())))
171+
return cholesky_jacobimatrix(@.(x^a * (1-x)^b * (t-x)^c), P)
172172
end
173173
end
174174
end
@@ -178,11 +178,11 @@ function semiclassical_jacobimatrix(Q::SemiclassicalJacobi, a, b, c)
178178
Δb = b-Q.b
179179
Δc = c-Q.c
180180

181-
# special cases
181+
# special cases
182182
if iszero(a) && iszero(b) && c == -one(eltype(Q.t)) # (a,b,c) = (0,0,-1) special case
183183
return semiclassical_jacobimatrix(Q.t, zero(Q.t), zero(Q.t), c)
184184
elseif iszero(Δa) && iszero(Δc) && Δb == 2 && b == 1
185-
# When going from P[t, a, -1, c] to P[t, a, 1, c], you can just take
185+
# When going from P[t, a, -1, c] to P[t, a, 1, c], you can just take
186186
return SymTridiagonal(Q.X.d[2:end], Q.X.du[2:end])
187187
elseif iszero(c) # classical Jacobi polynomial special case
188188
return jacobimatrix(Normalized(jacobi(b, a, UnitInterval{eltype(Q.t)}())))
@@ -233,15 +233,14 @@ function semiclassical_jacobimatrix(Q::SemiclassicalJacobi, a, b, c)
233233
end
234234
end
235235

236-
LanczosPolynomial(P::SemiclassicalJacobi{T}) where T =
237-
LanczosPolynomial(orthogonalityweight(P), Normalized(jacobi(P.b, P.a, UnitInterval{T}())), P.X.dv.data)
236+
ConvertedOrthogonalPolynomial(P::SemiclassicalJacobi{T}) where T = ConvertedOrthogonalPolynomial(orthogonalityweight(P), P.X, parent(P.X.dv).U, parent(P.X.dv).P)
238237

239238
"""
240239
toclassical(P::SemiclassicalJacobi)
241240
242-
gives either a mapped `Jacobi` or `LanczosPolynomial` version of `P`.
241+
gives either a mapped `Jacobi` or `CholeskyPolynomial` version of `P`.
243242
"""
244-
toclassical(P::SemiclassicalJacobi{T}) where T = iszero(P.c) ? Normalized(jacobi(P.b, P.a, UnitInterval{T}())) : LanczosPolynomial(P)
243+
toclassical(P::SemiclassicalJacobi{T}) where T = iszero(P.c) ? Normalized(jacobi(P.b, P.a, UnitInterval{T}())) : ConvertedOrthogonalPolynomial(P)
245244

246245
copy(P::SemiclassicalJacobi) = P
247246
axes(P::SemiclassicalJacobi{T}) where T = (Inclusion(UnitInterval{T}()),OneToInf())
@@ -281,7 +280,7 @@ function op_lowering(Q, y)
281280
end
282281

283282
function semijacobi_ldiv(Q, P::SemiclassicalJacobi)
284-
if P.a 0 && P.b  0 && P.c 0
283+
if P.a 0 && P.b 0 && P.c 0
285284
= toclassical(P)
286285
(Q \ P̃)/_p0(P̃)
287286
else
@@ -298,7 +297,7 @@ end
298297
"""
299298
semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
300299
301-
Returns conversion operator from SemiclassicalJacobi `P` to SemiclassicalJacobi `Q` in a single step via decomposition.
300+
Returns conversion operator from SemiclassicalJacobi `P` to SemiclassicalJacobi `Q` in a single step via decomposition.
302301
Numerically unstable if the parameter modification is large. Typically one should instead use `P \\ Q` which is equivalent to `semijacobi_ldiv(P,Q)` and proceeds step by step.
303302
"""
304303
function semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
@@ -365,7 +364,7 @@ end
365364
"""
366365
semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
367366
368-
Returns conversion operator from SemiclassicalJacobi `P` to SemiclassicalJacobi `Q`. Integer distances are covered by decomposition methods, for non-integer cases a Lanczos fallback is attempted.
367+
Returns conversion operator from SemiclassicalJacobi `P` to SemiclassicalJacobi `Q`. Integer distances are covered by decomposition methods.
369368
"""
370369
function semijacobi_ldiv(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
371370
@assert Q.t P.t
@@ -396,7 +395,7 @@ function semijacobi_ldiv(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
396395
QQ = SemiclassicalJacobi(Q.t, Q.a, Q.b, Q.c+1+iseven(Δc), P)
397396
return ApplyArray(*,semijacobi_ldiv_direct(Q, QQ),semijacobi_ldiv(QQ, P))
398397
end
399-
else # fallback to Lancos
398+
else # fallback
400399
R = SemiclassicalJacobi(P.t, mod(P.a,-1), mod(P.b,-1), mod(P.c,-1))
401400
= toclassical(R)
402401
return (P \ R) * _p0(R̃) * (R̃ \ Q)
@@ -406,8 +405,8 @@ end
406405
struct SemiclassicalJacobiLayout <: AbstractOPLayout end
407406
MemoryLayout(::Type{<:SemiclassicalJacobi}) = SemiclassicalJacobiLayout()
408407

409-
copy(L::Ldiv{<:NormalizedOPLayout,SemiclassicalJacobiLayout}) = copy(Ldiv{ApplyLayout{typeof(*)},SemiclassicalJacobiLayout}(L.A, L.B))
410-
copy(L::Ldiv{SemiclassicalJacobiLayout,<:NormalizedOPLayout}) = copy(Ldiv{SemiclassicalJacobiLayout,ApplyLayout{typeof(*)}}(L.A, L.B))
408+
copy(L::Ldiv{<:AbstractNormalizedOPLayout,SemiclassicalJacobiLayout}) = copy(Ldiv{ApplyLayout{typeof(*)},SemiclassicalJacobiLayout}(L.A, L.B))
409+
copy(L::Ldiv{SemiclassicalJacobiLayout,<:AbstractNormalizedOPLayout}) = copy(Ldiv{SemiclassicalJacobiLayout,ApplyLayout{typeof(*)}}(L.A, L.B))
411410

412411
copy(L::Ldiv{ApplyLayout{typeof(*)},SemiclassicalJacobiLayout}) = copy(Ldiv{ApplyLayout{typeof(*)},BasisLayout}(L.A, L.B))
413412
copy(L::Ldiv{SemiclassicalJacobiLayout,ApplyLayout{typeof(*)}}) = copy(Ldiv{BasisLayout,ApplyLayout{typeof(*)}}(L.A, L.B))
@@ -419,6 +418,7 @@ copy(L::Ldiv{WeightedOPLayout,SemiclassicalJacobiLayout}) = copy(Ldiv{WeightedOP
419418
copy(L::Ldiv{SemiclassicalJacobiLayout,WeightedOPLayout}) = copy(Ldiv{BasisLayout,WeightedOPLayout}(L.A, L.B))
420419

421420

421+
simplifiable(L::Ldiv{SemiclassicalJacobiLayout,<:AbstractBasisLayout}) = Val(true)
422422
copy(L::Ldiv{SemiclassicalJacobiLayout}) = semijacobi_ldiv(L.A, L.B)
423423
copy(L::Ldiv{SemiclassicalJacobiLayout,<:AbstractBasisLayout}) = semijacobi_ldiv(L.A, L.B)
424424
copy(L::Ldiv{SemiclassicalJacobiLayout,BroadcastLayout{typeof(*)}}) = semijacobi_ldiv(L.A, L.B)
@@ -435,25 +435,25 @@ function copy(L::Ldiv{SemiclassicalJacobiLayout,SemiclassicalJacobiLayout})
435435
(inv(M_Q) * L') * M_P
436436
end
437437

438-
function \(A::SemiclassicalJacobi, B::SemiclassicalJacobi{T}) where {T}
438+
function \(A::SemiclassicalJacobi, B::SemiclassicalJacobi{T}) where {T}
439439
if A.b == -1 && B.b -1
440-
return UpperTriangular(ApplyArray(inv, B \ A))
440+
return UpperTriangular(ApplyArray(inv, B \ A))
441441
elseif B.b == -1 && A.b -1
442442
# First convert Bᵗᵃ⁻¹ᶜ into Bᵗᵃ⁰ᶜ
443-
Bᵗᵃ⁰ᶜ = SemiclassicalJacobi(B.t, B.a, zero(B.b), B.c, A)
443+
Bᵗᵃ⁰ᶜ = SemiclassicalJacobi(B.t, B.a, zero(B.b), B.c, A)
444444
Bᵗᵃ¹ᶜ = SemiclassicalJacobi(B.t, B.a, one(B.a), B.c, A)
445445
Rᵦₐ₁ᵪᵗᵃ⁰ᶜ = Weighted(Bᵗᵃ⁰ᶜ) \ Weighted(Bᵗᵃ¹ᶜ)
446446
b1 = Rᵦₐ₁ᵪᵗᵃ⁰ᶜ[band(0)]
447447
b0 = Vcat(one(T), Rᵦₐ₁ᵪᵗᵃ⁰ᶜ[band(-1)])
448448
Rᵦₐ₋₁ᵪᵗᵃ⁰ᶜ = Bidiagonal(b0, b1, :U)
449-
# Then convert Bᵗᵃ⁰ᶜ into A and complete
449+
# Then convert Bᵗᵃ⁰ᶜ into A and complete
450450
Rₐ₀ᵪᴬ = UpperTriangular(A \ Bᵗᵃ⁰ᶜ)
451451
return ApplyArray(*, Rₐ₀ᵪᴬ, Rᵦₐ₋₁ᵪᵗᵃ⁰ᶜ)
452452
elseif A.b == B.b == -1
453453
Bᵗᵃ¹ᶜ = SemiclassicalJacobi(B.t, B.a, one(B.b), B.c, B)
454454
Aᵗᵃ¹ᶜ = SemiclassicalJacobi(A.t, A.a, one(A.b), A.c, A)
455455
Rₐ₁ᵪᵗᵘ¹ᵛ = Aᵗᵃ¹ᶜ \ Bᵗᵃ¹ᶜ
456-
# Make 1 ⊕ Rₐ₁ᵪᵗᵘ¹ᵛ
456+
# Make 1 ⊕ Rₐ₁ᵪᵗᵘ¹ᵛ
457457
V = eltype(Rₐ₁ᵪᵗᵘ¹ᵛ)
458458
Rₐ₋₁ᵪᵗᵘ⁻¹ᵛ = Vcat(
459459
Hcat(one(V), Zeros{V}(1, ∞)),
@@ -464,8 +464,8 @@ function \(A::SemiclassicalJacobi, B::SemiclassicalJacobi{T}) where {T}
464464
return semijacobi_ldiv(A, B)
465465
end
466466
end
467-
\(A::LanczosPolynomial, B::SemiclassicalJacobi) = semijacobi_ldiv(A, B)
468-
\(A::SemiclassicalJacobi, B::LanczosPolynomial) = semijacobi_ldiv(A, B)
467+
\(A::ConvertedOrthogonalPolynomial, B::SemiclassicalJacobi) = semijacobi_ldiv(A, B)
468+
\(A::SemiclassicalJacobi, B::ConvertedOrthogonalPolynomial) = semijacobi_ldiv(A, B)
469469
function \(w_A::WeightedSemiclassicalJacobi{T}, w_B::WeightedSemiclassicalJacobi{T}) where T
470470
wA,A = w_A.args
471471
wB,B = w_B.args
@@ -479,12 +479,12 @@ function \(w_A::WeightedSemiclassicalJacobi{T}, w_B::WeightedSemiclassicalJacobi
479479
@assert A.a + 1 == B.a && A.c + 1 == B.c
480480
Q = SemiclassicalJacobi(B.t, B.a, one(B.b), B.c, B)
481481
P = SemiclassicalJacobi(A.t, A.a, one(A.b), A.c, A)
482-
wP = Weighted(P)
482+
wP = Weighted(P)
483483
wQ = Weighted(Q)
484484
R22 = wP \ wQ
485485
α, β = _linear_coefficients(P.t, P.a, P.b, P.c)
486-
ℓ₁ = A.t - 1
487-
ℓ₂ = 1 + α - A.t
486+
ℓ₁ = A.t - 1
487+
ℓ₂ = 1 + α - A.t
488488
ℓ₃ = inv(β)
489489
d0 = Vcat(ℓ₁, R22[band(0)])
490490
d1 = Vcat(ℓ₂, R22[band(-1)])
@@ -505,13 +505,13 @@ function \(w_A::WeightedSemiclassicalJacobi{T}, w_B::WeightedSemiclassicalJacobi
505505
elseif wA.a == wB.a && wA.b == wB.b && wA.c+1 == wB.c
506506
@assert A.a == B.a && A.b == B.b && A.c+1 == B.c
507507
-op_lowering(A,A.t)
508-
elseif wA.a+1  wB.a
508+
elseif wA.a+1 wB.a
509509
C = SemiclassicalJacobi(A.t, A.a+1, A.b, A.c, A)
510510
w_C = SemiclassicalJacobiWeight(wA.t, wA.a+1, wA.b, wA.c) .* C
511511
L_2 = w_C \ w_B
512512
L_1 = w_A \ w_C
513513
L_1 * L_2
514-
elseif wA.b+1  wB.b
514+
elseif wA.b+1 wB.b
515515
C = SemiclassicalJacobi(A.t, A.a, A.b+1, A.c, A)
516516
w_C = SemiclassicalJacobiWeight(wA.t, wA.a, wA.b+1, wA.c) .* C
517517
L_2 = w_C \ w_B
@@ -529,19 +529,19 @@ end
529529
\(w_A::Weighted{<:Any,<:SemiclassicalJacobi}, w_B::Weighted{<:Any,<:SemiclassicalJacobi}) = convert(WeightedBasis, w_A) \ convert(WeightedBasis, w_B)
530530

531531
function \(w_A::HalfWeighted{lr, T, <:SemiclassicalJacobi}, B::AbstractQuasiArray{V}) where {lr, T, V}
532-
WP = convert(WeightedBasis, w_A)
533-
w_A.P.b -1 && return WP \ B # no need to special case here
532+
WP = convert(WeightedBasis, w_A)
533+
w_A.P.b -1 && return WP \ B # no need to special case here
534534
!iszero(WP.args[1].b) && throw(ArgumentError("Cannot expand in a weighted basis including 1/(1-x)."))
535-
# To expand f(x) = w(x)P(x)𝐟, note that P = [1 (1-x)Q] so
535+
# To expand f(x) = w(x)P(x)𝐟, note that P = [1 (1-x)Q] so
536536
# f(x) = w(x)[1 (1-x)Q(x)][f₀; 𝐟₁] = w(x)f₀ + w(x)(1-x)Q(x)𝐟₁. Thus,
537-
# f(1) = w(1)f₀ ⟹ f₀ = f(1) / w(1)
538-
# Then, f(x) - w(x)f₀ = w(x)(1-x)Q(x)𝐟₁, so that 𝐟₁ is just the expansion of
537+
# f(1) = w(1)f₀ ⟹ f₀ = f(1) / w(1)
538+
# Then, f(x) - w(x)f₀ = w(x)(1-x)Q(x)𝐟₁, so that 𝐟₁ is just the expansion of
539539
# f(x) - w(x)f₀ in the w(x)(1-x)Q(x) basis.
540-
w, P = WP.args
541-
f₀ = B[end] / w[end]
540+
w, P = WP.args
541+
f₀ = B[end] / w[end]
542542
C = B - w * f₀
543543
Q = SemiclassicalJacobiWeight(w.t, w.a, one(w.b), w.c) .* SemiclassicalJacobi(P.t, P.a, one(P.b), P.c, P)
544-
f = Q \ C
544+
f = Q \ C
545545
return Vcat(f₀, f)
546546
end
547547

@@ -563,8 +563,8 @@ function ldiv(Q::SemiclassicalJacobi, f::AbstractQuasiVector)
563563
elseif isinteger(Q.a) && (isinteger(Q.b) && Q.b 0) && isinteger(Q.c) # (a,b,c) are integers -> use QR/Cholesky
564564
= Normalized(jacobi(Q.b, Q.a, UnitInterval{T}()))
565565
return (Q \ SemiclassicalJacobi(Q.t, Q.a, Q.b, 0)) * _p0(R̃) * (R̃ \ f)
566-
elseif isinteger(Q.a) && isone(-Q.b) && isinteger(Q.c)
567-
return semijacobi_ldiv(Q, f) # jacobi(< 0, Q.a) fails in the method above. jacobi(-1, 0) also leads to NaNs in coefficients
566+
elseif isinteger(Q.a) && isone(-Q.b) && isinteger(Q.c)
567+
return semijacobi_ldiv(Q, f) # jacobi(< 0, Q.a) fails in the method above. jacobi(-1, 0) also leads to NaNs in coefficients
568568
else # fallback to Lanzcos
569569
= toclassical(SemiclassicalJacobi(Q.t, mod(Q.a,-1), mod(Q.b,-1), mod(Q.c,-1)))
570570
return (Q \ R̃) * (R̃ \ f)
@@ -639,7 +639,7 @@ function SemiclassicalJacobiFamily{T}(data::Vector, t, a, b, c) where T
639639
end
640640

641641
function _getsecondifpossible(v)
642-
length(v) > 1 && return v[2]
642+
length(v) > 1 && return v[2]
643643
return v[1]
644644
end
645645

@@ -651,9 +651,9 @@ end
651651

652652
Base.broadcasted(::Type{SemiclassicalJacobi}, t::Number, a::Number, b::Number, c::Number) = SemiclassicalJacobi(t, a, b, c)
653653
Base.broadcasted(::Type{SemiclassicalJacobi{T}}, t::Number, a::Number, b::Number, c::Number) where T = SemiclassicalJacobi{T}(t, a, b, c)
654-
Base.broadcasted(::Type{SemiclassicalJacobi}, t::Number, a::Union{AbstractUnitRange,Number}, b::Union{AbstractUnitRange,Number}, c::Union{AbstractUnitRange,Number}) =
654+
Base.broadcasted(::Type{SemiclassicalJacobi}, t::Number, a::Union{AbstractUnitRange,Number}, b::Union{AbstractUnitRange,Number}, c::Union{AbstractUnitRange,Number}) =
655655
SemiclassicalJacobiFamily(t, a, b, c)
656-
Base.broadcasted(::Type{SemiclassicalJacobi{T}}, t::Number, a::Union{AbstractUnitRange,Number}, b::Union{AbstractUnitRange,Number}, c::Union{AbstractUnitRange,Number}) where T =
656+
Base.broadcasted(::Type{SemiclassicalJacobi{T}}, t::Number, a::Union{AbstractUnitRange,Number}, b::Union{AbstractUnitRange,Number}, c::Union{AbstractUnitRange,Number}) where T =
657657
SemiclassicalJacobiFamily{T}(t, a, b, c)
658658

659659

@@ -664,7 +664,7 @@ function LazyArrays.cache_filldata!(P::SemiclassicalJacobiFamily, inds::Abstract
664664
t,a,b,c = P.t,P.a,P.b,P.c
665665
isrange = P.b isa AbstractUnitRange
666666
for k in inds
667-
# If P.data[k-2] is not normalised (aka b = -1), cholesky fails. With the current design, this is only a problem if P.b
667+
# If P.data[k-2] is not normalised (aka b = -1), cholesky fails. With the current design, this is only a problem if P.b
668668
# is a range since we can translate between polynomials that both have b = -1.
669669
Pprev = (isrange && P.b[k-2] == -1) ? P.data[k-1] : P.data[k-2] # isrange && P.b[k-2] == -1 could also be !isnormalized(P.data[k-2])
670670
P.data[k] = SemiclassicalJacobi(t, _broadcast_getindex(a,k), _broadcast_getindex(b,k), _broadcast_getindex(c,k), Pprev)
@@ -704,7 +704,7 @@ function SemiclassicalJacobiCWeightFamily{T}(t::Number, a::Number, b::Number, c:
704704
return SemiclassicalJacobiCWeightFamily{T}(SemiclassicalJacobiWeight.(t,a:a,b:b,c), t, a, b, c)
705705
end
706706

707-
Base.broadcasted(::Type{SemiclassicalJacobiWeight}, t::Number, a::Number, b::Number, c::Union{AbstractUnitRange,Number}) =
707+
Base.broadcasted(::Type{SemiclassicalJacobiWeight}, t::Number, a::Number, b::Number, c::Union{AbstractUnitRange,Number}) =
708708
SemiclassicalJacobiCWeightFamily(t, a, b, c)
709709

710710
_unweightedsemiclassicalsum(a,b,c,t) = pFq((a+1,-c),(a+b+2, ), 1/t)
@@ -714,7 +714,7 @@ function Base.broadcasted(::typeof(sum), W::SemiclassicalJacobiCWeightFamily{T})
714714
cmin = minimum(c); cmax = maximum(c);
715715
@assert isinteger(cmax) && isinteger(cmin)
716716
# This is needed at high parameter values.
717-
# Manually setting setprecision(2048) allows accurate computation even for very high c.
717+
# Manually setting setprecision(2048) allows accurate computation even for very high c.
718718
t,a,b = convert(BigFloat,t),convert(BigFloat,a),convert(BigFloat,b)
719719
F = zeros(BigFloat,cmax+1)
720720
F[1] = _unweightedsemiclassicalsum(a,b,0,t) # c=0

test/runtests.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ end
7272
R = Q \ P
7373
Ralt = semijacobi_ldiv_direct(Q,P)
7474
@test R[1:20,1:20] Ralt[1:20,1:20]
75+
76+
@test (P \ legendre(0..1))[1:10,1:10] * (legendre(0..1) \ Normalized(legendre(0..1)))[1:10,1:10] (P \ Normalized(legendre(0..1)))[1:10,1:10]
77+
@test_broken (Normalized(legendre(0..1)) \ legendre(0..1))[1:10,1:10] * (legendre(0..1) \ P)[1:10,1:10] (Normalized(legendre(0..1)) \ P)[1:10,1:10]
78+
7579
# set 2
7680
P = SemiclassicalJacobi(1.23,4,1,2)
7781
Q = SemiclassicalJacobi(1.23,7,4,6)
@@ -274,7 +278,7 @@ end
274278
U = SemiclassicalJacobi(2, 1/2, 0, 1/2, T)
275279
x = axes(T,1)
276280

277-
ucfs = (T \ exp.(x))
281+
ucfs = T \ exp.(x)
278282
u = T * ucfs
279283
@test u[0.1] exp(0.1)
280284
@test T[:,1:20] \ exp.(x) ucfs[1:20]

0 commit comments

Comments
 (0)