KokkosBatched::Rotm

Defined in header: KokkosBatched_Rotm.hpp

struct SerialRotm {
  template <typename XViewType, typename YViewType, typename ParamViewType>
  KOKKOS_INLINE_FUNCTION static int invoke(const XViewType &x, const YViewType &y, const ParamViewType &param);
};

template <typename MemberType>
struct TeamRotm {
  template <typename XViewType, typename YViewType, typename ParamViewType>
  KOKKOS_INLINE_FUNCTION static int invoke(const MemberType &member, const XViewType &x, const YViewType &y,
                                           const ParamViewType &param);
};

template <typename MemberType>
struct TeamVectorRotm {
  template <typename XViewType, typename YViewType, typename ParamViewType>
  KOKKOS_INLINE_FUNCTION static int invoke(const MemberType &member, const XViewType &x, const YViewType &y,
                                           const ParamViewType &param);
};

Applies the modified Givens transformation

\[\begin{split}H = \begin{bmatrix} h_{11} & h_{12} \\ h_{21} & h_{22} \end{bmatrix}\end{split}\]

to vectors \(x\) and \(y\):

\[\begin{split}\begin{align} x(i) &= h_{11} \times x(i) + h_{12} \times y(i) \\ y(i) &= h_{21} \times x(i) + h_{22} \times y(i) \end{align}\end{split}\]

This operation is equivalent to the BLAS routine SROTM or DROTM for single or double precision. A \(flag\) and matrix H are stored in a 5-element vector \(param\) as follows:

\[\begin{split}\begin{align} param(0) &= flag \\ param(1) &= h_{11} \\ param(2) &= h_{21} \\ param(3) &= h_{12} \\ param(4) &= h_{22} \end{align}\end{split}\]

where \(flag\) is a scalar that indicates the form of the rotation matrix H. The value of \(flag\) can be -1, 0, 1, or -2, which corresponds to the following forms of H:

\(flag == -1\)

\(flag == 0\)

\(flag == 1\)

\(flag == -2\)

\(\begin{bmatrix} h_{11} & h_{12} \\ h_{21} & h_{22} \end{bmatrix}\)

\(\begin{bmatrix} 1.0 & h_{12} \\ h_{21} & 1.0 \end{bmatrix}\)

\(\begin{bmatrix} h_{11} & 1.0 \\ -1.0 & h_{22} \end{bmatrix}\)

\(\begin{bmatrix} 1.0 & 0.0 \\ 0.0 & 1.0 \end{bmatrix}\)

Note

This function does not support complex data types since the modified Givens rotation is not defined for complex numbers.

Parameters

x:

On input, \(x\) is a length \(n\) vector. On output, \(x\) is overwritten by the rotated vector.

y:

On input, \(y\) is a length \(n\) vector. On output, \(y\) is overwritten by the rotated vector.

param:

A length 5 vector, a rank 1 view, containing the parameters of the modified Givens rotation. The first element of \(param\) is a flag that indicates the form of the rotation matrix H, and the remaining four elements are the entries of the rotation matrix H.

Type Requirements

  • MemberType must be a Kokkos team member handle (only for TeamRotm and TeamVectorRotm).

  • XViewType must be a Kokkos View of rank 1 containing a vector \(X\) that satisfies:

    • std::is_same_v<typename XViewType::non_const_value_type, typename XViewType::value_type> == true

    • !KokkosKernels::ArithTraits<typename XViewType::value_type>::is_complex

  • YViewType must be a Kokkos View of rank 1 containing a vector \(Y\) that satisfies:

    • std::is_same_v<typename YViewType::non_const_value_type, typename YViewType::value_type> == true

    • !KokkosKernels::ArithTraits<typename YViewType::value_type>::is_complex

  • ParamViewType must be a Kokkos View of rank 1 containing a vector \(param\) that satisfies:

    • !KokkosKernels::ArithTraits<typename ParamViewType::value_type>::is_complex

Example

 1#include <iostream>
 2#include <Kokkos_Core.hpp>
 3#include <KokkosBatched_Rotm.hpp>
 4#include <KokkosBatched_Rotmg.hpp>
 5
 6using ExecutionSpace = Kokkos::DefaultExecutionSpace;
 7
 8/// \brief Example of batched rotm and rotmg
 9/// rotmg constructs the modified Givens rotation matrix H which eliminates the second component of a 2-vector [d1, d2]
10/// and applies the rotation to a 2-vector [x1, y1].
11/// Then apply the rotation to vectors X and Y:
12/// [[X'],  = H  * [[X],
13///  [Y']]          [Y]]
14///
15/// Usage example:
16/// d1 = 1.0, d2 = 1.0, x1 = 3.0, y1 = 4.0
17/// X = [3, 3, 3], Y = [4, 4, 4]
18/// X' = [6.25, 6.25, 6.25], Y' = [0, 0, 0]
19///
20int main(int /*argc*/, char** /*argv*/) {
21  Kokkos::initialize();
22  {
23    using View1DType = Kokkos::View<double*, ExecutionSpace>;
24    using View2DType = Kokkos::View<double**, ExecutionSpace>;
25    const int Nb = 10, n = 3;
26
27    // Values d1 and d2 we want to rotate
28    View1DType d1("d1", Nb), d2("d2", Nb), x1("x1", Nb), y1("y1", Nb);
29
30    // Vector X and Y of the rot/rotg operation
31    View2DType param("param", Nb, 5);
32    View2DType X("X", Nb, n), Y("Y", Nb, n);
33
34    // Initialize d1, d2, X and Y
35    const double a = 3.0, b = 4.0;
36    Kokkos::deep_copy(d1, 1.0);
37    Kokkos::deep_copy(d2, 1.0);
38    Kokkos::deep_copy(x1, a);
39    Kokkos::deep_copy(y1, b);
40    Kokkos::deep_copy(X, a);
41    Kokkos::deep_copy(Y, b);
42
43    // Compute a modified Givens rotation coefficients and apply the rotation to X and Y
44    ExecutionSpace exec;
45    using policy_type = Kokkos::RangePolicy<ExecutionSpace, Kokkos::IndexType<int>>;
46    policy_type policy{exec, 0, Nb};
47    Kokkos::parallel_for(
48        "rotm/rotmg", policy, KOKKOS_LAMBDA(int ib) {
49          auto sub_d1    = Kokkos::subview(d1, ib);
50          auto sub_d2    = Kokkos::subview(d2, ib);
51          auto sub_x1    = Kokkos::subview(x1, ib);
52          auto sub_y1    = Kokkos::subview(y1, ib);
53          auto sub_param = Kokkos::subview(param, ib, Kokkos::ALL());
54          KokkosBatched::Rotmg::invoke(sub_d1, sub_d2, sub_x1, sub_y1, sub_param);
55
56          auto sub_X = Kokkos::subview(X, ib, Kokkos::ALL());
57          auto sub_Y = Kokkos::subview(Y, ib, Kokkos::ALL());
58          KokkosBatched::SerialRotm::invoke(sub_X, sub_Y, sub_param);
59        });
60
61    // Confirm that the results are correct
62    auto h_X     = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, X);
63    auto h_Y     = Kokkos::create_mirror_view_and_copy(Kokkos::HostSpace{}, Y);
64    bool correct = true;
65    double eps   = 1.0e-12;
66    for (int ib = 0; ib < Nb; ib++) {
67      for (int j = 0; j < n; j++) {
68        if (Kokkos::abs(h_X(ib, j) - 6.25) > eps) correct = false;
69        if (Kokkos::abs(h_Y(ib, j)) > eps) correct = false;
70      }
71    }
72
73    if (correct) {
74      std::cout << "rotm/rotmg works correctly!" << std::endl;
75    }
76  }
77  Kokkos::finalize();
78}

output:

rotm/rotmg works correctly!