# Define a Givens rotation (or Jacobi rotation) matrix of size M

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.

• {{Sin[w], Cos[w]}, {Cos[w], -Sin[w]}} is not a rotation matrix, since its determinant is not 1. – J. M.'s ennui Nov 13 '17 at 9:29

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}]]


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.

• 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}]] – J. M.'s ennui Nov 13 '17 at 9:52
• @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. – Henrik Schumacher Nov 13 '17 at 10:04