You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用带索引的标准库函数替代迭代器?Eigen::VectorXd调用std::partial_sum方案

在Eigen::VectorXd上实现前缀和的几种方案

嘿,这个问题我之前也踩过坑!Eigen确实没给VectorXd这类稠密向量提供标准STL迭代器,但完全不用自己手动写索引循环,有几个更优雅高效的办法:

1. 优先用Eigen原生的cumsum()方法(最推荐)

Eigen的Array模块自带了前缀和实现cumsum(),而VectorXd可以非常方便地转成ArrayXd来使用,用完再转回Vector就行——而且这个方法是Eigen优化过的,性能比STL的std::partial_sum还要好(毕竟Eigen会做向量化加速)。

示例代码:

#include <Eigen/Dense>
#include <iostream>

int main() {
    Eigen::VectorXd vec(5);
    vec << 1, 2, 3, 4, 5;
    
    // 转成Array调用cumsum,再转回Vector
    Eigen::VectorXd partial_sum = vec.array().cumsum();
    
    std::cout << partial_sum << std::endl;
    // 输出结果:1, 3, 6, 10, 15
    return 0;
}

如果需要原地修改向量,直接vec = vec.array().cumsum();就行,非常简洁。

2. 自己实现极简索引迭代器(适配STL算法)

如果你一定要用std::partial_sum,可以写一个轻量的索引式迭代器包装Eigen向量。这个迭代器基于索引操作,满足STL随机访问迭代器的要求,完全能适配std::partial_sum这类算法。

示例迭代器实现+用法:

#include <Eigen/Dense>
#include <numeric>
#include <iostream>

template<typename VectorType>
struct EigenVectorIterator {
    // STL迭代器必备的类型定义
    using value_type = typename VectorType::Scalar;
    using reference = value_type&;
    using pointer = value_type*;
    using difference_type = std::ptrdiff_t;
    using iterator_category = std::random_access_iterator_tag;

    EigenVectorIterator(VectorType& vec, Eigen::Index idx) : vec_(&vec), idx_(idx) {}

    // 解引用操作
    reference operator*() { return (*vec_)(idx_); }
    pointer operator->() { return &(*vec_)(idx_); }

    // 自增自减
    EigenVectorIterator& operator++() { ++idx_; return *this; }
    EigenVectorIterator operator++(int) { auto temp = *this; ++idx_; return temp; }
    EigenVectorIterator& operator--() { --idx_; return *this; }
    EigenVectorIterator operator--(int) { auto temp = *this; --idx_; return temp; }

    // 加减偏移
    EigenVectorIterator operator+(difference_type n) const { return EigenVectorIterator(*vec_, idx_ + n); }
    EigenVectorIterator operator-(difference_type n) const { return EigenVectorIterator(*vec_, idx_ - n); }
    difference_type operator-(const EigenVectorIterator& other) const { return idx_ - other.idx_; }

    // 比较运算符
    bool operator==(const EigenVectorIterator& other) const { return vec_ == other.vec_ && idx_ == other.idx_; }
    bool operator!=(const EigenVectorIterator& other) const { return !(*this == other); }
    bool operator<(const EigenVectorIterator& other) const { return idx_ < other.idx_; }
};

int main() {
    Eigen::VectorXd vec(5);
    vec << 1, 2, 3, 4, 5;
    Eigen::VectorXd result(vec.size());

    std::partial_sum(
        EigenVectorIterator(vec, 0),
        EigenVectorIterator(vec, vec.size()),
        EigenVectorIterator(result, 0)
    );

    std::cout << result << std::endl;
    return 0;
}

这个迭代器很简单,只实现了std::partial_sum需要的核心操作,你可以根据需求扩展其他运算符。

额外说明:为什么Eigen不提供STL迭代器?

Eigen的核心设计是表达式模板,它会在编译期优化整个计算流程(比如向量化、避免临时变量)。而STL迭代器是基于逐元素访问的模式,会破坏这种优化链条,所以Eigen更推荐用它自己的成员方法来完成这类操作——这也是为什么第一个方案是最优解的原因。

内容的提问来源于stack exchange,提问作者philx_x

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 09:00:01