@@ -662,6 +662,66 @@ function _circshift!(dest, rdest, src, rsrc, inds, shiftamt)
662662 copy! (dest, CartesianRange (rdest), src, CartesianRange (rsrc))
663663end
664664
665+ # circcopy!
666+ """
667+ circcopy!(dest, src)
668+
669+ Copy `src` to `dest`, indexing each dimension modulo its length.
670+ `src` and `dest` must have the same size, but can be offset in
671+ their indices; any offset results in a (circular) wraparound. If the
672+ arrays have overlapping indices, then on the domain of the overlap
673+ `dest` agrees with `src`.
674+
675+ ```jldoctest
676+ julia> src = reshape(collect(1:16), (4,4))
677+ 4×4 Array{Int64,2}:
678+ 1 5 9 13
679+ 2 6 10 14
680+ 3 7 11 15
681+ 4 8 12 16
682+
683+ julia> dest = OffsetArray(Int, (-1,1));
684+
685+ julia> circcopy!(dest, src)
686+ OffsetArrays.OffsetArray{Int64,2,Array{Int64,2}} with indices 0:3×2:5:
687+ 8 12 16 4
688+ 5 9 13 1
689+ 6 10 14 2
690+ 7 11 15 3
691+
692+ julia> dest[1:3,2:4] == src[1:3,2:4]
693+ true
694+ """
695+ function circcopy! (dest, src)
696+ dest === src && throw (ArgumentError (" dest and src must be separate arrays" ))
697+ indssrc, indsdest = indices (src), indices (dest)
698+ if (szsrc = map (length, indssrc)) != (szdest = map (length, indsdest))
699+ throw (DimensionMismatch (" src and dest must have the same sizes (got $szsrc and $szdest )" ))
700+ end
701+ shift = map ((isrc, idest)-> first (isrc)- first (idest), indssrc, indsdest)
702+ all (x-> x== 0 , shift) && return copy! (dest, src)
703+ _circcopy! (dest, (), indsdest, src, (), indssrc)
704+ end
705+
706+ @inline function _circcopy! (dest, rdest, indsdest:: Tuple{AbstractUnitRange,Vararg{Any}} ,
707+ src, rsrc, indssrc:: Tuple{AbstractUnitRange,Vararg{Any}} )
708+ indd1, inds1 = indsdest[1 ], indssrc[1 ]
709+ l = length (indd1)
710+ s = mod (first (inds1)- first (indd1), l)
711+ sdf = first (indd1)+ s
712+ rd1, rd2 = first (indd1): sdf- 1 , sdf: last (indd1)
713+ ssf = last (inds1)- s
714+ rs1, rs2 = first (inds1): ssf, ssf+ 1 : last (inds1)
715+ tindsd, tindss = tail (indsdest), tail (indssrc)
716+ _circcopy! (dest, (rdest... , rd1), tindsd, src, (rsrc... , rs2), tindss)
717+ _circcopy! (dest, (rdest... , rd2), tindsd, src, (rsrc... , rs1), tindss)
718+ end
719+
720+ # At least one of indsdest, indssrc are empty (and both should be, since we've checked)
721+ function _circcopy! (dest, rdest, indsdest, src, rsrc, indssrc)
722+ copy! (dest, CartesianRange (rdest), src, CartesianRange (rsrc))
723+ end
724+
665725# ## BitArrays
666726
667727# # getindex
0 commit comments