Как использовать диапазоны C ++ для реализации numpy .ndindex? - PullRequest
6 голосов
/ 20 января 2020

Я хотел бы реализовать эквивалент numpy.ndindex в C ++. Предполагается генерировать индексы для многомерного массива заданных размеров.

Вот реализация для двумерного массива.

template <typename T>
inline auto NDIndex(T d0, T d1) {
  using namespace ranges;
  return views::cartesian_product(views::indices(d0), views::indices(d1));
}

// Usage
for (const auto[i1, i2] : NDIndex(5, 4)) {
  arr[i1][i2] = ...
}

Я хотел бы обобщить его для произвольного количество измерений без ущерба для производительности. Я в порядке с использованием скобки в интерфейсе, например, NDIndex({5, 4}). Я могу придумать несколько решений, но я не уверен, что бы решить эту проблему статически.

Ответы [ 2 ]

4 голосов
/ 20 января 2020

views::cartesian_product - это уже вариади c, вам просто нужно расширить пакет в него.

template <typename... Ts>
inline auto NDIndex(Ts ... ds) {
  using namespace ranges;
  return views::cartesian_product(views::indices(ds)...);
}

// Usage
int main() {
    for (const auto[i1, i2] : NDIndex(5, 4)) {
    }
    for (const auto[i1, i2, i3] : NDIndex(5, 4, 7)) {
    }
}
3 голосов
/ 20 января 2020

Это можно сделать следующим образом

#include <range/v3/view/indices.hpp>
#include <range/v3/view/cartesian_product.hpp>


template <unsigned... Ind>
constexpr inline auto NDIndex() {
  using namespace ranges;
  return views::cartesian_product(views::indices(Ind)...);
}


int main() {

    for (const auto[i1, i2] : NDIndex<5, 4>()) {
    }


    for (const auto[i1, i2, i3] : NDIndex<5, 4, 7>()) {
    }
}

Живой пример

...