@@ -48,9 +48,9 @@ function getindex(P::SemiclassicalJacobiWeight, x::Real)
48
48
end
49
49
50
50
function sum (P:: SemiclassicalJacobiWeight{T} ) where T
51
- (t,a,b,c) = map (big, map (float, ( P. t,P. a,P. b,P. c)) )
52
- # ( t,a,b,c) = P.t, P.a, P.b, P.c
53
- return convert (T, t^ c * beta ( 1 + a, 1 + b) * _₂F₁general2 ( 1 + a ,- c, 2 + a+ b, 1 / t))
51
+ (t,a,b,c) = ( P. t, P. a, P. b, P. c)
52
+ t,a,b,c = convert (BigFloat,t), convert (BigFloat,a), convert (BigFloat,b), convert (BigFloat,c) # This is needed at high parameter values
53
+ return abs ( convert (T, t^ c* exp ( loggamma (a + 1 ) + loggamma (b + 1 ) - loggamma (a + b + 2 )) * pFq ((a + 1 ,- c),( a+ b+ 2 , ), 1 / t) ))
54
54
end
55
55
56
56
function summary (io:: IO , P:: SemiclassicalJacobiWeight )
@@ -258,14 +258,15 @@ function semijacobi_ldiv(P::SemiclassicalJacobi, Q)
258
258
end
259
259
260
260
# returns conversion operator from SemiclassicalJacobi P to SemiclassicalJacobi Q in a single step via decomposition.
261
- function semijacobi_ldiv_direct (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi )
262
- (Q == P) && return SymTridiagonal (Ones (∞),Zeros (∞))
263
- Δa = Q. a- P. a
264
- Δb = Q. b- P. b
265
- Δc = Q. c- P. c
261
+ semijacobi_ldiv_direct (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi ) = semijacobi_ldiv_direct (Q. t, Q. a, Q. b, Q. c, P)
262
+ function semijacobi_ldiv_direct (Qt, Qa, Qb, Qc, P:: SemiclassicalJacobi )
263
+ (Qt ≈ P. t) && (Qa ≈ P. a) && (Qb ≈ P. b) && (Qc ≈ P. c) && return SymTridiagonal (Ones (∞),Zeros (∞))
264
+ Δa = Qa- P. a
265
+ Δb = Qb- P. b
266
+ Δc = Qc- P. c
266
267
M = Diagonal (Ones (∞))
267
268
if iseven (Δa) && iseven (Δb) && iseven (Δc)
268
- M = qr (P. X^ (Δa÷ 2 )* (I- P. X)^ (Δb÷ 2 )* (Q . t * I- P. X)^ (Δc÷ 2 )). R
269
+ M = qr (P. X^ (Δa÷ 2 )* (I- P. X)^ (Δb÷ 2 )* (Qt * I- P. X)^ (Δc÷ 2 )). R
269
270
return ApplyArray (* , Diagonal (sign .(view (M,band (0 ))).* Fill (abs .(1 / M[1 ]),∞)), M)
270
271
elseif isone (Δa) && iszero (Δb) && iszero (Δc) # special case (Δa,Δb,Δc) = (1,0,0)
271
272
M = cholesky (P. X). U
@@ -274,37 +275,38 @@ function semijacobi_ldiv_direct(Q::SemiclassicalJacobi, P::SemiclassicalJacobi)
274
275
M = cholesky (I- P. X). U
275
276
return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M)
276
277
elseif iszero (Δa) && iszero (Δb) && isone (Δc) # special case (Δa,Δb,Δc) = (0,0,1)
277
- M = cholesky (Q . t * I- P. X). U
278
+ M = cholesky (Qt * I- P. X). U
278
279
return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M)
279
280
elseif isinteger (Δa) && isinteger (Δb) && isinteger (Δc)
280
- M = cholesky (Symmetric (P. X^ (Δa)* (I- P. X)^ (Δb)* (Q . t * I- P. X)^ (Δc))). U
281
+ M = cholesky (Symmetric (P. X^ (Δa)* (I- P. X)^ (Δb)* (Qt * I- P. X)^ (Δc))). U
281
282
return ApplyArray (* , Diagonal (Fill (1 / M[1 ],∞)), M) # match normalization choice P_0(x) = 1
282
283
else
283
284
error (" Implement" )
284
285
end
285
286
end
286
287
287
288
# returns conversion operator from SemiclassicalJacobi P to SemiclassicalJacobi Q.
288
- function semijacobi_ldiv (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi )
289
- @assert Q. t ≈ P. t
290
- (Q == P) && return SymTridiagonal (Ones (∞),Zeros (∞))
291
- Δa = Q. a- P. a
292
- Δb = Q. b- P. b
293
- Δc = Q. c- P. c
289
+ semijacobi_ldiv (Q:: SemiclassicalJacobi , P:: SemiclassicalJacobi ) = semijacobi_ldiv (Q. t, Q. a, Q. b, Q. c, P)
290
+ function semijacobi_ldiv (Qt, Qa, Qb, Qc, P:: SemiclassicalJacobi )
291
+ @assert Qt ≈ P. t
292
+ (Qt ≈ P. t) && (Qa ≈ P. a) && (Qb ≈ P. b) && (Qc ≈ P. c) && return SymTridiagonal (Ones (∞),Zeros (∞))
293
+ Δa = Qa- P. a
294
+ Δb = Qb- P. b
295
+ Δc = Qc- P. c
294
296
if isinteger (Δa) && isinteger (Δb) && isinteger (Δc) # (Δa,Δb,Δc) are integers -> use QR/Cholesky iteratively
295
297
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 )))
296
- M = semijacobi_ldiv_direct (Q , P)
298
+ M = semijacobi_ldiv_direct (Qt, Qa, Qb, Qc , P)
297
299
elseif Δa > 0 # iterative modification by 1
298
- M = ApplyArray (* ,semijacobi_ldiv_direct (Q, SemiclassicalJacobi (Q . t, Q . a - 1 - iseven (Δa), Q . b, Q . c )),semijacobi_ldiv (SemiclassicalJacobi (Q . t, Q . a - 1 - iseven (Δa), Q . b, Q . c) , P))
300
+ 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))
299
301
elseif Δb > 0
300
- M = ApplyArray (* ,semijacobi_ldiv_direct (Q, SemiclassicalJacobi (Q . t, Q . a, Q . b - 1 - iseven (Δb), Q . c )),semijacobi_ldiv (SemiclassicalJacobi (Q . t, Q . a, Q . b - 1 - iseven (Δb), Q . c) , P))
302
+ 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))
301
303
elseif Δc > 0
302
- M = ApplyArray (* ,semijacobi_ldiv_direct (Q, SemiclassicalJacobi (Q . t, Q . a, Q . b, Q . c - 1 - iseven (Δc))),semijacobi_ldiv (SemiclassicalJacobi (Q . t, Q . a, Q . b, Q . c - 1 - iseven (Δc) ), P))
304
+ 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))
303
305
end
304
306
else # fallback to Lancos
305
307
R = SemiclassicalJacobi (P. t, mod (P. a,- 1 ), mod (P. b,- 1 ), mod (P. c,- 1 ))
306
308
R̃ = toclassical (R)
307
- return (P \ R) * _p0 (R̃) * (R̃ \ Q )
309
+ return (P \ R) * _p0 (R̃) * (R̃ \ SemiclassicalJacobi (Qt, Qa, Qb, Qc) )
308
310
end
309
311
end
310
312
343
345
\ (A:: SemiclassicalJacobi , B:: SemiclassicalJacobi ) = semijacobi_ldiv (A, B)
344
346
\ (A:: LanczosPolynomial , B:: SemiclassicalJacobi ) = semijacobi_ldiv (A, B)
345
347
\ (A:: SemiclassicalJacobi , B:: LanczosPolynomial ) = semijacobi_ldiv (A, B)
346
- function \ (w_A:: WeightedSemiclassicalJacobi , w_B:: WeightedSemiclassicalJacobi )
348
+ function \ (w_A:: WeightedSemiclassicalJacobi{T} , w_B:: WeightedSemiclassicalJacobi{T} ) where T
347
349
wA,A = w_A. args
348
350
wB,B = w_B. args
349
351
@assert wA. t == wB. t == A. t == B. t
@@ -352,7 +354,8 @@ function \(w_A::WeightedSemiclassicalJacobi, w_B::WeightedSemiclassicalJacobi)
352
354
Δc = B. c- A. c
353
355
354
356
if (wA. a == A. a) && (wA. b == A. b) && (wA. c == A. c) && (wB. a == B. a) && (wB. b == B. b) && (wB. c == B. c) && isinteger (A. a) && isinteger (A. b) && isinteger (A. c) && isinteger (B. a) && isinteger (B. b) && isinteger (B. c)
355
- k = sum (SemiclassicalJacobiWeight (B. t,B. a,B. b,B. c))/ sum (SemiclassicalJacobiWeight (A. t,A. a,A. b,A. c)) # = (A \ SemiclassicalJacobiWeight(A.t,Δa,Δb,Δc))[1]
357
+ # k = (A \ SemiclassicalJacobiWeight(A.t,Δa,Δb,Δc))[1]
358
+ k = sumquotient (SemiclassicalJacobiWeight (B. t,B. a,B. b,B. c),SemiclassicalJacobiWeight (A. t,A. a,A. b,A. c))
356
359
return (ApplyArray (* ,Diagonal (Fill (k,∞)),(B \ A)))'
357
360
elseif wA. a == wB. a && wA. b == wB. b && wA. c == wB. c # fallback to Christoffel–Darboux
358
361
A \ B
@@ -509,6 +512,86 @@ function LazyArrays.cache_filldata!(P::SemiclassicalJacobiFamily, inds::Abstract
509
512
P
510
513
end
511
514
515
+ # ##
516
+ # here we construct hierarchies of c weight sums by means of contiguous recurrence relations
517
+ # ##
518
+
519
+ """ "
520
+ A SemiclassicalJacobiCWeightFamily
521
+
522
+ is a vector containing a sequence of weights of the form `x^a * (1-x)^b * (t-x)^c` where `a` and `b` are scalars and `c` is a range of values with integer spacing; where `x in 0..1`. It is automatically generated when calling `SemiclassicalJacobiWeight.(t,a,b,cmin:cmax)`.
523
+ """
524
+ struct SemiclassicalJacobiCWeightFamily{T, C} <: AbstractVector{SemiclassicalJacobiWeight{T}}
525
+ data:: Vector{SemiclassicalJacobiWeight{T}}
526
+ t:: T
527
+ a:: T
528
+ b:: T
529
+ c:: C
530
+ datasize:: Tuple{Int}
531
+ end
532
+
533
+ getindex (W:: SemiclassicalJacobiCWeightFamily , inds) = getindex (W. data, inds)
534
+
535
+ size (W:: SemiclassicalJacobiCWeightFamily ) = (length (W. c),)
536
+
537
+ function SemiclassicalJacobiCWeightFamily {T} (data:: Vector , t, a, b, c) where T
538
+ checkrangesizes (a, b, c)
539
+ SemiclassicalJacobiCWeightFamily {T,typeof(c)} (data, t, a, b, c, (length (data),))
540
+ end
541
+
542
+ SemiclassicalJacobiCWeightFamily (t, a, b, c) = SemiclassicalJacobiCWeightFamily {float(promote_type(typeof(t),eltype(a),eltype(b),eltype(c)))} (t, a, b, c)
543
+ function SemiclassicalJacobiCWeightFamily {T} (t:: Number , a:: Number , b:: Number , c:: Union{AbstractUnitRange,Number} ) where T
544
+ return SemiclassicalJacobiCWeightFamily {T} (SemiclassicalJacobiWeight .(t,a: a,b: b,c), t, a, b, c)
545
+ end
546
+
547
+ Base. broadcasted (:: Type{SemiclassicalJacobiWeight} , t:: Number , a:: Number , b:: Number , c:: Union{AbstractUnitRange,Number} ) =
548
+ SemiclassicalJacobiCWeightFamily (t, a, b, c)
549
+
550
+ _unweightedsemiclassicalsum = (a,b,c,t) -> pFq ((a+ 1 ,- c),(a+ b+ 2 , ), 1 / t)
551
+
552
+ function Base. broadcasted (:: typeof (sum), W:: SemiclassicalJacobiCWeightFamily{T} ) where T
553
+ a = W. a; b = W. b; c = W. c; t = W. t;
554
+ cmin = minimum (c); cmax = maximum (c);
555
+ @assert isinteger (cmax) && isinteger (cmin)
556
+ # This is needed at high parameter values.
557
+ # Manually setting setprecision(2048) allows accurate computation even for very high c.
558
+ t,a,b = convert (BigFloat,t),convert (BigFloat,a),convert (BigFloat,b)
559
+ F = zeros (BigFloat,cmax+ 1 )
560
+ F[1 ] = _unweightedsemiclassicalsum (a,b,0 ,t) # c=0
561
+ cmax == 0 && return abs .(convert .(T,t.^ c.* exp (loggamma (a+ 1 )+ loggamma (b+ 1 )- loggamma (a+ b+ 2 )).* getindex (F,1 : 1 )))
562
+ F[2 ] = _unweightedsemiclassicalsum (a,b,1 ,t) # c=1
563
+ @inbounds for n in 1 : cmax- 1
564
+ F[n+ 2 ] = ((n- 1 )/ t+ 1 / t- n)/ (n+ a+ b+ 2 )* F[n]+ (a+ b+ 4 + 2 * n- 2 - (n+ a+ 1 )/ t)/ (n+ a+ b+ 2 )* F[n+ 1 ]
565
+ end
566
+ return abs .(convert .(T,t.^ c.* exp (loggamma (a+ 1 )+ loggamma (b+ 1 )- loggamma (a+ b+ 2 )).* getindex (F,W. c.+ 1 )))
567
+ end
568
+
569
+ """ "
570
+ sumquotient(wP, wQ) computes sum(wP)/sum(wQ) by taking into account cancellations, allowing more stable computations for high weight parameters.
571
+ """
572
+ function sumquotient (wP:: SemiclassicalJacobiWeight{T} ,wQ:: SemiclassicalJacobiWeight{T} ) where T
573
+ @assert wP. t ≈ wQ. t
574
+ @assert isinteger (wP. c) && isinteger (wQ. c)
575
+ a = wP. a; b = wP. b; c = Int (wP. c); t = wP. t;
576
+ # This is needed at high parameter values.
577
+ t,a,b = convert (BigFloat,t),convert (BigFloat,a),convert (BigFloat,b)
578
+ F = zeros (BigFloat,max (2 ,c+ 1 ))
579
+ F[1 ] = _unweightedsemiclassicalsum (a,b,0 ,t) # c=0
580
+ F[2 ] = _unweightedsemiclassicalsum (a,b,1 ,t) # c=1
581
+ @inbounds for n in 1 : c- 1
582
+ F[n+ 2 ] = ((n- 1 )/ t+ 1 / t- n)/ (n+ a+ b+ 2 )* F[n]+ (a+ b+ 4 + 2 * n- 2 - (n+ a+ 1 )/ t)/ (n+ a+ b+ 2 )* F[n+ 1 ]
583
+ end
584
+ a = wQ. a; b = wQ. b; c = Int (wQ. c);
585
+ t,a,b = convert (BigFloat,t),convert (BigFloat,a),convert (BigFloat,b)
586
+ G = zeros (BigFloat,max (2 ,c+ 1 ))
587
+ G[1 ] = _unweightedsemiclassicalsum (a,b,0 ,t) # c=0
588
+ G[2 ] = _unweightedsemiclassicalsum (a,b,1 ,t) # c=1
589
+ @inbounds for n in 1 : c- 1
590
+ G[n+ 2 ] = ((n- 1 )/ t+ 1 / t- n)/ (n+ a+ b+ 2 )* G[n]+ (a+ b+ 4 + 2 * n- 2 - (n+ a+ 1 )/ t)/ (n+ a+ b+ 2 )* G[n+ 1 ]
591
+ end
592
+ return abs .(convert .(T,t.^ (Int (wP. c)- c). * exp (loggamma (wP. a+ 1 )+ loggamma (wP. b+ 1 )- loggamma (wP. a+ wP. b+ 2 )- loggamma (a+ 1 )- loggamma (b+ 1 )+ loggamma (a+ b+ 2 ))* F[Int (wP. c)+ 1 ]/ G[c+ 1 ]))
593
+ end
594
+
512
595
include (" neg1c.jl" )
513
596
514
597
end
0 commit comments