Namespaces
Variants

std::partial_sum

De es.cppreference.net
 
 
Biblioteca de algoritmos
Algoritmos restringidos y algoritmos sobre rangos (C++20)
Algoritmos restringidos, p.ej. ranges::copy, ranges::sort, ...
Operaciones de secuencia no modificadoras    
Operaciones por lotes
(C++17)
Operaciones de búsqueda
Operaciones de secuencia modificadoras
Operaciones de copia
(C++11)
(C++11)
Operaciones de intercambio
Operaciones de transformación
Operaciones de generación
Operaciones de eliminación
Operaciones de cambio de orden
(hasta C++17)(C++11)
(C++20)(C++20)
Operaciones de muestreo
(C++17)

Operaciones de ordenación y relacionadas
Operaciones de particionamiento
(C++11)    

Operaciones de ordenación
Operaciones de búsqueda binaria
(en rangos particionados)
Operaciones de conjunto (en rangos ordenados)
Operaciones de fusión (en rangos ordenados)
Operaciones de montículo
Operaciones de mínimo/máximo
(C++11)
(C++17)
Operaciones de comparación lexicográfica
Operaciones de permutación


 
 
Definido en el encabezado <numeric>
template< class InputIt, class OutputIt >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first );
(1) (constexpr desde C++20)
template< class InputIt, class OutputIt, class BinaryOp >
OutputIt partial_sum( InputIt first, InputIt last,
                      OutputIt d_first, BinaryOp op );
(2) (constexpr desde C++20)
1) Si [first, last) está vacío, no hace nada.
En caso contrario, realiza las siguientes operaciones en orden:
  1. Crea un acumulador acc, cuyo tipo es el tipo de valor de InputIt, y lo inicializa con *first.
  2. Asigna acc a *d_first.
  3. Para cada entero i en [1, std::distance(first, last)), realiza las siguientes operaciones en orden:
a) Calcula acc + *iter(hasta C++20)std::move(acc) + *iter(desde C++20), donde iter es el siguiente iterador i-ésimo de first.
b) Asigna el resultado a acc.
c) Asigna acc[1] a *dest, donde dest es el siguiente iterador i-ésimo de d_first.
2) Igual que (1), pero calcula op(acc, *iter)(hasta C++20)op(std::move(acc), *iter)(desde C++20) en su lugar.

Dado binary_op como la operación binaria real:

  • Si se cumple alguna de las siguientes condiciones, el programa está mal formado:
  • El tipo de valor de InputIt no se puede construir desde *first.
  • acc no es escribible en d_first.
  • El resultado de binary_op(acc, *iter)(hasta C++20)binary_op(std::move(acc), *iter)(desde C++20) no se puede convertir implícitamente al tipo de valor de InputIt.
  • Dado d_last como el iterador a devolver, si se cumple alguna de las siguientes condiciones, el comportamiento no está definido:
  • binary_op modifica cualquier elemento de [first, last) o [d_first, d_last).
  • binary_op invalida cualquier iterador o subrango en [first, last] o [d_first, d_last].


  1. ↑ El valor real a asignar es el resultado de la asignación en el paso anterior. Suponemos que el resultado de la asignación es acc aquí.

Parámetros

first, last - el par de iteradores que definen el rango de elementos a sumar
d_first - el inicio del rango de destino; puede ser igual a first
op - objeto función de operación binaria que se aplicará.

La firma de la función debe ser equivalente a la siguiente:

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

La firma no necesita tener const &.
El tipo Type1 debe ser tal que un objeto de tipo std::iterator_traits<InputIt>::value_type pueda convertirse implícitamente a Type1. El tipo Type2 debe ser tal que un objeto de tipo InputIt pueda desreferenciarse y luego convertirse implícitamente a Type2. El tipo Ret debe ser tal que un objeto de tipo InputIt pueda desreferenciarse y asignarse un valor de tipo Ret. ​

Requisitos de tipo
-
InputIt debe cumplir los requisitos de LegacyInputIterator.
-
OutputIt debe cumplir los requisitos de LegacyOutputIterator.

Valor de retorno

Iterador al elemento después del último elemento escrito, o d_first si [first, last) está vacío.

Complejidad

Dado N como std::distance(first, last):

1) Exactamente N-1 aplicaciones de operator+.
2) Exactamente N-1 aplicaciones de la función binaria op.

Posible implementación

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

Notas

acc fue introducido debido a la resolución de LWG issue 539. La razón de usar acc en lugar de sumar directamente los resultados (es decir, *(d_first + 2) = (*first + *(first + 1)) + *(first + 2);) es porque la semántica de esto último es confusa si los siguientes tipos no coinciden:

  • el tipo de valor de InputIt
  • el tipo o tipos escribibles de OutputIt
  • los tipos de los parámetros de operator+ o op
  • el tipo de retorno de operator+ o op

acc sirve como el objeto intermedio para almacenar y proporcionar los valores para cada paso del cálculo:

  • su tipo es el tipo de valor de InputIt
  • se escribe en d_first
  • su valor se pasa a operator+ o op
  • almacena el valor de retorno de operator+ o 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>{});

Ejemplo

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

Salida:

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

Informes de defectos

Los siguientes informes de defectos que cambian el comportamiento se aplicaron retroactivamente a los estándares C++ previamente publicados.

DR Aplicado a Comportamiento publicado Comportamiento correcto
LWG 242 C++98 op no podía tener efectos secundarios no puede modificar los rangos involucrados
LWG 539 C++98 faltaban los requisitos de tipo necesarios para que las evaluaciones y asignaciones fueran válidas
evaluaciones y asignaciones a ser válidas faltaban
añadido

Véase también

calcula las diferencias entre elementos adyacentes en un rango
(plantilla de función)
suma o pliega un rango de elementos
(plantilla de función)
similar a std::partial_sum, incluye el elemento de entrada i-ésimo en la suma i-ésima
(plantilla de función)
similar a std::partial_sum, excluye el elemento de entrada i-ésimo de la suma i-ésima
(plantilla de función)