I'm trying to combine three signal waveforms into a single, interleaved waveform. I need to know the best way to do it in C++ STL. Better solutions would use as much C++ STL style as possible, avoid redundant code, etc. Is there some STL "tuple" type class that would do this for me? I need contiguous storage at all times for backward compatibility with other code (therefore, vector). The best solution would be correct and easy to understand. Space and speed are not as high of a priority as correctness and ease of understanding.
The output waveform must be ordered like this: first sample from first channel, first sample from second channel, first sample from third channel, then continue with the second sample from each channel and repeat for all samples. I know that all three input waveforms have the same number of samples.
In Matlab, I would have done it like this:
function outputWaveform=Interleave3(a, b, c) outputWaveform=zeros([1 3*length(a)]); outputWaveform(1:3:end)=a(:); outputWaveform(2:3:end)=b(:); outputWaveform(3:3:end)=c(:);
This is my first C++ STL attempt:
typedef vector<double> dVector; typedef vector<double>::iterator dVectorIT; dVector Interleave3(dVector a, dVector b, dVector c) { dVector result(0, 3*a.size()); dVectorIT aIT=a.begin(), bIT=b.begin(), cIT=c.begin(), rIT=result.begin(); for(; aIT != a.end(); ++aIT, ++bIT, ++cIT) { *rIT++=*aIT; *rIT++=*bIT; *rIT++=*cIT; } return result; }
It works, but is there a better way to do this? I hoped there might be some clever way to do it in one line with transform(). Can you append b to a, then c to a, then transform the temporary "a1a2a3...-b1b2b3...-c1c2c3..." vector into "a1b1c1a2b2c2a3b3c3..."?
Bonus question: I also need the inverse operation (to split an output waveform of 3*N samples into 3 vectors of N samples each). The Matlab solution is quite easy:
function [a, b, c]=Deinterleave3(outputWaveform) a=outputWaveform(1:3:end); b=outputWaveform(2:3:end); c=outputWaveform(3:3:end);
C++ STL seems fairly awkward, and I bet there's a better way to do it than this:
typedef vector<double> dVector; typedef vector<double>::iterator dVectorIT; void Deinterleave3(dVector outputWaveform, dVector &a, dVector &b, dVector &c) { ASSERT( !(outputWaveform.size()%3) ); a.clear(); b.clear(); c.clear(); dVectorIT oIT=outputWaveform.begin(); for(; oIT != outputWaveform.end(); ) { a.push_back( *oIT++ ); b.push_back( *oIT++ ); c.push_back( *oIT++ ); } }
Is there some clever combination of transform() and back_inserter() which would do the inverse operation? Again, using a temporary vector would be acceptable.
Boost has a "zip iterator," but I can't figure out if it would perform either the interleaving or deinterleaving operation.
EDIT: fixed the missing angle brackets (<>). The HTML filter ate them! Also, I have a new idea about how to fix this with a custom iterator.