私はいくつかの解決策をテストしました、そしてそれは次のようです:
- 古き良き「forループ」が最速です
- ビットセットはdynamic_bitsetよりもはるかに高速です(当然のことながら)。メモリ割り当てが必要ない場合、オーバーヘッドは低くなりますが、それでも存在します。
- 当たり前のように思えるかもしれませんが、新しいビットセットを作成せずにビットセットを別のビットセットに直接追加する方が高速です。このソリューションは、最初のビットセットを変更しないでおく必要がある場合には適していません(明らかです)。
- 3つのソリューションでは同じ結果が得られないため、必要に応じて調整を行う必要があります(以下を参照)。
これが私のテストコードです:
#include <iostream>
#include <bitset>
#include <boost/dynamic_bitset/dynamic_bitset.hpp>
#include "scul/PreciseTimer.h"
boost::dynamic_bitset<> concatOperatorsDyn( const boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2)
{
boost::dynamic_bitset<> bs1Copy(bs1);
boost::dynamic_bitset<> bs2Copy(bs2);
size_t totalSize=bs1.size()+bs2.size();
bs1Copy.resize(totalSize);
bs2Copy.resize(totalSize);
bs1Copy<<=bs2.size();
bs1Copy|=bs2Copy;
return bs1Copy;
}
template<size_t sRes,size_t s1,size_t s2>
std::bitset<sRes> concatString( const std::bitset<s1>& bs1,const std::bitset<s2>& bs2)
{
std::string s1=bs1.to_string<char,std::char_traits<char>,std::allocator<char> >();
std::string s2=bs2.to_string<char,std::char_traits<char>,std::allocator<char> >();
std::bitset<sRes> res(s1+s2);
return res;
}
template<size_t sRes,size_t s1,size_t s2>
std::bitset<sRes> concatLoop( const std::bitset<s1>& bs1,const std::bitset<s2>& bs2)
{
std::bitset<sRes> res;
for(size_t i=0;i<s1;i++)
res[i]=bs1[i];
for(size_t i=0;i<s2;i++)
res[i+s1]=bs2[i];
return res;
}
boost::dynamic_bitset<> concatLoopDyn( const boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2)
{
boost::dynamic_bitset<> res(bs1);
res.resize(bs1.size()+bs2.size());
size_t bs1Size=bs1.size();
size_t bs2Size=bs2.size();
for(size_t i=0;i<bs2.size();i++)
res[i+bs1Size]=bs2[i];
return res;
}
boost::dynamic_bitset<> concatStringDyn( const boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2)
{
std::string s1;
std::string s2;
to_string(bs1,s1);
to_string(bs2,s2);
boost::dynamic_bitset<> res(s1+s2);
return res;
}
template<size_t s1,size_t s2>
void injectLoop( std::bitset<s1>& bs1,const std::bitset<s2>& bs2,int start=s1-s2)
{
for(size_t i=0;i<s2;i++)
bs1[i+start]=bs2[i];
}
void injectLoopDyn( boost::dynamic_bitset<>& bs1,const boost::dynamic_bitset<>& bs2,int start)
{
for(size_t i=0;i<bs2.size();i++)
bs1[i+start]=bs2[i];
}
void testBitstream()
{
const std::bitset<20> bs1(std::string("11111111110000000000"));
std::bitset<30> bs1Bis(std::string("11111111110000000000"));
const std::bitset<10> bs2(std::string("0000011111"));
std::bitset<30> bs3;
const boost::dynamic_bitset<> bs1D(std::string("11111111110000000000"));
boost::dynamic_bitset<> bs1DBis(std::string("11111111110000000000"));
bs1DBis.resize(30);
const boost::dynamic_bitset<> bs2D(std::string("0000011111"));
boost::dynamic_bitset<> bs3D;
scul::PreciseTimer t;
double d=0.;
int nbIter=100;
std::cout<<"Bitset concat with strings"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
bs3=concatString<30,20,10>(bs1,bs2);
d=t.stop();
std::cout<<bs3.to_string<char,std::char_traits<char>,std::allocator<char> >()<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;;
std::cout<<"Bitset concat with loop"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
bs3=concatLoop<30,20,10>(bs1,bs2);
d=t.stop();
std::cout<<bs3.to_string<char,std::char_traits<char>,std::allocator<char> >()<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;
std::cout<<"Bitset inject with loop"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
injectLoop<30,10>(bs1Bis,bs2);
d=t.stop();
std::cout<<bs1Bis.to_string<char,std::char_traits<char>,std::allocator<char> >()<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;
std::cout<<"Dynamicbitset concat with loop"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
bs3D=concatLoopDyn(bs1D,bs2D);
d=t.stop();
std::string s;
to_string(bs3D,s);
std::cout<<s<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;
std::cout<<"Dynamicbitset inject with loop"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
injectLoopDyn(bs1DBis,bs2D,20);
d=t.stop();
to_string(bs1DBis,s);
std::cout<<s<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;
std::cout<<"Dynamicbitset concat with operators"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
bs3D=concatOperatorsDyn(bs1D,bs2D);
d=t.stop();
to_string(bs3D,s);
std::cout<<s<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;
std::cout<<"Dynamicbitset concat with strings"<<std::endl;
t.start();
for(int i=0;i<nbIter;++i)
bs3D=concatStringDyn(bs1D,bs2D);
d=t.stop();
to_string(bs3D,s);
std::cout<<s<<std::endl;
std::cout<<"duration="<<d<<std::endl<<std::endl;
}
これが私のコンピューターのVS7.1で得られる出力です:
Bitset concat with strings
111111111100000000000000011111
duration=0.000366713
Bitset concat with loop
000001111111111111110000000000
duration=7.99985e-006
Bitset inject with loop
000001111111111111110000000000
duration=2.87995e-006
Dynamicbitset concat with loop
000001111111111111110000000000
duration=0.000132158
Dynamicbitset inject with loop
000001111111111111110000000000
duration=3.19994e-006
Dynamicbitset concat with operators
111111111100000000000000011111
duration=0.000191676
Dynamicbitset concat with strings
111111111100000000000000011111
duration=0.000404152
ループを使用して作成した関数は、異なる結果を生成することに気付くでしょう。それは、最初のビットセットのmsb(右側のlsb)の後に2番目のビットセットのlsbを配置するように書いたためです。文字列または「ビット演算子」関数を使用すると、呼び出し元のパラメーターを切り替えるだけです。