名前空間
変種
操作

std::partial_sum

From cppreference.com
< cpp‎ | algorithm
 
 
アルゴリズムライブラリ
制約付きアルゴリズムとRangeアルゴリズム (C++20)
制約付きアルゴリズム、例: ranges::copy, ranges::sort, ...
実行ポリシー (C++17)
シーケンスを変更しない操作
一括操作
(C++17)
検索操作
(C++11)                (C++11)(C++11)

シーケンスを変更する操作
コピー操作
(C++11)
(C++11)
スワップ操作
変換操作
生成操作
削除操作
順序変更操作
(C++17まで)(C++11)
(C++20)(C++20)
サンプリング操作
(C++17)

ソートおよび関連操作
パーティション操作
ソート操作
二分探索操作
(パーティション化された範囲)
集合操作 (ソート済み範囲)
マージ操作 (ソート済み範囲)
ヒープ操作
最小/最大操作
(C++11)
(C++17)
辞書順比較操作
順列操作
Cライブラリ
数値演算
partial_sum
(C++17)   
未初期化メモリに対する操作
 
 
ヘッダー <numeric> で定義
template< class InputIt, class OutputIt >

OutputIt partial_sum( InputIt first, InputIt last,

                      OutputIt d_first );
(1) (C++20 以降 constexpr)
template< class InputIt, class OutputIt, class BinaryOp >

OutputIt partial_sum( InputIt first, InputIt last,

                      OutputIt d_first, BinaryOp op );
(2) (C++20 以降 constexpr)
1) [firstlast)が空の場合、何も行いません。
それ以外の場合は、以下の操作を順番に実行します。
  1. アキュムレータ acc を作成します。この型は InputIt値型 であり、*first で初期化されます。
  2. acc*d_first に代入します。
  3. [1std::distance(first, last)) の各整数 i について、以下の操作を順番に実行します。
a) iterfirst の次の i 番目のイテレータとして、acc + *iter(until C++20)std::move(acc) + *iter(since C++20) を計算します。
b) 結果を acc に代入します。
c) destd_first の次の i 番目のイテレータとして、acc[1]*dest に代入します。
2) (1) と同じですが、op(acc, *iter)(until C++20)op(std::move(acc), *iter)(since C++20) の代わりに、op(acc, *iter)(until C++20)op(std::move(acc), *iter)(since C++20) を計算します。

実際のバイナリ操作として binary_op が与えられた場合

  • 以下のいずれかの条件が満たされる場合、プログラムは不適格です。
  • InputIt の値型は *first から構築できません。
  • accd_first書き込み可能 ではありません。
  • binary_op(acc, *iter)(until C++20)binary_op(std::move(acc), *iter)(since C++20) の結果は、InputIt の値型に暗黙的に変換可能ではありません。
  • 返される d_last を、以下のいずれかの条件が満たされた場合、動作は未定義です。
  • binary_op は、[firstlast) または [d_firstd_last) のいずれかの要素を変更します。
  • binary_op は、[firstlast] または [d_firstd_last] のいずれかのイテレータまたはサブ範囲を無効にします。


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

目次

[編集] Parameters

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 の値を代入可能でなければなりません。

型要件
-
InputItLegacyInputIterator の要件を満たす必要があります。
-
OutputItLegacyOutputIterator の要件を満たさなければなりません。

[編集] Return value

書き込まれた最後の要素の次の要素を指すイテレータ。ただし、[firstlast) が空の場合は d_first を返します。

[編集] Complexity

std::distance(first, last)N とする

1) N-1 回の operator+ の適用。
2) 二項関数 opN-1 回の適用。

[編集] Possible implementation

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;
}

[編集] Notes

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

  • 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: uses operator+(char, char) and assigns char values to int array
std::partial_sum(i_array, i_array + 4, o_array);
 
// Error: cannot assign not_int values to int array
std::partial_sum(e_array, e_array + 4, o_array);
 
// OK: performs conversions when needed
// 1. creates “acc” of type char (the value type)
// 2. the char arguments are used for long multiplication (char -> long)
// 3. the long product is assigned to “acc” (long -> char)
// 4. “acc” is assigned to an element of “o_array” (char -> int)
// 5. go back to step 2 to process the remaining elements in the input range
std::partial_sum(i_array, i_array + 4, o_array, std::multiplies<long>{});

[編集] Example

#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 << "The first " << v.size() << " even numbers are: ";
    // write the result to the cout stream
    std::partial_sum(v.cbegin(), v.cend(), 
                     std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
 
    // write the result back to the vector v
    std::partial_sum(v.cbegin(), v.cend(),
                     v.begin(), std::multiplies<int>());
 
    std::cout << "The first " << v.size() << " powers of 2 are: ";
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

出力

The first 10 even numbers are: 2 4 6 8 10 12 14 16 18 20 
The first 10 powers of 2 are: 2 4 8 16 32 64 128 256 512 1024

[編集] Defect reports

以下の動作変更を伴う欠陥報告が、以前に公開されたC++標準に遡って適用されました。

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

[編集] See also

範囲内の隣接する要素間の差を計算する
(関数テンプレート) [編集]
範囲の要素を合計または畳み込む
(関数テンプレート) [編集]
std::partial_sum と同様で、i 番目の入力要素を i 番目の合計に含めます。
(関数テンプレート) [編集]
std::partial_sum と同様で、i 番目の入力要素を i 番目の合計から除外します。
(関数テンプレート) [編集]
English 日本語 中文(简体) 中文(繁體)