diff --git a/Project.toml b/Project.toml index 97fe7d9d..d2ca1fba 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ApproxFunBase" uuid = "fbd15aa5-315a-5a7d-a8a4-24992e37be05" -version = "0.9.11" +version = "0.9.12" [deps] AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" diff --git a/src/ApproxFunBase.jl b/src/ApproxFunBase.jl index c4cbc10d..e329fa1e 100644 --- a/src/ApproxFunBase.jl +++ b/src/ApproxFunBase.jl @@ -147,6 +147,17 @@ function _IteratorSize(::Type{T}) where {T<:Tuple} any(x -> x isa Base.IsInfinite, s) ? Base.IsInfinite() : Base.HasLength() end +_IteratorSize(::Type{<:AbstractVector{<:AbstractFill{<:Any,<:Any, + <:Tuple{Vararg{InfRanges}}}}}) = Base.IsInfinite() +_IteratorSize(::Type{<:AbstractVector{<:InfRanges}}) = Base.IsInfinite() +_IteratorSize(::Type{<:AbstractVector{<:Union{Vector{<:Integer}, + SVector{<:Any,<:Integer}}}}) = Base.HasLength() +_IteratorSize(::Type{<:AbstractVector}) = Base.SizeUnknown() + +tuple_to_SVector(t::Tuple) = SVector(t) +tuple_to_SVector(x) = x +_vcat_toabsvec(args...) = mapreduce(tuple_to_SVector, vcat, args) + include("LinearAlgebra/LinearAlgebra.jl") include("Fun.jl") include("onehotvector.jl") diff --git a/src/LinearAlgebra/helper.jl b/src/LinearAlgebra/helper.jl index 72d24601..b2ea6bc6 100644 --- a/src/LinearAlgebra/helper.jl +++ b/src/LinearAlgebra/helper.jl @@ -689,15 +689,13 @@ conv(x::AbstractFill, y::AbstractFill) = DSP.conv(x, y) # TODO: cache sums -struct BlockInterlacer{DMS<:Tuple{Vararg{AbstractVector{Int}}}} +struct BlockInterlacer{DMS} blocks::DMS end const TrivialInterlacer{d,Ax} = BlockInterlacer{<:NTuple{d,Ones{Int,1,Tuple{Ax}}}} -BlockInterlacer(v::AbstractVector) = BlockInterlacer(Tuple(v)) - eltype(::Type{<:BlockInterlacer}) = Tuple{Int,Int} dimensions(b::BlockInterlacer) = map(sum,b.blocks) @@ -724,10 +722,16 @@ function done(it::BlockInterlacer,st) return true end -iterate(it::BlockInterlacer) = +iterate(it::BlockInterlacer{<:Tuple}) = iterate(it, (1,1,ntuple(_ -> tuple(), length(it.blocks)), ntuple(zero,length(it.blocks)))) +iterate(it::BlockInterlacer{<:AbstractVector}) = + iterate(it, (1,1, [tuple() for _ in 1:length(it.blocks)], + [zero(i) for i in 1:length(it.blocks)])) + +_setindex(coll, v, ind) = (coll[ind] = v; coll) +_setindex(coll::Tuple, v, ind) = Base.setindex(coll, v, ind) function iterate(it::BlockInterlacer, (N,k,blkst,lngs)) done(it, (N,k,blkst,lngs)) && return nothing @@ -747,7 +751,7 @@ function iterate(it::BlockInterlacer, (N,k,blkst,lngs)) return iterate(it,(N+1,1,blkst,lngs)) end - lngs = Base.setindex(lngs, lngs[N]+1, N) + lngs = _setindex(lngs, lngs[N]+1, N) return (N,lngs[N]),(N,k+1,blkst,lngs) end diff --git a/src/Spaces/SumSpace.jl b/src/Spaces/SumSpace.jl index 37fe1c81..1b35e641 100644 --- a/src/Spaces/SumSpace.jl +++ b/src/Spaces/SumSpace.jl @@ -25,7 +25,7 @@ ncomponents(f::Fun) = ncomponents(space(f)) BlockInterlacer(sp::DirectSumSpace) = BlockInterlacer(map(blocklengths,sp.spaces)) interlacer(sp::DirectSumSpace) = BlockInterlacer(sp) -interlacer(sp::Space) = BlockInterlacer(tuple(blocklengths(sp))) +interlacer(sp::Space) = BlockInterlacer(blocklengths(sp)) function blocklengths(sp::DirectSumSpace) bl=map(blocklengths,components(sp)) @@ -50,6 +50,21 @@ end SumSpace(sp::Tuple) = SumSpace{typeof(sp),domaintype(first(sp)), mapreduce(rangetype,promote_type,sp)}(sp) +SumSpace(A::SumSpace,B::SumSpace) = SumSpace(tuple(A.spaces...,B.spaces...)) + +SumSpace(A::Space,B::SumSpace) = SumSpace(tuple(A,B.spaces...)) +SumSpace(A::SumSpace,B::Space) = SumSpace(tuple(A.spaces...,B)) +SumSpace(A::Space...) = SumSpace(A) +SumSpace(sp::AbstractArray) = SumSpace(tuple(sp...)) + +canonicalspace(A::SumSpace) = SumSpace(sort(collect(A.spaces))) + +# TODO: Fix this Hack +SumSpace(A::ConstantSpace{AnyDomain}, B::ConstantSpace{AnyDomain}) = error("Should not happen") +SumSpace(A::SumSpace, B::ConstantSpace{AnyDomain}) = SumSpace(A, setdomain(B, domain(A))) +SumSpace(B::ConstantSpace{AnyDomain}, A::SumSpace) = SumSpace(setdomain(B, domain(A)), A) +SumSpace(A::Space, B::ConstantSpace{AnyDomain}) = SumSpace(A, setdomain(B, domain(A))) +SumSpace(B::ConstantSpace{AnyDomain}, A::Space) = SumSpace(setdomain(B, domain(A)), A) struct PiecewiseSpace{SV,D<:UnionDomain,R} <: DirectSumSpace{SV,D,R} spaces::SV @@ -57,7 +72,7 @@ struct PiecewiseSpace{SV,D<:UnionDomain,R} <: DirectSumSpace{SV,D,R} new{SV,D,R}(tuple(map(typ->typ(dom),SV.parameters)...)) PiecewiseSpace{SV,D,R}(dom::UnionDomain) where {SV,D,R} = new{SV,D,R}(tuple(map((typ,dom)->typ(dom),SV.parameters,dom.domains)...)) - PiecewiseSpace{SV,D,R}(sp::Tuple) where {SV,D,R} = + PiecewiseSpace{SV,D,R}(sp::SV) where {SV,D,R} = new{SV,D,R}(sp) end @@ -65,34 +80,21 @@ function _PiecewiseSpace(sp) PiecewiseSpace{typeof(sp),typeof(UnionDomain(map(domain,sp))), mapreduce(rangetype,promote_type,sp)}(sp) end -function PiecewiseSpace(spin::Tuple) - sp=tuple(union(spin)...) # remove duplicates +function PiecewiseSpace(spacesin::Union{Tuple{Vararg{Space}}, AbstractVector{<:Space}}) + sp = union(spacesin) # remove duplicates _PiecewiseSpace(sp) end -PiecewiseSpace(spin::Set) = PiecewiseSpace(collect(spin)) - - +PiecewiseSpace(spacesin::Set) = PiecewiseSpace(collect(spacesin)) -for TYP in (:SumSpace,:PiecewiseSpace) - @eval begin - $TYP(A::$TYP,B::$TYP) = $TYP(tuple(A.spaces...,B.spaces...)) - - $TYP(A::Space,B::$TYP) = $TYP(tuple(A,B.spaces...)) - $TYP(A::$TYP,B::Space) = $TYP(tuple(A.spaces...,B)) - $TYP(A::Space...) = $TYP(A) - $TYP(sp::AbstractArray) = $TYP(tuple(sp...)) +PiecewiseSpace(A::PiecewiseSpace, B::PiecewiseSpace) = + PiecewiseSpace(_vcat_toabsvec(A.spaces, B.spaces)) - canonicalspace(A::$TYP) = $TYP(sort(collect(A.spaces))) - end -end +PiecewiseSpace(A::Space,B::PiecewiseSpace) = PiecewiseSpace(_vcat_toabsvec(A, B.spaces)) +PiecewiseSpace(A::PiecewiseSpace,B::Space) = PiecewiseSpace(_vcat_toabsvec(A.spaces, B)) +PiecewiseSpace(A::Space...) = PiecewiseSpace(A) -# TODO: Fix this Hack -SumSpace(A::ConstantSpace{AnyDomain}, B::ConstantSpace{AnyDomain}) = error("Should not happen") -SumSpace(A::SumSpace, B::ConstantSpace{AnyDomain}) = SumSpace(A, setdomain(B, domain(A))) -SumSpace(B::ConstantSpace{AnyDomain}, A::SumSpace) = SumSpace(setdomain(B, domain(A)), A) -SumSpace(A::Space, B::ConstantSpace{AnyDomain}) = SumSpace(A, setdomain(B, domain(A))) -SumSpace(B::ConstantSpace{AnyDomain}, A::Space) = SumSpace(setdomain(B, domain(A)), A) +canonicalspace(A::PiecewiseSpace) = PiecewiseSpace(sort(convert_vector_or_svector(A.spaces))) pieces(sp::PiecewiseSpace) = sp.spaces piece(s::Space,k) = pieces(s)[k] diff --git a/test/SpacesTest.jl b/test/SpacesTest.jl index 39690aba..519773a0 100644 --- a/test/SpacesTest.jl +++ b/test/SpacesTest.jl @@ -361,4 +361,20 @@ using LinearAlgebra @test length(A) == 0 @test ApproxFunBase.dimension(A) == 0 end + + @testset "PiecewiseSpace" begin + ps = PiecewiseSpace([PointSpace(1:2), PointSpace(3:4)]) + @test PiecewiseSpace(ps, ps) == ps + @test ApproxFunBase.canonicalspace(ps) == ps + d = domain(ps) + @test all(x -> x in d, 1:4) + @test all(x -> !(x in d), 5:6) + d2 = domain(PiecewiseSpace(ps, PointSpace(5:6))) + @test all(x -> x in d2, 5:6) + d2 = domain(PiecewiseSpace(PointSpace(5:6), ps)) + @test all(x -> x in d2, 5:6) + + ps2 = PiecewiseSpace([PointSpace(3:4), PointSpace(1:2)]) + @test ApproxFunBase.canonicalspace(ps2) == ps + end end diff --git a/test/runtests.jl b/test/runtests.jl index 24d5911e..6e9da25b 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -12,6 +12,7 @@ using Infinities using LinearAlgebra using Random using SpecialFunctions +using StaticArrays using Test @testset "Project quality" begin @@ -87,6 +88,21 @@ end @test first(C, 10) == C[1:10] == B[1:10] == first(B, 10) @test C[2:10][1:2:end] == B[2:10][1:2:end] end + + a = [1,2] + sa = SVector(1,2) + f = Fill(2,∞) + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer((f, f))) == Base.IsInfinite() + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer([f, f])) == Base.IsInfinite() + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer((1:∞, 1:∞))) == Base.IsInfinite() + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer([1:∞, 1:∞])) == Base.IsInfinite() + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer([sa, sa])) == Base.HasLength() + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer([a, a])) == Base.HasLength() + @test Base.IteratorSize(ApproxFunBase.BlockInterlacer((a, a))) == Base.HasLength() + + b1 = ApproxFunBase.BlockInterlacer([Fill(2,2), 1:2]) + b2 = ApproxFunBase.BlockInterlacer((Fill(2,2), 1:2)) + @test collect(b1) == collect(b2) end @testset "issue #94" begin