He probado varias soluciones y parece que:
- un buen viejo "bucle" es el más rápido
- bitset es mucho más rápido que dynamic_bitset (no sorprendente), si no se necesita asignación de memoria, la sobrecarga es menor, pero aún existe.
- Puede parecer obvio, pero agregar directamente un conjunto de bits a otro sin crear uno nuevo es más rápido. Esta solución no es adecuada si necesita mantener inalterado el primer conjunto de bits (también obvio).
- Las 3 soluciones no producen el mismo resultado, tienes que hacer un ajuste dependiendo de lo que quieras (ver a continuación).
Aquí está mi código de prueba:
#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;
}
Aquí está la salida llego con VS7.1 en mi equipo:
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
se puede observar que la función que escribió usando bucles producir diferentes resultados Es porque escribí entonces para poner el lsb del segundo bitset después del msb del primero (lsb a la derecha).Con la función de cadena o "operador de bit" solo tiene que cambiar los parámetros de llamada.
No sé ... quieres rendimiento pero luego usas cadenas para tus campos de bits que asignan memoria en el montón ... de alguna manera esto no coincide - concatenar los dos no será el problema de rendimiento aquí. – humbagumba
Usar una cadena en el código de muestra anterior es solo para dar un buen ejemplo legible. Pensé con las cuerdas que es fácil de leer que 1111 y 00 resultan en 111100. – MOnsDaR