1
$\begingroup$

I want to realize a function R with parameters a, b, w which creates an M × M Givens rotation (sometimes called Jacobi rotation) matrix; i.e., a matrix R of size M × M equal to the identity matrix except for the entries in position (a, a), (a, b), (b, a) and (b, b) which are substituted with the entries of the matrix

{{Sin[w], Cos[w]}, {Cos[w], -Sin[w]}}

The solution I found is

R[a_, b_, w_] :=  Table[
   If[(m == a && n == a),
      Sin[w],
      If[(m== a && n == b),
         Cos[w],
         If[(m == b && n == a),
            Cos[w],
            If[(m == b && n == b),
               -Sin[w], 
               If[m == n, 1, 0]
            ]
         ]
      ]
   ], {m, 1, M}, {n, 1, M}]

but I wonder if there is a simpler/more efficient/elegant way to define the function.

$\endgroup$
1
  • 1
    $\begingroup$ {{Sin[w], Cos[w]}, {Cos[w], -Sin[w]}} is not a rotation matrix, since its determinant is not 1. $\endgroup$ Commented Nov 13, 2017 at 9:29

2 Answers 2

4
$\begingroup$
givens[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] := 
       RotationMatrix[θ, {UnitVector[n, j], UnitVector[n, k]}]

givens[ϕ, 5, {2, 5}] // MatrixForm

$$\begin{pmatrix} 1 & 0 & 0 & 0 & 0 \\ 0 & \cos (\varphi ) & 0 & 0 & -\sin (\varphi ) \\ 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 & 0 \\ 0 & \sin (\varphi ) & 0 & 0 & \cos (\varphi ) \\ \end{pmatrix}$$


As I noted in a comment to Henrik's answer, a simple way to generate a sparse version is the following:

givens2[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] :=
        With[{c = Cos[θ], s = Sin[θ]},
             SparseArray[{{j, j} | {k, k} -> c, {j, k} -> -s, {k, j} -> s,
                          Band[{1, 1}] -> 1}, {n, n}]]

or

givens3[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] :=
        With[{c = Cos[θ], s = Sin[θ]},
             SparseArray[{{j, j} | {k, k} -> c, {j, k} -> -s, {k, j} -> s,
                          {m_, m_} -> 1}, {n, n}]]
$\endgroup$
2
$\begingroup$

I really like SparseArrays, you know. Here is another proposal based on the answer by @J.M.

givens2[ϕ_, n_Integer?Positive, {a_Integer?Positive, b_Integer?Positive}] := 
  With[{ilist = Delete[Range[n], {{a}, {b}}]},
   SparseArray[
    Rule[
     Join[ Transpose[{ilist, ilist}], {{a, a}, {a, b}, {b, a}, {b, b}}], 
     Join[ConstantArray[1.,Length[ilist]], {Cos[ϕ], -Sin[ϕ], Sin[ϕ], Cos[ϕ]}]
     ],
    {n, n}, 0.]];

Normal[givens2[0.25 Pi, 5, {2, 5}]]

{{1., 0., 0., 0., 0.}, {0., 0.707107, 0., 0., -0.707107}, {0., 0., 1., 0., 0.}, {0., 0., 0., 1., 0.}, {0., 0.707107, 0., 0., 0.707107}}

Of course, the real point of a Givens rotation is that it can be applied to vectors without creating any matrix.

$\endgroup$
2
  • $\begingroup$ Much shorter: givens2[θ_, n_Integer?Positive, {j_Integer?Positive, k_Integer?Positive}] := With[{c = Cos[θ], s = Sin[θ]}, SparseArray[{{j, j} | {k, k} -> c, {j, k} -> -s, {k, j} -> s, Band[{1, 1}] -> 1}, {n, n}]] $\endgroup$ Commented Nov 13, 2017 at 9:52
  • $\begingroup$ @J.M. Ah, ingenius! I am not used to utilize patterns for creation of SparseArrays (I usually work with unstructured grids). I think you should post it! And that the Band entries for j and k are ignored is really subtle. $\endgroup$ Commented Nov 13, 2017 at 10:04

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.