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