- [mathjax enable]
- linalg[meta header]
- function template[meta id-type]
- std::linalg[meta namespace]
- cpp26[meta cpp]
namespace std::linalg {
template<in-vector InVec, class Scalar>
sum_of_squares_result<Scalar> vector_sum_of_squares(
InVec v,
sum_of_squares_result<Scalar> init); // (1)
template<class ExecutionPolicy,
in-vector InVec,
class Scalar>
sum_of_squares_result<Scalar> vector_sum_of_squares(
ExecutionPolicy&& exec,
InVec v,
sum_of_squares_result<Scalar> init); // (2)
}
- in-vector[link inout-vector.md]
- sum_of_squares_result[link sum_of_squares_result.md]
アンダーフローとオーバーフローが起きないようスケールされた、ベクトルの成分の2乗和を計算する。すなわち、戻り値をresult
とし、説明用の関数
template<class Scalar>
Scalar get_sum_of_squares(sum_of_squares_result<Scalar> result) {
return std::pow(result.scaling_factor, 2) * result.scaled_sum_of_squares;
}
- sum_of_squares_result[link sum_of_squares_result.md]
を定義すると、以下の式が成り立つように計算する。
ただし、n
はv
の次元である。
- (1), (2):
decltype(
abs-if-needed
(declval<typename InVec::value_type>()))
がScalar
に変換可能。 - (2):
is_execution_policy
<ExecutionPolicy>::value
がtrue
- (1): 以下の条件を満たす
sum_of_squares_result
<Scalar>
型の値result
を返す。-
result.scaling_factor
がinit.scaling_factor
と$\max_{i = 0, \dots, n - 1}|\verb|v[|i\verb|]||$の最大値。ただし、n
はv
の次元である。 - 概要に記載した式を満たす。
-
- (2): (1)の並列アルゴリズム版。
sum_of_squares_result
<Scalar>
init.scaled_sum_of_squares
は0以上でなければならない。- もし
InVec::value_type
とScalar
がどちらも浮動小数点数型またはstd::complex
の特殊化で、Scalar
がInVec::value_type
より精度が高い場合、和の各項はScalar
またはより高い精度の型が使われる。
[注意] 処理系にあるコンパイラで確認していないため、間違っているかもしれません。
#include <array>
#include <cmath>
#include <execution>
#include <iostream>
#include <linalg>
#include <mdspan>
template<class Scalar>
Scalar get_sum_of_squares(std::linalg::sum_of_squares_result<Scalar> result) {
return std::pow(result.scaling_factor, 2) * result.scaled_sum_of_squares;
}
int main()
{
constexpr size_t N = 4;
std::array<double, N> vec;
std::mdspan v(vec.data(), N);
for(int i = 0; i < v.extent(0); ++i) {
v[i] = std::pow(-1.0, i) / (i + 1);
}
auto init = std::linalg::sum_of_squares_result<double>{.scaling_factor = 1.0 / 5,
.scaled_sum_of_squares = 1.0};
std::cout << get_sum_of_squares(
std::linalg::vector_sum_of_squares(v, init)) // (1)
<< get_sum_of_squares(
std::linalg::vector_sum_of_squares(std::execution::par, v, init)) << '\n' // (2)
<< get_sum_of_squares(
std::linalg::vector_sum_of_squares(v)) << '\n' // (3)
<< get_sum_of_squares(
std::linalg::vector_sum_of_squares(std::execution::par, v)) << '\n'; // (4)
return 0;
}
- std::linalg::vector_sum_of_squares[color ff0000]
- std::linalg::sum_of_squares_result[link sum_of_squares_result.md]
1.46361
1.46361
1.42361
1.42361
- C++26
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??