Skip to content

Commit

Permalink
Merge branch 'master' into Tri_Diag_Unify
Browse files Browse the repository at this point in the history
  • Loading branch information
N5N3 committed Sep 23, 2021
2 parents b519518 + c3fd814 commit 14e01c8
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 35 deletions.
46 changes: 11 additions & 35 deletions base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1006,44 +1006,20 @@ end

function copyto_unaliased!(deststyle::IndexStyle, dest::AbstractArray, srcstyle::IndexStyle, src::AbstractArray)
isempty(src) && return dest
destinds, srcinds = LinearIndices(dest), LinearIndices(src)
idf, isf = first(destinds), first(srcinds)
Δi = idf - isf
(checkbounds(Bool, destinds, isf+Δi) & checkbounds(Bool, destinds, last(srcinds)+Δi)) ||
throw(BoundsError(dest, srcinds))
if deststyle isa IndexLinear
if srcstyle isa IndexLinear
# Single-index implementation
@inbounds for i in srcinds
dest[i + Δi] = src[i]
end
else
# Dual-index implementation
i = idf - 1
@inbounds for a in src
dest[i+=1] = a
end
end
else
iterdest, itersrc = eachindex(dest), eachindex(src)
if iterdest == itersrc
# Shared-iterator implementation
for I in iterdest
@inbounds dest[I] = src[I]
end
else
# Dual-iterator implementation
ret = iterate(iterdest)
@inbounds for a in src
idx, state = ret
dest[idx] = a
ret = iterate(iterdest, state)
end
end
end
length(dest) < length(src) && throw(BoundsError(dest, LinearIndices(src)))
_unaliased_copyto!(deststyle, dest, srcstyle, src)
return dest
end

# IndexCartesian and CartesianIndices has not been defined, only implement Linear to Linear here.
function _unaliased_copyto!(::IndexLinear, dest::AbstractArray, ::IndexLinear, src::AbstractArray)
@_inline_meta
Δi = firstindex(dest) - firstindex(src)
for i in eachindex(src)
@inbounds dest[i + Δi] = src[i]
end
end

function copyto!(dest::AbstractArray, dstart::Integer, src::AbstractArray)
copyto!(dest, dstart, src, first(LinearIndices(src)), length(src))
end
Expand Down
81 changes: 81 additions & 0 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1130,6 +1130,87 @@ in the range of `Rdest`. The sizes of the two regions must match.
"""
copyto!(::AbstractArray, ::CartesianIndices, ::AbstractArray, ::CartesianIndices)

function _unaliased_copyto!(::IndexLinear, dest::AbstractArray, ::IndexStyle, src::AbstractArray)
@_inline_meta
iter, j = eachindex(src), firstindex(dest) - 1
if size(src, 1) >= 16
# manually expand the inner loop similar to @simd
@inbounds for II in simd_outer_range(iter)
n = 0
while n < simd_inner_length(iter, II)
dest[j += 1] = src[simd_index(iter, II, n)]
n += 1
end
end
else
for I in iter
@inbounds dest[j += 1] = src[I]
end
end
end

# Linear to Cartesian unaliased copy
function _unaliased_copyto!(::IndexStyle, dest::AbstractArray, ::IndexLinear, src::AbstractArray)
@_inline_meta
iter = eachindex(dest)
i, final = firstindex(src) - 1, lastindex(src)
if size(dest, 1) >= 16
# manually expand the inner loop similar to @simd
@inbounds for II in simd_outer_range(iter)
n, len = 0, simd_inner_length(iter, II)
if i + len < final
while n < len
dest[simd_index(iter, II, n)] = src[i += 1]
n += 1
end
continue
end
while i < final
dest[simd_index(iter, II, n)] = src[i += 1]
n += 1
end
break
end
elseif length(dest) == length(src)
for I in iter
@inbounds dest[I] = src[i += 1]
end
else
# use zip based interator
invoke(_unaliased_copyto!,
Tuple{IndexStyle, AbstractArray, IndexStyle, AbstractArray},
IndexStyle(dest), dest, IndexLinear(), src)
end
end

function _unaliased_copyto!(::IndexStyle, dest::AbstractArray, ::IndexStyle, src::AbstractArray)
@_inline_meta
iterdest, itersrc = eachindex(dest), eachindex(src)
iterdest == itersrc && return _shared_unaliased_copyto!(dest, src, itersrc)
@inbounds for (J, I) in zip(iterdest, itersrc)
dest[J] = src[I]
end
end

function _shared_unaliased_copyto!(dest::AbstractArray, src::AbstractArray, iter)
@_inline_meta
if size(src, 1) >= 16
# manually expand the inner loop similar to @simd
@inbounds for II in simd_outer_range(iter)
n = 0
while n < simd_inner_length(iter, II)
I′ = simd_index(iter, II, n)
dest[I′] = src[I′]
n += 1
end
end
else
for I in iter
@inbounds dest[I] = src[I]
end
end
end

# circshift!
circshift!(dest::AbstractArray, src, ::Tuple{}) = copyto!(dest, src)
"""
Expand Down
12 changes: 12 additions & 0 deletions test/copy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -238,3 +238,15 @@ end
@testset "deepcopy_internal arrays" begin
@test (@inferred Base.deepcopy_internal(zeros(), IdDict())) == zeros()
end

@testset "copyto_unaliased!" begin
s = [1:140 141:280]
r = ones(Int, 17, 17)
@test copyto!(copy(r), s) == reshape([1:280;ones(9)], 17, 17)
@test copyto!(copy(r), s) == copyto!(copy(r), view(s, axes(s)...)) ==
copyto!(copy(r)', s) == copyto!(copy(r)', view(s, axes(s)...))
s = reshape(1:289, 17, 17)
r = ones(Int, 17, 17)
@test copyto!(copy(r), s) == copyto!(copy(r), view(s, axes(s)...)) ==
copyto!(copy(r)', s) == copyto!(copy(r)', view(s, axes(s)...)) == s
end

0 comments on commit 14e01c8

Please sign in to comment.