Namespaces
Variants

std::partial_sum

ja.cppreference.net より
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとレンジ上のアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy、 ranges::sort、 ...
ソートと関連操作
分割操作
(C++11)    

ソート操作
二分探索操作
(分割されたレンジ上で)
集合操作(ソート済みレンジ上で)
マージ操作(ソート済みレンジ上で)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作


 
 
ヘッダ <numeric>
template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first );
(1) (constexpr(C++20以降))
template< class InputIt, class OutputIt, class BinaryOp >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first, BinaryOp op );
(2) (constexpr(C++20以降))
1) もし [first, last) が空の場合は、何もしない。
そうでなければ、以下の操作を順に実行する:
  1. アキュムレータ acc を作成し、その型は 値型 の InputIt であり、それを *first で初期化する。
  2. acc を *d_first に代入する。
  3. i の各整数 [1, std::distance(first, last)) に対して、以下の操作を順に実行する:
a) acc + *iter(C++20まで)std::move(acc) + *iter(C++20以降) を計算する。ここで iter は i番目の のイテレータ first である。
b) 結果を acc に代入する。
c) acc[1] を *dest に代入する。ここで dest は i番目の のイテレータ d_first である。
2) (1) と同じだが、代わりに op(acc, *iter)(C++20まで)op(std::move(acc), *iter)(C++20以降) を計算する。

binary_op を実際の二項演算として:

  • 以下の条件のいずれかが満たされる場合、プログラムは不適格である:
  • InputIt の値型は *first から構築可能でない。
  • acc は 書き込み可能d_first に書き込み可能でない。
  • binary_op(acc, *iter)(C++20まで)binary_op(std::move(acc), *iter)(C++20以降) の結果は InputIt の値型に暗黙変換可能でない。
  • d_last をイテレータとして 返される、以下の条件のいずれかが満たされる場合、動作は未定義である:
  • binary_op は [first, last) または [d_first, d_last) の任意の要素を変更する。
  • binary_op は [first, last] または [d_first, d_last] 内の任意のイテレータまたは部分レンジを無効化する。


  1. ↑ 代入される実際の値は、前のステップでの代入の結果である。ここでは代入結果を acc と仮定する。

パラメータ

first, last - 合計する要素の範囲を定義するイテレータのペア
d_first - 宛先範囲の先頭。 first と等しくてもよい
op - 適用される二項演算関数オブジェクト。

関数のシグネチャは以下と同等であるべきです:

Ret fun ( const Type1 & a, const Type2 & b ) ;

シグネチャは const & を持つ必要はありません。
型 Type1 は、 std:: iterator_traits < InputIt > :: value_type のオブジェクトが Type1 に暗黙的に変換可能でなければなりません。型 Type2 は、 InputIt のオブジェクトが間接参照され、その後 Type2 に暗黙的に変換可能でなければなりません。型 Ret は、 InputIt のオブジェクトが間接参照され、型 Ret の値を代入可能でなければなりません。 ​

型要件
-
InputIt は LegacyInputIterator の要件を満たさなければなりません。
-
OutputIt は LegacyOutputIterator の要件を満たさなければなりません。

戻り値

書き込まれた最後の要素の次の要素を指すイテレータ、または d_first が返される( [ first , last ) が空の場合)。

計算量

与えられた N を std:: distance ( first, last ) として:

1) 正確に N-1 回の operator + の適用。
2) 厳密に N-1 回の二項関数 op の適用。

実装例

partial_sum (1)
template<class InputIt, class OutputIt>
constexpr // since C++20
OutputIt partial_sum(InputIt first, InputIt last, OutputIt d_first)
{
    if (first == last)
        return d_first;
    typename std::iterator_traits<InputIt>::value_type sum = *first;
    *d_first = sum;
    while (++first != last)
    {
        sum = std::move(sum) + *first; // std::move since C++20
        *++d_first = sum;
    }
    return ++d_first;
    // or, since C++14:
    // return std::partial_sum(first, last, d_first, std::plus<>());
}
partial_sum (2)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // since C++20
OutputIt partial_sum(InputIt first, InputIt last, 
                     OutputIt d_first, BinaryOp op)
{
    if (first == last)
        return d_first;
    typename std::iterator_traits<InputIt>::value_type acc = *first;
    *d_first = acc;
    while (++first != last)
    {
        acc = op(std::move(acc), *first); // std::move since C++20
        *++d_first = acc;
    }
    return ++d_first;
}

注記

acc は、 LWG issue 539 の解決により導入されました。 acc を使用する理由(すなわち、直接結果を合計する * ( d_first + 2 ) = ( * first + * ( first + 1 ) ) + * ( first + 2 ) ; の代わりに)は、以下の型が一致しない場合に後者の意味が曖昧になるためです:

  • InputItの値型
  • OutputItの書き込み可能な型
  • operator + または op のパラメータの型
  • operator + または op の戻り値の型

acc は、計算の各ステップで値を保存および提供する中間オブジェクトとして機能します:

  • その型は InputIt の値型である
  • それは d_first に書き込まれる
  • その値は operator + または op に渡される
  • それは operator + または op の戻り値を格納する
enum not_int { x = 1, y = 2 };
char i_array[4] = {100, 100, 100, 100};
not_int e_array[4] = {x, x, y, y};
int  o_array[4];
// OK: operator+(char, char)を使用し、char値をint配列に代入
std::partial_sum(i_array, i_array + 4, o_array);
// エラー: not_int値をint配列に代入できません
std::partial_sum(e_array, e_array + 4, o_array);
// OK: 必要時に変換を実行
// 1. 型char(値型)の「acc」を作成
// 2. char引数はlong乗算に使用(char -> long)
// 3. longの積が「acc」に代入(long -> char)
// 4. 「acc」が「o_array」の要素に代入(char -> int)
// 5. 入力範囲の残りの要素を処理するためステップ2に戻る
std::partial_sum(i_array, i_array + 4, o_array, std::multiplies<long>{});

例

#include <functional>
#include <iostream>
#include <iterator>
#include <numeric>
#include <vector>
int main()
{
    std::vector<int> v(10, 2); // v = {2, 2, 2, 2, 2, 2, 2, 2, 2, 2}
    std::cout << "最初の " << v.size() << " 個の偶数: ";
    // 結果をcoutストリームに出力
    std::partial_sum(v.cbegin(), v.cend(), 
                     std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    // 結果をベクトルvに書き戻す
    std::partial_sum(v.cbegin(), v.cend(),
                     v.begin(), std::multiplies<int>());
    std::cout << "最初の " << v.size() << " 個の2の累乗: ";
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

出力:

最初の 10 個の偶数: 2 4 6 8 10 12 14 16 18 20 
最初の 10 個の2の累乗: 2 4 8 16 32 64 128 256 512 1024

不具合報告

以下の動作変更の欠陥報告書は、以前に公開されたC++規格に対して遡及的に適用されました。

DR 適用対象 公開時の動作 正しい動作
LWG 242 C++98 op 副作用を持つことができなかった 関連する範囲を変更できない
LWG 539 C++98 結果の評価と代入が有効となるための
型要件が欠落していた
追加された

関連項目

範囲内の隣接する要素間の差分を計算する
(関数テンプレート)
範囲の要素を合計または畳み込む
(関数テンプレート)
std::partial_sum と類似しており、 i 番目 の入力要素を i 番目 の合計に含める
(関数テンプレート)
std::partial_sum と類似しており、 i 番目 の入力要素を i 番目 の合計から除外する
(関数テンプレート)