@@ -144,7 +144,7 @@ function semiclassical_jacobimatrix(t, a, b, c)
144144 iszero (c) && return jacobimatrix (P)
145145 if isone (c)
146146 return cholesky_jacobimatrix (Symmetric (P \ ((t.- axes (P,1 )). * P)), P)
147- elseif isone (c / 2 )
147+ elseif c == 2
148148 return qr_jacobimatrix (Symmetric (P \ ((t.- axes (P,1 )). * P)), P)
149149 elseif isinteger (c) && c ≥ 0 # reduce other integer c cases to hierarchy
150150 return SemiclassicalJacobi .(t, a, b, 0 : Int (c))[end ]. X
@@ -180,19 +180,27 @@ function semiclassical_jacobimatrix(Q::SemiclassicalJacobi, a, b, c)
180180 cholesky_jacobimatrix (I- Q. X,Q)
181181 elseif iszero (Δa) && iszero (Δb) && isone (Δc)
182182 cholesky_jacobimatrix (Q. t* I- Q. X,Q)
183+ elseif isone (- Δa) && iszero (Δb) && iszero (Δc) # in these cases we currently have to reconstruct
184+ # TODO : This is re-constructing. It should instead use reverse Cholesky (or an alternative)!
185+ semiclassical_jacobimatrix (Q. t,a,b,c)
186+ elseif iszero (Δa) && isone (- Δb) && iszero (Δc)
187+ # TODO : This is re-constructing. It should instead use reverse Cholesky (or an alternative)!
188+ semiclassical_jacobimatrix (Q. t,a,b,c)
189+ elseif iszero (Δa) && iszero (Δb) && isone (- Δc)
190+ # TODO : This is re-constructing. It should instead use reverse Cholesky (or an alternative)!
191+ semiclassical_jacobimatrix (Q. t,a,b,c)
183192 elseif a > Q. a # iterative raising by 1
184193 semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a+ 1 , Q. b, Q. c, Q), a, b, c)
185194 elseif b > Q. b
186195 semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a, Q. b+ 1 , Q. c, Q), a, b, c)
187196 elseif c > Q. c
188197 semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a, Q. b, Q. c+ 1 , Q), a, b, c)
189- # TODO : Implement lowering via QL/reverse Cholesky or via inverting R?
190- # elseif b < Q.b # iterative lowering by 1
191- # semiclassical_jacobimatrix(SemiclassicalJacobi(Q.t, Q.a, Q.b-1, Q.c, Q), a, b, c)
192- # elseif c < Q.c
193- # semiclassical_jacobimatrix(SemiclassicalJacobi(Q.t, Q.a, Q.b, Q.c-1, Q), a, b, c)
194- # elseif a < Q.a
195- # semiclassical_jacobimatrix(SemiclassicalJacobi(Q.t, Q.a-1, Q.b, Q.c, Q), a, b, c)
198+ elseif a < Q. a # iterative lowering by 1
199+ semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a- 1 , Q. b, Q. c, Q), a, b, c)
200+ elseif b < Q. b
201+ semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a, Q. b- 1 , Q. c, Q), a, b, c)
202+ elseif c < Q. c
203+ semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a, Q. b, Q. c- 1 , Q), a, b, c)
196204 else
197205 error (" Not Implemented" )
198206 end
@@ -206,7 +214,6 @@ LanczosPolynomial(P::SemiclassicalJacobi{T}) where T =
206214
207215gives either a mapped `Jacobi` or `LanczosPolynomial` version of `P`.
208216"""
209- # TODO : Use ConvertedOPs for integer special cases?
210217toclassical (P:: SemiclassicalJacobi{T} ) where T = iszero (P. c) ? Normalized (jacobi (P. b, P. a, UnitInterval {T} ())) : LanczosPolynomial (P)
211218
212219copy (P:: SemiclassicalJacobi ) = P
@@ -231,6 +238,7 @@ jacobimatrix(P::SemiclassicalJacobi) = P.X
231238
232239"""
233240 op_lowering(Q, y)
241+
234242Gives the Lowering operator from OPs w.r.t. (x-y)*w(x) to Q
235243as constructed from Chistoffel–Darboux
236244"""
@@ -260,56 +268,111 @@ function semijacobi_ldiv(P::SemiclassicalJacobi, Q)
260268 (P \ R) * _p0 (R̃) * (R̃ \ Q)
261269end
262270
263- # returns conversion operator from SemiclassicalJacobi P to SemiclassicalJacobi Q in a single step via decomposition.
264- semijacobi_ldiv_direct (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi ) = semijacobi_ldiv_direct (Q. t, Q. a, Q. b, Q. c, P)
265- function semijacobi_ldiv_direct (Qt, Qa, Qb, Qc, P:: SemiclassicalJacobi )
266- (Qt ≈ P. t) && (Qa ≈ P. a) && (Qb ≈ P. b) && (Qc ≈ P. c) && return SymTridiagonal (Ones (∞),Zeros (∞))
267- Δa = Qa- P. a
268- Δb = Qb- P. b
269- Δc = Qc- P. c
270- M = Diagonal (Ones (∞))
271- if iseven (Δa) && iseven (Δb) && iseven (Δc)
272- M = qr (P. X^ (Δa÷ 2 )* (I- P. X)^ (Δb÷ 2 )* (Qt* I- P. X)^ (Δc÷ 2 )). R
273- return ApplyArray (* , Diagonal (sign .(view (M,band (0 ))).* Fill (abs .(1 / M[1 ]),∞)), M)
274- elseif isone (Δa) && iszero (Δb) && iszero (Δc) # special case (Δa,Δb,Δc) = (1,0,0)
271+ """
272+ semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
273+
274+ Returns conversion operator from SemiclassicalJacobi `P` to SemiclassicalJacobi `Q` in a single step via decomposition.
275+ 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.
276+ """
277+ function semijacobi_ldiv_direct (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi )
278+ (Q. t ≈ P. t) && (Q. a ≈ P. a) && (Q. b ≈ P. b) && (Q. c ≈ P. c) && return SquareEye {eltype(Q.t)} ((axes (P,2 ),))
279+ Δa = Q. a- P. a
280+ Δb = Q. b- P. b
281+ Δc = Q. c- P. c
282+ # special case (Δa,Δb,Δc) = (2,0,0)
283+ if (Δa == 2 ) && iszero (Δb) && iszero (Δc)
284+ M = qr (P. X). R
285+ return ApplyArray (* , Diagonal (sign .(view (M,band (0 )))/ abs (M[1 ])), M)
286+ # special case (Δa,Δb,Δc) = (0,2,0)
287+ elseif iszero (Δa) && (Δb == 2 ) && iszero (Δc)
288+ M = qr (I- P. X). R
289+ return ApplyArray (* , Diagonal (sign .(view (M,band (0 )))/ abs (M[1 ])), M)
290+ # special case (Δa,Δb,Δc) = (0,0,2)
291+ elseif iszero (Δa) && iszero (Δb) && (Δc == 2 )
292+ M = qr (Q. t* I- P. X). R
293+ return ApplyArray (* , Diagonal (sign .(view (M,band (0 )))/ abs (M[1 ])), M)
294+ # special case (Δa,Δb,Δc) = (-2,0,0)
295+ elseif (Δa == - 2 ) && iszero (Δb) && iszero (Δc)
296+ M = qr (Q. X). R
297+ return ApplyArray (\ , M, Diagonal (sign .(view (M,band (0 )))* abs (M[1 ])))
298+ # special case (Δa,Δb,Δc) = (0,-2,0)
299+ elseif iszero (Δa) && (Δb == - 2 ) && iszero (Δc)
300+ M = qr (I- Q. X). R
301+ return ApplyArray (\ , M, Diagonal (sign .(view (M,band (0 )))* abs (M[1 ])))
302+ # special case (Δa,Δb,Δc) = (0,0,-2)
303+ elseif iszero (Δa) && iszero (Δb) && (Δc == - 2 )
304+ M = qr (Q. t* I- Q. X). R
305+ return ApplyArray (\ , M, Diagonal (sign .(view (M,band (0 )))* abs (M[1 ])))
306+ # special case (Δa,Δb,Δc) = (1,0,0)
307+ elseif isone (Δa) && iszero (Δb) && iszero (Δc)
275308 M = cholesky (P. X). U
276- return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M)
277- elseif iszero (Δa) && isone (Δb) && iszero (Δc) # special case (Δa,Δb,Δc) = (0,1,0)
309+ return M/ M[1 ]
310+ # special case (Δa,Δb,Δc) = (0,1,0)
311+ elseif iszero (Δa) && isone (Δb) && iszero (Δc)
278312 M = cholesky (I- P. X). U
313+ return M/ M[1 ]
314+ # special case (Δa,Δb,Δc) = (0,0,1)
315+ elseif iszero (Δa) && iszero (Δb) && isone (Δc)
316+ M = cholesky (Q. t* I- P. X). U
317+ return M/ M[1 ]
318+ # special case (Δa,Δb,Δc) = (-1,0,0)
319+ elseif isone (- Δa) && iszero (Δb) && iszero (Δc)
320+ M = cholesky (Q. X). U
321+ return UpperTriangular (ApplyArray (inv,M/ M[1 ]))
322+ # special case (Δa,Δb,Δc) = (0,-1,0)
323+ elseif iszero (Δa) && isone (- Δb) && iszero (Δc)
324+ M = cholesky (I- Q. X). U
325+ return UpperTriangular (ApplyArray (inv,M/ M[1 ]))
326+ # special case (Δa,Δb,Δc) = (0,0,-1)
327+ elseif iszero (Δa) && iszero (Δb) && isone (- Δc)
328+ M = cholesky (Q. t* I- Q. X). U
329+ return UpperTriangular (ApplyArray (inv,M/ M[1 ]))
330+ elseif isinteger (Δa) && isinteger (Δb) && isinteger (Δc) && (Δa ≥ 0 ) && (Δb ≥ 0 ) && (Δc ≥ 0 )
331+ M = cholesky (Symmetric (P. X^ (Δa)* (I- P. X)^ (Δb)* (Q. t* I- P. X)^ (Δc))). U
279332 return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M)
280- elseif iszero (Δa) && iszero (Δb) && isone (Δc) # special case (Δa,Δb,Δc) = (0,0,1)
281- M = cholesky (Qt* I- P. X). U
282- return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M)
283- elseif isinteger (Δa) && isinteger (Δb) && isinteger (Δc)
284- M = cholesky (Symmetric (P. X^ (Δa)* (I- P. X)^ (Δb)* (Qt* I- P. X)^ (Δc))). U
285- return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M) # match normalization choice P_0(x) = 1
286333 else
287- error (" Implement" )
334+ error (" Implement modification by ( $Δa , $Δb , $Δc ) " )
288335 end
289336end
290337
291- # returns conversion operator from SemiclassicalJacobi P to SemiclassicalJacobi Q.
292- semijacobi_ldiv (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi ) = semijacobi_ldiv (Q. t, Q. a, Q. b, Q. c, P)
293- function semijacobi_ldiv (Qt, Qa, Qb, Qc, P:: SemiclassicalJacobi )
294- @assert Qt ≈ P. t
295- (Qt ≈ P. t) && (Qa ≈ P. a) && (Qb ≈ P. b) && (Qc ≈ P. c) && return SymTridiagonal (Ones (∞),Zeros (∞))
296- Δa = Qa- P. a
297- Δb = Qb- P. b
298- Δc = Qc- P. c
338+ """
339+ semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
340+
341+ 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.
342+ """
343+ function semijacobi_ldiv (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi )
344+ @assert Q. t ≈ P. t
345+ T = promote_type (eltype (Q), eltype (P))
346+ (Q. t ≈ P. t) && (Q. a ≈ P. a) && (Q. b ≈ P. b) && (Q. c ≈ P. c) && return return SquareEye {eltype(Q.t)} ((axes (P,2 ),))
347+ Δa = Q. a- P. a
348+ Δb = Q. b- P. b
349+ Δc = Q. c- P. c
299350 if isinteger (Δa) && isinteger (Δb) && isinteger (Δc) # (Δa,Δb,Δc) are integers -> use QR/Cholesky iteratively
300- if ((isone (Δa)|| isone (Δa/ 2 )) && iszero (Δb) && iszero (Δc)) || (iszero (Δa) && (isone (Δb)|| isone (Δb/ 2 )) && iszero (Δc)) || (iszero (Δa) && iszero (Δb) && (isone (Δc)|| isone (Δc/ 2 )))
301- M = semijacobi_ldiv_direct (Qt, Qa, Qb, Qc, P)
302- elseif Δa > 0 # iterative modification by 1
303- M = ApplyArray (* ,semijacobi_ldiv_direct (Qt, Qa, Qb, Qc, SemiclassicalJacobi (Qt, Qa- 1 - iseven (Δa), Qb, Qc, P)),semijacobi_ldiv (Qt, Qa- 1 - iseven (Δa), Qb, Qc, P))
351+ if ((isone (abs (Δa))|| (Δa == 2 )) && iszero (Δb) && iszero (Δc)) || (iszero (Δa) && (isone (abs (Δb))|| (Δb == 2 )) && iszero (Δc)) || (iszero (Δa) && iszero (Δb) && (isone (abs (Δc))|| (Δc == 2 )))
352+ return semijacobi_ldiv_direct (Q, P)
353+ elseif Δa > 0 # iterative raising by 1
354+ QQ = SemiclassicalJacobi (Q. t, Q. a- 1 - iseven (Δa), Q. b, Q. c, P)
355+ return ApplyArray (* ,semijacobi_ldiv_direct (Q, QQ),semijacobi_ldiv (QQ, P))
304356 elseif Δb > 0
305- M = ApplyArray (* ,semijacobi_ldiv_direct (Qt, Qa, Qb, Qc, SemiclassicalJacobi (Qt, Qa, Qb- 1 - iseven (Δb), Qc, P)),semijacobi_ldiv (Qt, Qa, Qb- 1 - iseven (Δb), Qc, P))
357+ QQ = SemiclassicalJacobi (Q. t, Q. a, Q. b- 1 - iseven (Δb), Q. c, P)
358+ return ApplyArray (* ,semijacobi_ldiv_direct (Q, QQ),semijacobi_ldiv (QQ, P))
306359 elseif Δc > 0
307- M = ApplyArray (* ,semijacobi_ldiv_direct (Qt, Qa, Qb, Qc, SemiclassicalJacobi (Qt, Qa, Qb, Qc- 1 - iseven (Δc), P)),semijacobi_ldiv (Qt, Qa, Qb, Qc- 1 - iseven (Δc), P))
360+ QQ = SemiclassicalJacobi (Q. t, Q. a, Q. b, Q. c- 1 - iseven (Δc), P)
361+ return ApplyArray (* ,semijacobi_ldiv_direct (Q, QQ),semijacobi_ldiv (QQ, P))
362+ elseif Δa < 0 # iterative lowering by 1
363+ QQ = SemiclassicalJacobi (Q. t, Q. a+ 1 + iseven (Δa), Q. b, Q. c, P)
364+ return ApplyArray (* ,semijacobi_ldiv_direct (Q, QQ),semijacobi_ldiv (QQ, P))
365+ elseif Δb < 0
366+ QQ = SemiclassicalJacobi (Q. t, Q. a, Q. b+ 1 + iseven (Δb), Q. c, P)
367+ return ApplyArray (* ,semijacobi_ldiv_direct (Q, QQ),semijacobi_ldiv (QQ, P))
368+ elseif Δc < 0
369+ QQ = SemiclassicalJacobi (Q. t, Q. a, Q. b, Q. c+ 1 + iseven (Δc), P)
370+ return ApplyArray (* ,semijacobi_ldiv_direct (Q, QQ),semijacobi_ldiv (QQ, P))
308371 end
309372 else # fallback to Lancos
310373 R = SemiclassicalJacobi (P. t, mod (P. a,- 1 ), mod (P. b,- 1 ), mod (P. c,- 1 ))
311374 R̃ = toclassical (R)
312- return (P \ R) * _p0 (R̃) * (R̃ \ SemiclassicalJacobi (Qt, Qa, Qb, Qc) )
375+ return (P \ R) * _p0 (R̃) * (R̃ \ Q )
313376 end
314377end
315378
@@ -596,5 +659,6 @@ function sumquotient(wP::SemiclassicalJacobiWeight{T},wQ::SemiclassicalJacobiWei
596659end
597660
598661include (" neg1c.jl" )
662+ include (" deprecated.jl" )
599663
600664end
0 commit comments