Skip to content

Commit 6bf1f07

Browse files
Update Interface for modified Chebyshev moment-based quadrature
For the two strings `clenshawcurtis` and `fejer`, there are now three methods each: `plan_*`, `*nodes`, `*weights`, where the Fejer methods are followed by a `1` or `2` to indicate the type. This is a better interface because `*nodes` is more extensible: different Chebyshev moments may be added for new quadrature rules. In particular, this commit also adds `log` moments.
1 parent bb3cf89 commit 6bf1f07

File tree

8 files changed

+169
-54
lines changed

8 files changed

+169
-54
lines changed

docs/src/index.md

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,8 @@ sphevaluate
134134

135135
## Internal Methods
136136

137+
### Miscellaneous Special Functions
138+
137139
```@docs
138140
FastTransforms.half
139141
```
@@ -162,38 +164,58 @@ FastTransforms.pochhammer
162164
FastTransforms.stirlingseries
163165
```
164166

167+
### Modified Chebyshev Moment-Based Quadrature
168+
165169
```@docs
166-
FastTransforms.clenshawcurtis
170+
FastTransforms.clenshawcurtisnodes
167171
```
168172

169173
```@docs
170174
FastTransforms.clenshawcurtisweights
171175
```
172176

173177
```@docs
174-
FastTransforms.fejer1
178+
FastTransforms.fejernodes1
175179
```
176180

177181
```@docs
178-
FastTransforms.fejer2
182+
FastTransforms.fejerweights1
179183
```
180184

181185
```@docs
182-
FastTransforms.fejerweights1
186+
FastTransforms.fejernodes2
183187
```
184188

185189
```@docs
186190
FastTransforms.fejerweights2
187191
```
188192

193+
```@docs
194+
FastTransforms.chebyshevmoments1
195+
```
196+
189197
```@docs
190198
FastTransforms.chebyshevjacobimoments1
191199
```
192200

201+
```@docs
202+
FastTransforms.chebyshevlogmoments1
203+
```
204+
205+
```@docs
206+
FastTransforms.chebyshevmoments2
207+
```
208+
193209
```@docs
194210
FastTransforms.chebyshevjacobimoments2
195211
```
196212

213+
```@docs
214+
FastTransforms.chebyshevlogmoments2
215+
```
216+
217+
### Jacobi Polynomial Increment and Decrement Operators
218+
197219
```@docs
198220
FastTransforms.incrementα!
199221
```

src/ChebyshevJacobiPlan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ function BackwardChebyshevJacobiPlan{T}(c_cheb::AbstractVector{T},α::T,β::T,M:
175175

176176
# Clenshaw-Curtis nodes and weights
177177
θ = N > 0 ? T[k/2N for k=zero(T):2N] : T[0]
178-
w = N > 0 ? clenshawcurtisweights(2N+1,α,β,p₁) : T[0]
178+
w = N > 0 ? clenshawcurtisweights!(chebyshevjacobimoments1(T, 2N+1, α, β), p₁) : T[0]
179179

180180
# Initialize sines and cosines
181181
tempsin = sinpi.(θ./2)

src/ChebyshevUltrasphericalPlan.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ function BackwardChebyshevUltrasphericalPlan{T}(c_ultra::AbstractVector{T},λ::T
169169

170170
# Clenshaw-Curtis nodes and weights
171171
θ = N > 0 ? T[k/2N for k=zero(T):2N] : T[0]
172-
w = N > 0 ? clenshawcurtisweights(2N+1-half(λ),λ-half(λ),p₁) : T[0]
172+
w = N > 0 ? clenshawcurtisweights!(chebyshevjacobimoments1(T, 2N+1, λ-half(λ), λ-half(λ)), p₁) : T[0]
173173

174174
# Initialize sines and cosines
175175
tempsin = sinpi.(θ)

src/FastTransforms.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ export triones, trizeros, trirand, trirandn, trievaluate
5151
#export ChebyshevJacobiPlan, jac2cheb, cheb2jac
5252
#export sqrtpi, pochhammer, stirlingseries, stirlingremainder, Aratio, Cratio, Anαβ
5353
#export Cnmαβ, Cnαβ, Cnmλ, Cnλ, Λ, absf, findmindices!
54-
#export clenshawcurtis, clenshawcurtis_plan, clenshawcurtisweights
55-
#export fejer1, fejer_plan1, fejerweights1
56-
#export fejer2, fejer_plan2, fejerweights2
54+
#export plan_clenshawcurtis, clenshawcurtisnodes, clenshawcurtisweights
55+
#export plan_fejer1, fejernodes1, fejerweights1
56+
#export plan_fejer2, fejernodes2, fejerweights2
5757
#export RecurrencePlan, forward_recurrence!, backward_recurrence
5858

5959
include("stepthreading.jl")

src/clenshawcurtis.jl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
clenshawcurtis_plan(μ) = length(μ) > 1 ? FFTW.plan_r2r!(μ, FFTW.REDFT00) : ones(μ)'
1+
plan_clenshawcurtis(μ) = length(μ) > 1 ? FFTW.plan_r2r!(μ, FFTW.REDFT00) : ones(μ)'
22

33
doc"""
4-
Compute nodes and weights of the Clenshaw—Curtis quadrature rule with a Jacobi weight.
4+
Compute nodes of the Clenshaw—Curtis quadrature rule.
55
"""
6-
clenshawcurtis{T<:AbstractFloat}(N::Int::T::T) = clenshawcurtis(N,α,β,clenshawcurtis_plan(zeros(T,N)))
7-
clenshawcurtis{T<:AbstractFloat}(N::Int::T::T,plan) = T[cospi(k/(N-one(T))) for k=0:N-1],clenshawcurtisweights(N,α,β,plan)
6+
clenshawcurtisnodes(::Type{T}, N::Int) where T = T[cospi(k/(N-one(T))) for k=0:N-1]
87

98
doc"""
10-
Compute weights of the Clenshaw—Curtis quadrature rule with a Jacobi weight.
9+
Compute weights of the Clenshaw—Curtis quadrature rule with modified Chebyshev moments of the first kind ``\mu``.
1110
"""
12-
clenshawcurtisweights{T<:AbstractFloat}(N::Int::T::T) = clenshawcurtisweights(N,α,β,clenshawcurtis_plan(zeros(T,N)))
13-
function clenshawcurtisweights{T<:AbstractFloat}(N::Int::T::T,plan)
14-
μ = chebyshevjacobimoments1(N,α,β)
15-
scale!(μ,inv(N-one(T)))
11+
clenshawcurtisweights::Vector) = clenshawcurtisweights!(copy(μ))
12+
clenshawcurtisweights!::Vector) = clenshawcurtisweights!(μ, plan_clenshawcurtis(μ))
13+
function clenshawcurtisweights!::Vector{T}, plan) where T
14+
N = length(μ)
15+
scale!(μ, inv(N-one(T)))
1616
plan*μ
17-
μ[1]/=2;μ[N]/=2
17+
μ[1] *= half(T); μ[N] *= half(T)
1818
return μ
1919
end
2020

src/fejer.jl

Lines changed: 20 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,38 @@
1-
fejer_plan1(μ) = FFTW.plan_r2r!(μ, FFTW.REDFT01)
2-
fejer_plan2(μ) = FFTW.plan_r2r!(μ, FFTW.RODFT00)
1+
plan_fejer1(μ) = FFTW.plan_r2r!(μ, FFTW.REDFT01)
32

43
doc"""
5-
Compute nodes and weights of Fejer's first quadrature rule with a Jacobi weight.
4+
Compute nodes of Fejer's first quadrature rule.
65
"""
7-
fejer1{T<:AbstractFloat}(N::Int::T::T) = fejer1(N,α,β,fejer_plan1(zeros(T,N)))
6+
fejernodes1(::Type{T}, N::Int) where T = T[sinpi((N-2k-one(T))/2N) for k=0:N-1]
87

98
doc"""
10-
Compute nodes and weights of Fejer's second quadrature rule with a Jacobi weight.
9+
Compute weights of Fejer's first quadrature rule with modified Chebyshev moments of the first kind ``\mu``.
1110
"""
12-
fejer2{T<:AbstractFloat}(N::Int::T::T) = fejer2(N,α,β,fejer_plan2(zeros(T,N)))
11+
fejerweights1::Vector) = fejerweights1!(copy(μ))
12+
fejerweights1!::Vector) = fejerweights1!(μ, plan_fejer1(μ))
13+
function fejerweights1!::Vector{T}, plan) where T
14+
N = length(μ)
15+
scale!(μ, inv(T(N)))
16+
return plan*μ
17+
end
1318

14-
fejer1{T<:AbstractFloat}(N::Int::T::T,plan) = T[sinpi((N-2k-one(T))/2N) for k=0:N-1],fejerweights1(N,α,β,plan)
15-
fejer2{T<:AbstractFloat}(N::Int::T::T,plan) = T[cospi((k+one(T))/(N+one(T))) for k=0:N-1],fejerweights2(N,α,β,plan)
1619

20+
plan_fejer2(μ) = FFTW.plan_r2r!(μ, FFTW.RODFT00)
1721

1822
doc"""
19-
Compute weights of Fejer's first quadrature rule with a Jacobi weight.
23+
Compute nodes of Fejer's second quadrature rule.
2024
"""
21-
fejerweights1{T<:AbstractFloat}(N::Int::T::T) = fejerweights1(N,α,β,fejer_plan1(zeros(T,N)))
25+
fejernodes2(::Type{T}, N::Int) where T = T[cospi((k+one(T))/(N+one(T))) for k=0:N-1]
2226

2327
doc"""
24-
Compute weights of Fejer's second quadrature rule with a Jacobi weight.
28+
Compute weights of Fejer's second quadrature rule with modified Chebyshev moments of the second kind ``\mu``.
2529
"""
26-
fejerweights2{T<:AbstractFloat}(N::Int::T::T) = fejerweights2(N,α,β,fejer_plan2(zeros(T,N)))
27-
28-
function fejerweights1{T<:AbstractFloat}(N::Int::T::T,plan)
29-
μ = chebyshevjacobimoments1(N,α,β)
30-
scale!(μ,inv(T(N)))
31-
return plan*μ
32-
end
33-
34-
function fejerweights2{T<:AbstractFloat}(N::Int::T::T,plan)
35-
μ = chebyshevjacobimoments2(N,α,β)
30+
fejerweights2::Vector) = fejerweights2!(copy(μ))
31+
fejerweights2!::Vector) = fejerweights2!(μ, plan_fejer2(μ))
32+
function fejerweights2!::Vector{T}, plan) where T
33+
N = length(μ)
3634
Np1 = N+one(T)
37-
scale!(μ,inv(Np1))
35+
scale!(μ, inv(Np1))
3836
plan*μ
3937
@inbounds for i=1:N μ[i] = sinpi(i/Np1)*μ[i] end
4038
return μ

src/specialfunctions.jl

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -404,15 +404,30 @@ function init_c₁c₂!(c₁::Vector,c₂::Vector,u::Vector,v::Vector,c::Vector,
404404
end
405405

406406

407+
doc"""
408+
Modified Chebyshev moments of the first kind:
409+
410+
```math
411+
\int_{-1}^{+1} T_n(x) {\rm\,d}x.
412+
```
413+
"""
414+
function chebyshevmoments1(::Type{T}, N::Int) where T
415+
μ = zeros(T, N)
416+
for i = 0:2:N-1
417+
@inbounds μ[i+1] = two(T)/T(1-i^2)
418+
end
419+
μ
420+
end
421+
407422
doc"""
408423
Modified Chebyshev moments of the first kind with respect to the Jacobi weight:
409424
410425
```math
411426
\int_{-1}^{+1} T_n(x) (1-x)^\alpha(1+x)^\beta{\rm\,d}x.
412427
```
413428
"""
414-
function chebyshevjacobimoments1{T<:AbstractFloat}(N::Int,α::T::T)
415-
μ = zeros(T,N)
429+
function chebyshevjacobimoments1(::Type{T}, N::Int, α, β) where T
430+
μ = zeros(T, N)
416431
N > 0 && (μ[1] = 2 .^+β+1)*beta+1+1))
417432
if N > 1
418433
μ[2] = μ[1]*-α)/+β+2)
@@ -423,15 +438,50 @@ function chebyshevjacobimoments1{T<:AbstractFloat}(N::Int,α::T,β::T)
423438
μ
424439
end
425440

441+
doc"""
442+
Modified Chebyshev moments of the first kind with respect to the logarithmic weight:
443+
444+
```math
445+
\int_{-1}^{+1} T_n(x) \log\left(\frac{1-x}{2}\right){\rm\,d}x.
446+
```
447+
"""
448+
function chebyshevlogmoments1(::Type{T}, N::Int) where T
449+
μ = zeros(T, N)
450+
N > 0 && (μ[1] = -two(T))
451+
if N > 1
452+
μ[2] = -one(T)
453+
for i=1:N-2
454+
cst = isodd(i) ? T(4)/T(i^2-4) : T(4)/T(i^2-1)
455+
@inbounds μ[i+2] = ((i-2)*μ[i]+cst)/(i+2)
456+
end
457+
end
458+
μ
459+
end
460+
461+
doc"""
462+
Modified Chebyshev moments of the second kind:
463+
464+
```math
465+
\int_{-1}^{+1} U_n(x) {\rm\,d}x.
466+
```
467+
"""
468+
function chebyshevmoments2(::Type{T}, N::Int) where T
469+
μ = zeros(T, N)
470+
for i = 0:2:N-1
471+
@inbounds μ[i+1] = two(T)/T(i+1)
472+
end
473+
μ
474+
end
475+
426476
doc"""
427477
Modified Chebyshev moments of the second kind with respect to the Jacobi weight:
428478
429479
```math
430480
\int_{-1}^{+1} U_n(x) (1-x)^\alpha(1+x)^\beta{\rm\,d}x.
431481
```
432482
"""
433-
function chebyshevjacobimoments2{T<:AbstractFloat}(N::Int,α::T::T)
434-
μ = zeros(T,N)
483+
function chebyshevjacobimoments2(::Type{T}, N::Int, α, β) where T
484+
μ = zeros(T, N)
435485
N > 0 && (μ[1] = 2 .^+β+1)*beta+1+1))
436486
if N > 1
437487
μ[2] = 2μ[1]*-α)/+β+2)
@@ -442,6 +492,24 @@ function chebyshevjacobimoments2{T<:AbstractFloat}(N::Int,α::T,β::T)
442492
μ
443493
end
444494

495+
doc"""
496+
Modified Chebyshev moments of the second kind with respect to the logarithmic weight:
497+
498+
```math
499+
\int_{-1}^{+1} U_n(x) \log\left(\frac{1-x}{2}\right){\rm\,d}x.
500+
```
501+
"""
502+
function chebyshevlogmoments2(::Type{T}, N::Int) where T
503+
μ = chebyshevlogmoments1(T, N)
504+
if N > 1
505+
μ[2] *= two(T)
506+
for i=1:N-2
507+
@inbounds μ[i+2] = 2μ[i+2] + μ[i]
508+
end
509+
end
510+
μ
511+
end
512+
445513
doc"""
446514
Compute Jacobi expansion coefficients in ``P_n^{(\alpha+1,\beta)}(x)`` given Jacobi expansion coefficients in ``P_n^{(\alpha,\beta)}(x)`` in-place.
447515
"""

test/basictests.jl

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
using Compat, FastTransforms, LowRankApprox
22
using Compat.Test
3-
import FastTransforms: Cnλ, Λ, lambertw, Cnαβ, Anαβ, fejer1, fejer2, clenshawcurtis
3+
import FastTransforms: Cnλ, Λ, lambertw, Cnαβ, Anαβ
4+
import FastTransforms: clenshawcurtisnodes, clenshawcurtisweights, fejernodes1, fejerweights1, fejernodes2, fejerweights2
5+
import FastTransforms: chebyshevmoments1, chebyshevmoments2, chebyshevjacobimoments1, chebyshevjacobimoments2, chebyshevlogmoments1, chebyshevlogmoments2
46

57
@testset "Special functions" begin
68
n = 0:1000_000
@@ -33,19 +35,44 @@ end
3335
N = 20
3436
f(x) = exp(x)
3537

36-
x,w = fejer1(N,0.,0.)
37-
@test norm(dot(f.(x),w)-2sinh(1)) 4eps()
38-
x,w = fejer2(N,0.,0.)
39-
@test norm(dot(f.(x),w)-2sinh(1)) 4eps()
40-
x,w = clenshawcurtis(N,0.,0.)
38+
x = clenshawcurtisnodes(Float64, N)
39+
μ = chebyshevmoments1(Float64, N)
40+
w = clenshawcurtisweights(μ)
4141
@test norm(dot(f.(x),w)-2sinh(1)) 4eps()
4242

43-
x,w = fejer1(N,0.25,0.35)
43+
μ = chebyshevjacobimoments1(Float64, N, 0.25, 0.35)
44+
w = clenshawcurtisweights(μ)
4445
@test norm(dot(f.(x),w)-2.0351088204147243) 4eps()
45-
x,w = fejer2(N,0.25,0.35)
46+
47+
μ = chebyshevlogmoments1(Float64, N)
48+
w = clenshawcurtisweights(μ)
49+
@test norm(sum(w./(x-3)) - π^2/12) 4eps()
50+
51+
x = fejernodes1(Float64, N)
52+
μ = chebyshevmoments1(Float64, N)
53+
w = fejerweights1(μ)
54+
@test norm(dot(f.(x),w)-2sinh(1)) 4eps()
55+
56+
μ = chebyshevjacobimoments1(Float64, N, 0.25, 0.35)
57+
w = fejerweights1(μ)
4658
@test norm(dot(f.(x),w)-2.0351088204147243) 4eps()
47-
x,w = clenshawcurtis(N,0.25,0.35)
59+
60+
μ = chebyshevlogmoments1(Float64, N)
61+
w = fejerweights1(μ)
62+
@test norm(sum(w./(x-3)) - π^2/12) 4eps()
63+
64+
x = fejernodes2(Float64, N)
65+
μ = chebyshevmoments2(Float64, N)
66+
w = fejerweights2(μ)
67+
@test norm(dot(f.(x),w)-2sinh(1)) 4eps()
68+
69+
μ = chebyshevjacobimoments2(Float64, N, 0.25, 0.35)
70+
w = fejerweights2(μ)
4871
@test norm(dot(f.(x),w)-2.0351088204147243) 4eps()
72+
73+
μ = chebyshevlogmoments2(Float64, N)
74+
w = fejerweights2(μ)
75+
@test norm(sum(w./(x-3)) - π^2/12) 4eps()
4976
end
5077

5178
@testset "Allocation-free ID matrix-vector products" begin

0 commit comments

Comments
 (0)