@@ -8,6 +8,9 @@ using Compat: axes, CartesianIndices
88
99export OffsetArray, OffsetVector, @unsafe
1010
11+ # # Major change in 0.7: OffsetArray now uses Offset axes
12+ const AxisType = VERSION < v " 0.7.0-DEV.5242" ? identity : Base. Slice
13+
1114# TODO : just use .+
1215# See https://github.com/JuliaLang/julia/pull/22932#issuecomment-330711997
1316if VERSION < v " 0.7.0-DEV.1759"
7477OffsetArray (A:: AbstractArray{T,0} , inds:: Tuple{} ) where {T} = OffsetArray {T,0,typeof(A)} (A, ())
7578OffsetArray (A:: AbstractArray{T,N} , inds:: Tuple{} ) where {T,N} = error (" this should never be called" )
7679function OffsetArray (A:: AbstractArray{T,N} , inds:: NTuple{N,AbstractUnitRange} ) where {T,N}
77- lA = map (length , axes (A))
78- lI = map (length , inds)
80+ lA = map (indexlength , axes (A))
81+ lI = map (indexlength , inds)
7982 lA == lI || throw (DimensionMismatch (" supplied axes do not agree with the size of the array (got size $lA for the array and $lI for the indices" ))
8083 OffsetArray (A, map (indexoffset, inds))
8184end
@@ -98,38 +101,48 @@ Base.eachindex(::IndexLinear, A::OffsetVector) = axes(A, 1)
98101# performance-critical and relies on axes, these are usually worth
99102# optimizing thoroughly.
100103@inline Compat. axes (A:: OffsetArray , d) =
101- 1 <= d <= length (A. offsets) ? plus (axes (parent (A))[d], A. offsets[d]) : (1 : 1 )
104+ 1 <= d <= length (A. offsets) ? AxisType ( plus (axes (parent (A))[d], A. offsets[d]) ) : (1 : 1 )
102105@inline Compat. axes (A:: OffsetArray ) =
103106 _axes (axes (parent (A)), A. offsets) # would rather use ntuple, but see #15276
104107@inline _axes (inds, offsets) =
105- (plus (inds[1 ], offsets[1 ]), _axes (tail (inds), tail (offsets))... )
108+ (AxisType ( plus (inds[1 ], offsets[1 ]) ), _axes (tail (inds), tail (offsets))... )
106109_axes (:: Tuple{} , :: Tuple{} ) = ()
107110Base. indices1 (A:: OffsetArray{T,0} ) where {T} = 1 : 1 # we only need to specialize this one
108111
112+
113+ const OffsetAxis = Union{Integer, UnitRange, Base. Slice{<: UnitRange }, Base. OneTo}
109114function Base. similar (A:: OffsetArray , :: Type{T} , dims:: Dims ) where T
110115 B = similar (parent (A), T, dims)
111116end
112- function Base. similar (A:: AbstractArray , :: Type{T} , inds:: Tuple{UnitRange ,Vararg{UnitRange }} ) where T
113- B = similar (A, T, map (length , inds))
117+ function Base. similar (A:: AbstractArray , :: Type{T} , inds:: Tuple{OffsetAxis ,Vararg{OffsetAxis }} ) where T
118+ B = similar (A, T, map (indexlength , inds))
114119 OffsetArray (B, map (indexoffset, inds))
115120end
116121
117- Base. similar (:: Type{T} , shape:: Tuple{UnitRange,Vararg{UnitRange}} ) where {T<: OffsetArray } =
118- OffsetArray (T (map (length, shape)), map (indexoffset, shape))
119- Base. similar (:: Type{T} , shape:: Tuple{UnitRange,Vararg{UnitRange}} ) where {T<: Array } =
120- OffsetArray (T (undef, map (length, shape)), map (indexoffset, shape))
121- Base. similar (:: Type{T} , shape:: Tuple{UnitRange,Vararg{UnitRange}} ) where {T<: BitArray } =
122- OffsetArray (T (undef, map (length, shape)), map (indexoffset, shape))
122+ Base. similar (:: Type{T} , shape:: Tuple{OffsetAxis,Vararg{OffsetAxis}} ) where {T<: AbstractArray } =
123+ OffsetArray (T (undef, map (indexlength, shape)), map (indexoffset, shape))
123124
125+ if VERSION < v " 0.7.0-DEV.5242"
126+ # Reshape's methods in Base changed, so using the new definitions leads to ambiguities
124127Base. reshape (A:: AbstractArray , inds:: Tuple{UnitRange,Vararg{UnitRange}} ) =
125128 OffsetArray (reshape (A, map (length, inds)), map (indexoffset, inds))
126-
127129Base. reshape (A:: OffsetArray , inds:: Tuple{UnitRange,Vararg{UnitRange}} ) =
128130 OffsetArray (reshape (parent (A), map (length, inds)), map (indexoffset, inds))
129-
130131function Base. reshape (A:: OffsetArray , inds:: Tuple{UnitRange,Vararg{Union{UnitRange,Int,Base.OneTo}}} )
131132 throw (ArgumentError (" reshape must supply UnitRange axes, got $(typeof (inds)) .\n Note that reshape(A, Val{N}) is not supported for OffsetArrays." ))
132133end
134+ else
135+ Base. reshape (A:: AbstractArray , inds:: Tuple{OffsetAxis,Vararg{OffsetAxis}} ) =
136+ OffsetArray (reshape (A, map (indexlength, inds)), map (indexoffset, inds))
137+
138+ # Reshaping OffsetArrays can "pop" the original OffsetArray wrapper and return
139+ # an OffsetArray(reshape(...)) instead of an OffsetArray(reshape(OffsetArray(...)))
140+ Base. reshape (A:: OffsetArray , inds:: Tuple{OffsetAxis,Vararg{OffsetAxis}} ) =
141+ OffsetArray (reshape (parent (A), map (indexlength, inds)), map (indexoffset, inds))
142+ # And for non-offset axes, we can just return a reshape of the parent directly
143+ Base. reshape (A:: OffsetArray , inds:: Tuple{Union{Integer,Base.OneTo},Vararg{Union{Integer,Base.OneTo}}} ) = reshape (parent (A), inds)
144+ Base. reshape (A:: OffsetArray , inds:: Dims ) = reshape (parent (A), inds)
145+ end
133146
134147if VERSION < v " 0.7.0-DEV.4873"
135148 # Julia PR #26733 removed similar(f, ...) in favor of just using method extension directly
@@ -201,7 +214,7 @@ offset(offsets::Tuple{Vararg{Int}}, inds::Tuple{}) = error("inds cannot be short
201214
202215indexoffset (r:: AbstractRange ) = first (r) - 1
203216indexoffset (i:: Integer ) = 0
204- indexlength (r:: AbstractRange ) = length (r)
217+ indexlength (r:: AbstractRange ) = Base . _length (r)
205218indexlength (i:: Integer ) = i
206219
207220macro unsafe (ex)
@@ -290,8 +303,10 @@ if VERSION >= v"0.7.0-DEV.1790"
290303 toplevel && print (io, " with eltype " , eltype (a))
291304 end
292305 printindices (io:: IO , ind1, inds... ) =
293- (print (io, ind1, " , " ); printindices (io, inds... ))
294- printindices (io:: IO , ind1) = print (io, ind1)
306+ (print (io, _unslice (ind1), " , " ); printindices (io, inds... ))
307+ printindices (io:: IO , ind1) = print (io, _unslice (ind1))
308+ _unslice (x) = x
309+ _unslice (x:: Base.Slice ) = x. indices
295310end
296311
297312end # module
0 commit comments