diff --git a/src/OffsetArrays.jl b/src/OffsetArrays.jl index 9d050094..98097d83 100644 --- a/src/OffsetArrays.jl +++ b/src/OffsetArrays.jl @@ -1,6 +1,7 @@ module OffsetArrays using Base: Indices, tail, @propagate_inbounds + @static if !isdefined(Base, :IdentityUnitRange) const IdentityUnitRange = Base.Slice else @@ -45,10 +46,12 @@ OffsetArray(A::AbstractArray{T,N}, offsets::Vararg{Int,N}) where {T,N} = OffsetArray(A, offsets) OffsetArray(A::AbstractArray{T,0}) where {T} = OffsetArray(A, ()) +# Create an uninitialized OffsetArray with given element type const ArrayInitializer = Union{UndefInitializer, Missing, Nothing} OffsetArray{T,N}(init::ArrayInitializer, inds::Indices{N}) where {T,N} = OffsetArray(Array{T,N}(init, map(indexlength, inds)), map(indexoffset, inds)) OffsetArray{T}(init::ArrayInitializer, inds::Indices{N}) where {T,N} = OffsetArray{T,N}(init, inds) +# Same thing, but taking multiple args for offsets/indices OffsetArray{T,N}(init::ArrayInitializer, inds::Vararg{AbstractUnitRange,N}) where {T,N} = OffsetArray{T,N}(init, inds) OffsetArray{T}(init::ArrayInitializer, inds::Vararg{AbstractUnitRange,N}) where {T,N} = OffsetArray{T,N}(init, inds) @@ -402,6 +405,23 @@ end no_offset_view(A::OffsetArray) = no_offset_view(parent(A)) +# Quick hack for matrix multiplication. +# Ideally, one would instead improve LinearAlgebra's support of custom indexing. +function Base.:(*)(A::OffsetMatrix, B::OffsetMatrix) + matmult_check_axes(A, B) + C = parent(A) * parent(B) + OffsetArray{eltype(C), 2, typeof(C)}(C, (A.offsets[1], B.offsets[2])) +end + +function Base.:(*)(A::OffsetMatrix, B::OffsetVector) + matmult_check_axes(A, B) + C = parent(A) * parent(B) + OffsetArray{eltype(C), 1, typeof(C)}(C, (A.offsets[1], )) +end +function matmult_check_axes(A, B) + axes(A, 2) === axes(B, 1) || axes(A, 2) == axes(B, 1) || + error("axes(A,2) = $(UnitRange(axes(A,2))) does not equal axes(B,1) = $(UnitRange(axes(B,1)))") +end #### # work around for segfault in searchsorted* diff --git a/test/runtests.jl b/test/runtests.jl index 1721621f..b2aca0b5 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -946,3 +946,34 @@ end @test searchsorted(o, 5) == 2:2 @test searchsorted(o, 6) == 3:2 end + +@testset "Matrix multiplication" begin + a = [1 2; 3 4] + v = [5, 6] + oa = OffsetArray(a, (2, 2)) + ov = OffsetVector(v, (2,)) + + @test parent(oa * oa) == a * a + @test axes(oa * oa) == axes(oa) + + @test parent(oa * ov) == a * v + @test axes(oa * ov) == (axes(oa, 1),) + + @test parent(ones(2, 2:3) * ones(2:3, 3:5)) == ones(2, 2) * ones(2, 3) + @test axes(ones(2, 2:3) * ones(2:3, 3:5)) == (1:2, 3:5) + + @test parent(ones(2, 2:3) * ones(2:3)) == ones(2, 2) * ones(2) + @test axes(ones(2, 2:3) * ones(2:3)) == (1:2,) + + # One-based arrays + oa2 = OffsetArray(a, axes(a)) + @test oa2 * a == a * a + @test a * oa2 == a * a + + @test oa2 * v == a * v + @test v' * oa2 == v' * a + + @test_throws Exception zeros(2, 2:3) * zeros(2:4, 2) + @test_throws Exception zeros(2, 2:3) * zeros(3:4, 2) + @test_throws Exception zeros(2, 2:3) * zeros(2:4) +end \ No newline at end of file