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)
}
概要
アンダーフローとオーバーフローが起きないようスケールされた、ベクトルの成分の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;
}
を定義すると、以下の式が成り立つように計算する。
$$ \verb|get_sum_of_squares(result)| = \sum_{i = 0}^{n - 1} |\verb|v[|i\verb|]||^2 + \verb|get_sum_of_squares(init)| $$
ただし、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;
}
出力
1.46361
1.46361
1.42361
1.42361
バージョン
言語
- C++26
処理系
- Clang: ??
- GCC: ??
- ICC: ??
- Visual C++: ??