最終更新日時(UTC):
が更新

履歴 編集

function template
<linalg>

std::linalg::apply_givens_rotation(C++26)

namespace std::linalg {
  template<inout-vector InOutVec1,
          inout-vector InOutVec2,
          class Real>
  void apply_givens_rotation(
    InOutVec1 x,
    InOutVec2 y,
    Real c,
    Real s);          // (1)

  template<class ExecutionPolicy,
          inout-vector InOutVec1,
          inout-vector InOutVec2,
          class Real>
  void apply_givens_rotation(
    ExecutionPolicy&& exec,
    InOutVec1 x,
    InOutVec2 y,
    Real c,
    Real s);          // (2)

  template<inout-vector InOutVec1,
          inout-vector InOutVec2,
          class Real>
  void apply_givens_rotation(
    InOutVec1 x,
    InOutVec2 y,
    Real c,
    complex<Real> s); // (3)

  template<class ExecutionPolicy,
          inout-vector InOutVec1,
          inout-vector InOutVec2,
          class Real>
  void apply_givens_rotation(
    ExecutionPolicy&& exec,
    InOutVec1 x,
    InOutVec2 y,
    Real c,
    complex<Real> s); // (4)
}

概要

csで指定された回転行列を2つのベクトルxyに対して、次のように掛けて代入する。 $$ \begin{pmatrix} \mathbf{x} \\ \mathbf{y} \end{pmatrix} \leftarrow \begin{pmatrix} c & s\\ -\overline{s} & c \end{pmatrix} \begin{pmatrix} \mathbf{x} \\ \mathbf{y} \end{pmatrix} $$

適格要件

事前条件

  • x.extent(0) == y.extent(0)
  • $c^2 + |s|^2 = 1$

効果

csで指定された回転を行ベクトルxyがこの順に隣り合うとして行う。

  • (1): 実回転行列に対して逐次実行する。
  • (2): 実回転行列に対して、指定された実行ポリシーに応じて実行する。
  • (3): sが複素数の回転行列に対して逐次実行する。
  • (4): sが複素数の回転行列に対して、指定された実行ポリシーに応じて実行する。

戻り値

なし

[注意] 処理系にあるコンパイラで確認していないため、間違っているかもしれません。

#include <cmath>
#include <complex>
#include <initializer_list>
#include <execution>
#include <iostream>
#include <linalg>
#include <mdspan>
#include <vector>

template <class Vector>
void print(Vector v) {
  for (int i = 0; i < v.extent(0) - 1; ++i) {
    std::cout << v[i] << ", ";
  }
  std::cout << v[v.extent(0) - 1] << std::endl;
}

int main()
{
  constexpr size_t N = 2;

  using Complex = std::complex<double>;

  {
    std::initializer_list<double> a_coeff = {1, std::sqrt(3.0)};
    std::initializer_list<double> b_coeff = {std::sqrt(3.0), -0.5};

    std::vector<double> a_vec(a_coeff);
    std::mdspan a(a_vec.data(), N);

    std::vector<double> b_vec(b_coeff);
    std::mdspan b(b_vec.data(), N);

    double c = 0.5;
    double s = -std::sqrt(3.0) / 2;

    // (1)
    std::linalg::apply_givens_rotation(a, b, c, s);
    print(a);
    print(b);

    // (2)
    // aとbを初期化
    a_vec = a_coeff;
    b_vec = b_coeff;
    std::linalg::apply_givens_rotation(std::execution::par, a, b, c, s);
    print(a);
    print(b);
  }

  {
    std::initializer_list<Complex> a_coeff = {Complex{1, 0}, Complex{std::sqrt(3.0), 0}};
    std::initializer_list<Complex> b_coeff = {Complex{0, std::sqrt(3.0)}, Complex{0, -0.5}};

    std::vector<Complex> a_vec(a_coeff);
    std::mdspan a(a_vec.data(), N);

    std::vector<Complex> b_vec(b_coeff);
    std::mdspan b(b_vec.data(), N);

    double  c = 0.5;
    Complex s = Complex{0, -std::sqrt(3.0) / 2};

    // (3)
    std::linalg::apply_givens_rotation(a, b, c, s);
    print(a);
    print(b);

    // (4)
    // aとbを初期化
    a_vec = a_coeff;
    b_vec = b_coeff;
    std::linalg::apply_givens_rotation(std::execution::par, a, b, c, s);
    print(a);
    print(b);
  }

  return 0;
}

出力

(1)
1, 0
0, -1
(2)
1, 0
0, -1
(3)
(1,0), (0,0)
(0,0), (0,-1)
(4)
(1,0), (0,0)
(0,0), (0,-1)

バージョン

言語

  • C++26

処理系

関連項目

参照