Jakiś czas temu napisałem prosty widok na macierz. Postanowiłem go trochę rozszerzyć i napisać przekombinowany widok na macierz n-wymiarową. Kodu jest trochę więcej niż poprzednio, więc nie zamieszczę całości w treści posta (jest dostępny tutaj), ale tylko zamieszczę efekty.
Użycie
Zaczynając od przykładowego kodu z poprzedniego posta:
vector<double> data{1,2,3,4,5,6,7,8,9,10,11,12}; simple_2d_matrix_view<double> m(data.data(), 2, 6); for(size_t i = 0; i < m.height(); ++i) { for(size_t j = 0; j < m.width(); ++j) { cout << m(i, j) << " "; } cout << "\n"; } |
Po minimalnej modyfikacji:
vector<double> data{1,2,3,4,5,6,7,8,9,10,11,12}; kq::matrix_2d_view<double> m(data.data(), 2, 6); for(size_t y = 0; y < m.height(); ++y) { for(size_t x = 0; x < m.width(); ++x) { cout << m(y, x) << " "; } cout << "\n"; } |
Wyjście:
1 2 3 4 5 6 7 8 9 10 11 12 |
Przy czym, po dodaniu obsługi iteratorów, można to zapisać ładniej:
for(auto const& row : m) { for(auto const& val : row) { cout << val << " "; } cout << '\n'; } |
lub:
for(auto const& row : m) { copy(row.begin(), row.end(), ostream_iterator<double>(cout, " ")); cout << '\n'; } |
Wyjście pozostanie bez zmian.
Wydajność
gcc i clang optymalizują całą abstrakcję do zera. Link do compiler explorera.
template<typename T> void sink(T); void foo() { std::array<int, 12> arr{1,2,3,4,5,6,7,8,9,10,11,12}; kq::matrix_view<const int, 2> v{arr.data(), 3, 4}; for(auto const& row : v) for(auto elem : row) sink(elem); } |
Kompiluje się do:
foo(): # @foo() push rax mov edi, 1 call void sink<int>(int) mov edi, 2 call void sink<int>(int) mov edi, 3 call void sink<int>(int) mov edi, 4 call void sink<int>(int) mov edi, 5 call void sink<int>(int) mov edi, 6 call void sink<int>(int) mov edi, 7 call void sink<int>(int) mov edi, 8 call void sink<int>(int) mov edi, 9 call void sink<int>(int) mov edi, 10 call void sink<int>(int) mov edi, 11 call void sink<int>(int) mov edi, 12 call void sink<int>(int) pop rax ret |