2012-11-16 12 views
10

Esiste una buona implementazione dell'algoritmo per calcolare la convoluzione di due intervalli in C++ STL (o addirittura boost)? cioè qualcosa con il prototipo (convoluzione di due gamme a..b e c..d):C++ stl convolution

template< class Iterator > 
void convolution(Iterator a, Iterator b, Iterator c, Iterator d); 

che possono modificare a..b gamma

+0

Non è difficile scrivere uno che aggiunge a un terzo intervallo inizialmente riempito di zeri. Sul posto, non lo so. – aschepler

+0

Supponendo che questa sarà una convoluzione discreta in cui le gamme hanno la stessa lunghezza, scrivendo che non è troppo difficile - sarebbe abbastanza simile alla trasformazione. In effetti, potresti persino essere in grado di utilizzare la trasformazione per fare ciò con il terzo parametro che è un iteratore inverso. – Yuushi

risposta

1

Sì std :: trasformare

std::transform(a, b, c, a, Op); 

// a b is the the first input range 
// c is the start of the second range (which must be at least as large as (b-a) 
// 
// We then use a as the output iterator as well. 

// Op is a BinaryFunction 

Per rispondere il commento su come eseguire accumulo di stato nei commenti:

struct Operator 
{ 
    State& state; 
    Operator(Sate& state) : state(state) {} 
    Type operator()(TypeR1 const& r1Value, TypeR2 const& r2Value) const 
    { 
     Plop(state, r1Value, r2Value); 
     return Convolute(state, r2Value, r2Value); 
    } 
}; 
State theState = 0; 
Operator Op(theState); 
+3

Mi sembra che ciascuno degli algoritmi STL sia costituito da un singolo ciclo di qualche tipo. Pertanto, molto probabilmente, non solo un algoritmo STL può esprimere la soluzione del problema, ma la combinazione (vale a dire 'std :: inner_product' e' std :: transform') può. – Orient

+0

Non vedo come 'Op' possa accumulare tutti i termini di prodotto O (n^2) senza costruire internamente un grande contenitore temporaneo. –

+0

@j_random_hacker: È facile far funzionare Op funtore. –

2

Non sono abbastanza sicuro di cosa debba essere una "convoluzione" da due sequenze a una di queste due sequenze: sembra essere una comprensione diversa dalla mia comprensione. Di seguito è una versione di convolution utilizzando un numero variabile di iteratori. Poiché in questo momento sono solo troppo pigro, userò una nozione un po 'rara di passare l'iteratore di destinazione come prima discussione piuttosto che come ultima argomentazione. Ecco un'implementazione di un corrispondente zip() algoritmi:

#include <tuple> 

namespace algo 
{ 
    template <typename... T> 
    void dummy(T...) 
    { 
    } 

    template <typename To, typename InIt, typename... It> 
    To zip(To to, InIt it, InIt end, It... its) 
    { 
     for (; it != end; ++it, ++to) { 
      *to = std::make_tuple(*it, *its...); 
      algo::dummy(++its...); 
     } 
     return to; 
    } 
}  

Ecco un semplice programma di test ho usato per verificare che il precedente non quello che intendevo fare:

#include <deque> 
#include <iostream> 
#include <iterator> 
#include <list> 
#include <vector> 

enum class e { a = 'a', b = 'b', c = 'c' }; 

std::ostream& operator<< (std::ostream& out, 
          std::tuple<int, double, e> const& v) 
{ 
    return out << "[" 
       << std::get<0>(v) << ", " 
       << std::get<1>(v) << ", " 
       << char(std::get<2>(v)) << "]"; 
} 

int main() 
{ 
    typedef std::tuple<int, double, e> tuple; 
    std::vector<int> v{ 1, 2, 3 }; 
    std::deque<double> d{ 1.1, 2.2, 3.3 }; 
    std::list<e>  l{ e::a, e::b, e::c }; 
    std::vector<tuple> r; 

    algo::zip(std::back_inserter(r), v.begin(), v.end(), d.begin(), l.begin()); 

    std::copy(r.begin(), r.end(), 
       std::ostream_iterator<tuple>(std::cout, "\n")); 
}           
+0

Con un po 'più di codice template, puoi anche assicurarti che le lunghezze degli iteratori passati in modo variabile corrispondano, a patto di chiamare zip (OutIt, InIt, InItPack ...) e InItPack contiene coppie di argomenti (* not * std: : coppia ). Tuttavia, si tratta di circa 150 righe di codice, principalmente a causa dell'uso gratuito di modelli ricorsivi per le funzioni di supporto. – moshbear