From 9dc5f381b7516a6f6676de21d1c924ecd1f3969f Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 20 Oct 2024 22:22:53 +0100 Subject: [PATCH 01/11] Expand functions in P'(x .^2 .* P) --- src/bases/bases.jl | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/src/bases/bases.jl b/src/bases/bases.jl index b1bdf50..90fabaa 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -145,8 +145,7 @@ function _broadcast_mul_ldiv(::Tuple{ScalarLayout,ApplyLayout{typeof(*)}}, A, B) a * (A \ b) end -_broadcast_mul_ldiv(::Tuple{ScalarLayout,AbstractBasisLayout}, A, B) = - _broadcast_mul_ldiv((ScalarLayout(),UnknownLayout()), A, B) +_broadcast_mul_ldiv(::Tuple{ScalarLayout,AbstractBasisLayout}, A, B) = _broadcast_mul_ldiv((ScalarLayout(),UnknownLayout()), A, B) _broadcast_mul_ldiv(_, A, B) = copy(Ldiv{typeof(MemoryLayout(A)),UnknownLayout}(A,B)) copy(L::Ldiv{<:AbstractBasisLayout,BroadcastLayout{typeof(*)}}) = _broadcast_mul_ldiv(map(MemoryLayout,arguments(L.B)), L.A, L.B) @@ -154,6 +153,38 @@ copy(L::Ldiv{<:MappedBasisLayouts,BroadcastLayout{typeof(*)}}) = _broadcast_mul_ +# multiplication operators, reexpand in basis A +@inline function _broadcast_mul_adj(::Tuple{Any,AbstractBasisLayout}, Ac, B) + a,b = arguments(B) + @assert a isa AbstractQuasiVector # Only works for vec .* mat + A = Ac' + ab = (A * (A \ a)) .* b # broadcasted should be overloaded + MemoryLayout(ab) isa BroadcastLayout && return Ac*transform_ldiv(A, ab) + Ac*ab +end + +@inline function _broadcast_mul_adj(::Tuple{Any,ApplyLayout{typeof(*)}}, Ac, B) + a,b = arguments(B) + @assert a isa AbstractQuasiVector # Only works for vec .* mat + args = arguments(*, b) + *(Ac*(a .* first(args)), tail(args)...) +end + + +function _broadcast_mul_adj(::Tuple{ScalarLayout,Any}, Ac, B) + a,b = arguments(B) + a * (Ac*b) +end + +function _broadcast_mul_adj(::Tuple{ScalarLayout,ApplyLayout{typeof(*)}}, Ac, B) + a,b = arguments(B) + a * (Ac*b) +end + +_broadcast_mul_adj(::Tuple{ScalarLayout,AbstractBasisLayout}, A, B) = _broadcast_mul_adj((ScalarLayout(),UnknownLayout()), A, B) +_broadcast_mul_adj(_, A, B) = copy(Mul{typeof(MemoryLayout(A)),UnknownLayout}(A,B)) + +copy(L::Mul{<:AdjointBasisLayout,BroadcastLayout{typeof(*)}}) = _broadcast_mul_adj(map(MemoryLayout,arguments(L.B)), L.A, L.B) """ From 8594a4e8a7fb20ec7de060e694b62a9752c03799 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 20 Oct 2024 22:23:30 +0100 Subject: [PATCH 02/11] Update ci.yml --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f1dda78..3cf21dc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,7 +20,8 @@ jobs: fail-fast: false matrix: version: - - '1.10' + - 'lts' + - '1' os: - ubuntu-latest - macOS-latest From 0c44156da7dcd01e9340ac4a22affe279cc0503b Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 21 Oct 2024 10:50:09 +0100 Subject: [PATCH 03/11] add tests and use expand --- Project.toml | 1 + src/bases/bases.jl | 4 ++-- test/Project.toml | 1 + test/test_chebyshev.jl | 5 ++++- 4 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 test/Project.toml diff --git a/Project.toml b/Project.toml index 6a68c9b..96f865b 100644 --- a/Project.toml +++ b/Project.toml @@ -8,6 +8,7 @@ ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" BandedMatrices = "aae01518-5342-5314-be14-df237901396f" BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf" +FastTransforms = "057dd010-8810-581a-b7be-e3fc3b93f78c" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" Infinities = "e1ba4f0e-776d-440f-acd9-e1d2e9742647" diff --git a/src/bases/bases.jl b/src/bases/bases.jl index 90fabaa..1eb63d9 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -122,7 +122,7 @@ copy(L::Ldiv{<:AbstractBasisLayout,<:AbstractWeightLayout}) = transform_ldiv(L.A @inline function _broadcast_mul_ldiv(::Tuple{Any,AbstractBasisLayout}, A, B) a,b = arguments(B) @assert a isa AbstractQuasiVector # Only works for vec .* mat - ab = (A * (A \ a)) .* b # broadcasted should be overloaded + ab = expand(a) .* b # broadcasted should be overloaded MemoryLayout(ab) isa BroadcastLayout && return transform_ldiv(A, ab) A \ ab end @@ -158,7 +158,7 @@ copy(L::Ldiv{<:MappedBasisLayouts,BroadcastLayout{typeof(*)}}) = _broadcast_mul_ a,b = arguments(B) @assert a isa AbstractQuasiVector # Only works for vec .* mat A = Ac' - ab = (A * (A \ a)) .* b # broadcasted should be overloaded + ab = expand(a) .* b # broadcasted should be overloaded MemoryLayout(ab) isa BroadcastLayout && return Ac*transform_ldiv(A, ab) Ac*ab end diff --git a/test/Project.toml b/test/Project.toml new file mode 100644 index 0000000..81648c0 --- /dev/null +++ b/test/Project.toml @@ -0,0 +1 @@ +[deps] diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index 0f2666b..6388d13 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -1,4 +1,5 @@ -using ContinuumArrays, LinearAlgebra, FastTransforms, QuasiArrays, ArrayLayouts, Base64, LazyArrays, Test +using ContinuumArrays, LinearAlgebra, QuasiArrays, ArrayLayouts, Base64, LazyArrays, Test +using FastTransforms import ContinuumArrays: Basis, Weight, Map, LazyQuasiArrayStyle, TransformFactorization, ExpansionLayout, checkpoints, MappedBasisLayout, MappedWeightedBasisLayout, SubWeightedBasisLayout, WeightedBasisLayout, WeightLayout, basis, grammatrix @@ -159,6 +160,8 @@ Base.:(==)(::FooBasis, ::FooBasis) = true ã = T * (T \ a) @test T \ (ã .* ã) ≈ [1.5,1,0.5,0,0] + + @test T'*(a .* T) isa Matrix end @testset "sum/dot/diff" begin From dfec0f0211717223045e956c65c7e19b2d236d7e Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 21 Oct 2024 17:16:51 +0100 Subject: [PATCH 04/11] Delete Project.toml --- test/Project.toml | 1 - 1 file changed, 1 deletion(-) delete mode 100644 test/Project.toml diff --git a/test/Project.toml b/test/Project.toml deleted file mode 100644 index 81648c0..0000000 --- a/test/Project.toml +++ /dev/null @@ -1 +0,0 @@ -[deps] From f7457e0cc5f5b39a9d6a76672f640a5d7c3bb468 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 22 Oct 2024 22:02:23 +0100 Subject: [PATCH 05/11] Update bases.jl --- src/bases/bases.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bases/bases.jl b/src/bases/bases.jl index 1eb63d9..90fabaa 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -122,7 +122,7 @@ copy(L::Ldiv{<:AbstractBasisLayout,<:AbstractWeightLayout}) = transform_ldiv(L.A @inline function _broadcast_mul_ldiv(::Tuple{Any,AbstractBasisLayout}, A, B) a,b = arguments(B) @assert a isa AbstractQuasiVector # Only works for vec .* mat - ab = expand(a) .* b # broadcasted should be overloaded + ab = (A * (A \ a)) .* b # broadcasted should be overloaded MemoryLayout(ab) isa BroadcastLayout && return transform_ldiv(A, ab) A \ ab end @@ -158,7 +158,7 @@ copy(L::Ldiv{<:MappedBasisLayouts,BroadcastLayout{typeof(*)}}) = _broadcast_mul_ a,b = arguments(B) @assert a isa AbstractQuasiVector # Only works for vec .* mat A = Ac' - ab = expand(a) .* b # broadcasted should be overloaded + ab = (A * (A \ a)) .* b # broadcasted should be overloaded MemoryLayout(ab) isa BroadcastLayout && return Ac*transform_ldiv(A, ab) Ac*ab end From 63df43ea35df32b07d305e020e02187bba951c24 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Wed, 23 Oct 2024 07:34:40 +0100 Subject: [PATCH 06/11] add coverage --- src/bases/bases.jl | 8 ++++++++ test/test_chebyshev.jl | 4 ++++ 2 files changed, 12 insertions(+) diff --git a/src/bases/bases.jl b/src/bases/bases.jl index 90fabaa..983021a 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -184,6 +184,14 @@ end _broadcast_mul_adj(::Tuple{ScalarLayout,AbstractBasisLayout}, A, B) = _broadcast_mul_adj((ScalarLayout(),UnknownLayout()), A, B) _broadcast_mul_adj(_, A, B) = copy(Mul{typeof(MemoryLayout(A)),UnknownLayout}(A,B)) +_broadcast_mul_adj_simplifiable(_, ::AbstractBasisLayout) = Val(true) +_broadcast_mul_adj_simplifiable(_, ::ApplyLayout{typeof(*)}) = Val(true) +_broadcast_mul_adj_simplifiable(::ScalarLayout, _) = Val(true) +_broadcast_mul_adj_simplifiable(::ScalarLayout, ::ApplyLayout{typeof(*)}) = Val(true) +_broadcast_mul_adj_simplifiable(::ScalarLayout, ::AbstractBasisLayout) = Val(true) +_broadcast_mul_adj_simplifiable(_, _) = Val(false) + +simplifiable(L::Mul{<:AdjointBasisLayout,BroadcastLayout{typeof(*)}}) = _broadcast_mul_adj_simplifiable(map(MemoryLayout,arguments(L.B))...) copy(L::Mul{<:AdjointBasisLayout,BroadcastLayout{typeof(*)}}) = _broadcast_mul_adj(map(MemoryLayout,arguments(L.B)), L.A, L.B) diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index 6388d13..d75cfe0 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -162,6 +162,10 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test T \ (ã .* ã) ≈ [1.5,1,0.5,0,0] @test T'*(a .* T) isa Matrix + @test T'*(a .* (T * (T \ a))) isa Vector + @test_broken T'f isa Vector + @test T'ã isa Vector + @test T'*(ã .* ã) isa Vector end @testset "sum/dot/diff" begin From 796fb38493626e78eb6b81dfe4f8ae3b74949702 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 10 Nov 2024 22:44:47 +0000 Subject: [PATCH 07/11] test adj broadcast --- Project.toml | 2 +- test/test_chebyshev.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 96f865b..0aff1b0 100644 --- a/Project.toml +++ b/Project.toml @@ -40,7 +40,7 @@ Infinities = "0.1" IntervalSets = "0.7" LazyArrays = "2" Makie = "0.20, 0.21" -QuasiArrays = "0.11.5" +QuasiArrays = "0.11.8" RecipesBase = "1.0" StaticArrays = "1.0" julia = "1.10" diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index d75cfe0..a703664 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -166,6 +166,7 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test_broken T'f isa Vector @test T'ã isa Vector @test T'*(ã .* ã) isa Vector + @test (2T)'*(a .* T) isa Matrix end @testset "sum/dot/diff" begin From bce16374af0c34b5f4a4f05a72ff5376caeea370 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 11 Nov 2024 22:44:23 +0000 Subject: [PATCH 08/11] Add tests --- src/bases/bases.jl | 1 + test/test_chebyshev.jl | 4 ++++ test/test_splines.jl | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/bases/bases.jl b/src/bases/bases.jl index 983021a..91709cf 100644 --- a/src/bases/bases.jl +++ b/src/bases/bases.jl @@ -690,6 +690,7 @@ diff_layout(::ExpansionLayout, A, dims...) = diff_layout(ApplyLayout{typeof(*)}( #### simplifiable(::Mul{<:AdjointBasisLayout, <:AbstractBasisLayout}) = Val(true) +@inline simplifiable(L::Mul{<:AdjointBasisLayout,ApplyLayout{typeof(*)}}) = simplifiable(*, L.A, first(arguments(*, L.B))) function copy(M::Mul{<:AdjointBasisLayout, <:AbstractBasisLayout}) A = (M.A)' A == M.B && return grammatrix(A) diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index a703664..e8e8765 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -167,6 +167,10 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test T'ã isa Vector @test T'*(ã .* ã) isa Vector @test (2T)'*(a .* T) isa Matrix + @test T'*(2T) isa Matrix + @test T'*(2T*randn(5)) isa Vector + @test LazyArrays.simplifiable(*, T', T*(1:5)) == Val(true) + @test (2T)'*(T*(1:5)) ≈ T'*(2T*(1:5)) ≈ T'BroadcastQuasiMatrix(*, 2, T*(1:5)) end @testset "sum/dot/diff" begin diff --git a/test/test_splines.jl b/test/test_splines.jl index 7b35ab9..fb9771d 100644 --- a/test/test_splines.jl +++ b/test/test_splines.jl @@ -362,7 +362,7 @@ import ContinuumArrays: basis, AdjointBasisLayout, ExpansionLayout, BasisLayout, @test Δ == -(*(B',D',D,B)) @test Δ == -(B'D'D*B) @test Δ == -((B'D')*(D*B)) - @test_broken Δ == -B'*(D'D)*B + @test Δ == -B'*(D'D)*B @test Δ == -(B'*(D'D)*B) f = L*exp.(L.points) # project exp(x) From 7058386b97101c1b6844e10ccf4c286029f9516c Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 12 Nov 2024 08:52:10 +0000 Subject: [PATCH 09/11] Update test_chebyshev.jl --- test/test_chebyshev.jl | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index e8e8765..e524518 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -169,8 +169,14 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test (2T)'*(a .* T) isa Matrix @test T'*(2T) isa Matrix @test T'*(2T*randn(5)) isa Vector - @test LazyArrays.simplifiable(*, T', T*(1:5)) == Val(true) @test (2T)'*(T*(1:5)) ≈ T'*(2T*(1:5)) ≈ T'BroadcastQuasiMatrix(*, 2, T*(1:5)) + @test T' * (a .* (T * (1:5))) ≈ T' * ((a .* T) * (1:5)) + + @test LazyArrays.simplifiable(*, T', T*(1:5)) == Val(true) + @test LazyArrays.simplifiable(*, T', (a .* (T * (1:5)))) == Val(true) + @test LazyArrays.simplifiable(*, T', a .* T) == Val(true) + @test LazyArrays.simplifiable(*, T', 2T) == Val(true) + @test LazyArrays.simplifiable(*, T', BroadcastQuasiMatrix(*, 2, T*(1:5))) == Val(true) end @testset "sum/dot/diff" begin From 14dddce6c4ceef96750f442a4ef8e2f137be28f6 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 12 Nov 2024 09:03:27 +0000 Subject: [PATCH 10/11] Update test_chebyshev.jl --- test/test_chebyshev.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index e524518..29ef367 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -171,6 +171,7 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test T'*(2T*randn(5)) isa Vector @test (2T)'*(T*(1:5)) ≈ T'*(2T*(1:5)) ≈ T'BroadcastQuasiMatrix(*, 2, T*(1:5)) @test T' * (a .* (T * (1:5))) ≈ T' * ((a .* T) * (1:5)) + @test T'BroadcastQuasiMatrix(*, 2, 2T) == 4*(T'T) @test LazyArrays.simplifiable(*, T', T*(1:5)) == Val(true) @test LazyArrays.simplifiable(*, T', (a .* (T * (1:5)))) == Val(true) From 2189a65ce1ced84a781bf8067b18dfd001b100c0 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Tue, 12 Nov 2024 09:19:11 +0000 Subject: [PATCH 11/11] add one mroe test --- Project.toml | 1 - test/test_chebyshev.jl | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 0aff1b0..08697eb 100644 --- a/Project.toml +++ b/Project.toml @@ -8,7 +8,6 @@ ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" BandedMatrices = "aae01518-5342-5314-be14-df237901396f" BlockArrays = "8e7c35d0-a365-5155-bbbb-fb81a777f24e" DomainSets = "5b8099bc-c8ec-5219-889f-1d9e522a28bf" -FastTransforms = "057dd010-8810-581a-b7be-e3fc3b93f78c" FillArrays = "1a297f60-69ca-5386-bcde-b61e274b549b" InfiniteArrays = "4858937d-0d70-526a-a4dd-2d5cb5dd786c" Infinities = "e1ba4f0e-776d-440f-acd9-e1d2e9742647" diff --git a/test/test_chebyshev.jl b/test/test_chebyshev.jl index 29ef367..194df90 100644 --- a/test/test_chebyshev.jl +++ b/test/test_chebyshev.jl @@ -178,6 +178,7 @@ Base.:(==)(::FooBasis, ::FooBasis) = true @test LazyArrays.simplifiable(*, T', a .* T) == Val(true) @test LazyArrays.simplifiable(*, T', 2T) == Val(true) @test LazyArrays.simplifiable(*, T', BroadcastQuasiMatrix(*, 2, T*(1:5))) == Val(true) + @test LazyArrays.simplifiable(*, T', BroadcastQuasiMatrix(*, 2, 2T)) == Val(true) end @testset "sum/dot/diff" begin