diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 4224867f..4991c31d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,11 +10,11 @@ jobs: fail-fast: false matrix: version: - - '1.7' + - 'lts' - '1' os: - ubuntu-latest - - macOS-latest +# - macOS-latest arch: - x86 - x64 @@ -22,8 +22,8 @@ jobs: - os: macOS-latest arch: x86 steps: - - uses: actions/checkout@v3 - - uses: julia-actions/setup-julia@v1 + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 with: version: ${{ matrix.version }} arch: ${{ matrix.arch }} @@ -41,6 +41,7 @@ jobs: - uses: julia-actions/julia-buildpkg@latest - uses: julia-actions/julia-runtest@latest - uses: julia-actions/julia-processcoverage@v1 - - uses: codecov/codecov-action@v3 + - uses: codecov/codecov-action@v4 with: + token: ${{ secrets.CODECOV_TOKEN }} file: lcov.info diff --git a/.github/workflows/downstream.yml b/.github/workflows/downstream.yml new file mode 100644 index 00000000..ba2c1dfa --- /dev/null +++ b/.github/workflows/downstream.yml @@ -0,0 +1,78 @@ +name: IntegrationTest +on: + push: + branches: [master] + tags: [v*] + paths-ignore: + - 'LICENSE' + - 'README.md' + - '.github/workflows/TagBot.yml' + pull_request: + paths-ignore: + - 'LICENSE' + - 'README.md' + - '.github/workflows/TagBot.yml' + +concurrency: + group: build-${{ github.event.pull_request.number || github.ref }}-${{ github.workflow }} + cancel-in-progress: true + +jobs: + pre_job: + # continue-on-error: true # Uncomment once integration is finished + runs-on: ubuntu-latest + # Map a step output to a job output + outputs: + should_skip: ${{ steps.skip_check.outputs.should_skip }} + steps: + - id: skip_check + uses: fkirc/skip-duplicate-actions@v5 + test: + needs: pre_job + if: needs.pre_job.outputs.should_skip != 'true' + name: ${{ matrix.package.group }}/${{ matrix.package.repo }}/${{ matrix.julia-version }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + julia-version: ['1'] + os: [ubuntu-latest] + package: + - {repo: ClassicalOrthogonalPolynomials.jl, group: JuliaApproximation} + - {repo: MultivariateOrthogonalPolynomials.jl, group: JuliaApproximation} + - {repo: ApproxFun.jl, group: JuliaApproximation} + + steps: + - uses: actions/checkout@v4 + - uses: julia-actions/setup-julia@v2 + with: + version: ${{ matrix.julia-version }} + arch: x64 + - uses: julia-actions/julia-buildpkg@latest + - name: Clone Downstream + uses: actions/checkout@v4 + with: + repository: ${{ matrix.package.group }}/${{ matrix.package.repo }} + path: downstream + - name: Load this and run the downstream tests + shell: julia --color=yes --project=downstream {0} + run: | + using Pkg + try + # force it to use this PR's version of the package + Pkg.develop(PackageSpec(path=".")) # resolver may fail with main deps + Pkg.update() + Pkg.test(; coverage = true) # resolver may fail with test time deps + catch err + err isa Pkg.Resolve.ResolverError || rethrow() + # If we can't resolve that means this is incompatible by SemVer and this is fine + # It means we marked this as a breaking change, so we don't need to worry about + # Mistakenly introducing a breaking change, as we have intentionally made one + @info "Not compatible with this release. No problem." exception=err + exit(0) # Exit immediately, as a success + end + - uses: julia-actions/julia-processcoverage@v1 + - uses: codecov/codecov-action@v4 + with: + token: ${{ secrets.CODECOV_TOKEN }} + files: lcov.info diff --git a/Project.toml b/Project.toml index a9269fe0..f5f447a8 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "FastTransforms" uuid = "057dd010-8810-581a-b7be-e3fc3b93f78c" -version = "0.16.4" +version = "0.16.5" [deps] AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" @@ -12,6 +12,7 @@ FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" GenericFFT = "a8297547-1b15-4a5a-a998-a2ac5f1cef28" Libdl = "8f399da3-3557-5675-b5ff-fb832c97cbdb" LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" +RecurrenceRelationships = "807425ed-42ea-44d6-a357-6771516d7b2c" Reexport = "189a3867-3050-52da-a836-e630ba90ab69" SpecialFunctions = "276daf66-3868-5448-9aa4-cd146d93841b" ToeplitzMatrices = "c751599d-da0a-543b-9d20-d0a503d91d24" @@ -24,12 +25,12 @@ FastGaussQuadrature = "0.4, 0.5, 1" FastTransforms_jll = "0.6.2" FillArrays = "0.9, 0.10, 0.11, 0.12, 0.13, 1" GenericFFT = "0.1" +RecurrenceRelationships = "0.1" Reexport = "0.2, 1.0" SpecialFunctions = "0.10, 1, 2" ToeplitzMatrices = "0.7.1, 0.8" julia = "1.7" - [extras] Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c" Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40" diff --git a/src/FastTransforms.jl b/src/FastTransforms.jl index 82c34990..6e6ce548 100644 --- a/src/FastTransforms.jl +++ b/src/FastTransforms.jl @@ -1,7 +1,7 @@ module FastTransforms using BandedMatrices, FastGaussQuadrature, FillArrays, LinearAlgebra, - Reexport, SpecialFunctions, ToeplitzMatrices + Reexport, SpecialFunctions, ToeplitzMatrices, RecurrenceRelationships @reexport using AbstractFFTs @reexport using FFTW @@ -32,6 +32,12 @@ import LinearAlgebra: mul!, lmul!, ldiv!, cholesky import GenericFFT: interlace # imported in downstream packages +import RecurrenceRelationships: clenshaw!, check_clenshaw_recurrences + +const _forwardrecurrence! = RecurrenceRelationships.forwardrecurrence! +const _clenshaw_next = RecurrenceRelationships.clenshaw_next +const _forwardrecurrence_next = RecurrenceRelationships.forwardrecurrence_next + export leg2cheb, cheb2leg, ultra2ultra, jac2jac, lag2lag, jac2ultra, ultra2jac, jac2cheb, cheb2jac, ultra2cheb, cheb2ultra, associatedjac2jac, @@ -53,7 +59,6 @@ export plan_leg2cheb, plan_cheb2leg, plan_ultra2ultra, plan_jac2jac, plan_tet2cheb, plan_tet_synthesis, plan_tet_analysis, plan_spinsph2fourier, plan_spinsph_synthesis, plan_spinsph_analysis -include("clenshaw.jl") include("libfasttransforms.jl") include("elliptic.jl") diff --git a/src/clenshaw.jl b/src/clenshaw.jl deleted file mode 100644 index 24a1ee59..00000000 --- a/src/clenshaw.jl +++ /dev/null @@ -1,221 +0,0 @@ -""" - forwardrecurrence!(v, A, B, C, x) - -evaluates the orthogonal polynomials at points `x`, -where `A`, `B`, and `C` are `AbstractVector`s containing the recurrence coefficients -as defined in DLMF, -overwriting `v` with the results. -""" -function forwardrecurrence!(v::AbstractVector{T}, A::AbstractVector, B::AbstractVector, C::AbstractVector, x, p0=one(T)) where T - N = length(v) - N == 0 && return v - length(A)+1 ≥ N && length(B)+1 ≥ N && length(C)+1 ≥ N || throw(ArgumentError("A, B, C must contain at least $(N-1) entries")) - p1 = convert(T, N == 1 ? p0 : muladd(A[1],x,B[1])*p0) # avoid accessing A[1]/B[1] if empty - _forwardrecurrence!(v, A, B, C, x, convert(T, p0), p1) -end - - -Base.@propagate_inbounds _forwardrecurrence_next(n, A, B, C, x, p0, p1) = muladd(muladd(A[n],x,B[n]), p1, -C[n]*p0) -# special case for B[n] == 0 -Base.@propagate_inbounds _forwardrecurrence_next(n, A, ::Zeros, C, x, p0, p1) = muladd(A[n]*x, p1, -C[n]*p0) -# special case for Chebyshev U -Base.@propagate_inbounds _forwardrecurrence_next(n, A::AbstractFill, ::Zeros, C::Ones, x, p0, p1) = muladd(getindex_value(A)*x, p1, -p0) - - -# this supports adaptivity: we can populate `v` for large `n` -function _forwardrecurrence!(v::AbstractVector, A::AbstractVector, B::AbstractVector, C::AbstractVector, x, p0, p1) - N = length(v) - N == 0 && return v - v[1] = p0 - N == 1 && return v - v[2] = p1 - _forwardrecurrence!(v, A, B, C, x, 2:N) -end - -function _forwardrecurrence!(v::AbstractVector, A::AbstractVector, B::AbstractVector, C::AbstractVector, x, kr::AbstractUnitRange) - n₀, N = first(kr), last(kr) - @boundscheck N > length(v) && throw(BoundsError(v, N)) - p0, p1 = v[n₀-1], v[n₀] - @inbounds for n = n₀:N-1 - p1,p0 = _forwardrecurrence_next(n, A, B, C, x, p0, p1),p1 - v[n+1] = p1 - end - v -end - - - - -forwardrecurrence(N::Integer, A::AbstractVector, B::AbstractVector, C::AbstractVector, x) = - forwardrecurrence!(Vector{promote_type(eltype(A),eltype(B),eltype(C),typeof(x))}(undef, N), A, B, C, x) - - -""" -clenshaw!(c, A, B, C, x) - -evaluates the orthogonal polynomial expansion with coefficients `c` at points `x`, -where `A`, `B`, and `C` are `AbstractVector`s containing the recurrence coefficients -as defined in DLMF, -overwriting `x` with the results. - -If `c` is a matrix this treats each column as a separate vector of coefficients, returning a vector -if `x` is a number and a matrix if `x` is a vector. -""" -clenshaw!(c::AbstractVector, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::AbstractVector) = - clenshaw!(c, A, B, C, x, Ones{eltype(x)}(length(x)), x) - -clenshaw!(c::AbstractMatrix, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::Number, f::AbstractVector) = - clenshaw!(c, A, B, C, x, one(eltype(x)), f) - - -clenshaw!(c::AbstractMatrix, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::AbstractVector, f::AbstractMatrix) = - clenshaw!(c, A, B, C, x, Ones{eltype(x)}(length(x)), f) - - -""" -clenshaw!(c, A, B, C, x, ϕ₀, f) - -evaluates the orthogonal polynomial expansion with coefficients `c` at points `x`, -where `A`, `B`, and `C` are `AbstractVector`s containing the recurrence coefficients -as defined in DLMF and ϕ₀ is the zeroth polynomial, -overwriting `f` with the results. -""" -function clenshaw!(c::AbstractVector, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::AbstractVector, ϕ₀::AbstractVector, f::AbstractVector) - f .= ϕ₀ .* clenshaw.(Ref(c), Ref(A), Ref(B), Ref(C), x) -end - - -function clenshaw!(c::AbstractMatrix, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::Number, ϕ₀::Number, f::AbstractVector) - size(c,2) == length(f) || throw(DimensionMismatch("coeffients size and output length must match")) - @inbounds for j in axes(c,2) - f[j] = ϕ₀ * clenshaw(view(c,:,j), A, B, C, x) - end - f -end - -function clenshaw!(c::AbstractMatrix, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::AbstractVector, ϕ₀::AbstractVector, f::AbstractMatrix) - (size(x,1),size(c,2)) == size(f) || throw(DimensionMismatch("coeffients size and output length must match")) - @inbounds for j in axes(c,2) - clenshaw!(view(c,:,j), A, B, C, x, ϕ₀, view(f,:,j)) - end - f -end - -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])) -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])) -# Chebyshev U -Base.@propagate_inbounds _clenshaw_next(n, A::AbstractFill, ::Zeros, C::Ones, x, c, bn1, bn2) = muladd(getindex_value(A)*x, bn1, -bn2+c[n]) - -# allow special casing first arg, for ChebyshevT in OrthogonalPolynomialsQuasi -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])) - - -""" - clenshaw(c, A, B, C, x) - -evaluates the orthogonal polynomial expansion with coefficients `c` at points `x`, -where `A`, `B`, and `C` are `AbstractVector`s containing the recurrence coefficients -as defined in DLMF. -`x` may also be a single `Number`. - -If `c` is a matrix this treats each column as a separate vector of coefficients, returning a vector -if `x` is a number and a matrix if `x` is a vector. -""" - -function clenshaw(c::AbstractVector, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::Number) - N = length(c) - T = promote_type(eltype(c),eltype(A),eltype(B),eltype(C),typeof(x)) - @boundscheck check_clenshaw_recurrences(N, A, B, C) - N == 0 && return zero(T) - @inbounds begin - bn2 = zero(T) - bn1 = convert(T,c[N]) - N == 1 && return bn1 - for n = N-1:-1:2 - bn1,bn2 = _clenshaw_next(n, A, B, C, x, c, bn1, bn2),bn1 - end - bn1 = _clenshaw_first(A, B, C, x, c, bn1, bn2) - end - bn1 -end - - -clenshaw(c::AbstractVector, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::AbstractVector) = - clenshaw!(c, A, B, C, copy(x)) - -function clenshaw(c::AbstractMatrix, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::Number) - T = promote_type(eltype(c),eltype(A),eltype(B),eltype(C),typeof(x)) - clenshaw!(c, A, B, C, x, Vector{T}(undef, size(c,2))) -end - -function clenshaw(c::AbstractMatrix, A::AbstractVector, B::AbstractVector, C::AbstractVector, x::AbstractVector) - T = promote_type(eltype(c),eltype(A),eltype(B),eltype(C),typeof(x)) - clenshaw!(c, A, B, C, x, Matrix{T}(undef, size(x,1), size(c,2))) -end - -### -# Chebyshev T special cases -### - -""" - clenshaw!(c, x) - -evaluates the first-kind Chebyshev (T) expansion with coefficients `c` at points `x`, -overwriting `x` with the results. -""" -clenshaw!(c::AbstractVector, x::AbstractVector) = clenshaw!(c, x, x) - - -""" - clenshaw!(c, x, f) - -evaluates the first-kind Chebyshev (T) expansion with coefficients `c` at points `x`, -overwriting `f` with the results. -""" -function clenshaw!(c::AbstractVector, x::AbstractVector, f::AbstractVector) - f .= clenshaw.(Ref(c), x) -end - -""" - clenshaw(c, x) - -evaluates the first-kind Chebyshev (T) expansion with coefficients `c` at the points `x`. -`x` may also be a single `Number`. -""" -function clenshaw(c::AbstractVector, x::Number) - N,T = length(c),promote_type(eltype(c),typeof(x)) - if N == 0 - return zero(T) - elseif N == 1 # avoid issues with NaN x - return first(c)*one(x) - end - - y = 2x - bk1,bk2 = zero(T),zero(T) - @inbounds begin - for k = N:-1:2 - bk1,bk2 = muladd(y,bk1,c[k]-bk2),bk1 - end - muladd(x,bk1,c[1]-bk2) - end -end - -function clenshaw!(c::AbstractMatrix, x::Number, f::AbstractVector) - size(c,2) == length(f) || throw(DimensionMismatch("coeffients size and output length must match")) - @inbounds for j in axes(c,2) - f[j] = clenshaw(view(c,:,j), x) - end - f -end - -function clenshaw!(c::AbstractMatrix, x::AbstractVector, f::AbstractMatrix) - (size(x,1),size(c,2)) == size(f) || throw(DimensionMismatch("coeffients size and output length must match")) - @inbounds for j in axes(c,2) - clenshaw!(view(c,:,j), x, view(f,:,j)) - end - f -end - -clenshaw(c::AbstractVector, x::AbstractVector) = clenshaw!(c, copy(x)) -clenshaw(c::AbstractMatrix, x::Number) = clenshaw!(c, x, Vector{promote_type(eltype(c),typeof(x))}(undef, size(c,2))) -clenshaw(c::AbstractMatrix, x::AbstractVector) = clenshaw!(c, x, Matrix{promote_type(eltype(c),eltype(x))}(undef, size(x,1), size(c,2))) diff --git a/src/libfasttransforms.jl b/src/libfasttransforms.jl index ea724ce9..d89f0490 100644 --- a/src/libfasttransforms.jl +++ b/src/libfasttransforms.jl @@ -61,12 +61,6 @@ function horner!(c::StridedVector{Float32}, x::Vector{Float32}, f::Vector{Float3 f end -function check_clenshaw_recurrences(N, A, B, C) - if length(A) < N || length(B) < N || length(C) < N+1 - throw(ArgumentError("A, B must contain at least $N entries and C must contain at least $(N+1) entrie")) - end -end - function check_clenshaw_points(x, ϕ₀, f) length(x) == length(ϕ₀) == length(f) || throw(ArgumentError("Dimensions must match")) end diff --git a/test/clenshawtests.jl b/test/clenshawtests.jl deleted file mode 100644 index f4e0798d..00000000 --- a/test/clenshawtests.jl +++ /dev/null @@ -1,139 +0,0 @@ -using FastTransforms, FillArrays, Test -import FastTransforms: clenshaw, clenshaw!, forwardrecurrence!, forwardrecurrence - -@testset "clenshaw" begin - @testset "Chebyshev T" begin - for elty in (Float64, Float32) - c = [1,2,3] - cf = elty.(c) - @test @inferred(clenshaw(c,1)) ≡ 1 + 2 + 3 - @test @inferred(clenshaw(c,0)) ≡ 1 + 0 - 3 - @test @inferred(clenshaw(c,0.1)) == 1 + 2*0.1 + 3*cos(2acos(0.1)) - @test @inferred(clenshaw(c,[-1,0,1])) == clenshaw!(c,[-1,0,1]) == [2,-2,6] - @test clenshaw(c,[-1,0,1]) isa Vector{Int} - @test @inferred(clenshaw(elty[],1)) ≡ zero(elty) - - x = elty[1,0,0.1] - @test @inferred(clenshaw(c,x)) ≈ @inferred(clenshaw!(c,copy(x))) ≈ - @inferred(clenshaw!(c,x,similar(x))) ≈ - @inferred(clenshaw(cf,x)) ≈ @inferred(clenshaw!(cf,copy(x))) ≈ - @inferred(clenshaw!(cf,x,similar(x))) ≈ elty[6,-2,-1.74] - - @testset "Strided" begin - cv = view(cf,:) - xv = view(x,:) - @test clenshaw!(cv, xv, similar(xv)) == clenshaw!(cf,x,similar(x)) - - cv2 = view(cf,1:2:3) - @test clenshaw!(cv2, xv, similar(xv)) == clenshaw([1,3], x) - - # modifies x and xv - @test clenshaw!(cv2, xv) == xv == x == clenshaw([1,3], elty[1,0,0.1]) - end - - @testset "matrix coefficients" begin - c = [1 2; 3 4; 5 6] - @test clenshaw(c,0.1) ≈ [clenshaw(c[:,1],0.1), clenshaw(c[:,2],0.1)] - @test clenshaw(c,[0.1,0.2]) ≈ [clenshaw(c[:,1], 0.1) clenshaw(c[:,2], 0.1); clenshaw(c[:,1], 0.2) clenshaw(c[:,2], 0.2)] - end - end - end - - @testset "Chebyshev U" begin - N = 5 - A, B, C = Fill(2,N-1), Zeros{Int}(N-1), Ones{Int}(N) - @testset "forwardrecurrence!" begin - @test @inferred(forwardrecurrence(N, A, B, C, 1)) == @inferred(forwardrecurrence!(Vector{Int}(undef,N), A, B, C, 1)) == 1:N - @test forwardrecurrence!(Vector{Int}(undef,N), A, B, C, -1) == (-1) .^ (0:N-1) .* (1:N) - @test forwardrecurrence(N, A, B, C, 0.1) ≈ forwardrecurrence!(Vector{Float64}(undef,N), A, B, C, 0.1) ≈ - sin.((1:N) .* acos(0.1)) ./ sqrt(1-0.1^2) - end - - c = [1,2,3] - @test c'forwardrecurrence(3, A, B, C, 0.1) ≈ clenshaw([1,2,3], A, B, C, 0.1) ≈ - 1 + (2sin(2acos(0.1)) + 3sin(3acos(0.1)))/sqrt(1-0.1^2) - - @testset "matrix coefficients" begin - c = [1 2; 3 4; 5 6] - @test clenshaw(c,A,B,C,0.1) ≈ [clenshaw(c[:,1],A,B,C,0.1), clenshaw(c[:,2],A,B,C,0.1)] - @test clenshaw(c,A,B,C,[0.1,0.2]) ≈ [clenshaw(c[:,1], A,B,C,0.1) clenshaw(c[:,2], A,B,C,0.1); clenshaw(c[:,1], A,B,C,0.2) clenshaw(c[:,2], A,B,C,0.2)] - end - end - - @testset "Chebyshev-as-general" begin - @testset "forwardrecurrence!" begin - N = 5 - A, B, C = [1; fill(2,N-2)], fill(0,N-1), fill(1,N) - Af, Bf, Cf = float(A), float(B), float(C) - @test forwardrecurrence(N, A, B, C, 1) == forwardrecurrence!(Vector{Int}(undef,N), A, B, C, 1) == ones(Int,N) - @test forwardrecurrence!(Vector{Int}(undef,N), A, B, C, -1) == (-1) .^ (0:N-1) - @test forwardrecurrence(N, A, B, C, 0.1) ≈ forwardrecurrence!(Vector{Float64}(undef,N), A, B, C, 0.1) ≈ cos.((0:N-1) .* acos(0.1)) - end - - c, A, B, C = [1,2,3], [1,2,2], fill(0,3), fill(1,4) - cf, Af, Bf, Cf = float(c), float(A), float(B), float(C) - @test @inferred(clenshaw(c, A, B, C, 1)) ≡ 6 - @test @inferred(clenshaw(c, A, B, C, 0.1)) ≡ -1.74 - @test @inferred(clenshaw([1,2,3], A, B, C, [-1,0,1])) == clenshaw!([1,2,3],A, B, C, [-1,0,1]) == [2,-2,6] - @test clenshaw(c, A, B, C, [-1,0,1]) isa Vector{Int} - @test @inferred(clenshaw(Float64[], A, B, C, 1)) ≡ 0.0 - - x = [1,0,0.1] - @test @inferred(clenshaw(c, A, B, C, x)) ≈ @inferred(clenshaw!(c, A, B, C, copy(x))) ≈ - @inferred(clenshaw!(c, A, B, C, x, one.(x), similar(x))) ≈ - @inferred(clenshaw!(cf, Af, Bf, Cf, x, one.(x),similar(x))) ≈ - @inferred(clenshaw([1.,2,3], A, B, C, x)) ≈ - @inferred(clenshaw!([1.,2,3], A, B, C, copy(x))) ≈ [6,-2,-1.74] - end - - @testset "Legendre" begin - @testset "Float64" begin - N = 5 - n = 0:N-1 - A = (2n .+ 1) ./ (n .+ 1) - B = zeros(N) - C = n ./ (n .+ 1) - v_1 = forwardrecurrence(N, A, B, C, 1) - v_f = forwardrecurrence(N, A, B, C, 0.1) - @test v_1 ≈ ones(N) - @test forwardrecurrence(N, A, B, C, -1) ≈ (-1) .^ (0:N-1) - @test v_f ≈ [1,0.1,-0.485,-0.1475,0.3379375] - - n = 0:N # need extra entry for C in Clenshaw - C = n ./ (n .+ 1) - for j = 1:N - c = [zeros(j-1); 1] - @test clenshaw(c, A, B, C, 1) ≈ v_1[j] # Julia code - @test clenshaw(c, A, B, C, 0.1) ≈ v_f[j] # Julia code - @test clenshaw!(c, A, B, C, [1.0,0.1], [1.0,1.0], [0.0,0.0]) ≈ [v_1[j],v_f[j]] # libfasttransforms - end - end - - @testset "BigFloat" begin - N = 5 - n = BigFloat(0):N-1 - A = (2n .+ 1) ./ (n .+ 1) - B = zeros(N) - C = n ./ (n .+ 1) - @test forwardrecurrence(N, A, B, C, parse(BigFloat,"0.1")) ≈ [1,big"0.1",big"-0.485",big"-0.1475",big"0.3379375"] - end - end - - @testset "Int" begin - N = 10; A = 1:10; B = 2:11; C = range(3; step=2, length=N+1) - v_i = forwardrecurrence(N, A, B, C, 1) - v_f = forwardrecurrence(N, A, B, C, 0.1) - @test v_i isa Vector{Int} - @test v_f isa Vector{Float64} - - j = 3 - @test clenshaw([zeros(Int,j-1); 1; zeros(Int,N-j)], A, B, C, 1) == v_i[j] - end - - @testset "Zeros diagonal" begin - N = 10; A = randn(N); B = Zeros{Int}(N); C = randn(N+1) - @test forwardrecurrence(N, A, B, C, 0.1) == forwardrecurrence(N, A, Vector(B), C, 0.1) - c = randn(N) - @test clenshaw(c, A, B, C, 0.1) == clenshaw(c, A, Vector(B), C, 0.1) - end -end diff --git a/test/runtests.jl b/test/runtests.jl index de16f36b..34202842 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -8,7 +8,6 @@ include("nuffttests.jl") include("paduatests.jl") include("gaunttests.jl") include("hermitetests.jl") -include("clenshawtests.jl") include("toeplitzplanstests.jl") include("toeplitzhankeltests.jl") include("symmetrictoeplitzplushankeltests.jl")