英文:
Eigen: scale the positive entries in loop-free manner
问题
我有一个 Eigen::Array<float, N, 1>
。我想要将所有正元素乘以一个正标量 s
,使得正元素的和变为目标值 t
。我可以使用以下代码来实现这个目标:
template<int N>
void positive_scale(Eigen::Array<float, N, 1>& A, float t) {
float pos_sum = 0;
for (int i = 0; i < N; ++i) {
if (A(i) > 0) pos_sum += A(i);
}
float s = t / pos_sum;
for (int i = 0; i < N; ++i) {
if (A(i) > 0) A(i) *= s;
}
}
我想知道是否有一种更加简洁、无需循环的方法来实现这个目标。例如,在Python的NumPy中,我们可以更加紧凑地编写如下代码:
def positive_scale(A, t):
A[A > 0] *= t / sum(A[A > 0])
英文:
I have an Eigen::Array<float, N, 1>
. I would like to multiply all the positive elements by a positive scalar s
chosen so that the positive elements instead sum to a target t
. I am able to do this with code like this:
template<int N>
void positive_scale(Eigen::Array<float, N, 1>& A, float t) {
float pos_sum = 0;
for (int i = 0; i < N; ++i) {
if (A(i) > 0) pos_sum += A(i);
}
float s = t / pos_sum;
for (int i = 0; i < N; ++i) {
if (A(i) > 0) A(i) *= s;
}
}
I am wondering if there is a more elegant, loop-free way to do this. In python numpy, for instance, we can write this much more compactly:
def positive_scale(A, t):
A[A > 0] *= t / sum(A[A > 0])
答案1
得分: 2
Eigen不支持像NumPy一样的布尔索引,但它有一个可以使用的select
方法。
void positive_scale(Eigen::Ref<Eigen::ArrayXf> inout, float target)
{
// 正数项的总和。完全矢量化
float pos_sum = inout.cwiseMax(0.f).sum();
float factor = target / pos_sum;
// 保留旧的负值。替换正值
inout = (inout > 0.f).select(inout * factor, inout);
}
英文:
Eigen does not support bools for indices in the way Numpy does, but it has a select
method that can be used.
void positive_scale(Eigen::Ref<Eigen::ArrayXf> inout, float target)
{
// sum of positive entries. Fully vectorized
float pos_sum = inout.cwiseMax(0.f).sum();
float factor = target / pos_sum;
// keep old negative values. Replace positive values
inout = (inout > 0.f).select(inout * factor, inout);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论