From d7ff02e043b872249b4208ec5d6219a57af31479 Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 23 Jan 2017 08:45:43 +0100 Subject: [PATCH 1/4] Add `setindex` for tuples --- base/tuple.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/base/tuple.jl b/base/tuple.jl index 05fdd8bd256a6..6e6add6675e2d 100644 --- a/base/tuple.jl +++ b/base/tuple.jl @@ -18,6 +18,14 @@ getindex(t::Tuple, i::Real) = getfield(t, convert(Int, i)) getindex{T}(t::Tuple, r::AbstractArray{T,1}) = tuple([t[ri] for ri in r]...) getindex(t::Tuple, b::AbstractArray{Bool,1}) = length(b) == length(t) ? getindex(t,find(b)) : throw(BoundsError(t, b)) +# returns new tuple; N.B.: becomes no-op if i is out-of-bounds +setindex(x::Tuple, v, i::Integer) = _setindex((), x, v, i::Integer) +function _setindex(y::Tuple, r::Tuple, v, i::Integer) + @_inline_meta + _setindex((y..., ifelse(length(y) + 1 == i, v, first(r))), tail(r), v, i) +end +_setindex(y::Tuple, r::Tuple{}, v, i::Integer) = y + ## iterating ## start(t::Tuple) = 1 From e36e14e7716da402281199ca7e54ea74de25fa4e Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Mon, 23 Jan 2017 13:17:03 +0100 Subject: [PATCH 2/4] Improve inferability of `slicedim` --- base/abstractarraymath.jl | 2 +- test/arrayops.jl | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/base/abstractarraymath.jl b/base/abstractarraymath.jl index 72eba80cfa3b1..2c6d79e657016 100644 --- a/base/abstractarraymath.jl +++ b/base/abstractarraymath.jl @@ -113,7 +113,7 @@ function slicedim(A::AbstractArray, d::Integer, i) d >= 1 || throw(ArgumentError("dimension must be ≥ 1")) nd = ndims(A) d > nd && (i == 1 || throw_boundserror(A, (ntuple(k->Colon(),nd)..., ntuple(k->1,d-1-nd)..., i))) - A[( n==d ? i : indices(A,n) for n in 1:nd )...] + A[setindex(indices(A), i, d)...] end function flipdim(A::AbstractVector, d::Integer) diff --git a/test/arrayops.jl b/test/arrayops.jl index f1070b925ebac..2ee397f82d0d7 100644 --- a/test/arrayops.jl +++ b/test/arrayops.jl @@ -1608,6 +1608,7 @@ B = 1.5:5.5 @test_throws ArgumentError slicedim(A,0,1) @test slicedim(A, 3, 1) == A @test_throws BoundsError slicedim(A, 3, 2) + @test @inferred(slicedim(A, 1, 2:2)) == collect(2:4:20)' end end From 9a95c65f4a47f1c796fb04f2598666c441bdbfff Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Tue, 24 Jan 2017 13:24:20 +0100 Subject: [PATCH 3/4] Remove `slicedim` specialization for `BitArray` --- base/bitarray.jl | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/base/bitarray.jl b/base/bitarray.jl index 1a0c6b4940a89..42cac47fd5d67 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1280,37 +1280,6 @@ end # TODO some of this could be optimized -function slicedim(A::BitArray, d::Integer, i::Integer) - d_in = size(A) - leading = d_in[1:(d-1)] - d_out = tuple(leading..., d_in[(d+1):end]...) - - M = prod(leading) - N = length(A) - stride = M * d_in[d] - - B = BitArray(d_out) - index_offset = 1 + (i-1)*M - - l = 1 - - if M == 1 - for j = 0:stride:(N-stride) - B[l] = A[j + index_offset] - l += 1 - end - else - for j = 0:stride:(N-stride) - offs = j + index_offset - for k = 0:(M-1) - B[l] = A[offs + k] - l += 1 - end - end - end - return B -end - function flipdim(A::BitArray, d::Integer) nd = ndims(A) 1 ≤ d ≤ nd || throw(ArgumentError("dimension $d is not 1 ≤ $d ≤ $nd")) From 8f9a62ee74f9c9693b2a8492e4f3c40ccca1addc Mon Sep 17 00:00:00 2001 From: Martin Holters Date: Wed, 25 Jan 2017 14:42:57 +0100 Subject: [PATCH 4/4] Add `slicedim(::BitVector, ::Integer, ::Integer)` to restore previous behavior --- base/bitarray.jl | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/base/bitarray.jl b/base/bitarray.jl index 42cac47fd5d67..b908a20d12001 100644 --- a/base/bitarray.jl +++ b/base/bitarray.jl @@ -1278,6 +1278,18 @@ end ## Data movement ## +# preserve some special behavior +function slicedim(A::BitVector, d::Integer, i::Integer) + d >= 1 || throw(ArgumentError("dimension must be ≥ 1")) + if d > 1 + i == 1 || throw_boundserror(A, (:, ntuple(k->1,d-2)..., i)) + A[:] + else + fill!(BitArray{0}(), A[i]) # generic slicedim would return A[i] here + end +end + + # TODO some of this could be optimized function flipdim(A::BitArray, d::Integer)