diff --git a/Project.toml b/Project.toml index 56c6550..bbd689a 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "QuasiArrays" uuid = "c4ea9172-b204-11e9-377d-29865faadc5c" authors = ["Sheehan Olver "] -version = "0.12.1" +version = "0.12.2" [deps] ArrayLayouts = "4c555306-a7a7-4459-81d9-ec55ddd5c99a" diff --git a/src/QuasiArrays.jl b/src/QuasiArrays.jl index f5af22f..7754590 100644 --- a/src/QuasiArrays.jl +++ b/src/QuasiArrays.jl @@ -52,7 +52,7 @@ import LazyArrays: MemoryLayout, UnknownLayout, Mul, ApplyLayout, BroadcastLayou _mul, rowsupport, DiagonalLayout, adjointlayout, transposelayout, conjlayout, sublayout, call, LazyArrayStyle, layout_getindex, _broadcast2broadcastarray, _applyarray_summary, _broadcastarray_summary, _broadcasted_mul, simplifiable, simplify, _mul_colsupport, _mul_rowsupport, - _adjoint, _transpose + _adjoint, _transpose, _vec_mul_arguments, _transposeifnumber import Base.IteratorsMD diff --git a/src/abstractquasiarraymath.jl b/src/abstractquasiarraymath.jl index cb8eb16..1789254 100644 --- a/src/abstractquasiarraymath.jl +++ b/src/abstractquasiarraymath.jl @@ -49,4 +49,4 @@ imag(x::AbstractQuasiArray{<:Real}) = zero(x) nd = ndims(A) d > nd && (i == 1 || throw(BoundsError(A, (ntuple(k->Colon(),d-1)..., i)))) return view(A, idxs...) -end +end \ No newline at end of file diff --git a/src/calculus.jl b/src/calculus.jl index 476ed44..ac3b015 100644 --- a/src/calculus.jl +++ b/src/calculus.jl @@ -26,19 +26,22 @@ for Sum in (:sum, :cumsum) end end +_colon2one(::Colon) = 1 +_colon2one(dims::Int) = dims + function cumsum_layout(LAY::ApplyLayout{typeof(*)}, V::AbstractQuasiVector, dims) a = arguments(LAY, V) - apply(*, cumsum(a[1]; dims=dims), tail(a)...) + apply(*, cumsum(a[1]; dims=_colon2one(dims)), tail(a)...) end -function sum_layout(LAY::ApplyLayout{typeof(*)}, V::AbstractQuasiVector, ::Colon) +function sum_layout(LAY::ApplyLayout{typeof(*)}, V::AbstractQuasiVector, dims) a = arguments(LAY, V) - only(*(sum(a[1]; dims=1), tail(a)...)) + only(*(sum(a[1]; dims=_colon2one(dims)), tail(a)...)) end -function sum_layout(LAY::ApplyLayout{typeof(*)}, V::AbstractQuasiMatrix, ::Colon) +function sum_layout(LAY::ApplyLayout{typeof(*)}, V::AbstractQuasiMatrix, dims) a = arguments(LAY, V) - only(*(sum(a[1]; dims=1), front(tail(a))..., sum(a[end]; dims=2))) + only(*(sum(a[1]; dims=_colon2one(dims)), front(tail(a))..., sum(a[end]; dims=2))) end sum_layout(::MemoryLayout, A, dims) = sum_size(size(A), A, dims) diff --git a/src/matmul.jl b/src/matmul.jl index 9ef06af..8cbe6ea 100644 --- a/src/matmul.jl +++ b/src/matmul.jl @@ -141,3 +141,7 @@ broadcasted(::LazyQuasiArrayStyle{N}, ::typeof(\), x::Number, A::MulQuasiArray{< ApplyQuasiArray(*, _ldiv_scal_reduce(x, arguments(A)...)...) broadcasted(::LazyQuasiArrayStyle{N}, ::typeof(/), A::MulQuasiArray{<:Any,N}, x::Number) where N = ApplyQuasiArray(*, _ldiv_scal_reduce(x, arguments(A)...)...) + +_transposeifnumber(a::AbstractQuasiArray{<:Number}) = transpose(a) +_vec_mul_arguments(args, (kr,jr)::Tuple{AbstractQuasiVector,Number}) = _mat_mul_arguments(args, (kr,jr)) +_vec_mul_arguments(args, (kr,jr)::Tuple{Number,AbstractQuasiVector}) = _vec_mul_arguments(reverse(map(_transposeifnumber, args)), (jr,kr)) \ No newline at end of file diff --git a/src/quasiadjtrans.jl b/src/quasiadjtrans.jl index 968c69f..34cb546 100644 --- a/src/quasiadjtrans.jl +++ b/src/quasiadjtrans.jl @@ -230,6 +230,9 @@ call(::ApplyLayout{typeof(*)}, V::QuasiTranspose) = * arguments(LAY::ApplyLayout{typeof(*)}, V::QuasiAdjoint) = reverse(adjoint.(arguments(LAY, V'))) arguments(LAY::ApplyLayout{typeof(*)}, V::QuasiTranspose) = reverse(transpose.(arguments(LAY, V'))) +call(lay::BroadcastLayout, At::QuasiTranspose) = call(lay, transpose(At)) +call(lay::BroadcastLayout, At::QuasiAdjoint{<:Real}) = call(lay, At') + # This is used in ContinuumArrays.jl to ensure x' is lazy BroadcastStyle(::Type{<:QuasiAdjoint{<:Any,<:Inclusion}}) = LazyQuasiArrayStyle{2}() diff --git a/src/quasireshapedarray.jl b/src/quasireshapedarray.jl index 2dea8d7..502b458 100644 --- a/src/quasireshapedarray.jl +++ b/src/quasireshapedarray.jl @@ -1,4 +1,30 @@ +vec_layout(lay, _) = error("overload vec_layout(::$(typeof(lay)), _)") + + +""" + vec(a::AbstractQuasiMatrix) + +reshapes a quasi-matrix into quasi-vector. The axes of the resulting +quasi-vector depends on the axes of the quasi-matrix: if the axes are +`(ax, Base.OneTo(1))` or `(Base.OneTo(1), ax)` then the unary dimension is dropped. +If the axes are both continuous then it may form a quasi-vector defined on the rectangle, +if MultivariateOrthogonalPolynomials.jl is loaded. +""" +vec(a::AbstractQuasiMatrix) = vec_layout(MemoryLayout(a), a) + + reshape(parent::AbstractQuasiArray{T,N}, ndims::Val{N}) where {T,N} = parent function reshape(parent::AbstractQuasiArray, ndims::Val{N}) where N reshape(parent, rdims(Val(N), axes(parent))) -end \ No newline at end of file +end + + +reshape_layout(lay, a, dims...) = error("overload reshape_layout(::$(typeof(lay)), _, dims...)") + + +""" + reshape(a::AbstractQuasiVector) + +will reshape a quasi-vector defined on a rectangle to a quasi-matrix. +""" +reshape(a::AbstractQuasiArray, dims...) = reshape_layout(MemoryLayout(a), a, dims...) \ No newline at end of file diff --git a/test/runtests.jl b/test/runtests.jl index 3ecfe1c..0184189 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -6,6 +6,7 @@ include("test_arrayops.jl") include("test_quasisubarray.jl") include("test_quasipermutedims.jl") include("test_quasireducedim.jl") +include("test_quasireshapedarray.jl") include("test_dense.jl") include("test_quasiadjtrans.jl") diff --git a/test/test_quasiadjtrans.jl b/test/test_quasiadjtrans.jl index 3a67f43..add0ba4 100644 --- a/test/test_quasiadjtrans.jl +++ b/test/test_quasiadjtrans.jl @@ -2,7 +2,9 @@ using QuasiArrays, Test, Base64, LinearAlgebra -import QuasiArrays: MemoryLayout +using QuasiArrays: MemoryLayout +using LazyArrays: BroadcastLayout + @testset "QuasiAdjoint/Transpose" begin @@ -258,4 +260,16 @@ import QuasiArrays: MemoryLayout @test summary(x') == "adjoint(QuasiVector{Int64, Tuple{Vector{Float64}}})" @test summary(transpose(x)) == "transpose(QuasiVector{Int64, Tuple{Vector{Float64}}})" end + + @testset "Broadcast AdjTrans" begin + x = QuasiArray([1,2],[0,0.5]) + @test MemoryLayout(BroadcastQuasiArray(exp, x)') isa BroadcastLayout + @test MemoryLayout(transpose(BroadcastQuasiArray(exp, x))) isa BroadcastLayout + @test BroadcastQuasiArray(exp, x)'[1,0.5] == exp(2) + @test transpose(BroadcastQuasiArray(exp, x))[1,0.5] == exp(2) + @test BroadcastQuasiArray(exp, x)'[1,0.5:0.5] == [exp(2)] + @test transpose(BroadcastQuasiArray(exp, x))[1,0.5:0.5] == [exp(2)] + @test exp.(axes(x,1)') isa BroadcastQuasiArray + @test exp.(transpose(axes(x,1))) isa BroadcastQuasiArray + end end \ No newline at end of file diff --git a/test/test_quasilazy.jl b/test/test_quasilazy.jl index 7447d4e..3682a13 100644 --- a/test/test_quasilazy.jl +++ b/test/test_quasilazy.jl @@ -1,6 +1,6 @@ using QuasiArrays, LazyArrays, ArrayLayouts, Base64, Test import QuasiArrays: QuasiLazyLayout, QuasiArrayApplyStyle, LazyQuasiMatrix, LazyQuasiArrayStyle -import LazyArrays: MulStyle, ApplyStyle +import LazyArrays: MulStyle, ApplyStyle, arguments struct MyQuasiLazyMatrix <: LazyQuasiMatrix{Float64} A::QuasiArray @@ -86,6 +86,18 @@ Base.getindex(A::MyQuasiLazyMatrix, x::Float64, y::Float64) = A.A[x,y] A = ApplyQuasiArray(*, ones(Inclusion([1,2,3]), Inclusion([4,5])), fill(2,Inclusion([4,5]))) @test stringmime("text/plain", A) == "(ones(Inclusion([1, 2, 3]), Inclusion([4, 5]))) * (fill(2, Inclusion([4, 5])))" end + + @testset "sub *" begin + A = QuasiArray(rand(3,3),(0:0.5:1,Base.OneTo(3))) + B = randn(3,3) + M = ApplyQuasiArray(*, A, B) + @test arguments(view(M,0.5,:)) == (B', A[0.5,:]) + @test arguments(view(M,:,2)) == (A, B[:,2]) + + M = ApplyQuasiArray(*, B, A') + @test arguments(view(M,:,0.5)) == (B, A[0.5,:]) + @test arguments(view(M,2,:)) == (A, B[2,:]) + end end @testset "\\" begin A = QuasiArray(rand(3,3),(0:0.5:1,0:0.5:1)) diff --git a/test/test_quasireshapedarray.jl b/test/test_quasireshapedarray.jl new file mode 100644 index 0000000..362bfa0 --- /dev/null +++ b/test/test_quasireshapedarray.jl @@ -0,0 +1,7 @@ +using QuasiArrays, Test + +@testset "quasireshapedarray" begin + A = QuasiArray(randn(2,3), (0:0.5:0.5, 1:0.5:2)) + @test_throws ErrorException vec(A) + @test_throws ErrorException reshape(A) +end \ No newline at end of file