5
$\begingroup$

I am writing a function to reverse a matrix and join the reversed version to the original one, making a new matrix which I call A. And after doing this, I reverse A and join it with original A to get the result I want.

I have written my code like this:

matJoin[mat_?MatrixQ] := 
  Module[{A, W, H}, 
    A = Join[mat, Reverse /@ mat, 2];
    {W, H} = Dimensions[mat];
    Join[A, ArrayReshape[Reverse @ Flatten[A], {H, 2 W}]]]

For example, for a random matrix mat=RandomInteger[10, {4, 4}]shown as below:

{{10, 0, 3, 6}, {1, 0, 1, 9}, {2, 2, 6, 9}, {4, 5, 7, 4}}

Applying it to the matJoin function I wrote: matJoin[mat]

The output was shown as below and it had served my purpose:

{{10, 0, 3, 6, 6, 3, 0, 10}, {1, 0, 1, 9, 9, 1, 0, 1}, {2, 2, 6, 9, 9, 6, 2, 2}, {4, 5, 7, 4, 4, 7, 5, 4}, {4, 5, 7, 4, 4, 7, 5, 4}, {2,
2, 6, 9, 9, 6, 2, 2}, {1, 0, 1, 9, 9, 1, 0, 1}, {10, 0, 3, 6, 6, 3,
0, 10}}

But my problems are:

  1. It only works for matrices with dimensions of even orders. If the W and H have odd values, the code doesn't work properly.
  2. I am thinking there is a better way to write the function to make it run faster.

Looking forward to your help.

$\endgroup$
2
  • 1
    $\begingroup$ It would be helpful if you were to edit this question to include an example of data which produces a wrong result and which shows what the right result would be for the data provided. $\endgroup$
    – m_goldberg
    Commented Nov 9, 2018 at 14:43
  • $\begingroup$ Thanks, already updated $\endgroup$
    – leon365
    Commented Nov 9, 2018 at 15:10

3 Answers 3

3
$\begingroup$
ClearAll[f]
f[m_?MatrixQ] := Module[{d = Dimensions@m,  rows, cols},
 rows = Join[#, 1 + d[[1]] - #] &@Range[d[[1]]];
 cols = Join[#, 1 + d[[2]] - #] &@Range[d[[2]]]; 
 m[[rows, cols]]];

f @ Array[Subscript[a, Row @ {##}]&, {4, 4}] // MatrixForm

enter image description here

f @ Array[Subscript[a, Row @ {##}]&, {3, 5}] // MatrixForm

enter image description here

Using Henrik's timing setup f is is about twice as fast as matJoin2:

SeedRandom[1]
mat = RandomReal[1, {1000, 1000}];

r = matJoin[mat]; // RepeatedTiming // First

0.022

r2 = matJoin2[mat]; // RepeatedTiming // First

0.014

r3 = f[mat]; // RepeatedTiming // First

0.0064

r == r2 == r3

True

Update: A faster version of Mike Honeychurch's g:

g2[mat_] := With[{a=Join[mat, Reverse[mat, 2], 2] }, Join[a, Reverse @ a]]

r4 = g[mat]; // RepeatedTiming // First 

0.090

r5 = g2[mat]; // RepeatedTiming // First 

0.046

r == r2 == r3 == r4 == r5

True

Note: Timings on Wolfram Cloud, Version "11.3.0 for Linux x86 (64-bit) (March 7, 2018)"

$\endgroup$
1
  • 1
    $\begingroup$ Ah, very good idea to boil it down to one single read-and-copy request. $\endgroup$ Commented Nov 9, 2018 at 16:01
2
$\begingroup$

Since you are asking about joining and reversing why not use Join and Reverse and use level specs?

mat = {{10, 0, 3, 6}, {1, 0, 1, 9}, {2, 2, 6, 9}, {4, 5, 7, 4}}

Join[Join[mat, Reverse[mat, 2], 2],Reverse@Join[mat, Reverse[mat, 2], 2]]

(*
{{10, 0, 3, 6, 6, 3, 0, 10}, {1, 0, 1, 9, 9, 1, 0, 1}, {2, 2, 6, 9, 9,
   6, 2, 2}, {4, 5, 7, 4, 4, 7, 5, 4}, {4, 5, 7, 4, 4, 7, 5, 4}, {2, 
  2, 6, 9, 9, 6, 2, 2}, {1, 0, 1, 9, 9, 1, 0, 1}, {10, 0, 3, 6, 6, 3, 
  0, 10}}
*)

Test 2

mat = Array[Subscript[a, Row@{##}] &, {3, 5}]

enter image description here

g[mat_] :=Join[Join[mat, Reverse[mat, 2], 2],Reverse@Join[mat, Reverse[mat, 2], 2]]

or

h[mat_] := Module[{mat2 = Join[mat, Reverse[mat, 2], 2]},
  Join[mat2, Reverse@mat2]
  ]

Timing on my machine has this solution the fastest as well as the most intuitive

$\endgroup$
1
$\begingroup$

This one appears to be twice as fast:

matJoin2[mat_?MatrixQ] := Module[{m, n, a, b},
  {m, n} = Dimensions[mat];
  a = mat[[Range[n, 1, -1]]];
  b = mat[[All, Range[m, 1, -1]]];
  ArrayFlatten[{{mat, b}, {a, b[[Range[m, 1, -1]]]}}]
  ]

Test:

mat = RandomReal[1, {1000, 1000}];
r = matJoin[mat]; // RepeatedTiming // First
r2 = matJoin2[mat]; // RepeatedTiming // First
r == r2

0.0276

0.014

True

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.