Iterate over all but d-th dimension of any boost::multi_array
很多时候,人们想要沿着
我能想到的最好的方法是实现一个
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 |
#include"boost/multi_array.hpp" #include <ostream> using namespace boost; typedef multi_array_types::index index_t; template <template <typename, std::size_t, typename…> class Array, template <template <typename, std::size_t, typename…> class Array, typename T> template <template <typename, std::size_t, typename…> class Array, // collapse dimensions [0,d) and (d,Ndims) // reshape to collapsed dimensions // call f for each slice [i,:,k] template <template <typename, std::size_t, typename…> class Array, |
这是测试程序
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 |
#include"f.hpp"
int main() { int i = 0; std::cout <<"work on boost::multi_array_ref" << std::endl; std::cout <<"work on boost::multi_array" << std::endl; std::cout <<"work on boost::detail::multi_array:sub_array" << std::endl; std::cout <<"work on boost::detail::multi_array:sub_array" << std::endl; //f(A[1]); // fails: rvalue A[1] is boost::multi_array_ref<double, 3ul>::reference |
显然,这种方法存在问题,即当将切片传递给
似乎更好(更像 C)的方法是从 boost 类型提供的迭代器中构造一个聚合迭代器,因为这会自动处理沿给定维度的非统一步幅。
注意:
SO 上已经有类似的问题,但没有一个让我很满意。我对
更新:
这相当于我在 Python 中想要的:
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 |
def idx_iterator(s, d, idx): if len(s) == 0: yield idx else: ii = (slice(None),) if d == 0 else xrange(s[0]) for i in ii: for new_idx in idx_iterator(s[1:], d – 1, idx + [i]): yield new_idx def iterator(A, d=0): def f(A): import numpy as np print"Work on flattened array" print"Work on array" print"Work on contiguous slice" print"Work on discontiguous slice" |
使用
好的,在花了大量时间研究
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 64 65 66 67 68 69 70 71 |
#include"boost/multi_array.hpp"
template <template <typename, std::size_t, typename…> class Array, array_type& A; SliceIterator(array_type& A, long d) : A(A), shape(A.shape()), d(d) { SliceIterator& operator++() { slice_type operator*() { // fakes for iterator protocol (actual implementations would be expensive) SliceIterator begin() {return *this;} template <template <typename, std::size_t, typename…> class Array, // overload for rvalue references |
可以作为
1
2 3 |
for (auto S : make_slice_iterator(A, d)) {
f(S); } |
适用于我的问题中的所有示例。
我必须说,
总之,我发现
的”放手”
-
我在网络上的任何地方都找不到
boost::multi_array 的任何严重用例 - 发展似乎在 2002 年基本停止
- StackOverflow 上的这个(和类似的)问题几乎没有引起任何兴趣 ;-)
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/268944.html