Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ClassicalOrthogonalPolynomials"
uuid = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd"
authors = ["Sheehan Olver <[email protected]>"]
version = "0.15.3"
version = "0.15.4"


[deps]
Expand Down
15 changes: 13 additions & 2 deletions src/classical/ultraspherical.jl
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,19 @@ function \(A::Ultraspherical, B::Jacobi)
Diagonal(Ã[1,:]./A[1,:]) * (Ã\B)
end
function \(A::Jacobi, B::Ultraspherical)
B̃ = Jacobi(B)
(A\B̃)*Diagonal(B[1,:]./B̃[1,:])
if B == Ultraspherical(-1/2) && (A == Jacobi(-1, 0) || A == Jacobi(0, -1))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a comment why this special case is needed.

Also, where in (A\B̃)*Diagonal(B[1,:]./B̃[1,:]) are the NaNs coming in?

Copy link
Member Author

@DanielVandH DanielVandH Sep 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The NaNs come from B̃[1,:], since

julia> Jacobi(-1, -1)[1, :]
ℵ₀-element view(::Jacobi{Float64, Int64}, 1.0, :) with eltype Float64 with indices OneToInf():
   1.0
   0.0
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN
 NaN
   

(since we haven't yet given a definition to Jacobi(-1, -1) in the code that works, although it'd be all zero anyway -except for the first two entries- I think?)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P_k^(-1,-1)(x) are well-defined:

image

I think using the series or Hypergeometric formula. They are just degenerate since P_1^(-1,-1)(x) = 0, so we cannot use the 3-term recurrence to build them.

So really we should be fixing evaluation for degenerate Jacobi polynomials.

Copy link
Member Author

@DanielVandH DanielVandH Sep 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Won't it still lead to a NaN anyway since $P_1^{(-1,-1)}(x) = 0$? We are dividing by it

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Touché

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

update the comment to mention even if it is defined the above won't work because of division by zero.

# In this case, Jacobi(-1, -1) is (currently) undefined, so the conversion via B̃ = Jacobi(B) leads to NaNs
# from evaluating in B̃[1, :]
T = promote_type(eltype(A), eltype(B))
n = -2one(T) ./ (2 .* (2:∞) .- one(T))
sgn = A == Jacobi(-1, 0) ? one(T) : -one(T)
dv = Vcat(one(T), -2one(T), n)
ev = Vcat(-sgn, sgn .* n)
LazyBandedMatrices.Bidiagonal(dv, ev, :U)
else
B̃ = Jacobi(B)
(A\B̃)*Diagonal(B[1,:]./B̃[1,:])
end
end

function \(wA::Weighted{<:Any,<:Ultraspherical}, wB::Weighted{<:Any,<:Jacobi})
Expand Down
11 changes: 11 additions & 0 deletions test/test_ultraspherical.jl
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,15 @@ using ClassicalOrthogonalPolynomials: grammatrix
@testset "ChebyshevInterval constructior" begin
@test ultraspherical(2,ChebyshevInterval()) ≡ Ultraspherical(2)
end
end

@testset "Jacobi(-1, 0) \\ Ultraspherical(-1/2) and Jacobi(0, -1) \\ Ultraspherical(-1/2)" begin
for A in (Jacobi(-1,0),Jacobi(0,-1))
B = Ultraspherical(-1/2)
R = A \ B
AR = A * R
lhs = AR[0.3918, 1:100]
rhs = B[0.3918, 1:100]
@test lhs ≈ rhs
end
end
Loading