Eigen3 (cpp) выберите столбец с заданной маской и суммой, где true

#c #openmp #vectorization #eigen #eigen3

#c #openmp #векторизация #eigen #eigen3

Вопрос:

У меня есть Eigen::Matrix2Xf строка, в которой позиции X и Y, а cols выступают в качестве индекса списка

Я хотел бы иметь сумму столбцов (по строкам), в которых выполняется какое-либо условие столбца, вот пример кода:

 Eigen::Vector2f computeStuff(Eigen::Matrix2Xf amp; values, const float max_norm){   const auto mask = values.colwise().norm().array() lt; max_norm;   return mask.select(values.colwise(), Eigen::Vector2f::Zero()).rowwise().sum();   }  

Но этот код не компилируется, жалуясь на типы матриц if/else, каков правильный (и вычислительно более быстрый) способ сделать это?

Также я знаю, что есть аналогичный вопрос с ответом, но они создают новый Eigen::Matrix2Xf с отфильтрованными значениями, заданными маской, этот код предназначен для запуска внутри #pragma omp parallel for , поэтому основная идея состоит в том, чтобы не создавать новую матрицу для поддержания согласованности кэша

Спасибо

Комментарии:

1. Скажем values , 2х4 … это 2 строки и 4 столбца. Тогда values.colwise().norm().array() lt; max_norm будет 1х4, одна строка и четыре столбца. Затем вы говорите, что хотите суммировать строки в values этом mask списке … values содержит только 2 строки и mask четыре столбца. Вы имеете в виду, что хотите суммировать столбцы , values которые выбирает маска?

2. @jwezorek да, именно это, извините, если я не был ясен, я задал вопрос

3. другое дело, как выход может быть a vector2f ? Результатом, если я понимаю, что вы пытаетесь сделать, будет вектор строк с любым количеством столбцов на входе. Если вы хотите, чтобы в нем были только ненулевые столбцы, и знаете, что их будет только два или что-то еще, с чем вы не сможете этого сделать .select(...) .

4. результатом будет a vector2f , идея состоит в том, чтобы замаскировать некоторые столбцы значений матрицы, а затем выполнить операцию сокращения по строкам, я хочу, чтобы была только сумма по строкам замаскированных столбцов

Ответ №1:

Основная проблема с вашим кодом заключается в том, что .select( ... ) по крайней мере один из его аргументов должен иметь ту же форму, что и маска. Аргументами могут быть две матрицы или матрица и скаляр или наоборот, но во всех случаях матрицы должны иметь форму маски.

В вашем коде mask есть вектор строк, но values это матрица 2 на x. Один из способов справиться с этим-просто скопировать вектор строк в матрицу из двух строк:

 #include lt;Eigen/Densegt; #include lt;iostreamgt;  Eigen::Vector2f computeStuff(Eigen::Matrix2Xfamp; values, const float max_norm) {   auto mask = (values.colwise().norm().array() lt; max_norm).replicate(2, 1);  return mask.select(values, 0).rowwise().sum(); }  int main() {   Eigen::Matrix2Xf mat(2,4);  mat lt;lt; 1, 4, 3, 2,   1, 2, 4, 3;   auto val = computeStuff(mat, 5);   std::cout lt;lt; val;   return 0; }  

В приведенном выше mask будет:

 1 1 0 1 1 1 0 1  

т. е. строка 1 1 0 1 дублируется один раз. Затем mask.select(values, 0) уступает

 1 4 0 2 1 2 0 3  

таким образом, результат будет

 7 6  

что, я думаю, именно то, чего вы хотите, если я правильно понимаю вопрос.