@@ -823,65 +823,45 @@ error_if_canonical_indexing(::LinearIndexing, ::AbstractArray, ::Any...) = nothi
823
823
_getindex (:: LinearIndexing , A:: AbstractArray , I... ) = error (" indexing $(typeof (A)) with types $(typeof (I)) is not supported" )
824
824
825
825
# # LinearFast Scalar indexing: canonical method is one Int
826
- _getindex (:: LinearFast , A:: AbstractVector , i:: Int ) = (@_propagate_inbounds_meta ; getindex (A, i))
827
- _getindex (:: LinearFast , A:: AbstractArray , i:: Int ) = (@_propagate_inbounds_meta ; getindex (A, i))
828
- _getindex {T} (:: LinearFast , A:: AbstractArray{T,0} ) = A[1 ]
829
- function _getindex {T,N} (:: LinearFast , A:: AbstractArray{T,N} , I:: Vararg{Int,N} )
830
- # We must check bounds for sub2ind; so we can then use @inbounds
826
+ _getindex (:: LinearFast , A:: AbstractArray , i:: Int ) = (@_propagate_inbounds_meta ; getindex (A, i))
827
+ _getindex (:: LinearFast , A:: AbstractArray ) = (@_propagate_inbounds_meta ; getindex (A, _to_linear_index (A)))
828
+ function _getindex (:: LinearFast , A:: AbstractArray , I:: Int... )
831
829
@_inline_meta
832
- @boundscheck checkbounds (A, I... )
833
- @inbounds r = getindex (A, sub2ind (A, I... ))
834
- r
835
- end
836
- function _getindex (:: LinearFast , A:: AbstractVector , I1:: Int , I:: Int... )
837
- @_inline_meta
838
- @boundscheck checkbounds (A, I1, I... )
839
- @inbounds r = getindex (A, I1)
840
- r
841
- end
842
- function _getindex (:: LinearFast , A:: AbstractArray , I:: Int... ) # TODO : DEPRECATE FOR #14770
843
- @_inline_meta
844
- @boundscheck checkbounds (A, I... )
845
- @inbounds r = getindex (A, sub2ind (A, I... ))
830
+ @boundscheck checkbounds (A, I... ) # generally _to_linear_index requires bounds checking
831
+ @inbounds r = getindex (A, _to_linear_index (A, I... ))
846
832
r
847
833
end
848
-
834
+ _to_linear_index (A:: AbstractArray , i:: Int ) = i
835
+ _to_linear_index (A:: AbstractVector , i:: Int , I:: Int... ) = i # TODO : DEPRECATE FOR #14770
836
+ _to_linear_index {T,N} (A:: AbstractArray{T,N} , I:: Vararg{Int,N} ) = (@_inline_meta ; sub2ind (A, I... ))
837
+ _to_linear_index (A:: AbstractArray ) = 1 # TODO : DEPRECATE FOR #14770
838
+ _to_linear_index (A:: AbstractArray , I:: Int... ) = (@_inline_meta ; sub2ind (A, I... )) # TODO : DEPRECATE FOR #14770
849
839
850
840
# # LinearSlow Scalar indexing: Canonical method is full dimensionality of Ints
851
- _getindex {T,N} (:: LinearSlow , A:: AbstractArray{T,N} , I:: Vararg{Int, N} ) = (@_propagate_inbounds_meta ; getindex (A, I... ))
852
- function _getindex (:: LinearSlow , A:: AbstractArray , i:: Int )
853
- # ind2sub requires all dimensions to be > 0; may as well just check bounds
841
+ _getindex (:: LinearSlow , A:: AbstractArray ) = (@_propagate_inbounds_meta ; getindex (A, _to_subscript_indices (A)... ))
842
+ function _getindex (:: LinearSlow , A:: AbstractArray , I:: Int... )
854
843
@_inline_meta
855
- @boundscheck checkbounds (A, i)
856
- @inbounds r = getindex (A, ind2sub (A, i )... )
844
+ @boundscheck checkbounds (A, I ... ) # generally _to_subscript_indices requires bounds checking
845
+ @inbounds r = getindex (A, _to_subscript_indices (A, I ... )... )
857
846
r
858
847
end
859
- @generated function _getindex {T,AN} (:: LinearSlow , A:: AbstractArray{T,AN} , I:: Int... ) # TODO : DEPRECATE FOR #14770
860
- N = length (I)
861
- if N > AN
862
- # Drop trailing ones
863
- Isplat = Expr[:(I[$ d]) for d = 1 : AN]
864
- Osplat = Expr[:(I[$ d] == 1 ) for d = AN+ 1 : N]
865
- quote
866
- @_propagate_inbounds_meta
867
- @boundscheck (& )($ (Osplat... )) || throw_boundserror (A, I)
868
- getindex (A, $ (Isplat... ))
869
- end
870
- else
871
- # Expand the last index into the appropriate number of indices
872
- Isplat = Expr[:(I[$ d]) for d = 1 : N- 1 ]
873
- sz = Expr (:tuple )
874
- sz. args = Expr[:(size (A, $ d)) for d= max (N,1 ): AN]
875
- szcheck = Expr[:(size (A, $ d) > 0 ) for d= max (N,1 ): AN]
876
- last_idx = N > 0 ? :(I[$ N]) : 1
877
- quote
878
- # ind2sub requires all dimensions to be > 0:
879
- @_propagate_inbounds_meta
880
- @boundscheck (& )($ (szcheck... )) || throw_boundserror (A, I)
881
- getindex (A, $ (Isplat... ), ind2sub ($ sz, $ last_idx)... )
882
- end
883
- end
848
+ _getindex {T,N} (:: LinearSlow , A:: AbstractArray{T,N} , I:: Vararg{Int, N} ) = (@_propagate_inbounds_meta ; getindex (A, I... ))
849
+ _to_subscript_indices (A:: AbstractArray , i:: Int ) = (@_inline_meta ; _unsafe_ind2sub (A, i))
850
+ _to_subscript_indices {T,N} (A:: AbstractArray{T,N} ) = (@_inline_meta ; fill_to_length ((), 1 , Val{N})) # TODO : DEPRECATE FOR #14770
851
+ _to_subscript_indices {T} (A:: AbstractArray{T,0} ) = () # TODO : REMOVE FOR #14770
852
+ _to_subscript_indices {T} (A:: AbstractArray{T,0} , i:: Int ) = () # TODO : REMOVE FOR #14770
853
+ _to_subscript_indices {T} (A:: AbstractArray{T,0} , I:: Int... ) = () # TODO : DEPRECATE FOR #14770
854
+ function _to_subscript_indices {T,N} (A:: AbstractArray{T,N} , I:: Int... ) # TODO : DEPRECATE FOR #14770
855
+ @_inline_meta
856
+ J, _ = IteratorsMD. split (I, Val{N}) # (maybe) drop any trailing indices
857
+ sz = _remaining_size (J, size (A)) # compute trailing size (overlapping the final index)
858
+ (front (J)... , _unsafe_ind2sub (sz, last (J))... ) # (maybe) extend the last index
884
859
end
860
+ _to_subscript_indices {T,N} (A:: AbstractArray{T,N} , I:: Vararg{Int,N} ) = I
861
+ _remaining_size (:: Tuple{Any} , t:: Tuple ) = t
862
+ _remaining_size (h:: Tuple , t:: Tuple ) = (@_inline_meta ; _remaining_size (tail (h), tail (t)))
863
+ _unsafe_ind2sub (:: Tuple{} , i) = () # ind2sub may throw(BoundsError()) in this case
864
+ _unsafe_ind2sub (sz, i) = (@_inline_meta ; ind2sub (sz, i))
885
865
886
866
# # Setindex! is defined similarly. We first dispatch to an internal _setindex!
887
867
# function that allows dispatch on array storage
@@ -899,65 +879,24 @@ end
899
879
_setindex! (:: LinearIndexing , A:: AbstractArray , v, I... ) = error (" indexing $(typeof (A)) with types $(typeof (I)) is not supported" )
900
880
901
881
# # LinearFast Scalar indexing
902
- _setindex! (:: LinearFast , A:: AbstractVector , v, i:: Int ) = (@_propagate_inbounds_meta ; setindex! (A, v, i))
903
882
_setindex! (:: LinearFast , A:: AbstractArray , v, i:: Int ) = (@_propagate_inbounds_meta ; setindex! (A, v, i))
904
- _setindex! {T} (:: LinearFast , A:: AbstractArray{T,0} , v) = (@_propagate_inbounds_meta ; setindex! (A, v, 1 ))
905
- function _setindex! {T,N} (:: LinearFast , A:: AbstractArray{T,N} , v, I:: Vararg{Int,N} )
906
- # We must check bounds for sub2ind; so we can then use @inbounds
907
- @_inline_meta
908
- @boundscheck checkbounds (A, I... )
909
- @inbounds r = setindex! (A, v, sub2ind (A, I... ))
910
- r
911
- end
912
- function _setindex! (:: LinearFast , A:: AbstractVector , v, I1:: Int , I:: Int... )
913
- @_inline_meta
914
- @boundscheck checkbounds (A, I1, I... )
915
- @inbounds r = setindex! (A, v, I1)
916
- r
917
- end
918
- function _setindex! (:: LinearFast , A:: AbstractArray , v, I:: Int... ) # TODO : DEPRECATE FOR #14770
883
+ _setindex! (:: LinearFast , A:: AbstractArray , v) = (@_propagate_inbounds_meta ; setindex! (A, v, _to_linear_index (A)))
884
+ function _setindex! (:: LinearFast , A:: AbstractArray , v, I:: Int... )
919
885
@_inline_meta
920
886
@boundscheck checkbounds (A, I... )
921
- @inbounds r = setindex! (A, v, sub2ind (A, I... ))
887
+ @inbounds r = setindex! (A, v, _to_linear_index (A, I... ))
922
888
r
923
889
end
924
890
925
891
# LinearSlow Scalar indexing
926
892
_setindex! {T,N} (:: LinearSlow , A:: AbstractArray{T,N} , v, I:: Vararg{Int, N} ) = (@_propagate_inbounds_meta ; setindex! (A, v, I... ))
927
- function _setindex! (:: LinearSlow , A:: AbstractArray , v, i :: Int )
928
- # ind2sub requires all dimensions to be > 0; may as well just check bounds
893
+ _setindex! (:: LinearSlow , A:: AbstractArray , v) = ( @_propagate_inbounds_meta ; setindex! (A, v, _to_subscript_indices (A) ... ) )
894
+ function _setindex! ( :: LinearSlow , A :: AbstractArray , v, I :: Int... )
929
895
@_inline_meta
930
- @boundscheck checkbounds (A, i )
931
- @inbounds r = setindex! (A, v, ind2sub (A, i )... )
896
+ @boundscheck checkbounds (A, I ... )
897
+ @inbounds r = setindex! (A, v, _to_subscript_indices (A, I ... )... )
932
898
r
933
899
end
934
- @generated function _setindex! {T,AN} (:: LinearSlow , A:: AbstractArray{T,AN} , v, I:: Int... ) # TODO : DEPRECATE FOR #14770
935
- N = length (I)
936
- if N > AN
937
- # Drop trailing ones
938
- Isplat = Expr[:(I[$ d]) for d = 1 : AN]
939
- Osplat = Expr[:(I[$ d] == 1 ) for d = AN+ 1 : N]
940
- quote
941
- # We only check the trailing ones, so just propagate @inbounds state
942
- @_propagate_inbounds_meta
943
- @boundscheck (& )($ (Osplat... )) || throw_boundserror (A, I)
944
- setindex! (A, v, $ (Isplat... ))
945
- end
946
- else
947
- # Expand the last index into the appropriate number of indices
948
- Isplat = Expr[:(I[$ d]) for d = 1 : N- 1 ]
949
- sz = Expr (:tuple )
950
- sz. args = Expr[:(size (A, $ d)) for d= max (N,1 ): AN]
951
- szcheck = Expr[:(size (A, $ d) > 0 ) for d= max (N,1 ): AN]
952
- last_idx = N > 0 ? :(I[$ N]) : 1
953
- quote
954
- # ind2sub requires all dimensions to be > 0:
955
- @_propagate_inbounds_meta
956
- @boundscheck (& )($ (szcheck... )) || throw_boundserror (A, I)
957
- setindex! (A, v, $ (Isplat... ), ind2sub ($ sz, $ last_idx)... )
958
- end
959
- end
960
- end
961
900
962
901
# # get (getindex with a default value) ##
963
902
0 commit comments