@@ -144,7 +144,7 @@ function semiclassical_jacobimatrix(t, a, b, c)
144
144
iszero (c) && return jacobimatrix (P)
145
145
if isone (c)
146
146
return cholesky_jacobimatrix (Symmetric (P \ ((t.- axes (P,1 )). * P)), P)
147
- elseif isone (c / 2 )
147
+ elseif c == 2
148
148
return qr_jacobimatrix (Symmetric (P \ ((t.- axes (P,1 )). * P)), P)
149
149
elseif isinteger (c) && c ≥ 0 # reduce other integer c cases to hierarchy
150
150
return SemiclassicalJacobi .(t, a, b, 0 : Int (c))[end ]. X
@@ -180,19 +180,27 @@ function semiclassical_jacobimatrix(Q::SemiclassicalJacobi, a, b, c)
180
180
cholesky_jacobimatrix (I- Q. X,Q)
181
181
elseif iszero (Δa) && iszero (Δb) && isone (Δc)
182
182
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)
183
192
elseif a > Q. a # iterative raising by 1
184
193
semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a+ 1 , Q. b, Q. c, Q), a, b, c)
185
194
elseif b > Q. b
186
195
semiclassical_jacobimatrix (SemiclassicalJacobi (Q. t, Q. a, Q. b+ 1 , Q. c, Q), a, b, c)
187
196
elseif c > Q. c
188
197
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)
196
204
else
197
205
error (" Not Implemented" )
198
206
end
@@ -206,7 +214,6 @@ LanczosPolynomial(P::SemiclassicalJacobi{T}) where T =
206
214
207
215
gives either a mapped `Jacobi` or `LanczosPolynomial` version of `P`.
208
216
"""
209
- # TODO : Use ConvertedOPs for integer special cases?
210
217
toclassical (P:: SemiclassicalJacobi{T} ) where T = iszero (P. c) ? Normalized (jacobi (P. b, P. a, UnitInterval {T} ())) : LanczosPolynomial (P)
211
218
212
219
copy (P:: SemiclassicalJacobi ) = P
@@ -231,6 +238,7 @@ jacobimatrix(P::SemiclassicalJacobi) = P.X
231
238
232
239
"""
233
240
op_lowering(Q, y)
241
+
234
242
Gives the Lowering operator from OPs w.r.t. (x-y)*w(x) to Q
235
243
as constructed from Chistoffel–Darboux
236
244
"""
@@ -260,56 +268,111 @@ function semijacobi_ldiv(P::SemiclassicalJacobi, Q)
260
268
(P \ R) * _p0 (R̃) * (R̃ \ Q)
261
269
end
262
270
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)
275
308
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)
278
312
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
279
332
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
286
333
else
287
- error (" Implement" )
334
+ error (" Implement modification by ( $Δa , $Δb , $Δc ) " )
288
335
end
289
336
end
290
337
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
299
350
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))
304
356
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))
306
359
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))
308
371
end
309
372
else # fallback to Lancos
310
373
R = SemiclassicalJacobi (P. t, mod (P. a,- 1 ), mod (P. b,- 1 ), mod (P. c,- 1 ))
311
374
R̃ = toclassical (R)
312
- return (P \ R) * _p0 (R̃) * (R̃ \ SemiclassicalJacobi (Qt, Qa, Qb, Qc) )
375
+ return (P \ R) * _p0 (R̃) * (R̃ \ Q )
313
376
end
314
377
end
315
378
@@ -596,5 +659,6 @@ function sumquotient(wP::SemiclassicalJacobiWeight{T},wQ::SemiclassicalJacobiWei
596
659
end
597
660
598
661
include (" neg1c.jl" )
662
+ include (" deprecated.jl" )
599
663
600
664
end
0 commit comments