C++20 格式的 Eigen3 库

问题描述 投票:0回答:2

我正在尝试使用 c++20 格式而不是 Eigen::IOFormat 打印 Eigen::Array 或 Eigen::Matrix。 我想用说明符控制矩阵中元素的精度和对齐方式,例如,

#include <Eigen/Core>
#include <format>
#include <iostream>

int main()
{
    Eigen::ArrayXXd mat( 3, 4 );
    mat.setZero();
    std::cout << std::format( "mat={:9.4f}\n", mat );
    return 0;
}

怎样才能得到下面的预期结果?

mat=   0.0000   0.0000   0.0000   0.0000
       0.0000   0.0000   0.0000   0.0000
       0.0000   0.0000   0.0000   0.0000
c++ c++20 eigen3
2个回答
1
投票

您可以查看https://gite.lirmm.fr/rpc/utils/eigen-fmt,看看它是否对您有帮助。

您基本上需要包含 这个头文件,以便使用

fmt
库获得对打印/格式的特征支持。由于
std::format
是基于
fmt
的,因此该代码应该是一个良好的开始,以实现您想要的目标。请注意,您可能需要进行一些调整。


0
投票

我使用基于对我有用的概念的解决方案。到目前为止已使用 Visual Studio 2022 进行了测试。

#include <string>
#include <iostream>
#include <format>
#include <Eigen/Eigen>


template <typename EigenExprTypeT>
concept EigenTypeMatExpr = requires(const EigenExprTypeT t) {
    std::remove_cvref_t<EigenExprTypeT>::RowsAtCompileTime;
    std::remove_cvref_t<EigenExprTypeT>::ColsAtCompileTime;
    typename std::remove_cvref_t<EigenExprTypeT>::Scalar;
    {
        t.size()
    } -> std::same_as<typename Eigen::Index>;
    {
        t.rows()
    } -> std::same_as<typename Eigen::Index>;
    {
        t.cols()
    } -> std::same_as<typename Eigen::Index>;
};

enum class EigenCustomFormats {
    Default,                //
    CleanFormat,            // cf
    HeavyFormat,            // hf
    SingleLineFormat,       // sfl
    HighPrecisionFormat,    // hpf
    DebuggingFormat         // df
};

static const auto defaultFormat = Eigen::IOFormat();
static const auto cleanFormat = Eigen::IOFormat(4, 0, ", ", "\n", "[", "]");
static const auto heavyFormat = Eigen::IOFormat(Eigen::FullPrecision, 0, ", ", ";\n", "[", "]", "[", "]");
static const auto singleLineFormat =
Eigen::IOFormat(Eigen::StreamPrecision, Eigen::DontAlignCols, ", ", ", ", "", "", "", "");
static const auto highPrecisionFormat =
Eigen::IOFormat(Eigen::FullPrecision, Eigen::DontAlignCols, " ", "\n", "", "", "", "");
static const auto debuggingFormat =
Eigen::IOFormat(Eigen::FullPrecision, Eigen::DontAlignCols, " ", "\n", "", "", "\n", "");


template <EigenTypeMatExpr MatT>
struct std::formatter<MatT> {
    constexpr auto parse(format_parse_context& ctx) {
        const std::string_view fmt(ctx.begin(), ctx.end());
        if (fmt.starts_with("cf"))
            _format = EigenCustomFormats::CleanFormat;
        if (fmt.starts_with("hf"))
            _format = EigenCustomFormats::HeavyFormat;
        if (fmt.starts_with("sfl"))
            _format = EigenCustomFormats::SingleLineFormat;
        if (fmt.starts_with("hpf"))
            _format = EigenCustomFormats::HighPrecisionFormat;
        if (fmt.starts_with("df"))
            _format = EigenCustomFormats::DebuggingFormat;
        return ctx.begin() + fmt.find_first_of('}');

    }

    // Format the type for output
    template <typename FormatContext>
    auto format(const MatT& m, FormatContext& ctx) const {
        switch (_format) {
        case EigenCustomFormats::CleanFormat:         return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(cleanFormat)).str());
        case EigenCustomFormats::HeavyFormat:         return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(heavyFormat)).str());
        case EigenCustomFormats::SingleLineFormat:    return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(singleLineFormat)).str());
        case EigenCustomFormats::HighPrecisionFormat: return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(highPrecisionFormat)).str());
        case EigenCustomFormats::DebuggingFormat:     return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(debuggingFormat)).str());
        default:                                      return std::format_to(ctx.out(), "{}", (std::stringstream{} << std::fixed << m.format(defaultFormat)).str());
        }

    }

private:
    EigenCustomFormats _format{ EigenCustomFormats::Default };
};

template <EigenTypeMatExpr MatT>
std::ostream& operator<<(std::ostream& os, const MatT& mat)
{
    return os << std::format("{:hf}", mat);
}

int main()
{

    Eigen::Matrix2f m = Eigen::Matrix2f::Random();
    std::cout << Eigen::Matrix2f::Random() << std::endl << std::endl << std::endl;
    std::cout << std::format("{}\n", Eigen::Matrix2f::Random()) << std::endl;
    std::cout << std::format("{:cf}\n", Eigen::Matrix2f::Random()) << std::endl;
    std::cout << std::format("{:hf}\n", Eigen::Matrix2f::Random()) << std::endl;
    std::cout << std::format("{:sfl}\n", Eigen::Matrix2f::Random()) << std::endl;
    std::cout << std::format("{:hpf}\n", Eigen::Matrix2f::Random()) << std::endl;
    std::cout << std::format("{:df}\n", Eigen::Matrix2f::Random()) << std::endl;

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.