@@ -1076,25 +1076,23 @@ function copyto!(deststyle::IndexStyle, dest::AbstractArray, srcstyle::IndexStyl
10761076 copyto_unaliased! (deststyle, dest, srcstyle, src′)
10771077end
10781078
1079- function copyto_unaliased! (deststyle:: IndexStyle , dest:: AbstractArray , srcstyle:: IndexStyle , src:: AbstractArray )
1079+ function copyto_unaliased! (:: IndexLinear , dest:: AbstractArray , :: IndexLinear , src:: AbstractArray )
1080+ @_propagate_inbounds_meta
1081+ copyto! (dest, firstindex (dest), src, firstindex (src), length (src))
1082+ end
1083+ function copyto_unaliased! (deststyle:: IndexStyle , dest:: AbstractArray , :: IndexStyle , src:: AbstractArray )
10801084 isempty (src) && return dest
10811085 destinds, srcinds = LinearIndices (dest), LinearIndices (src)
10821086 idf, isf = first (destinds), first (srcinds)
10831087 Δi = idf - isf
1084- (checkbounds (Bool, destinds, isf+ Δi) & checkbounds (Bool, destinds, last (srcinds)+ Δi)) ||
1088+ @boundscheck (checkbounds (Bool, destinds, isf+ Δi) & checkbounds (Bool, destinds, last (srcinds)+ Δi)) ||
10851089 throw (BoundsError (dest, srcinds))
10861090 if deststyle isa IndexLinear
1087- if srcstyle isa IndexLinear
1088- # Single-index implementation
1089- @inbounds for i in srcinds
1090- dest[i + Δi] = src[i]
1091- end
1092- else
1093- # Dual-index implementation
1094- i = idf - 1
1095- @inbounds for a in src
1096- dest[i+= 1 ] = a
1097- end
1091+ # IndexStyle(src) is IndexCartesian, as the linear indexing case is handled separately
1092+ # Dual-index implementation
1093+ i = idf - 1
1094+ @inbounds for a in src
1095+ dest[i+= 1 ] = a
10981096 end
10991097 else
11001098 iterdest, itersrc = eachindex (dest), eachindex (src)
@@ -1123,15 +1121,40 @@ function copyto!(dest::AbstractArray, dstart::Integer, src::AbstractArray, sstar
11231121 copyto! (dest, dstart, src, sstart, last (srcinds)- sstart+ 1 )
11241122end
11251123
1124+ # we add an extra level of indirection to forward the copy
1125+ # to the parent for contiguous linear views
11261126function copyto! (dest:: AbstractArray , dstart:: Integer ,
1127+ src:: AbstractArray , sstart:: Integer , n:: Integer )
1128+ @_propagate_inbounds_meta
1129+ # check if the arrays are views that may be unwrapped
1130+ # if yes, try to use the copyto! implementation for the parents
1131+ # if no, then fall back to the default implementation that loops over the arrays
1132+ __copyto! (dest, _unwrap_view (dest, dstart)... , src, _unwrap_view (src, sstart)... , n)
1133+ end
1134+ # if the array A is not a view, there's nothig to unwrap
1135+ _unwrap_view (A, ind) = A, ind
1136+ # fallback method if the arrays aren't views, in which case there's nothing to unwrap
1137+ function __copyto! (dest:: A , :: A , dstart, src:: B , :: B , sstart, n) where {A,B}
1138+ @_propagate_inbounds_meta
1139+ _copyto! (dest, dstart, src, sstart, n)
1140+ end
1141+ # try copying to the parents if there is at least one contiguous view
1142+ function __copyto! (_, destp, dstart, _, srcp, sstart, n)
1143+ @_propagate_inbounds_meta
1144+ copyto! (destp, dstart, srcp, sstart, n)
1145+ end
1146+
1147+ function _copyto! (dest:: AbstractArray , dstart:: Integer ,
11271148 src:: AbstractArray , sstart:: Integer ,
11281149 n:: Integer )
11291150 n == 0 && return dest
11301151 n < 0 && throw (ArgumentError (LazyString (" tried to copy n=" ,
11311152 n," elements, but n should be non-negative" )))
11321153 destinds, srcinds = LinearIndices (dest), LinearIndices (src)
1133- (checkbounds (Bool, destinds, dstart) && checkbounds (Bool, destinds, dstart+ n- 1 )) || throw (BoundsError (dest, dstart: dstart+ n- 1 ))
1134- (checkbounds (Bool, srcinds, sstart) && checkbounds (Bool, srcinds, sstart+ n- 1 )) || throw (BoundsError (src, sstart: sstart+ n- 1 ))
1154+ @boundscheck begin
1155+ (checkbounds (Bool, destinds, dstart) && checkbounds (Bool, destinds, dstart+ n- 1 )) || throw (BoundsError (dest, dstart: dstart+ n- 1 ))
1156+ (checkbounds (Bool, srcinds, sstart) && checkbounds (Bool, srcinds, sstart+ n- 1 )) || throw (BoundsError (src, sstart: sstart+ n- 1 ))
1157+ end
11351158 src′ = unalias (dest, src)
11361159 @inbounds for i = 0 : n- 1
11371160 dest[dstart+ i] = src′[sstart+ i]
0 commit comments