2

I have the vector

Eigen::VectorXf test(4);
test << 1.231, 1.23, 0.41, 1.233;

I'm trying to get the indexes of where test.array() > 1. I would expect the result to be in array form (std::vector is fine) and I want to take advantage of eigens optimisations (i.e. no unnecessary for loops). The result should be {0, 1, 3}. How would I go about doing this?

edit

There is a question that I was sent that is similar Eigen Indices of Dense Matrix meeting Condition

But the key difference is that I'm using vectors, therefore everything is based in one dimension

edit 2

for reference here is how I would do the same in xtensor

auto indexes = xt::flatten_indices(xt::argwhere(xt::greater(xt::flatten(data), 1)));

Tom
  • 1,235
  • 9
  • 22
  • Does this answer your question? [Eigen Indices of Dense Matrix meeting Condition](https://stackoverflow.com/questions/50027494/eigen-indices-of-dense-matrix-meeting-condition) – Askold Ilvento May 18 '20 at 15:22
  • @AskoldIlvento In my case, it's a vector. – Tom May 18 '20 at 17:19
  • http://www.cplusplus.com/reference/functional/greater/ - then just print 1 or 0 instead of sort? – Michael Dorgan May 18 '20 at 17:33
  • @MichaelDorgan I'm trying to get the indexes, not the values – Tom May 18 '20 at 17:35
  • Run it in a foreach loop then and store the index on true/false in another array? Or do you need something more compact? From your output, it looks like you just wanted an array of true/false. if you want an array of indexes, update the question. – Michael Dorgan May 18 '20 at 17:38
  • @MichaelDorgan I've updated the question. I want to achieve this via eigens optimised features, so no for loops at all. And the result should be any array, std::vector is fine. – Tom May 18 '20 at 17:57
  • (Internally, there will be a for loop to iterate through each entry and compare, it must be at least O(n) to run on each index, but I got you.) – Michael Dorgan May 18 '20 at 18:02
  • @MichaelDorgan Yes your right. But I don't want to write any loops that are not necessary as peformance is important for me. – Tom May 18 '20 at 18:03
  • Out of curiousity, you have used a profiler to look at your optimized compiled code to determine where the hotspots are? Without that, performance work is guessing at best. – Michael Dorgan May 18 '20 at 18:09
  • Yes I time the code with a basic timer class, and then work out averages based off of the results so I have a good idea if one solution is better then the other. I test with large inputs and small inputs. – Tom May 18 '20 at 18:11

1 Answers1

2

Based off this answer Eigen Indices of Dense Matrix meeting Condition, I got the result using visitors. This time I'm checking if the values are NaN rather then greater than 1.

template<typename Func>
struct lambda_as_visitor_wrapper : Func {
    lambda_as_visitor_wrapper(const Func& f) : Func(f) {}
    template<typename S, typename I>
    void init(const S& v, I i, I j) { return Func::operator()(v, i, j); }
};

template<typename Mat, typename Func>
void visit_lambda(const Mat& m, const Func& f)
{
    lambda_as_visitor_wrapper<Func> visitor(f);
    m.visit(visitor);
}


...
    std::vector<int> indices;
    int th = 1;

    visit_lambda(open.data,
        [&indices, th](double v, int i, int j) {
            if (std::isnan(v))
                indices.push_back(i);
        });

And although I'm not going to go into too much detail about the data used, the xtensor equivalent of this

xt::flatten_indices(xt::argwhere(xt::isnan(open2.data)))

was much slower, with Eigen clocking in at approximately 8x faster (366 floats).

Tom
  • 1,235
  • 9
  • 22