From 937aac6962a9f4d7917d9e60ffee157b9b7880e7 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Fri, 21 Jun 2019 16:49:47 +0100 Subject: [PATCH 1/6] Add Interlace --- src/lazyconcat.jl | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/lazyconcat.jl b/src/lazyconcat.jl index 952ff771..e1a552e9 100644 --- a/src/lazyconcat.jl +++ b/src/lazyconcat.jl @@ -390,4 +390,24 @@ function in(x, V::Vcat) in(x, a) && return true end false +end + + + +struct Interlace{T, N, AA, INDS} <: AbstractArray{T,N} + arrays::AA + inds::INDS +end + +Interlace(a::AbstractArray{<:AbstractArray{T,N},N}, inds) where {T,N} = Interlace{T,N,typeof(a), typeof(inds)}(a, inds) + +length(A::Interlace) = sum(length(A.arrays)) +size(A::Interlace, m) = sum(size.(A.arrays,m)) +size(A::Interlace{<:Any,1}) = (size(A,1),) +function getindex(A::Interlace{<:Any,1}, k::Integer) + for (a,ind) in zip(A.arrays, A.inds) + κ = findfirst(isequal(k), ind) + isnothing(κ) || return a[something(κ)] + end + throw(BoundsError(A, k)) end \ No newline at end of file From d42407ce40b9496018a6c72764f0849c3f64ca7c Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 24 Nov 2019 10:55:56 +0000 Subject: [PATCH 2/6] Create interlace.jl --- src/interlace.jl | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/interlace.jl diff --git a/src/interlace.jl b/src/interlace.jl new file mode 100644 index 00000000..a3da7f62 --- /dev/null +++ b/src/interlace.jl @@ -0,0 +1,17 @@ +struct Interlace{T, N, AA, INDS} <: AbstractArray{T,N} + arrays::AA + inds::INDS +end + +Interlace(a::AbstractArray{<:AbstractArray{T,N},N}, inds) where {T,N} = Interlace{T,N,typeof(a), typeof(inds)}(a, inds) + +length(A::Interlace) = sum(length(A.arrays)) +size(A::Interlace, m) = sum(size.(A.arrays,m)) +size(A::Interlace{<:Any,1}) = (size(A,1),) +function getindex(A::Interlace{<:Any,1}, k::Integer) + for (a,ind) in zip(A.arrays, A.inds) + κ = findfirst(isequal(k), ind) + isnothing(κ) || return a[something(κ)] + end + throw(BoundsError(A, k)) +end From 5d562742eeed7995461b3f06f13ad8397c6905be Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 24 Nov 2019 11:02:08 +0000 Subject: [PATCH 3/6] Update LazyArrays.jl --- src/LazyArrays.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/src/LazyArrays.jl b/src/LazyArrays.jl index 71a908d7..60c35a8f 100644 --- a/src/LazyArrays.jl +++ b/src/LazyArrays.jl @@ -71,5 +71,6 @@ include("lazyconcat.jl") include("lazysetoperations.jl") include("lazyoperations.jl") include("lazymacro.jl") +include("interlace.jl") end # module From 5736435ea904906652fe47a4e7b50456e2d295a7 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Sun, 24 Nov 2019 22:44:54 +0000 Subject: [PATCH 4/6] Interlace improvements, add BroadcastArray{T,N} cases --- src/interlace.jl | 10 ++++++++-- src/lazybroadcasting.jl | 2 ++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/interlace.jl b/src/interlace.jl index a3da7f62..2176c518 100644 --- a/src/interlace.jl +++ b/src/interlace.jl @@ -3,9 +3,10 @@ struct Interlace{T, N, AA, INDS} <: AbstractArray{T,N} inds::INDS end -Interlace(a::AbstractArray{<:AbstractArray{T,N},N}, inds) where {T,N} = Interlace{T,N,typeof(a), typeof(inds)}(a, inds) +Interlace(a::NTuple{M,AbstractVector{T}}, inds::NTuple{M,AbstractVector{Int}}) where {T,M} = + Interlace{T,1,typeof(a), typeof(inds)}(a, inds) -length(A::Interlace) = sum(length(A.arrays)) +length(A::Interlace) = sum(map(length,A.arrays)) size(A::Interlace, m) = sum(size.(A.arrays,m)) size(A::Interlace{<:Any,1}) = (size(A,1),) function getindex(A::Interlace{<:Any,1}, k::Integer) @@ -15,3 +16,8 @@ function getindex(A::Interlace{<:Any,1}, k::Integer) end throw(BoundsError(A, k)) end + +Interlace(a::AbstractVector, b::AbstractVector) = + Interlace((a,b), (1:2:(2length(a)-1), 2:2:2length(b))) + +interlace(a...) = Array(Interlace(a...)) \ No newline at end of file diff --git a/src/lazybroadcasting.jl b/src/lazybroadcasting.jl index fdf08dc0..ca770ea7 100644 --- a/src/lazybroadcasting.jl +++ b/src/lazybroadcasting.jl @@ -29,6 +29,8 @@ BroadcastArray(bc::Broadcasted{S}) where S = _BroadcastArray(instantiate(Broadcasted{S}(bc.f, _broadcast2broadcastarray(bc.args...)))) BroadcastArray(f, A, As...) = BroadcastArray(broadcasted(f, A, As...)) +BroadcastArray{T,N}(f, A...) where {T,N} = BroadcastArray{T,N,typeof(f),typeof(A)}(f, A) + BroadcastMatrix(f, A...) = BroadcastMatrix(broadcasted(f, A...)) BroadcastVector(f, A...) = BroadcastVector(broadcasted(f, A...)) From 071355612cd7eb82bd3b519f7fb9d23e522e24c5 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 25 Nov 2019 11:44:37 +0000 Subject: [PATCH 5/6] Add tests, fast copyto! --- Project.toml | 2 +- src/LazyArrays.jl | 3 ++- src/interlace.jl | 28 +++++++++++++++++++++++++++- test/interlacetests.jl | 9 +++++++++ 4 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 test/interlacetests.jl diff --git a/Project.toml b/Project.toml index 3932a966..46715ac3 100644 --- a/Project.toml +++ b/Project.toml @@ -1,6 +1,6 @@ name = "LazyArrays" uuid = "5078a376-72f3-5289-bfd5-ec5146d43c02" -version = "0.14.8" +version = "0.15" [deps] diff --git a/src/LazyArrays.jl b/src/LazyArrays.jl index 60c35a8f..76e09690 100644 --- a/src/LazyArrays.jl +++ b/src/LazyArrays.jl @@ -60,7 +60,8 @@ end export Mul, Applied, MulArray, MulVector, MulMatrix, InvMatrix, PInvMatrix, Hcat, Vcat, Kron, BroadcastArray, BroadcastMatrix, BroadcastVector, cache, Ldiv, Inv, PInv, Diff, Cumsum, - applied, materialize, materialize!, ApplyArray, ApplyMatrix, ApplyVector, apply, ⋆, @~, LazyArray + applied, materialize, materialize!, ApplyArray, ApplyMatrix, ApplyVector, apply, ⋆, @~, LazyArray, + Interlace, interlace include("lazyapplying.jl") diff --git a/src/interlace.jl b/src/interlace.jl index 2176c518..09b7f0b8 100644 --- a/src/interlace.jl +++ b/src/interlace.jl @@ -3,8 +3,27 @@ struct Interlace{T, N, AA, INDS} <: AbstractArray{T,N} inds::INDS end -Interlace(a::NTuple{M,AbstractVector{T}}, inds::NTuple{M,AbstractVector{Int}}) where {T,M} = + +_sortunion(inds...) = sort!(union(inds...)) +function _sortunion(inds::Vararg{StepRange,N}) where N + all(isequal(N), map(step, inds)) || throw(ArgumentError("incompatible")) + sort([map(first, inds)...]) == OneTo(N) || throw(ArgumentError("incompatible")) + n = mapreduce(length, +, inds) + maximum(map(last, inds)) == n || throw(ArgumentError("incompatible lengths")) + OneTo(n) +end + + +function check_interlace_inds(a, inds) + map(length,a) == map(length,inds) || throw(ArgumentError("Lengths must be compatible")) + n = mapreduce(length, +, a) + _sortunion(inds...) == OneTo(n) || throw(ArgumentError("Every index must be mapped to")) +end + +function Interlace(a::NTuple{M,AbstractVector{T}}, inds::NTuple{M,AbstractVector{Int}}) where {T,M} + check_interlace_inds(a, inds) Interlace{T,1,typeof(a), typeof(inds)}(a, inds) +end length(A::Interlace) = sum(map(length,A.arrays)) size(A::Interlace, m) = sum(size.(A.arrays,m)) @@ -17,6 +36,13 @@ function getindex(A::Interlace{<:Any,1}, k::Integer) throw(BoundsError(A, k)) end +function copyto!(dest::AbstractVector, src::Interlace{<:Any,1}) + for (a,ind) in zip(src.arrays, src.inds) + copyto!(view(dest, ind), a) + end + dest +end + Interlace(a::AbstractVector, b::AbstractVector) = Interlace((a,b), (1:2:(2length(a)-1), 2:2:2length(b))) diff --git a/test/interlacetests.jl b/test/interlacetests.jl new file mode 100644 index 00000000..f9e07111 --- /dev/null +++ b/test/interlacetests.jl @@ -0,0 +1,9 @@ +using LazyArrays, Test + +@testset "Interlace" begin + @test_throws ArgumentError Interlace(1:5, 10:15) + @test_throws ArgumentError Interlace(1:5, 10:12) + @test eltype(Interlace(1:5, 10:13)) == Int + @test Interlace(1:5, 10:13) == interlace(1:5,10:13) == [1,10,2,11,3,12,4,13,5] + @test Interlace(1:5, 10:14) == interlace(1:5,10:14) == [1,10,2,11,3,12,4,13,5,14] +end \ No newline at end of file From 207bedfd9e08209d9a4c0d24b554312e0bf80815 Mon Sep 17 00:00:00 2001 From: Sheehan Olver Date: Mon, 25 Nov 2019 17:05:47 +0000 Subject: [PATCH 6/6] Update interlace.jl --- src/interlace.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/interlace.jl b/src/interlace.jl index 09b7f0b8..f1e2b441 100644 --- a/src/interlace.jl +++ b/src/interlace.jl @@ -5,7 +5,7 @@ end _sortunion(inds...) = sort!(union(inds...)) -function _sortunion(inds::Vararg{StepRange,N}) where N +function _sortunion(inds::Vararg{AbstractRange,N}) where N all(isequal(N), map(step, inds)) || throw(ArgumentError("incompatible")) sort([map(first, inds)...]) == OneTo(N) || throw(ArgumentError("incompatible")) n = mapreduce(length, +, inds)