# How to extract and replace submatrix of a doubly-periodic matrix?

How can I effectively extract and replace a rectangular subpart of a toroidal matrix, i.e. one where boundaries are connected at opposite ends? Since the submatrix can overhang the edges, a simple Take won't work, as the submatrix cannot be extracted if it is not continuous. At present, I construct a table of positions that are extracted/replaced via ReplacePart, but I feel there must be more elegant and faster solutions. Such answers could add to the usefulness of Elegant operations on matrix rows and columns. Consider the following example:

n = 8; (* matrix edge length *)
m = 4; (* submatrix edge length *)

matrix = Table[0, {n}, {n}];
sub = RandomReal[{.2, 1}, {m, m}]; (* random submatrix *)
pos = {6, 7}; (* position of sub assuming bottom left corner as origo *)

subPos = Table[{i, j}, {i, m}, {j, m}];
repPos = Map[Mod[# + pos - 1, n, 1] &, subPos, {2}]; (* list of positions to extract *)

new = ReplacePart[ReplacePart[matrix, Flatten@MapThread[Rule, {repPos, sub}, 2]], pos -> 2];
(* Replace the explicit list of positions with the elements of sub *)

ArrayPlot[Reverse@Transpose@new,
ColorRules -> {2 -> Pink, 0 -> White}, Mesh -> All, ImageSize -> 300]


Pink cell indicates the origin of the submatrix.

Question: Can the extraction/replacement done faster, assuming that matrix and sub could be huge (e.g. 10 000x10 000 and 50x50, respectively)?

-
+1 Excellently presented question. I wish we had many more of those. –  halirutan Sep 25 '12 at 2:07

 n = 8; m = 4;
origin ={6,7};
matrix = Table[0, {n}, {n}];
sub2 = Array[s, {m, m}];
sub3 = RandomReal[{.2, 1}, {m, m}];
sub3[[1,1]]=2;

{dimmat, dimsub} = Dimensions /@ {matrix, sub2};
(* using Istvan's suggestion for generating row and column indices of the part to be replaced:*)
{rows, columns} =  Mod[Range @@@ Transpose@{origin, origin + dimsub - 1}, dimmat, 1];
matrix[[rows, columns]] = sub2;
matrix // Grid


matrix[[rows, columns]] = sub3;
matrix // Grid


ArrayPlot[Reverse@Transpose@matrix,
ColorRules -> {2 -> Pink, 0 -> White}, Mesh -> All, ImageSize -> 300]


Note: Finding the row and column indices takes almost no time. For random 10,000x10,000 matrixs and random 50 by 50 submatrices, with random origins in the last 100x100 block, it takes less than a second to replace the parts of the matrix.

-
Thanks, I always forget about this way of part extraction and reassignment! However, I still would prefer the modulo: {rows, columns} = Mod[Range @@@ Transpose@{origin, origin + m - 1}, n, 1]. –  István Zachar Sep 24 '12 at 13:55
Istvan, thanks for the accept. I also prefer your Mod[...]. –  kguler Sep 24 '12 at 22:25