Skip to content

Commit 9703ea6

Browse files
Support clenshaw! with any DenseColumnMajor blas vector (#113)
* Support clenshaw! with any DenseColumnMajor blas vector * Fix out of bounds error * reactivate coverage * v0.9.3 * Allow strided coefficients * fix c-call * Test Zeros diagonal special case * Update clenshawtests.jl Co-authored-by: Mikael Slevinsky <Richard.Slevinsky@umanitoba.ca>
1 parent f89dbb3 commit 9703ea6

File tree

7 files changed

+70
-32
lines changed

7 files changed

+70
-32
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ jobs:
4141
${{ runner.os }}-
4242
- uses: julia-actions/julia-buildpkg@latest
4343
- uses: julia-actions/julia-runtest@latest
44-
- uses: julia-actions/julia-uploadcodecov@latest
45-
env:
46-
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
44+
- uses: julia-actions/julia-processcoverage@v1
45+
- uses: codecov/codecov-action@v1
46+
with:
47+
file: lcov.info
4748
docs:
4849
name: Documentation
4950
runs-on: ubuntu-latest

Project.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
name = "FastTransforms"
22
uuid = "057dd010-8810-581a-b7be-e3fc3b93f78c"
3-
version = "0.9.2"
3+
version = "0.9.3"
44

55
[deps]
66
AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c"
7+
ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a"
78
BinaryProvider = "b99e7846-7c00-51b0-8f62-c81ae34c0232"
89
DSP = "717857b8-e6f2-59f4-9121-6e50c889abd2"
910
FFTW = "7a1cc6ca-52ef-59f5-83cd-3a7055c09341"
@@ -19,6 +20,7 @@ ToeplitzMatrices = "c751599d-da0a-543b-9d20-d0a503d91d24"
1920

2021
[compat]
2122
AbstractFFTs = "0.4, 0.5"
23+
ArrayLayouts = "0.3.7"
2224
BinaryProvider = "0.5"
2325
DSP = "0.6"
2426
FFTW = "1"

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# FastTransforms.jl
22

3-
[![Build Status](https://github.com/JuliaApproximation/FastTransforms.jl/workflows/CI/badge.svg)](https://github.com/JuliaApproximation/FastTransforms.jl/actions?query=workflow%3ACI) [![Travis](https://travis-ci.org/JuliaApproximation/FastTransforms.jl.svg?branch=master)](https://travis-ci.org/JuliaApproximation/FastTransforms.jl) [![codecov](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl) [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/stable) [![](https://img.shields.io/badge/docs-latest-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/latest)
3+
[![Build Status](https://github.com/JuliaApproximation/FastTransforms.jl/workflows/CI/badge.svg)](https://github.com/JuliaApproximation/FastTransforms.jl/actions?query=workflow%3ACI) [![Travis](https://travis-ci.org/JuliaApproximation/FastTransforms.jl.svg?branch=master)](https://travis-ci.org/JuliaApproximation/FastTransforms.jl) [![codecov](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl/branch/master/graph/badge.svg)](https://codecov.io/gh/JuliaApproximation/FastTransforms.jl) [![](https://img.shields.io/badge/docs-stable-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/stable) [![](https://img.shields.io/badge/docs-dev-blue.svg)](https://JuliaApproximation.github.io/FastTransforms.jl/dev)
44

55
`FastTransforms.jl` allows the user to conveniently work with orthogonal polynomials with degrees well into the millions.
66

src/FastTransforms.jl

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
module FastTransforms
22

33
using FastGaussQuadrature, LinearAlgebra
4-
using Reexport, SpecialFunctions, ToeplitzMatrices, FillArrays
4+
using Reexport, SpecialFunctions, ToeplitzMatrices, FillArrays, ArrayLayouts
55

66
import DSP
77

@@ -48,6 +48,8 @@ export plan_leg2cheb, plan_cheb2leg, plan_ultra2ultra, plan_jac2jac,
4848
plan_tet2cheb, plan_tet_synthesis, plan_tet_analysis,
4949
plan_spinsph2fourier, plan_spinsph_synthesis, plan_spinsph_analysis
5050

51+
include("clenshaw.jl")
52+
5153
include("libfasttransforms.jl")
5254

5355
export plan_nufft, plan_nufft1, plan_nufft2, plan_nufft3, plan_inufft1, plan_inufft2
@@ -96,6 +98,6 @@ lgamma(x) = logabsgamma(x)[1]
9698

9799
include("specialfunctions.jl")
98100

99-
include("clenshaw.jl")
101+
100102

101103
end # module

src/clenshaw.jl

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,14 @@ function clenshaw!(c::AbstractVector, A::AbstractVector, B::AbstractVector, C::A
6868
end
6969

7070

71-
@inline _clenshaw_next(n, A, B, C, x, c, bn1, bn2) = muladd(muladd(A[n],x,B[n]), bn1, muladd(-C[n+1],bn2,c[n]))
72-
@inline _clenshaw_next(n, A, ::Zeros, C, x, c, bn1, bn2) = muladd(A[n]*x, bn1, muladd(-C[n+1],bn2,c[n]))
71+
Base.@propagate_inbounds _clenshaw_next(n, A, B, C, x, c, bn1, bn2) = muladd(muladd(A[n],x,B[n]), bn1, muladd(-C[n+1],bn2,c[n]))
72+
Base.@propagate_inbounds _clenshaw_next(n, A, ::Zeros, C, x, c, bn1, bn2) = muladd(A[n]*x, bn1, muladd(-C[n+1],bn2,c[n]))
7373
# Chebyshev U
74-
@inline _clenshaw_next(n, A::AbstractFill, ::Zeros, C::Ones, x, c, bn1, bn2) = muladd(getindex_value(A)*x, bn1, -bn2+c[n])
74+
Base.@propagate_inbounds _clenshaw_next(n, A::AbstractFill, ::Zeros, C::Ones, x, c, bn1, bn2) = muladd(getindex_value(A)*x, bn1, -bn2+c[n])
75+
76+
# allow special casing first arg, for ChebyshevT in OrthogonalPolynomialsQuasi
77+
Base.@propagate_inbounds _clenshaw_first(A, B, C, x, c, bn1, bn2) = muladd(muladd(A[1],x,B[1]), bn1, muladd(-C[2],bn2,c[1]))
78+
7579

7680
"""
7781
clenshaw(c, A, B, C, x)
@@ -90,9 +94,11 @@ function clenshaw(c::AbstractVector, A::AbstractVector, B::AbstractVector, C::Ab
9094
@inbounds begin
9195
bn2 = zero(T)
9296
bn1 = convert(T,c[N])
93-
for n = N-1:-1:1
97+
N == 1 && return bn1
98+
for n = N-1:-1:2
9499
bn1,bn2 = _clenshaw_next(n, A, B, C, x, c, bn1, bn2),bn1
95100
end
101+
bn1 = _clenshaw_first(A, B, C, x, c, bn1, bn2)
96102
end
97103
bn1
98104
end
@@ -120,7 +126,9 @@ clenshaw!(c::AbstractVector, x::AbstractVector) = clenshaw!(c, x, x)
120126
evaluates the first-kind Chebyshev (T) expansion with coefficients `c` at points `x`,
121127
overwriting `f` with the results.
122128
"""
123-
function clenshaw!(c::AbstractVector, x::AbstractVector, f::AbstractVector)
129+
clenshaw!(c::AbstractVector, x::AbstractVector, f::AbstractVector) = _clenshaw!(MemoryLayout(c), MemoryLayout(x), MemoryLayout(f), c, x, f)
130+
131+
function _clenshaw!(_, _, _, c::AbstractVector, x::AbstractVector, f::AbstractVector)
124132
f .= clenshaw.(Ref(c), x)
125133
end
126134

src/libfasttransforms.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,19 @@ function check_clenshaw_points(x, ϕ₀, f)
7373
length(x) == length(ϕ₀) == length(f) || throw(ArgumentError("Dimensions must match"))
7474
end
7575

76-
function clenshaw!(c::Vector{Float64}, x::Vector{Float64}, f::Vector{Float64})
77-
@assert length(x) == length(f)
78-
ccall((:ft_clenshaw, libfasttransforms), Cvoid, (Cint, Ptr{Float64}, Cint, Cint, Ptr{Float64}, Ptr{Float64}), length(c), c, 1, length(x), x, f)
76+
function check_clenshaw_points(x, f)
77+
length(x) == length(f) || throw(ArgumentError("Dimensions must match"))
78+
end
79+
80+
function _clenshaw!(::AbstractStridedLayout, ::AbstractColumnMajor, ::AbstractColumnMajor, c::AbstractVector{Float64}, x::AbstractVector{Float64}, f::AbstractVector{Float64})
81+
@boundscheck check_clenshaw_points(x, f)
82+
ccall((:ft_clenshaw, libfasttransforms), Cvoid, (Cint, Ptr{Float64}, Cint, Cint, Ptr{Float64}, Ptr{Float64}), length(c), c, stride(c,1), length(x), x, f)
7983
f
8084
end
8185

82-
function clenshaw!(c::Vector{Float32}, x::Vector{Float32}, f::Vector{Float32})
83-
@assert length(x) == length(f)
84-
ccall((:ft_clenshawf, libfasttransforms), Cvoid, (Cint, Ptr{Float32}, Cint, Cint, Ptr{Float32}, Ptr{Float32}), length(c), c, 1, length(x), x, f)
86+
function _clenshaw!(::AbstractStridedLayout, ::AbstractColumnMajor, ::AbstractColumnMajor, c::AbstractVector{Float32}, x::AbstractVector{Float32}, f::AbstractVector{Float32})
87+
@boundscheck check_clenshaw_points(x, f)
88+
ccall((:ft_clenshawf, libfasttransforms), Cvoid, (Cint, Ptr{Float32}, Cint, Cint, Ptr{Float32}, Ptr{Float32}), length(c), c, stride(c,1), length(x), x, f)
8589
f
8690
end
8791

test/clenshawtests.jl

Lines changed: 35 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,34 @@ import FastTransforms: clenshaw, clenshaw!, forwardrecurrence!, forwardrecurrenc
33

44
@testset "clenshaw" begin
55
@testset "Chebyshev T" begin
6-
c = [1,2,3]
7-
cf = float(c)
8-
@test @inferred(clenshaw(c,1)) 1 + 2 + 3
9-
@test @inferred(clenshaw(c,0)) 1 + 0 - 3
10-
@test @inferred(clenshaw(c,0.1)) == 1 + 2*0.1 + 3*cos(2acos(0.1))
11-
@test @inferred(clenshaw(c,[-1,0,1])) == clenshaw!(c,[-1,0,1]) == [2,-2,6]
12-
@test clenshaw(c,[-1,0,1]) isa Vector{Int}
13-
@test @inferred(clenshaw(Float64[],1)) 0.0
6+
for elty in (Float64, Float32)
7+
c = [1,2,3]
8+
cf = elty.(c)
9+
@test @inferred(clenshaw(c,1)) 1 + 2 + 3
10+
@test @inferred(clenshaw(c,0)) 1 + 0 - 3
11+
@test @inferred(clenshaw(c,0.1)) == 1 + 2*0.1 + 3*cos(2acos(0.1))
12+
@test @inferred(clenshaw(c,[-1,0,1])) == clenshaw!(c,[-1,0,1]) == [2,-2,6]
13+
@test clenshaw(c,[-1,0,1]) isa Vector{Int}
14+
@test @inferred(clenshaw(elty[],1)) zero(elty)
1415

15-
x = [1,0,0.1]
16-
@test @inferred(clenshaw(c,x)) @inferred(clenshaw!(c,copy(x)))
17-
@inferred(clenshaw!(c,x,similar(x)))
18-
@inferred(clenshaw(cf,x)) @inferred(clenshaw!(cf,copy(x)))
19-
@inferred(clenshaw!(cf,x,similar(x))) [6,-2,-1.74]
16+
x = elty[1,0,0.1]
17+
@test @inferred(clenshaw(c,x)) @inferred(clenshaw!(c,copy(x)))
18+
@inferred(clenshaw!(c,x,similar(x)))
19+
@inferred(clenshaw(cf,x)) @inferred(clenshaw!(cf,copy(x)))
20+
@inferred(clenshaw!(cf,x,similar(x))) elty[6,-2,-1.74]
21+
22+
@testset "Strided" begin
23+
cv = view(cf,:)
24+
xv = view(x,:)
25+
@test clenshaw!(cv, xv, similar(xv)) == clenshaw!(cf,x,similar(x))
26+
27+
cv2 = view(cf,1:2:3)
28+
@test clenshaw!(cv2, xv, similar(xv)) == clenshaw([1,3], x)
29+
30+
# modifies x and xv
31+
@test clenshaw!(cv2, xv) == xv == x == clenshaw([1,3], elty[1,0,0.1])
32+
end
33+
end
2034
end
2135

2236
@testset "Chebyshev U" begin
@@ -101,6 +115,13 @@ import FastTransforms: clenshaw, clenshaw!, forwardrecurrence!, forwardrecurrenc
101115
@test v_f isa Vector{Float64}
102116

103117
j = 3
104-
clenshaw([zeros(Int,j-1); 1; zeros(Int,N-j)], A, B, C, 1) == v_i[j]
118+
@test clenshaw([zeros(Int,j-1); 1; zeros(Int,N-j)], A, B, C, 1) == v_i[j]
119+
end
120+
121+
@testset "Zeros diagonal" begin
122+
N = 10; A = randn(N); B = Zeros{Int}(N); C = randn(N+1)
123+
@test forwardrecurrence(N, A, B, C, 0.1) == forwardrecurrence(N, A, Vector(B), C, 0.1)
124+
c = randn(N)
125+
@test clenshaw(c, A, B, C, 0.1) == clenshaw(c, A, Vector(B), C, 0.1)
105126
end
106127
end

0 commit comments

Comments
 (0)