Namespaces
Variants

std::partial_sum

От ru.cppreference.net
 
 
Библиотека алгоритмов
Ограниченные алгоритмы и алгоритмы для диапазонов (C++20)
Ограниченные алгоритмы, например ranges::copy, ranges::sort, ...
Немодифицирующие операции последовательностей    
Пакетные операции
(C++17)
Операции поиска
Модифицирующие операции последовательностей
Операции копирования
(C++11)
(C++11)
Операции обмена
Операции преобразования
Операции генерации
Операции удаления
Операции изменения порядка
(until C++17)(C++11)
(C++20)(C++20)
Операции выборки
(C++17)

Сортировка и связанные операции
Операции разделения
(C++11)    

Операции сортировки
Операции бинарного поиска
(на разделенных диапазонах)
Операции с множествами (на отсортированных диапазонах)
Операции слияния (на отсортированных диапазонах)
Операции с кучей
Операции минимума/максимума
(C++11)
(C++17)
Операции лексикографического сравнения
Операции перестановок


Политики выполнения (C++17)
(только для пояснения*)(C++26)

Числовые операции
(C++11)
(C++17)
(C++17)    

Специализированные <memory> алгоритмы

Специализированные <random> алгоритмы
Библиотека C









 
 
Определены в заголовке <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↑

8

См. также 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 acc был введен из-за разрешения LWG issue 539. Причина использования acc вместо прямого суммирования результатов (т.е. *(d_first + 2) = (*first + *(first + 1)) + *(first + 2);) заключается в том, что семантика последнего сбивает с толку, если следующие типы не совпадают:

  • тип значения InputIt
  • тип(ы), доступные для записи OutputIt
  • типы параметров operator+ или op
  • возвращаемый тип operator+ или op

acc 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>{});

Пример

#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

Отчеты о дефектах

Следующие отчеты о дефектах, изменяющие поведение, были применены ретроактивно к ранее опубликованным стандартам C++.

DR Применено к Поведение, опубликованное Корректное поведение
LWG 242 C++98 op op не мог иметь побочных эффектов он не может изменять задействованные диапазоны
LWG 539 C++98 отсутствовали требования к типам, необходимые для корректности вычислений и присваиваний результата
добавлены

См. также

вычисляет разности между соседними элементами в диапазоне
(шаблон функции)
суммирует или сворачивает диапазон элементов
(шаблон функции)
аналогичен std::partial_sum, включает i-й входной элемент в i-ю сумму
(шаблон функции)
аналогичен std::partial_sum, исключает i-й входной элемент из i-й суммы
(шаблон функции)