C++ STL (またはブースト) で 2 つの範囲の畳み込みを計算するためのアルゴリズムの優れた実装はありますか? つまり、プロトタイプを持つもの (2 つの範囲a..b
との畳み込みc..d
):
template< class Iterator >
void convolution(Iterator a, Iterator b, Iterator c, Iterator d);
a..b
範囲を変更する
C++ STL (またはブースト) で 2 つの範囲の畳み込みを計算するためのアルゴリズムの優れた実装はありますか? つまり、プロトタイプを持つもの (2 つの範囲a..b
との畳み込みc..d
):
template< class Iterator >
void convolution(Iterator a, Iterator b, Iterator c, Iterator d);
a..b
範囲を変更する
2 つのシーケンスからこれら 2 つのシーケンスの 1 つへの「畳み込み」がどうあるべきかよくわかりません。それは私の理解とは異なる理解のようです。以下は、可変数の反復子を使用した畳み込みのバージョンです。私は今のところ怠惰すぎるので、最後の引数としてではなく最初の引数として宛先イテレータを渡すというやや珍しい概念を使用します。zip()
対応するアルゴリズムの実装を次に示します。
#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;
}
}
以下は、上記が意図したとおりに動作することを確認するために使用した簡単なテスト プログラムです。
#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"));
}
はい std::transform
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
コメントで状態の蓄積を実行する方法に関するコメントに答えるには:
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);