Namespaces
Variants

std:: partial_sum

From cppreference.net
Algorithm library
Constrained algorithms and algorithms on ranges (C++20)
Constrained algorithms, e.g. ranges::copy , ranges::sort , ...
Execution policies (C++17)
Non-modifying sequence operations
Batch operations
(C++17)
Search operations
Modifying sequence operations
Copy operations
(C++11)
(C++11)
Swap operations
Transformation operations
Generation operations
Removing operations
Order-changing operations
(until C++17) (C++11)
(C++20) (C++20)
Sampling operations
(C++17)

Sorting and related operations
Partitioning operations
Sorting operations
Binary search operations
(on partitioned ranges)
Set operations (on sorted ranges)
Merge operations (on sorted ranges)
Heap operations
Minimum/maximum operations
Lexicographical comparison operations
Permutation operations
C library
Numeric operations
Operations on uninitialized memory
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.
De lo contrario, realiza las siguientes operaciones en orden:
  1. Crea un acumulador acc , cuyo tipo es el value type 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 i ésimo iterador de first .
b) Asigna el resultado a acc .
c) Asigna acc [1] a * dest , donde dest es el siguiente i ésimo iterador de d_first .
2) Igual que (1) , pero calcula op ( acc, * iter ) (until C++20) op ( std :: move ( acc ) , * iter ) (since C++20) en su lugar.

Dado binary_op como la operación binaria real:

  • Si se satisface cualquiera de las siguientes condiciones, el programa está mal formado:
  • El tipo de valor de InputIt no es construible 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 es convertible implícitamente al tipo de valor de InputIt .
  • Dado d_last como el iterador a ser devuelto , si alguna de las siguientes condiciones se satisface, el comportamiento es indefinido:
  • 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 que se asignará es el resultado de la asignación en el paso anterior. Asumimos que el resultado de la asignación es acc aquí.

Contenidos

Parámetros

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

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 ser desreferenciado y luego convertido implícitamente a Type2 . El tipo Ret debe ser tal que un objeto de tipo InputIt pueda ser desreferenciado y asignado un valor de tipo Ret . ​

Requisitos de tipo
-
InputIt debe cumplir con los requisitos de LegacyInputIterator .
-
OutputIt debe cumplir con 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 del operator + .
2) Exactamente N-1 aplicaciones de la función binaria op .

Implementación posible

partial_sum (1)
template<class InputIt, class OutputIt>
constexpr // desde 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 desde C++20
        *++d_first = sum;
    }
    return ++d_first;
    // o, desde C++14:
    // return std::partial_sum(first, last, d_first, std::plus<>());
}
partial_sum (2)
template<class InputIt, class OutputIt, class BinaryOp>
constexpr // desde 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 desde C++20
        *++d_first = acc;
    }
    return ++d_first;
}

Notas

acc se introdujo 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 este último es confusa si los siguientes tipos no coinciden:

  • el tipo de valor de InputIt
  • el(los) tipo(s) escribible(s) 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];
// CORRECTO: utiliza operator+(char, char) y asigna valores char al array int
std::partial_sum(i_array, i_array + 4, o_array);
// ERROR: no se pueden asignar valores not_int al array int
std::partial_sum(e_array, e_array + 4, o_array);
// CORRECTO: realiza conversiones cuando es necesario
// 1. crea "acc" de tipo char (el tipo de valor)
// 2. los argumentos char se usan para multiplicación long (char -> long)
// 3. el producto long se asigna a "acc" (long -> char)
// 4. "acc" se asigna a un elemento de "o_array" (char -> int)
// 5. vuelve al paso 2 para procesar los elementos restantes en el rango de entrada
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 << "Los primeros " << v.size() << " números pares son: ";
    // escribir el resultado al flujo cout
    std::partial_sum(v.cbegin(), v.cend(), 
                     std::ostream_iterator<int>(std::cout, " "));
    std::cout << '\n';
    // escribir el resultado de vuelta al vector v
    std::partial_sum(v.cbegin(), v.cend(),
                     v.begin(), std::multiplies<int>());
    std::cout << "Las primeras " << v.size() << " potencias de 2 son: ";
    for (int n : v)
        std::cout << n << ' ';
    std::cout << '\n';
}

Salida:

Los primeros 10 números pares son: 2 4 6 8 10 12 14 16 18 20 
Las primeras 10 potencias de 2 son: 2 4 8 16 32 64 128 256 512 1024

Informes de defectos

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

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 de resultados y asignaciones fueran válidas
añadidos

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 i ésimo elemento de entrada en la i ésima suma
(plantilla de función)
similar a std::partial_sum , excluye el i ésimo elemento de entrada de la i ésima suma
(plantilla de función)