From 041359d9061c9e8bd5ff0294e283a0e51a0d5121 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Fri, 20 Feb 2026 12:24:15 +0000 Subject: [PATCH 1/5] Suppport generators in expan --- Project.toml | 2 +- src/bases/bases.jl | 2 ++ test/test_chebyshev.jl | 4 ++++ 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 2990148..89de0f1 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "ContinuumArrays" uuid = "7ae1f121-cc2c-504b-ac30-9b923412ae5c" -version = "0.20.3" +version = "0.20.4" [deps] AbstractFFTs = "621f4979-c628-5d54-868e-fcf4e3e8185c" diff --git a/src/bases/bases.jl b/src/bases/bases.jl index a9a52c2..d36be9b 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -376,6 +376,8 @@ function expand(v) end +expand(g::Base.Generator{<:Inclusion}; kwds...) = expand(g.f.(g.iter); kwds...) +expand(g::Base.Generator{<:Domain}; kwds...) = expand(Base.Generator(g.f, Inclusion(g.iter)); kwds...) # type piracy... diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index fc6298c..b01fb7f 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -295,4 +295,8 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test_throws ErrorException maximum(exp.(x)) @test_throws ErrorException minimum(exp.(x)) end + + @testset "generator" begin + @test expand(exp(t) for t in (-1..1))[0.1] ≈ exp(0.1) + end end From 239bfe44b0bdef3921fb3f08ebefb51e715d4129 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 21 Feb 2026 09:45:50 +0000 Subject: [PATCH 2/5] Overload collect instead of expand --- src/ContinuumArrays.jl | 7 ++++++- src/bases/bases.jl | 6 +++--- test/test_chebyshev.jl | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/ContinuumArrays.jl b/src/ContinuumArrays.jl index 60332a3..6e9a147 100644 --- a/src/ContinuumArrays.jl +++ b/src/ContinuumArrays.jl @@ -3,7 +3,7 @@ using IntervalSets, DomainSets, LinearAlgebra, LazyArrays, FillArrays, BandedMat import Base: @_inline_meta, @_propagate_inbounds_meta, axes, size, getindex, convert, prod, *, /, \, +, -, ==, ^, IndexStyle, IndexLinear, ==, OneTo, tail, similar, copyto!, copy, diff, first, last, show, isempty, findfirst, findlast, findall, Slice, union, minimum, maximum, extrema, sum, _sum, _maximum, _minimum, - getproperty, isone, iszero, zero, abs, <, ≤, >, ≥, string, summary, to_indices, view, @propagate_inbounds + getproperty, isone, iszero, zero, abs, <, ≤, >, ≥, string, summary, to_indices, view, @propagate_inbounds, collect import Base.Broadcast: materialize, BroadcastStyle, broadcasted, Broadcasted import LazyArrays: MemoryLayout, Applied, ApplyStyle, flatten, _flatten, colsupport, combine_mul_styles, AbstractArrayApplyStyle, adjointlayout, arguments, _mul_arguments, call, broadcastlayout, layout_getindex, UnknownLayout, @@ -37,6 +37,7 @@ cardinality(::AbstractInterval) = ℵ₁ cardinality(::Union{FullSpace{<:AbstractFloat},EuclideanDomain,DomainSets.RealNumbers,DomainSets.ComplexNumbers}) = ℵ₁ cardinality(::Union{DomainSets.Integers,DomainSets.Rationals,DomainSets.NaturalNumbers}) = ℵ₀ +Inclusion(d::ProductDomain{T}) where T = Inclusion{float(T)}(d) Inclusion(d::AbstractInterval{T}) where T = Inclusion{float(T)}(d) first(S::Inclusion{<:Any,<:AbstractInterval}) = leftendpoint(S.domain) last(S::Inclusion{<:Any,<:AbstractInterval}) = rightendpoint(S.domain) @@ -102,6 +103,10 @@ checkpoints(d::AbstractInterval{T}) where T = width(d) .* SVector{3,float(T)}(0. checkpoints(d::UnionDomain) = mapreduce(checkpoints,union,d.domains) checkpoints(x::Inclusion) = checkpoints(x.domain) checkpoints(A::AbstractQuasiMatrix) = checkpoints(axes(A,1)) +function checkpoints(P::ProductDomain) + x,y = map(checkpoints, components(P)) + SVector.(x, y') +end include("operators.jl") diff --git a/src/bases/bases.jl b/src/bases/bases.jl index d36be9b..7e4b752 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -376,9 +376,9 @@ function expand(v) end -expand(g::Base.Generator{<:Inclusion}; kwds...) = expand(g.f.(g.iter); kwds...) -expand(g::Base.Generator{<:Domain}; kwds...) = expand(Base.Generator(g.f, Inclusion(g.iter)); kwds...) # type piracy... - +collect(g::Base.Generator{<:Inclusion}; kwds...) = expand(g.f.(g.iter); kwds...) +collect(g::Base.Generator{<:Domain}; kwds...) = collect(Base.Generator(g.f, Inclusion(g.iter)); kwds...) +collect(g::Base.Generator{<:Base.Iterators.ProductIterator{<:Tuple{Vararg{Domain}}}}; kwds...) = collect(Base.Generator(g.f, ×(g.iter.iterators...)); kwds...) @inline copy(L::Ldiv{<:AbstractBasisLayout}) = basis_ldiv_size(size(L), L.A, L.B) diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index b01fb7f..1bb1c72 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -297,6 +297,6 @@ Base.:(==)(::FooBasis, ::FooBasis) = true end @testset "generator" begin - @test expand(exp(t) for t in (-1..1))[0.1] ≈ exp(0.1) + @test [exp(t) for t in -1..1][0.1] ≈ exp(0.1) end end From 75e8fb715078f8c349ababc9528faa26f5baec32 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sat, 21 Feb 2026 09:49:12 +0000 Subject: [PATCH 3/5] add docs for affine --- src/maps.jl | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/maps.jl b/src/maps.jl index 2ca2efe..31d96a9 100644 --- a/src/maps.jl +++ b/src/maps.jl @@ -147,6 +147,13 @@ end first(A::AffineMap{T}) where T = convert(T, first(A.range))::T last(A::AffineMap{T}) where T = convert(T, last(A.range))::T +""" + affine(a, b) + +constructs a quasivector corresponding to the affine map between two domains/quasivectors. For example: + + affine(1..2, 2..3)[1.5] == 2.5 +""" affine(a::AbstractQuasiVector, b::AbstractQuasiVector) = AffineMap(a, b) affine(a, b::AbstractQuasiVector) = affine(Inclusion(a), b) affine(a::AbstractQuasiVector, b) = affine(a, Inclusion(b)) From 38052b6a355c394c9bff48653f8c12bea0ea82ad Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 23 Feb 2026 08:47:22 +0000 Subject: [PATCH 4/5] expand as generator --- src/bases/bases.jl | 6 +++--- test/test_chebyshev.jl | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/bases/bases.jl b/src/bases/bases.jl index 7e4b752..4e3d074 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -376,9 +376,9 @@ function expand(v) end -collect(g::Base.Generator{<:Inclusion}; kwds...) = expand(g.f.(g.iter); kwds...) -collect(g::Base.Generator{<:Domain}; kwds...) = collect(Base.Generator(g.f, Inclusion(g.iter)); kwds...) -collect(g::Base.Generator{<:Base.Iterators.ProductIterator{<:Tuple{Vararg{Domain}}}}; kwds...) = collect(Base.Generator(g.f, ×(g.iter.iterators...)); kwds...) +expand(g::Base.Generator{<:Inclusion}) = expand(g.f.(g.iter)) +expand(g::Base.Generator{<:Domain}) = expand(Base.Generator(g.f, Inclusion(g.iter))) +expand(g::Base.Generator{<:Base.Iterators.ProductIterator{<:Tuple{Vararg{Domain}}}}) = expand(Base.Generator(g.f, ×(g.iter.iterators...))) @inline copy(L::Ldiv{<:AbstractBasisLayout}) = basis_ldiv_size(size(L), L.A, L.B) diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index 1bb1c72..938570c 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -297,6 +297,7 @@ Base.:(==)(::FooBasis, ::FooBasis) = true end @testset "generator" begin - @test [exp(t) for t in -1..1][0.1] ≈ exp(0.1) + @test expand(exp(t) for t in -1..1)[0.1] ≈ [exp(t) for t in -1..1][0.1] ≈ exp(0.1) + @test [exp(x*cos(y)) for x in Inclusion(0:0.5:1), y in Inclusion(1:0.5:2)][0.5,1.5] ≈ exp(0.5*cos(1.5)) end end From c67cd27cc6cafbdcabbf1154f06164ba272d8d13 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 23 Feb 2026 16:06:13 +0000 Subject: [PATCH 5/5] Update index.md --- docs/src/index.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/src/index.md b/docs/src/index.md index 27e814b..e685b7a 100644 --- a/docs/src/index.md +++ b/docs/src/index.md @@ -49,6 +49,9 @@ weaklaplacian ## Routines +```@docs +affine +``` ```@docs transform ```