问题描述
我正在写一堆(约十几个)算法,按照以下模式迭代处理一个向量:
I'm writing up a bunch (~ a dozen) algorithms that iteratively process a vector in the following pattern:
ArrayXd prev;
ArrayXd curr;
prev = some_initial_vector();
for (i = 0; i < N; ++i) {
// do lots of stuff, many lines to compute curr
// use lots of algorithm specific variables initialised above
...
prev = curr;
}
return curr;
我想有一种方法来返回 curr
以及 ArrayXXd
中的行。
I would like to have a way of returning the entire history of the values of curr
as well, as rows in an ArrayXXd
.
这是通过写两个类,它们显示一个 curr
句柄,一个作为 ArrayXd&
另一个作为 Block< ArrayXXd,1,-1>
,但失败为。
I have tried solving this by writing two classes that exhibit a curr
handle, one as an ArrayXd &
the other as a Block<ArrayXXd, 1, -1>
, but that failed as it's not possible to reassign Block
s.
是解决这个问题的好办法吗?也许我可以在 std :: vector中存储
,然后。 Block
s或 ArrayXd
What is a good way of solving this problem? Maybe I could store the Block
s or the ArrayXd
s themselves in a std::vector
and then convert that to an ArrayXXd
at the end.
修改:添加了示例输入和输出
Added sample input, output
struct NotAccumulator {
typedef ArrayXd return_type;
ArrayXd curr;
ArrayXd prev;
void record () {}
return_type result() {
return prev;
}
};
struct RowAccumulator {
typedef ArrayXXd return_type;
ArrayXd curr;
ArrayXd prev;
RowAccumulator(const uint N) {
history.reserve(N);
}
void record () {
history.push_back(curr);
}
return_type result () {
uint rows = history.size();
uint cols = history[0].size();
ArrayXXd result_matrix (rows, cols);
for(uint i = 0; i < rows; ++i) {
result_matrix.row(i) = Map<ArrayXd> (history[i].data(), cols);
}
return result_matrix;
}
private:
std::vector<ArrayXd> history;
};
template <typename Accumulator>
typename Accumulator::return_type add_one(const ArrayXd & start, const uint how_many_times, Accumulator & u) {
u.prev = start;
for (uint i = 0; i < how_many_times; ++i) {
u.curr = 1 + u.prev;
u.record();
u.prev = u.curr;
}
return u.result();
}
ArrayXd start (3);
start << 1, 0, -1;
NotAccumulator notAccumulator;
RowAccumulator rowAccumulator (5);
cout << add_one(start, 5, notAccumulator) << endl;
// outputs 6 5 4
cout << add_one(start, 5, rowAccumulator) << endl;
// outputs 2 1 0\n 3 2 1\n ... 6 5 4
推荐答案
如果你想尽可能避免数据复制,可以分配 N
-row ArrayXXd
,并避免使用 return
。
If you want to avoid the data copy as much as possible, you could allocate the N
-row ArrayXXd
in advance and avoid using return
.
c $ c> prev 和 curr
也是不必要的。以下代码还假设预先已知迭代次数 N
。
Buffers like prev
and curr
are unnecessary too. The following code also assumes the number of iterations N
is known in advance.
void GenerateHistory(int N, ArrayXXd* result) {
result.row(0) = gen_row0_without_prev();
for(int curr=1; curr<N; curr++) {
result.row(curr) = gen_row_with_prev_row(result.row(curr-1));
}
}
您可以使用
int N = 100;
int m = 20;
ArrayXXd history(N, m);
GenerateHistory(N, &history);
EDIT
在旁边。
EDIT
Let's put the copying issue aside. Here's an updated code that should fulfill the requirement according to your code sample.
ArrayXXd add_one(const ArrayXd& start, int num_iterations, bool acc) {
if (acc) {
ArrayXXd result = start;
for(int i=0; i<num_iterations; i++) {
result = result + 1;
}
return result;
} else {
ArrayXXd result(num_iterations, start.cols());
result.row(0)=start+1;
for(int i=1; i<num_iterations; i++) {
result.row(i)=result.row(i-1);
}
return result;
}
}
ArrayXd start (3);
start << 1, 0, -1;
bool acc = true;
cout << add_one(start, 5, !acc) << endl;
// outputs 6 5 4
cout << add_one(start, 5, acc) << endl;
// outputs 2 1 0\n 3 2 1\n ... 6 5 4
这篇关于返回所有行,或只返回最后一行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!