Robert
Robert

Reputation: 2389

Decimate vector in eigen

I have a float array Eigen::ArrayXf which I need to decimate (i.e. pick 1 out of f.i. 8 samples).

Eigen::ArrayXf decimatedSignal = Eigen::Map<Eigen::ArrayXf, 0, Eigen::InnerStride<8> >(signal.data(), length, 1).eval();

which works, with a caveat: I need to know how long length is, and it can be specified too long, leading to runtime errors.

Q: is there a way to decimate all that is possible, so that resultant length is == signal.size() / 8 ?

Upvotes: 0

Views: 499

Answers (1)

Avi Ginsburg
Avi Ginsburg

Reputation: 10596

Two things. You are using the c'tor for mapping a matrix:

Map ( PointerArgType dataPtr, Index nbRows, Index nbCols, const StrideType & a_stride = StrideType() )

Constructor in the dynamic-size matrix case.

Parameters

dataPtr  pointer to the array to map
nbRows    the number of rows of the matrix expression
nbCols    the number of columns of the matrix expression
a_stride  optional Stride object, passing the strides. 

I think you want the c'tor for a vector:

Map ( PointerArgType dataPtr, Index a_size, const StrideType & a_stride = StrideType() )

Constructor in the dynamic-size vector case.

Parameters

dataPtr  pointer to the array to map
a_size    the size of the vector expression
a_stride  optional Stride object, passing the strides. 

The second thing is that you want length == signal.size())/8. Is that always a whole integer, or are you rounding up? If the data is 16 in length and you want the positions [0] and [8], then use 1+(signal.size()-1)/8 as the length parameter:

Eigen::ArrayXf decimatedSignal = Eigen::Map<Eigen::ArrayXf, 0, Eigen::InnerStride<8> >(signal.data(), 1+((signal.size()-1)/8) ).eval();

For example:

#include <Eigen/Core>
#include <iostream>

using std::cout;
using std::endl;

int main(int argc, char *argv[])
{
    Eigen::VectorXf signal;
    signal.setLinSpaced(64, 0.0, 63.);
    cout << "Original signal:" << endl << signal.transpose() << endl;

    Eigen::ArrayXf decimatedSignal = Eigen::Map<Eigen::ArrayXf, 0, 
        Eigen::InnerStride<8> >(signal.data(), 1+((signal.size()-1)/8)).eval();

    cout << endl << "Decimated:" << endl << decimatedSignal.transpose() << endl;

    return 0;
}

outputs

Original signal: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63

Decimated: 0 8 16 24 32 40 48 56

which I think is exactly what you want.

Upvotes: 1

Related Questions