Namensräume
Varianten
Aktionen

std::inner_product

Von cppreference.com
< cpp‎ | algorithm
 
 
Algorithmenbibliothek
Beschränkte Algorithmen und Algorithmen für Bereiche (C++20)
Beschränkte Algorithmen, z.B. ranges::copy, ranges::sort, ...
Ausführungsrichtlinien (C++17)
Nicht-modifizierende Sequenzoperationen
Stapeloperationen
(C++17)
Suchoperationen
(C++11)                (C++11)(C++11)

Modifizierende Sequenzoperationen
Kopieroperationen
(C++11)
(C++11)
Tauschoperationen
Transformationsoperationen
Generierungsoperationen
Entfernungsoperationen
Ordnungsändernde Operationen
(bis C++17)(C++11)
(C++20)(C++20)
Stichprobenoperationen
(C++17)

Sortier- und verwandte Operationen
Partitionierungsoperationen
Sortieroperationen
Binäre Suchoperationen
(auf partitionierten Bereichen)
Mengenoperationen (auf sortierten Bereichen)
Zusammenführungsoperationen (auf sortierten Bereichen)
Heapoperationen
Minimum/Maximum-Operationen
(C++11)
(C++17)
Lexikographische Vergleichsoperationen
Permutationsoperationen
C-Bibliothek
Numerische Operationen
(C++11)
inner_product
Operationen auf uninitialisiertem Speicher
 
 
Definiert in der Header-Datei <numeric>
template< class InputIt1, class InputIt2, class T >

T inner_product( InputIt1 first1, InputIt1 last1,

                 InputIt2 first2, T init );
(1) (constexpr seit C++20)
template< class InputIt1, class InputIt2, class T,

          class BinaryOp1, class BinaryOp2 >
T inner_product( InputIt1 first1, InputIt1 last1,
                 InputIt2 first2, T init,

                 BinaryOp1 op1, BinaryOp2 op2 );
(2) (constexpr seit C++20)

Berechnet das Skalarprodukt (d.h. die Summe der Produkte) oder führt eine geordnete Map/Reduce-Operation für den Bereich [first1last1) und den Bereich von std::distance(first1, last1) Elementen beginnend bei first2.

1) Initialisiert den Akkumulator acc (vom Typ T) mit dem Anfangswert init und modifiziert ihn dann mit dem Ausdruck acc = acc + (*i1) * (*i2)(until C++20)acc = std::move(acc) + (*i1) * (*i2)(since C++20) für jeden Iterator i1 im Bereich [first1last1) in Ordnung und seinen entsprechenden Iterator i2 im Bereich beginnend bei first2. Für die eingebaute Bedeutung von + und *, berechnet dies das Skalarprodukt der beiden Bereiche.
2) Initialisiert den Akkumulator acc (vom Typ T) mit dem Anfangswert init und modifiziert ihn dann mit dem Ausdruck acc = op1(acc, op2(*i1, *i2))(until C++20)acc = op1(std::move(acc), op2(*i1, *i2))(since C++20) für jeden Iterator i1 im Bereich [first1last1) in Ordnung und seinen entsprechenden Iterator i2 im Bereich beginnend bei first2.

Gegeben last2 als den std::distance(first1, last1)ten nächsten Iterator von first2, ist das Verhalten undefiniert, wenn eine der folgenden Bedingungen erfüllt ist

  • T ist nicht CopyConstructible.
  • T ist nicht CopyAssignable.
  • op1 oder op2 modifizieren ein Element von [first1last1) oder [first2last2).
  • op1 oder op2 machen einen Iterator oder Teilbereich in [first1last1] oder [first2last2] ungültig.

Inhalt

[edit] Parameter

first1, last1 - das Iteratorenpaar, das den Bereich von Elementen definiert, die
first2 - der Anfang des zweiten Bereichs von Elementen
init - Anfangswert der Summe der Produkte
op1 - binäres Operationsfunktions-Objekt, das angewendet wird. Diese "Summen"-Funktion nimmt einen Rückgabewert von op2 und den aktuellen Wert des Akkumulators entgegen und erzeugt einen neuen Wert, der im Akkumulator gespeichert wird.

Die Signatur der Funktion sollte äquivalent zu folgender sein:

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

Die Signatur muss nicht const & haben.
Die Typen  Type1 und  Type2 müssen so beschaffen sein, dass Objekte der Typen T und Type3 implizit in  Type1 bzw.  Type2 konvertiert werden können. Der Typ Ret muss so beschaffen sein, dass einem Objekt vom Typ T ein Wert vom Typ Ret zugewiesen werden kann.

op2 - binäres Operationsfunktions-Objekt, das angewendet wird. Diese "Produkt"-Funktion nimmt einen Wert aus jedem Bereich und erzeugt einen neuen Wert.

Die Signatur der Funktion sollte äquivalent zu folgender sein:

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

Die Signatur muss nicht const & haben.
Die Typen  Type1 und  Type2 müssen so beschaffen sein, dass Objekte der Typen InputIt1 und InputIt2 dereferenziert und dann implizit in  Type1 bzw.  Type2 konvertiert werden können. Der Typ Ret muss so beschaffen sein, dass einem Objekt vom Typ Type3 ein Wert vom Typ Ret zugewiesen werden kann.

Typanforderungen
-
InputIt1, InputIt2 müssen die Anforderungen an LegacyInputIterator erfüllen.

[edit] Rückgabewert

acc nach allen Modifikationen.

[edit] Mögliche Implementierung

inner_product (1)
template<class InputIt1, class InputIt2, class T>
constexpr // since C++20
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init)
{
    while (first1 != last1)
    {
        init = std::move(init) + (*first1) * (*first2); // std::move since C++20
        ++first1;
        ++first2;
    }
 
    return init;
}
inner_product (2)
template<class InputIt1, class InputIt2, class T,
         class BinaryOp1, class BinaryOp2>
constexpr // since C++20
T inner_product(InputIt1 first1, InputIt1 last1, InputIt2 first2, T init,
                BinaryOp1 op1, BinaryOp2 op2)
{
    while (first1 != last1)
    {
        init = op1(std::move(init), op2(*first1, *first2)); // std::move since C++20
        ++first1;
        ++first2;
    }
 
    return init;
}

[edit] Anmerkungen

Die parallelisierbare Version dieses Algorithmus, std::transform_reduce, erfordert, dass op1 und op2 kommutativ und assoziativ sind, aber std::inner_product stellt keine solchen Anforderungen und führt die Operationen immer in der angegebenen Reihenfolge aus.

[edit] Beispiel

#include <functional>
#include <iostream>
#include <numeric>
#include <vector>
 
int main()
{
    std::vector<int> a{0, 1, 2, 3, 4};
    std::vector<int> b{5, 4, 2, 3, 1};
 
    int r1 = std::inner_product(a.begin(), a.end(), b.begin(), 0);
    std::cout << "Inner product of a and b: " << r1 << '\n';
 
    int r2 = std::inner_product(a.begin(), a.end(), b.begin(), 0,
                                std::plus<>(), std::equal_to<>());
    std::cout << "Number of pairwise matches between a and b: " <<  r2 << '\n';
}

Ausgabe

Inner product of a and b: 21
Number of pairwise matches between a and b: 2

[edit] Fehlermeldungen

Die folgenden Verhaltensändernden Fehlerberichte wurden rückwirkend auf zuvor veröffentlichte C++-Standards angewendet.

DR angewendet auf Verhalten wie veröffentlicht Korrigiertes Verhalten
LWG 242 C++98 op1 und op2 könnten keine Nebeneffekte haben sie können die beteiligten Bereiche nicht modifizieren

[edit] Siehe auch

wendet eine aufrufbare Funktion an und reduziert dann nicht-sequenziell
(Funktionstemplate) [bearbeiten]
summiert oder faltet eine Reihe von Elementen
(Funktionstemplate) [bearbeiten]
berechnet die partielle Summe einer Elementreihe
(Funktionstemplate) [bearbeiten]