Skip to content

Commit 74c0ff3

Browse files
committed
More fixes to ReshapedArrays
1 parent 6b3d657 commit 74c0ff3

File tree

11 files changed

+99
-44
lines changed

11 files changed

+99
-44
lines changed

base/bitarray.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,11 @@ function copy!(dest::BitArray, doffs::Integer, src::BitArray, soffs::Integer, n:
278278
return dest
279279
end
280280

281-
function reshape{N}(B::BitArray, dims::NTuple{N,Int})
281+
reshape(B::BitVector, dims::Tuple{Int}) = reshape_ba(B, dims)
282+
reshape(B::BitArray, dims::Tuple{Int}) = reshape_ba(B, dims)
283+
reshape{N}(B::BitArray, dims::NTuple{N,Int}) = reshape_ba(B, dims)
284+
285+
function reshape_ba{N}(B::BitArray, dims::NTuple{N,Int})
282286
prod(dims) == length(B) ||
283287
throw(DimensionMismatch("new dimensions $(dims) must be consistent with array size $(length(B))"))
284288
dims == size(B) && return B

base/reshapedarray.jl

Lines changed: 54 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ immutable ReshapedArray{T,N,P<:AbstractArray,MI<:Tuple{Vararg{SignedMultiplicati
77
end
88
ReshapedArray{T,N}(parent::AbstractArray{T}, dims::NTuple{N,Int}, mi) = ReshapedArray{T,N,typeof(parent),typeof(mi)}(parent, dims, mi)
99

10+
# LinearFast ReshapedArray
11+
typealias ReshapedArrayLF{T,N,P<:AbstractArray} ReshapedArray{T,N,P,Tuple{}}
12+
1013
# Fast iteration on ReshapedArrays: use the parent iterator
1114
immutable ReshapedRange{I,M}
1215
iter::I
1316
mi::NTuple{M,SignedMultiplicativeInverse{Int}}
1417
end
15-
ReshapedRange(A::ReshapedArray) = reshapedrange(A.parent, A.mi)
18+
ReshapedRange(A::ReshapedArray) = reshapedrange(parent(A), A.mi)
1619
function reshapedrange{M}(P, mi::NTuple{M})
1720
iter = eachindex(P)
1821
ReshapedRange{typeof(iter),M}(iter, mi)
@@ -22,26 +25,35 @@ immutable ReshapedIndex{T}
2225
parentindex::T
2326
end
2427

25-
eachindex(A::ReshapedArray) = ReshapedRange(A)
28+
# eachindex(A::ReshapedArray) = ReshapedRange(A) # TODO: uncomment this line
2629
start(R::ReshapedRange) = start(R.iter)
27-
done(R::ReshapedRange, i) = done(R.iter, i)
28-
function next(R::ReshapedRange, i)
29-
@_inline_meta
30+
@inline done(R::ReshapedRange, i) = done(R.iter, i)
31+
@inline function next(R::ReshapedRange, i)
3032
item, inext = next(R.iter, i)
3133
ReshapedIndex(item), inext
3234
end
35+
length(R::ReshapedRange) = length(R.iter)
3336

3437
function reshape(parent::AbstractArray, dims::Dims)
3538
prod(dims) == length(parent) || throw(DimensionMismatch("parent has $(length(parent)) elements, which is incompatible with size $dims"))
3639
_reshape((parent, linearindexing(parent)), dims)
3740
end
3841
reshape(R::ReshapedArray, dims::Dims) = reshape(R.parent, dims)
42+
reshape(a::AbstractArray, len::Int) = reshape(a, (len,))
3943
reshape(a::AbstractArray, dims::Int...) = reshape(a, dims)
4044

45+
# When reshaping Vector->Vector, don't wrap with a ReshapedArray
46+
reshape{T}(v::ReshapedArray{T,1}, dims::Tuple{Int}) = reshape(v.parent, dims[1])
47+
reshape(v::AbstractVector, dims::Tuple{Int}) = reshape(v, dims[1])
48+
function reshape(v::AbstractVector, len::Int)
49+
len == length(v) || throw(DimensionMismatch("parent has $(length(v)) elements, which is incompatible with length $len"))
50+
v
51+
end
52+
4153
function _reshape(p::Tuple{AbstractArray,LinearSlow}, dims::Dims)
4254
parent = p[1]
43-
strds = strides(parent)
44-
mi = map(SignedMultiplicativeInverse, tail(strds))
55+
strds = front(size_strides(parent))
56+
mi = map(SignedMultiplicativeInverse, strds)
4557
ReshapedArray(parent, dims, reverse(mi))
4658
end
4759

@@ -50,24 +62,45 @@ function _reshape(p::Tuple{AbstractArray,LinearFast}, dims::Dims)
5062
ReshapedArray(parent, dims, ())
5163
end
5264

65+
@inline size_strides(A::AbstractArray) = tail(size_strides((1,), size(A)...))
66+
size_strides(out::Tuple) = out
67+
@inline size_strides(out, s, sz...) = size_strides((out..., out[end]*s), sz...)
68+
5369
size(A::ReshapedArray) = A.dims
5470
size(A::ReshapedArray, d) = d <= ndims(A) ? A.dims[d] : 1
55-
similar(A::ReshapedArray, eltype::Type, dims...) = similar(A.parent, eltype, dims...)
56-
linearindexing{T,N,P<:AbstractArray}(::Type{ReshapedArray{T,N,P,Tuple{}}}) = LinearFast()
57-
58-
ind2sub_rs(::Tuple{}, i::Int) = i
59-
ind2sub_rs(strds, i) = (@_inline_meta; ind2sub_rs((), strds, i-1))
60-
ind2sub_rs(out, ::Tuple{}, ind) = (@_inline_meta; (ind+1, out...))
61-
function ind2sub_rs(out, strds, ind)
62-
@_inline_meta
71+
similar(A::ReshapedArray, eltype::Type) = similar(parent(A), eltype, size(A))
72+
similar(A::ReshapedArray, eltype::Type, dims...) = similar(parent(A), eltype, dims...)
73+
linearindexing{R<:ReshapedArrayLF}(::Type{R}) = LinearFast()
74+
parent(A::ReshapedArray) = A.parent
75+
parentindexes(A::ReshapedArray) = map(s->1:s, size(parent(A)))
76+
reinterpret{T}(::Type{T}, A::ReshapedArray, dims::Dims) = reinterpret(T, parent(A), dims)
77+
78+
@inline ind2sub_rs(::Tuple{}, i::Int) = i
79+
@inline ind2sub_rs(strds, i) = ind2sub_rs((), strds, i-1)
80+
@inline ind2sub_rs(out, ::Tuple{}, ind) = (ind+1, out...)
81+
@inline function ind2sub_rs(out, strds, ind)
6382
d, r = divrem(ind, strds[1])
6483
ind2sub_rs((d+1, out...), tail(strds), r)
6584
end
6685

67-
getindex(A::ReshapedArray, index::Int) = A.parent[ind2sub_rs(A.mi, index)]
68-
getindex(A::ReshapedArray, indexes::Int...) = (@_inline_meta; A.parent[ind2sub_rs(A.mi, sub2ind(size(A), indexes...))...])
69-
getindex(A::ReshapedArray, index::ReshapedIndex) = A.parent[index.parentindex]
86+
@inline getindex(A::ReshapedArrayLF, index::Int) = (@boundscheck checkbounds(A, index); @inbounds ret = parent(A)[index]; ret)
87+
@inline getindex(A::ReshapedArray, indexes::Int...) = (@boundscheck checkbounds(A, indexes...); _unsafe_getindex(A, indexes...))
88+
@inline getindex(A::ReshapedArray, index::ReshapedIndex) = (@boundscheck checkbounds(parent(A), index.parentindex); @inbounds ret = parent(A)[index.parentindex]; ret)
89+
90+
@inline _unsafe_getindex(A::ReshapedArray, indexes::Int...) = (@inbounds ret = parent(A)[ind2sub_rs(A.mi, sub2ind(size(A), indexes...))...]; ret)
91+
@inline _unsafe_getindex(A::ReshapedArrayLF, indexes::Int...) = (@inbounds ret = parent(A)[sub2ind(size(A), indexes...)]; ret)
92+
93+
@inline setindex!(A::ReshapedArrayLF, val, index::Int) = (@boundscheck checkbounds(A, index); @inbounds parent(A)[index] = val; val)
94+
@inline setindex!(A::ReshapedArray, val, indexes::Int...) = (@boundscheck checkbounds(A, indexes...); _unsafe_setindex!(A, val, indexes...))
95+
@inline setindex!(A::ReshapedArray, val, index::ReshapedIndex) = (@boundscheck checkbounds(parent(A), index.parentindex); @inbounds parent(A)[index.parentindex] = val; val)
96+
97+
@inline _unsafe_setindex!(A::ReshapedArray, val, indexes::Int...) = (@inbounds parent(A)[ind2sub_rs(A.mi, sub2ind(size(A), indexes...))...] = val; val)
98+
@inline _unsafe_setindex!(A::ReshapedArrayLF, val, indexes::Int...) = (@inbounds parent(A)[sub2ind(size(A), indexes...)] = val; val)
99+
100+
typealias ArrayT{N, T} Array{T,N}
101+
convert{T,S,N}(::Type{Array{T,N}}, V::ReshapedArray{S,N}) = copy!(Array(T, size(V)), V)
102+
convert{T,N}(::Type{ArrayT{N}}, V::ReshapedArray{T,N}) = copy!(Array(T, size(V)), V)
70103

71-
setindex!(A::ReshapedArray, val, index::Int) = (@_inline_meta; A.parent[ind2sub_rs(A.mi, index)...] = val)
72-
setindex!(A::ReshapedArray, val, indexes::Int...) = (@_inline_meta; A.parent[ind2sub_rs(A.mi, sub2ind(size(A), indexes...))...] = val)
73-
setindex!(A::ReshapedArray, val, index::ReshapedIndex) = A.parent[index.parentindex] = val
104+
unsafe_convert{T}(::Type{Ptr{T}}, a::ReshapedArray{T}) = unsafe_convert(Ptr{T}, parent(a))
105+
unsafe_convert{T,N,P<:ReshapedArray,I<:Tuple{Vararg{Union{RangeIndex, NoSlice}}}}(::Type{Ptr{T}}, V::SubArray{T,N,P,I}) =
106+
unsafe_convert(Ptr{T}, V.parent) + (first_index(V)-1)*sizeof(T)

base/sharedarray.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,11 @@ length(S::SharedArray) = prod(S.dims)
236236
size(S::SharedArray) = S.dims
237237
linearindexing{S<:SharedArray}(::Type{S}) = LinearFast()
238238

239-
function reshape{T,N}(a::SharedArray{T}, dims::NTuple{N,Int})
239+
reshape(a::SharedVector, dims::Tuple{Int}) = reshape_sa(a, dims)
240+
reshape(a::SharedArray, dims::Tuple{Int}) = reshape_sa(a, dims)
241+
reshape{N}(a::SharedArray, dims::NTuple{N,Int}) = reshape_sa(a, dims)
242+
243+
function reshape_sa{T,N}(a::SharedArray{T}, dims::NTuple{N,Int})
240244
(length(a) != prod(dims)) && throw(DimensionMismatch("dimensions must be consistent with array size"))
241245
refs = Array(Future, length(a.pids))
242246
for (i, p) in enumerate(a.pids)

base/sysimg.jl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,9 +102,10 @@ include("set.jl")
102102
include("iterator.jl")
103103

104104
# Definition of StridedArray
105-
typealias StridedArray{T,N,A<:DenseArray,I<:Tuple{Vararg{Union{RangeIndex, NoSlice, AbstractCartesianIndex}}},MI} Union{DenseArray{T,N}, SubArray{T,N,A,I}, ReshapedArray{T,N,A,MI}}
106-
typealias StridedVector{T,A<:DenseArray,I<:Tuple{Vararg{Union{RangeIndex, NoSlice, AbstractCartesianIndex}}},MI} Union{DenseArray{T,1}, SubArray{T,1,A,I}, ReshapedArray{T,1,A,MI}}
107-
typealias StridedMatrix{T,A<:DenseArray,I<:Tuple{Vararg{Union{RangeIndex, NoSlice, AbstractCartesianIndex}}},MI} Union{DenseArray{T,2}, SubArray{T,2,A,I}, ReshapedArray{T,2,A,MI}}
105+
typealias StridedReshapedArray{T,N,A<:DenseArray} ReshapedArray{T,N,A}
106+
typealias StridedArray{T,N,A<:Union{DenseArray,StridedReshapedArray},I<:Tuple{Vararg{Union{RangeIndex, NoSlice, AbstractCartesianIndex}}}} Union{DenseArray{T,N}, SubArray{T,N,A,I}, StridedReshapedArray{T,N}}
107+
typealias StridedVector{T,A<:Union{DenseArray,StridedReshapedArray},I<:Tuple{Vararg{Union{RangeIndex, NoSlice, AbstractCartesianIndex}}}} Union{DenseArray{T,1}, SubArray{T,1,A,I}, StridedReshapedArray{T,1}}
108+
typealias StridedMatrix{T,A<:Union{DenseArray,StridedReshapedArray},I<:Tuple{Vararg{Union{RangeIndex, NoSlice, AbstractCartesianIndex}}}} Union{DenseArray{T,2}, SubArray{T,2,A,I}, StridedReshapedArray{T,2}}
108109
typealias StridedVecOrMat{T} Union{StridedVector{T}, StridedMatrix{T}}
109110

110111
# For OS specific stuff

base/tuple.jl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,19 @@ indexed_next(I, i, state) = done(I,state) ? throw(BoundsError()) : next(I, state
3939
eltype(::Type{Tuple{}}) = Bottom
4040
eltype{T,_}(::Type{NTuple{_,T}}) = T
4141

42+
# front (the converse of tail: it skips the last entry)
43+
44+
function front(t::Tuple)
45+
@_inline_meta
46+
_front((), t...)
47+
end
48+
front(::Tuple{}) = error("Cannot call front on an empty tuple")
49+
_front(out, v) = out
50+
function _front(out, v, t...)
51+
@_inline_meta
52+
_front((out..., v), t...)
53+
end
54+
4255
## mapping ##
4356

4457
ntuple(f::Function, n::Integer) =

test/abstractarray.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ import Base: trailingsize
7878
const can_inline = Base.JLOptions().can_inline != 0
7979
function test_scalar_indexing{T}(::Type{T}, shape, ::Type{TestAbstractArray})
8080
N = prod(shape)
81-
A = reshape(1:N, shape)
81+
A = reshape(collect(1:N), shape)
8282
B = T(A)
8383
@test A == B
8484
# Test indexing up to 5 dimensions
@@ -186,7 +186,7 @@ end
186186

187187
function test_vector_indexing{T}(::Type{T}, shape, ::Type{TestAbstractArray})
188188
N = prod(shape)
189-
A = reshape(1:N, shape)
189+
A = reshape(collect(1:N), shape)
190190
B = T(A)
191191
idxs = rand(1:N, 3, 3, 3)
192192
@test B[idxs] == A[idxs] == idxs
@@ -202,7 +202,7 @@ end
202202

203203
function test_primitives{T}(::Type{T}, shape, ::Type{TestAbstractArray})
204204
N = prod(shape)
205-
A = reshape(1:N, shape)
205+
A = reshape(collect(1:N), shape)
206206
B = T(A)
207207

208208
# last(a)
@@ -222,7 +222,7 @@ function test_primitives{T}(::Type{T}, shape, ::Type{TestAbstractArray})
222222
end
223223

224224
# reshape(a::AbstractArray, dims::Dims)
225-
@test_throws ArgumentError reshape(B, (0, 1))
225+
@test_throws DimensionMismatch reshape(B, (0, 1))
226226

227227
# copy!(dest::AbstractArray, src::AbstractArray)
228228
@test_throws BoundsError copy!(Array(Int, 10), [1:11...])
@@ -252,7 +252,7 @@ type UnimplementedArray{T, N} <: AbstractArray{T, N} end
252252

253253
function test_getindex_internals{T}(::Type{T}, shape, ::Type{TestAbstractArray})
254254
N = prod(shape)
255-
A = reshape(1:N, shape)
255+
A = reshape(collect(1:N), shape)
256256
B = T(A)
257257

258258
@test getindex(A) == 1
@@ -272,7 +272,7 @@ end
272272

273273
function test_setindex!_internals{T}(::Type{T}, shape, ::Type{TestAbstractArray})
274274
N = prod(shape)
275-
A = reshape(1:N, shape)
275+
A = reshape(collect(1:N), shape)
276276
B = T(A)
277277

278278
Base.unsafe_setindex!(B, 1)
@@ -362,7 +362,7 @@ function test_ind2sub(::Type{TestAbstractArray})
362362
n = rand(2:5)
363363
dims = tuple(rand(1:5, n)...)
364364
len = prod(dims)
365-
A = reshape(1:len, dims...)
365+
A = reshape(collect(1:len), dims...)
366366
I = ind2sub(dims, [1:len...])
367367
for i in 1:len
368368
idx = [ I[j][i] for j in 1:n ]

test/fft.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ b = rand(17,14)
3131
b[3:6,9:12] = m4
3232
sm4 = slice(b,3:6,9:12)
3333

34-
m3d = map(Float32,reshape(1:5*3*2, 5, 3, 2))
34+
m3d = map(Float32,copy(reshape(1:5*3*2, 5, 3, 2)))
3535
true_fftd3_m3d = Array(Float32, 5, 3, 2)
3636
true_fftd3_m3d[:,:,1] = 17:2:45
3737
true_fftd3_m3d[:,:,2] = -15
@@ -277,7 +277,7 @@ end
277277

278278
# test inversion, scaling, and pre-allocated variants
279279
for T in (Complex64, Complex128)
280-
for x in (T[1:100;], reshape(T[1:200;], 20,10))
280+
for x in (T[1:100;], copy(reshape(T[1:200;], 20,10)))
281281
y = similar(x)
282282
for planner in (plan_fft, plan_fft_, plan_ifft, plan_ifft_)
283283
p = planner(x)

test/linalg/arnoldi.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ let
126126
(Q,R)=qr(randn(100,50))
127127
Q=reshape(Q,(50,2,50))
128128
# Construct trace-preserving completely positive map from this
129-
Phi=CPM(Q)
129+
Phi=CPM(copy(Q))
130130
(d,v,nconv,numiter,numop,resid) = eigs(Phi,nev=1,which=:LM)
131131
# Properties: largest eigenvalue should be 1, largest eigenvector, when reshaped as matrix
132132
# should be a Hermitian positive definite matrix (up to an arbitrary phase)

test/show.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,8 +377,8 @@ A = reshape(1:16,4,4)
377377
@test replstr(Bidiagonal(A,false)) == "4x4 Bidiagonal{$Int}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n ⋅ 7 11 ⋅\n ⋅ ⋅ 12 16"
378378
@test replstr(SymTridiagonal(A+A')) == "4x4 SymTridiagonal{$Int}:\n 2 7 ⋅ ⋅\n 7 12 17 ⋅\n ⋅ 17 22 27\n ⋅ ⋅ 27 32"
379379
@test replstr(Tridiagonal(diag(A,-1),diag(A),diag(A,+1))) == "4x4 Tridiagonal{$Int}:\n 1 5 ⋅ ⋅\n 2 6 10 ⋅\n ⋅ 7 11 15\n ⋅ ⋅ 12 16"
380-
@test replstr(UpperTriangular(A)) == "4x4 UpperTriangular{$Int,Array{$Int,2}}:\n 1 5 9 13\n ⋅ 6 10 14\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16"
381-
@test replstr(LowerTriangular(A)) == "4x4 LowerTriangular{$Int,Array{$Int,2}}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n 3 7 11 ⋅\n 4 8 12 16"
380+
@test replstr(UpperTriangular(copy(A))) == "4x4 UpperTriangular{$Int,Array{$Int,2}}:\n 1 5 9 13\n ⋅ 6 10 14\n ⋅ ⋅ 11 15\n ⋅ ⋅ ⋅ 16"
381+
@test replstr(LowerTriangular(copy(A))) == "4x4 LowerTriangular{$Int,Array{$Int,2}}:\n 1 ⋅ ⋅ ⋅\n 2 6 ⋅ ⋅\n 3 7 11 ⋅\n 4 8 12 16"
382382

383383
# Issue #15525, printing of vcat
384384
@test sprint(show, :([a;])) == ":([a;])"

test/sparsedir/sparse.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ for i = 1 : 10
6363
end
6464

6565
# sparse ref
66-
a116 = reshape(1:16, 4, 4)
66+
a116 = copy(reshape(1:16, 4, 4))
6767
s116 = sparse(a116)
6868
p = [4, 1, 2, 3, 2]
6969
@test full(s116[p,:]) == a116[p,:]

0 commit comments

Comments
 (0)