Skip to content

Commit 4789503

Browse files
authored
Extra Legendre constructors, sum and dot for generic quasi-vectors (#137)
* Extra Legendre constructors * v0.8.2 * Add routines for non-expanded functions * singularities on onclusion * dot tests * tests pass * Update show * sum_layout * v0.10 * Update documentation.yml
1 parent c068d2b commit 4789503

File tree

10 files changed

+62
-30
lines changed

10 files changed

+62
-30
lines changed

.github/workflows/documentation.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v2
1717
- uses: julia-actions/setup-julia@v1
1818
with:
19-
version: '1.7'
19+
version: '1.9'
2020
- name: Install dependencies
2121
run: julia --project=docs/ -e 'using Pkg; Pkg.develop(PackageSpec(path=pwd())); Pkg.instantiate()'
2222
- name: Build and deploy

Project.toml

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "ClassicalOrthogonalPolynomials"
22
uuid = "b30e2e7b-c4ee-47da-9d5f-2c5c27239acd"
33
authors = ["Sheehan Olver <[email protected]>"]
4-
version = "0.9.0"
4+
version = "0.10"
55

66
[deps]
77
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
@@ -29,19 +29,19 @@ ArrayLayouts = "1.0.1"
2929
BandedMatrices = "0.17.17"
3030
BlockArrays = "0.16.9"
3131
BlockBandedMatrices = "0.12"
32-
ContinuumArrays = "0.12.4"
33-
DomainSets = "0.5.6, 0.6"
32+
ContinuumArrays = "0.13"
33+
DomainSets = "0.6"
3434
FFTW = "1.1"
35-
FastGaussQuadrature = "0.4.3, 0.5"
35+
FastGaussQuadrature = "0.5"
3636
FastTransforms = "0.15.2"
3737
FillArrays = "1"
3838
HypergeometricFunctions = "0.3.4"
3939
InfiniteArrays = "0.12.11"
4040
InfiniteLinearAlgebra = "0.6.16"
41-
IntervalSets = "0.5, 0.6, 0.7"
41+
IntervalSets = "0.7"
4242
LazyArrays = "1.0.1"
4343
LazyBandedMatrices = "0.8.5"
44-
QuasiArrays = "0.9.6"
44+
QuasiArrays = "0.10"
4545
SpecialFunctions = "1.0, 2"
4646
julia = "1.9"
4747

src/ClassicalOrthogonalPolynomials.jl

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ import QuasiArrays: cardinality, checkindex, QuasiAdjoint, QuasiTranspose, Inclu
3434

3535
import InfiniteArrays: OneToInf, InfAxes, Infinity, AbstractInfUnitRange, InfiniteCardinal, InfRanges
3636
import InfiniteLinearAlgebra: chop!, chop, pad, choplength, compatible_resize!
37-
import ContinuumArrays: Basis, Weight, basis, @simplify, Identity, AbstractAffineQuasiVector, ProjectionFactorization,
37+
import ContinuumArrays: Basis, Weight, basis_axes, @simplify, Identity, AbstractAffineQuasiVector, ProjectionFactorization,
3838
grid, plotgrid, _plotgrid, _grid, transform_ldiv, TransformFactorization, QInfAxes, broadcastbasis, ExpansionLayout, basismap,
3939
AffineQuasiVector, AffineMap, WeightLayout, AbstractWeightedBasisLayout, WeightedBasisLayout, WeightedBasisLayouts, demap, AbstractBasisLayout, BasisLayout,
40-
checkpoints, weight, unweighted, MappedBasisLayouts, __sum, invmap, plan_ldiv, layout_broadcasted, MappedBasisLayout, SubBasisLayout, _broadcastbasis,
40+
checkpoints, weight, unweighted, MappedBasisLayouts, sum_layout, invmap, plan_ldiv, layout_broadcasted, MappedBasisLayout, SubBasisLayout, _broadcastbasis,
4141
plan_transform, plan_grid_transform, MAX_PLOT_POINTS, MulPlan
4242
import FastTransforms: Λ, forwardrecurrence, forwardrecurrence!, _forwardrecurrence!, clenshaw, clenshaw!,
4343
_forwardrecurrence_next, _clenshaw_next, check_clenshaw_recurrences, ChebyshevGrid, chebyshevpoints, Plan, ScaledPlan, th_cheb2leg
@@ -94,7 +94,7 @@ _equals(::MappedBasisLayouts, ::MappedOPLayout, P, Q) = demap(P) == demap(Q) &&
9494
_broadcastbasis(::typeof(+), ::MappedOPLayout, ::MappedOPLayout, P, Q) = _broadcastbasis(+, MappedBasisLayout(), MappedBasisLayout(), P, Q)
9595
_broadcastbasis(::typeof(+), ::MappedOPLayout, M::MappedBasisLayout, P, Q) = _broadcastbasis(+, MappedBasisLayout(), M, P, Q)
9696
_broadcastbasis(::typeof(+), L::MappedBasisLayout, ::MappedOPLayout, P, Q) = _broadcastbasis(+, L, MappedBasisLayout(), P, Q)
97-
__sum(::MappedOPLayout, A, dims) = __sum(MappedBasisLayout(), A, dims)
97+
sum_layout(::MappedOPLayout, A, dims) = sum_layout(MappedBasisLayout(), A, dims)
9898

9999
# demap to avoid Golub-Welsch fallback
100100
ContinuumArrays.transform_ldiv_if_columns(L::Ldiv{MappedOPLayout,Lay}, ax::OneTo) where Lay = ContinuumArrays.transform_ldiv_if_columns(Ldiv{MappedBasisLayout,Lay}(L.A,L.B), ax)
@@ -161,13 +161,16 @@ gives the singularity structure of an expansion, e.g.,
161161
`JacobiWeight`.
162162
"""
163163
singularities(::WeightLayout, w) = w
164-
singularities(lay::BroadcastLayout, a) = singularitiesbroadcast(call(a), map(singularities, arguments(lay, a))...)
164+
singularities(lay::BroadcastLayout, a::AbstractQuasiVector) = singularitiesbroadcast(call(a), map(singularities, arguments(lay, a))...)
165165
singularities(::WeightedBasisLayouts, a) = singularities(BroadcastLayout{typeof(*)}(), a)
166166
singularities(::WeightedOPLayout, a) = singularities(weight(a))
167167
singularities(w) = singularities(MemoryLayout(w), w)
168168
singularities(::ExpansionLayout, f) = singularities(basis(f))
169169

170-
singularities(S::SubQuasiArray) = singularities(parent(S))[parentindices(S)[1]]
170+
singularitiesview(w, ::Inclusion) = w # for now just assume it doesn't change
171+
singularities(S::SubQuasiArray) = singularitiesview(singularities(parent(S)), parentindices(S)[1])
172+
173+
basis_axes(::Inclusion{<:Any,<:AbstractInterval}, v) = basis_singularities(singularities(v))
171174

172175
struct NoSingularities end
173176

src/classical/jacobi.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,8 @@ jacobi(a,b, d::AbstractInterval{T}) where T = Jacobi{float(promote_type(eltype(a
8383

8484
Jacobi(P::Legendre{T}) where T = Jacobi(zero(T), zero(T))
8585

86+
basis_singularities(w::JacobiWeight) = Weighted(Jacobi(w.a, w.b))
87+
8688
"""
8789
jacobip(n, a, b, z)
8890
@@ -154,7 +156,8 @@ axes(::AbstractJacobi{T}) where T = (Inclusion{T}(ChebyshevInterval{real(T)}()),
154156
==(A::Legendre, B::Weighted{<:Any,<:AbstractJacobi}) = A == B.P
155157
==(A::Weighted{<:Any,<:AbstractJacobi}, B::Legendre) = A.P == B
156158

157-
159+
show(io::IO, w::AbstractJacobiWeight) = summary(io, w)
160+
show(io::IO, P::AbstractJacobi) = summary(io, P)
158161
summary(io::IO, P::Jacobi) = print(io, "Jacobi($(P.a), $(P.b))")
159162

160163
###

src/classical/legendre.jl

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,13 @@ singularitiesbroadcast(::typeof(^), L::LegendreWeight, ::NoSingularities) = L
3535
singularitiesbroadcast(::typeof(/), ::NoSingularities, L::LegendreWeight) = L # can't find roots
3636

3737
singularities(::AbstractJacobi{T}) where T = LegendreWeight{T}()
38-
singularities(::Inclusion{T,<:AbstractInterval}) where T = LegendreWeight{T}()
39-
singularities(d::Inclusion{T,<:Interval}) where T = LegendreWeight{T}()[affine(d,ChebyshevInterval{T}())]
38+
singularities(::Inclusion{T,<:ChebyshevInterval}) where T = LegendreWeight{T}()
39+
singularities(d::Inclusion{T,<:AbstractInterval}) where T = LegendreWeight{T}()[affine(d,ChebyshevInterval{T}())]
4040
singularities(::AbstractFillLayout, P) = LegendreWeight{eltype(P)}()
4141

42+
basis_singularities(::LegendreWeight{T}) where T = Legendre{T}()
43+
basis_singularities(v::SubQuasiArray) = view(basis_singularities(parent(v)), parentindices(v)[1], :)
44+
4245
struct Legendre{T} <: AbstractJacobi{T} end
4346
Legendre() = Legendre{Float64}()
4447

@@ -49,6 +52,8 @@ weighted(P::SubQuasiArray{<:Any,2,<:Normalized{<:Any,<:Legendre}}) = P
4952

5053
legendre() = Legendre()
5154
legendre(d::AbstractInterval{T}) where T = Legendre{float(T)}()[affine(d,ChebyshevInterval{T}()), :]
55+
legendre(d::ChebyshevInterval{T}) where T = Legendre{float(T)}()
56+
legendre(d::Inclusion) = legendre(d.domain)
5257

5358
"""
5459
legendrep(n, z)
@@ -161,14 +166,3 @@ function _sum(P::Legendre{T}, dims) where T
161166
end
162167

163168
_sum(p::SubQuasiArray{T,1,Legendre{T},<:Tuple{Inclusion,Int}}, ::Colon) where T = parentindices(p)[2] == 1 ? convert(T, 2) : zero(T)
164-
165-
166-
###
167-
# dot
168-
###
169-
170-
_dot(::Inclusion{<:Any,<:ChebyshevInterval}, a, b) = _dot(singularities(a), singularities(b), a, b)
171-
function _dot(::LegendreWeight, ::LegendreWeight, a, b)
172-
P = Legendre{promote_type(eltype(a),eltype(b))}()
173-
dot(P\a, (massmatrix(P) * (P\b)))
174-
end

src/classical/ultraspherical.jl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ UltrasphericalWeight{T}(λ) where T = UltrasphericalWeight{T,typeof(λ)}(λ)
1313
UltrasphericalWeight(λ) = UltrasphericalWeight{float(typeof(λ)),typeof(λ)}(λ)
1414
UltrasphericalWeight(::LegendreWeight{T}) where T = UltrasphericalWeight(one(T)/2)
1515

16+
summary(io::IO, w::UltrasphericalWeight) = print(io, "UltrasphericalWeight($(w.λ))")
17+
1618
==(a::UltrasphericalWeight, b::UltrasphericalWeight) = a.λ == b.λ
1719

1820
function getindex(w::UltrasphericalWeight, x::Number)
@@ -36,6 +38,8 @@ end
3638

3739
Ultraspherical(::ChebyshevU{T}) where T = Ultraspherical{T}(1)
3840

41+
summary(io::IO, w::Ultraspherical) = print(io, "Ultraspherical($(w.λ))")
42+
3943
const WeightedUltraspherical{T} = WeightedBasis{T,<:UltrasphericalWeight,<:Ultraspherical}
4044

4145
orthogonalityweight(C::Ultraspherical) = UltrasphericalWeight(C.λ)

src/normalized.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -298,10 +298,10 @@ function mul(A::Derivative, B::Weighted{<:Any,<:SubQuasiArray{<:Any,2,<:Abstract
298298
end
299299
mul(Ac::QuasiAdjoint{<:Any, Weighted{<:Any,<:SubQuasiArray{<:Any,2,<:AbstractQuasiMatrix,<:Tuple{<:AbstractAffineQuasiVector,<:Any}}}}, Bc::QuasiAdjoint{<:Any,<:Derivative}) = mul(Bc', Ac')'
300300

301-
summary(io::IO, Q::Weighted) = print(io, "Weighted($(Q.P))")
301+
show(io::IO, Q::Weighted) = print(io, "Weighted($(Q.P))")
302302

303-
__sum(::AbstractNormalizedOPLayout, A, dims) = __sum(ApplyLayout{typeof(*)}(), A, dims)
304-
function __sum(::WeightedOPLayout, A, dims)
303+
sum_layout(::AbstractNormalizedOPLayout, A, dims) = sum_layout(ApplyLayout{typeof(*)}(), A, dims)
304+
function sum_layout(::WeightedOPLayout, A, dims)
305305
@assert dims == 1
306306
Hcat(sum(weight(A)), Zeros{eltype(A)}(1,∞))
307307
end

test/runtests.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,20 @@ include("test_roots.jl")
5656

5757
f = x -> ChebyshevT{eltype(x)}()[x,1:5]
5858
@test ForwardDiff.derivative(f,0.1) [0;(1:4).*U[0.1,1:4]]
59+
end
60+
61+
@testset "basis" begin
62+
for x in (Inclusion(ChebyshevInterval()), Inclusion(1 .. 2))
63+
a,b = first(x),last(x)
64+
@test sum(x) == b-a
65+
@test sum(x .^ 2) (b^3 - a^3)/3
66+
@test sum(exp.(x)) exp(b) - exp(a)
67+
@test dot(x, x) sum(expand(x .^2))
68+
@test dot(x.^2, x.^2) sum(expand(x .^4))
69+
@test dot(exp.(x), x.^2) sum(expand(x .^2 .* exp.(x)))
70+
@test dot(x, exp.(x)) dot(exp.(x), x)
71+
end
72+
73+
# A = x .^ (0:2)'
74+
# sum(A; dims=1)
5975
end

test/test_legendre.jl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,17 @@ import QuasiArrays: MulQuasiArray
8686
@test W isa Clenshaw
8787
@test W * [1; 2; zeros(∞)] P \ (w .* (P[:,1:2] * [1,2]))
8888

89+
f = expand(P, exp)
90+
@test (w .* f)[0.1] w[0.1]exp(0.1)
91+
8992
M = P'P
9093
@test M isa Diagonal
9194
@test P'x [0; 2/3; zeros(∞)]
92-
@test P'exp.(x) M * (P\exp.(x))
95+
@test P'f M * (P\f)
96+
97+
v = f.args[2]
98+
@test v'*M isa Adjoint
99+
@test v'*M*v dot(f,f) f'f
93100
end
94101

95102
@testset "test on functions" begin

test/test_ultraspherical.jl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,4 +145,9 @@ import LazyArrays: rowsupport, colsupport
145145
c = [1; 2; 3; zeros(BigFloat,∞)]
146146
@test C³[big(1)/10,:]'*(C³ \ U) * c U[big(1)/10,:]'c
147147
end
148+
149+
@testset "show" begin
150+
@test stringmime("text/plain",UltrasphericalWeight(1)) == "UltrasphericalWeight(1)"
151+
@test stringmime("text/plain",Ultraspherical(1)) == "Ultraspherical(1)"
152+
end
148153
end

0 commit comments

Comments
 (0)