2323
2424size {T,N} (t:: AbstractArray{T,N} , d) = d <= N ? size (t)[d] : 1
2525size {N} (x, d1:: Integer , d2:: Integer , dx:: Vararg{Integer, N} ) = (size (x, d1), size (x, d2), ntuple (k-> size (x, dx[k]), Val{N})... )
26+
27+ # trait to indicate "vetted" usage for indexing that may not start at 1
28+ abstract IndicesSafety
29+ immutable SafeIndices <: IndicesSafety end
30+ immutable UnsafeIndices <: IndicesSafety end
31+
32+ macro safeindices (ex)
33+ esc (_safeindices (ex))
34+ end
35+
36+ function _safeindices (ex:: Expr )
37+ if ex. head == :call
38+ f = ex. args[1 ]
39+ if f == :size || f == :length
40+ return Expr (:call , f, :(Base. SafeIndices ()), ex. args[2 : end ]. .. )
41+ end
42+ end
43+ return Expr (ex. head, map (_safeindices, ex. args)... )
44+ end
45+
46+ _safeindices (arg) = arg
47+
48+ # The default is that size is safe, but array types that use non-1
49+ # indexing should specialize this to make it unsafe without
50+ # SafeIndices().
51+ size ( :: IndicesSafety , A) = size (A)
52+ size ( :: IndicesSafety , A:: AbstractArray , d) = size (A,d) # fixme
53+ # size(s::IndicesSafety, A::AbstractArray, d) = d <= ndims(A) ? size(s, A)[d] : 1
54+ size {N} (s:: IndicesSafety , A:: AbstractArray , d1:: Integer , d2:: Integer , dx:: Vararg{Integer, N} ) = (size (s, A, d1), size (s, A, d2), ntuple (k-> size (s, A, dx[k]), Val{N})... )
55+
2656"""
2757 indices(A, d)
2858
2959Returns the valid range of indices for array `A` along dimension `d`.
3060"""
3161function indices (A:: AbstractArray , d)
3262 @_inline_meta
33- 1 : size (A,d)
63+ 1 : size (SafeIndices (), A,d)
3464end
3565"""
3666 indices(A)
@@ -61,15 +91,17 @@ is `indices(A, 1)`.
6191Calling this function is the "safe" way to write algorithms that
6292exploit linear indexing.
6393"""
64- linearindices (A) = 1 : length (A)
94+ linearindices (A) = 1 : length (SafeIndices (), A)
6595linearindices (A:: AbstractVector ) = indices1 (A)
6696eltype {T} (:: Type{AbstractArray{T}} ) = T
6797eltype {T,N} (:: Type{AbstractArray{T,N}} ) = T
6898elsize {T} (:: AbstractArray{T} ) = sizeof (T)
6999ndims {T,N} (:: AbstractArray{T,N} ) = N
70100ndims {T,N} (:: Type{AbstractArray{T,N}} ) = N
71101ndims {T<:AbstractArray} (:: Type{T} ) = ndims (supertype (T))
72- length (t:: AbstractArray ) = prod (size (t)):: Int
102+ length (s:: IndicesSafety , t:: AbstractArray ) = prod (size (s,t))
103+ length (s:: IndicesSafety , t) = length (t)
104+ length (t:: AbstractArray ) = length (UnsafeIndices (), t)
73105endof (a:: AbstractArray ) = length (a)
74106first (a:: AbstractArray ) = a[first (eachindex (a))]
75107
@@ -120,13 +152,14 @@ function isassigned(a::AbstractArray, i::Int...)
120152end
121153
122154# used to compute "end" for last index
123- function trailingsize (A, n)
124- s = 1
155+ function trailingsize (s :: IndicesSafety , A, n)
156+ sz = 1
125157 for i= n: ndims (A)
126- s *= size (A,i)
158+ sz *= size (s, A,i)
127159 end
128- return s
160+ return sz
129161end
162+ trailingsize (A, n) = trailingsize (UnsafeIndices (), A, n)
130163
131164# # Traits for array types ##
132165
@@ -178,21 +211,22 @@ start at something different from 1), it is equivalent to `indices(A,
178211d)`.
179212"""
180213shape (a, d) = shape (indicesbehavior (a), a, d)
181- shape (:: IndicesStartAt1 , a) = size (a)
182- shape (:: IndicesStartAt1 , a, d) = size (a, d)
214+ shape (:: IndicesStartAt1 , a) = size (SafeIndices (), a)
215+ shape (:: IndicesStartAt1 , a, d) = size (SafeIndices (), a, d)
183216shape (:: IndicesBehavior , a) = indices (a)
184217shape (:: IndicesBehavior , a, d) = indices (a, d)
185218
186219# # Bounds checking ##
187- @generated function trailingsize {T,N,n} (A:: AbstractArray{T,N} , :: Type{Val{n}} )
220+ @generated function trailingsize {T,N,n} (s :: IndicesSafety , A:: AbstractArray{T,N} , :: Type{Val{n}} )
188221 (isa (n, Int) && isa (N, Int)) || error (" Must have concrete type" )
189222 n > N && return 1
190- ex = :(size (A, $ n))
223+ ex = :(size (s, A, $ n))
191224 for m = n+ 1 : N
192- ex = :($ ex * size (A, $ m))
225+ ex = :($ ex * size (s, A, $ m))
193226 end
194227 Expr (:block , Expr (:meta , :inline ), ex)
195228end
229+ trailingsize {n} (A:: AbstractArray , :: Type{Val{n}} ) = trailingsize (UnsafeIndices (), A, Val{n})
196230
197231# check along a single dimension
198232"""
@@ -265,13 +299,9 @@ _chkbnds(A::AbstractArray, ::NTuple{1,Bool}, I::AbstractVector{Bool}) = length(A
265299_chkbnds (A:: AbstractVector , :: NTuple{1,Bool} , I:: AbstractArray{Bool} ) = length (A) == length (I)
266300_chkbnds (A:: AbstractVector , :: NTuple{1,Bool} , I:: AbstractVector{Bool} ) = indices (A) == indices (I)
267301# Linear indexing:
268- function _chkbnds (A:: AbstractVector , :: NTuple{1,Bool} , I)
269- @_inline_meta
270- checkindex (Bool, indices1 (A), I)
271- end
272302function _chkbnds (A:: AbstractArray , :: NTuple{1,Bool} , I)
273303 @_inline_meta
274- checkindex (Bool, 1 : length (A), I)
304+ checkindex (Bool, linearindices (A), I)
275305end
276306# When all indices have been checked:
277307_chkbnds {M} (A, checked:: NTuple{M,Bool} ) = checked[M]
@@ -359,7 +389,7 @@ similar( a::AbstractArray, T::Type, dims::DimsInteger) = similar(a, T, convert
359389# similar creates an Array by default
360390similar ( a:: AbstractArray , T:: Type , dims:: Dims ) = Array (T, dims)
361391
362- _similar (:: IndicesStartAt1 , a:: AbstractArray , T:: Type ) = similar (a, T, size (a))
392+ _similar (:: IndicesStartAt1 , a:: AbstractArray , T:: Type ) = similar (a, T, size (SafeIndices (), a))
363393_similar (:: IndicesBehavior , a:: AbstractArray , T:: Type ) = similar (a, T, indices (a))
364394
365395"""
@@ -525,7 +555,7 @@ function copy!(::LinearIndexing, dest::AbstractArray, ::LinearSlow, src::Abstrac
525555end
526556
527557function copy! (dest:: AbstractArray , dstart:: Integer , src:: AbstractArray )
528- copy! (dest, dstart, src, first (linearindices (src)), length (src))
558+ copy! (dest, dstart, src, first (linearindices (src)), length (SafeIndices (), src))
529559end
530560
531561function copy! (dest:: AbstractArray , dstart:: Integer , src:: AbstractArray , sstart:: Integer )
@@ -650,7 +680,7 @@ function _maxlength(A, B, C...)
650680 max (length (A), _maxlength (B, C... ))
651681end
652682
653- isempty (a:: AbstractArray ) = (length (a) == 0 )
683+ isempty (a:: AbstractArray ) = (length (SafeIndices (), a) == 0 )
654684
655685# # Conversions ##
656686
@@ -1417,7 +1447,7 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector)
14171447 idx[d] = Colon ()
14181448 end
14191449
1420- r1 = f (view (A, idx... ) )
1450+ r1 = f (A[ idx... ] )
14211451
14221452 # determine result size and allocate
14231453 Rsize = copy (dimsA)
@@ -1427,7 +1457,7 @@ function mapslices(f, A::AbstractArray, dims::AbstractVector)
14271457 end
14281458 nextra = max (0 ,length (dims)- ndims (r1))
14291459 if eltype (Rsize) == Int
1430- Rsize[dims] = [size (r1)... , ntuple (d-> 1 , nextra)... ]
1460+ Rsize[dims] = [size (SafeIndices (), r1)... , ntuple (d-> 1 , nextra)... ]
14311461 else
14321462 Rsize[dims] = [indices (r1)... , ntuple (d-> 1 : 1 , nextra)... ]
14331463 end
0 commit comments