Eigen:返回对带有编译时维度检查的矩阵块的引用

2024-01-13

我要问的是一个概括这个问题 https://stackoverflow.com/questions/13548253/eigen-library-return-a-matrix-block-in-a-function-as-lvalue。具体来说,我想围绕遗留的 C 和 Fortran 库制作一个 C++ Eigen 包装器,它使用 2D 数据结构:

[   x[0,0] ...   x[0,w-1] ]
[   u[0,0] ...   u[0,w-1] ]
[          ...            ]
[ x[c-1,0] ... x[c-1,w-1] ]
[ u[c-1,0] ... u[c-1,w-1] ]

其中每个条目x[i,j] and u[i,j]它们本身就是大小为 (nx1) and (mx1) 分别。 这会导致一些复杂(且容易出错)的指针算术以及一些非常不可读的代码。

因此,我想编写一个 Eigen 类,其唯一目的是使提取该矩阵的条目尽可能容易。在 C++14 中,看起来像这样data_getter.h:

#ifndef DATA_GETTER_HEADER
#define DATA_GETTER_HEADER

#include "Eigen/Dense"

template<typename T, int n, int m, int c, int w>
class DataGetter {
public:

    /** Return a reference to the data as a matrix */
    static auto asMatrix(T *raw_ptr) {
        auto out = Eigen::Map<Eigen::Matrix<T, (n + m) * c, w>>(raw_ptr);
        static_assert(decltype(out)::RowsAtCompileTime == (n + m) * c);
        static_assert(decltype(out)::ColsAtCompileTime == w);
        return out;
    }

    /** Return a reference to the submatrix
     * [ x[i,0], ..., x[i,w-1]]
     * [ u[i,0], ..., u[i,w-1]] */
    static auto W(T *raw_ptr, int i) {
        auto out = asMatrix(raw_ptr).template middleRows<n + m>((n + m) * i);
        static_assert(decltype(out)::RowsAtCompileTime == (n + m));
        static_assert(decltype(out)::ColsAtCompileTime == w);
        return out;
    }

    /** Return a reference to the submatrix [ x[i,0], ..., x[i,w-1]] */
    static auto X(T *raw_ptr, int i) {
        auto out = W(raw_ptr, i).template topRows<n>();
        static_assert(decltype(out)::RowsAtCompileTime == n);
        static_assert(decltype(out)::ColsAtCompileTime == w);
        return out;
    }

    /** Return a reference to x[i,j] */
    static auto X(T *raw_ptr, int i, int j) {
        auto out = X(raw_ptr, i).col(j);
        static_assert(decltype(out)::RowsAtCompileTime == n);
        static_assert(decltype(out)::ColsAtCompileTime == 1);
        return out;
    }

    /** Return a reference to the submatrix [ u[i,0], ..., u[i,w-1]] */
    static auto U(T *raw_ptr, int i) {
        auto out = W(raw_ptr, i).template bottomRows<m>();
        static_assert(decltype(out)::RowsAtCompileTime == m);
        static_assert(decltype(out)::ColsAtCompileTime == w);
        return out;
    }

    /** Return a reference to u[i,j] */
    static auto U(T *raw_ptr, int i, int j) {
        auto out = U(raw_ptr, i).col(j);
        static_assert(decltype(out)::RowsAtCompileTime == m);
        static_assert(decltype(out)::ColsAtCompileTime == 1);
        return out;
    }

    /** Return a reference to the submatrix
     * [ x[0,i], ..., x[c-1,i]]
     * [ u[0,i], ..., u[c-1,i]] */
    static auto C(T *raw_ptr, int i) {
        auto out = Eigen::Map<Eigen::Matrix<T, n + m, c>>(
                asMatrix(raw_ptr).col(i).template topRows<(n + m) * c>().data());
        static_assert(decltype(out)::RowsAtCompileTime == (n + m));
        static_assert(decltype(out)::ColsAtCompileTime == c);
        return out;
    }

    /** Return a reference to the submatrix [ x[0,i], ..., x[c-1,i]] */
    static auto Xc(T *raw_ptr, int i) {
        auto out = C(raw_ptr, i).template topRows<n>();
        static_assert(decltype(out)::RowsAtCompileTime == n);
        static_assert(decltype(out)::ColsAtCompileTime == c);
        return out;
    }

    /** Return a reference to the submatrix [ u[0,i], ..., u[c-1,i]] */
    static auto Uc(T *raw_ptr, int i) {
        auto out = C(raw_ptr, i).template bottomRows<m>();
        static_assert(decltype(out)::RowsAtCompileTime == m);
        static_assert(decltype(out)::ColsAtCompileTime == c);
        return out;
    }
};

#endif /* DATA_GETTER_HEADER */

这是一个测试程序,演示了它是如何工作的:

#include <iostream>
#include <vector>
#include "Eigen/Dense"
#include "data_getter.h"

using namespace std;
using namespace Eigen;

template<typename T>
void printSize(MatrixBase<T> &mat) {
    cout << T::RowsAtCompileTime << " x " << T::ColsAtCompileTime;
}

int main() {

    using T = double;
    const int n = 2;
    const int m = 3;
    const int c = 2;
    const int w = 5;
    const int size = w * (c * (n + m));
    std::vector<T> vec;
    for (int i = 0; i < size; ++i)
        vec.push_back(i);

    /* Define the interface that we will use a lot */
    using Data = DataGetter<T, n, m, c, w>;

    /* Now let's map that pointer to some submatrices */
    Ref<Matrix<T, (n + m) * c, w>> allData = Data::asMatrix(vec.data());
    Ref<Matrix<T, n, w>> x1 = Data::X(vec.data(), 1);
    Ref<Matrix<T, n, c>> xc2 = Data::Xc(vec.data(), 2);
    Ref<Matrix<T, n + m, c>> xuc2 = Data::C(vec.data(), 2);
    Ref<Matrix<T, n, 1>> x12 = Data::X(vec.data(), 1, 2);

    cout << "Data::asMatrix( T* ): ";
    printSize(allData);
    cout << endl << endl << allData << endl << endl;
    cout << "Data::X( T*, 1 )    : ";
    printSize(x1);
    cout << endl << endl << x1 << endl << endl;
    cout << "Data::Xc( T*, 2 )   : ";
    printSize(xc2);
    cout << endl << endl << xc2 << endl << endl;
    cout << "Data::C( T*, 2 )    : ";
    printSize(xuc2);
    cout << endl << endl << xuc2 << endl << endl;
    cout << "Data::X( T*, 1, 2 ) : ";
    printSize(x12);
    cout << endl << endl << x12 << endl << endl;

    /* Now changes to x12 should be reflected in the other variables */
    x12.setZero();

    cout << "-----" << endl << endl << "x12.setZero() " << endl << endl << "-----" << endl;

    cout << "allData" << endl << endl << allData << endl << endl;
    cout << "x1" << endl << endl << x1 << endl << endl;
    cout << "xc2" << endl << endl << xc2 << endl << endl;
    cout << "xuc2" << endl << endl << xuc2 << endl << endl;
    cout << "x12" << endl << endl << x12 << endl << endl;
    return 0;
}

具体来说,它产生以下输出(如预期):

Data::asMatrix( T* ): 10 x 5

 0 10 20 30 40
 1 11 21 31 41
 2 12 22 32 42
 3 13 23 33 43
 4 14 24 34 44
 5 15 25 35 45
 6 16 26 36 46
 7 17 27 37 47
 8 18 28 38 48
 9 19 29 39 49

Data::X( T*, 1 )    : 2 x 5

 5 15 25 35 45
 6 16 26 36 46

Data::Xc( T*, 2 )   : 2 x 2

20 25
21 26

Data::C( T*, 2 )    : 5 x 2

20 25
21 26
22 27
23 28
24 29

Data::X( T*, 1, 2 ) : 2 x 1

25
26

-----

x12.setZero() 

-----
allData

 0 10 20 30 40
 1 11 21 31 41
 2 12 22 32 42
 3 13 23 33 43
 4 14 24 34 44
 5 15  0 35 45
 6 16  0 36 46
 7 17 27 37 47
 8 18 28 38 48
 9 19 29 39 49

x1

 5 15  0 35 45
 6 16  0 36 46

xc2

20  0
21  0

xuc2

20  0
21  0
22 27
23 28
24 29

x12

0
0

问题是对维度的编译时检查似乎不起作用。在里面data_getter.h,你可能会注意到我放了一堆static_assert尺寸。这可能看起来有点矫枉过正,但我​​想确保表达式确实执行编译时操作,以便我们可以检查维度。如果它们是动态表达式,那么大小都将为-1。

然而,尽管事实上所有的static_assert通过,似乎没有对引用进行任何编译时检查。例如,如果我们更改测试程序中的以下行

Ref<Matrix<T, (n + m) * c, w>> allData = Data::asMatrix(vec.data());

into

Ref<Matrix<T, (n + m) * c + 1, w>> allData = Data::asMatrix(vec.data());

代码可以编译,但会产生运行时崩溃。这似乎表明Ref正在丢弃维度。那么我应该如何定义这些变量呢?

可能想到的一个想法是将这些返回值定义为auto以及。然而,这是Eigen 文档明确不鼓励 https://eigen.tuxfamily.org/dox/TopicPitfalls.html因为如果我们最终在循环中使用输出,则可能会导致表达式被一遍又一遍地求值。这就是我使用的原因Refs。另外,明确说明大小似乎是个好主意,因为我们在编译时就知道它......

那么这是 Ref 中的一个错误吗?对于所有访问器方法吐出的变量,我应该使用什么类型?


如果你在评论中错过了它......@ggael 说 EigenRef在编译时不检查尺寸。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Eigen:返回对带有编译时维度检查的矩阵块的引用 的相关文章

  • 在 C++ 中使用 matlab 结构(matlab 函数调用的返回值)(由 matlab 编译器生成的库)

    你好 我有一个相当简单的 matlab 函数 例如 function MYSTRUCT myfunc MYSTRUCT prop1 test MYSTRUCT prop2 foo MYSTRUCT prop3 42 end 我用 matla
  • 单个对象的 Monogame XNA 变换矩阵?

    我读过一些解释 XNA Monogame 变换矩阵的教程 问题是这些矩阵应用于 SpriteBatch Begin matrix 这意味着所有 Draw 代码都将被转换 如何将变换矩阵应用于单个可绘制对象 就我而言 我想转换滚动背景 使其自
  • 获取两个工作日之间的天数差异

    这听起来很简单 但我不明白其中的意义 那么获取两次之间的天数的最简单方法是什么DayOfWeeks当第一个是起点时 如果下一个工作日较早 则应考虑在下周 The DayOfWeek 枚举 http 20 20 5B1 5D 3a 20htt
  • 如何使用 LINQ2SQL 连接两个不同上下文的表?

    我的应用程序中有 2 个数据上下文 不同的数据库 并且需要能够通过上下文 B 中的表的右连接来查询上下文 A 中的表 我该如何在 LINQ2SQL 中执行此操作 Why 我们正在使用 SaaS 产品来跟踪我们的时间 项目等 并希望向该产品发
  • 如何检测表单的任何控件的变化?

    如何检测 C 中表单的任何控件的更改 由于我在一个表单上有许多控件 并且如果表单中的任何控件值发生更改 我需要禁用按钮 我正在寻找一些内置函数 事件处理程序 属性 并且不想为此创建自定义函数 不 我不知道任何时候都会触发任何事件any控制表
  • 使用自定义堆的类似 malloc 的函数

    如果我希望使用自定义预分配堆构造类似 malloc 的功能 那么 C 中最好的方法是什么 我的具体问题是 我有一个可映射 类似内存 的设备 已将其放入我的地址空间中 但我需要获得一种更灵活的方式来使用该内存来存储将随着时间的推移分配和释放的
  • 外键与独立关系 - Entity Framework 5 有改进吗?

    我读过了several http www ladislavmrnka com 2011 05 foreign key vs independent associations in ef 4 文章和问题 https stackoverflow
  • CMake 无法确定目标的链接器语言

    首先 我查看了this https stackoverflow com questions 11801186 cmake unable to determine linker language with c发帖并找不到解决我的问题的方法 我
  • AES 128 CBC 蒙特卡罗测试

    我正在 AES 128 CBC 上执行 MCT 如中所述http csrc nist gov groups STM cavp documents aes AESAVS pdf http csrc nist gov groups STM ca
  • “接口”类似于 boost::bind 的语义

    我希望能够将 Java 的接口语义与 C 结合起来 起初 我用过boost signal为给定事件回调显式注册的成员函数 这非常有效 但后来我发现一些函数回调池是相关的 因此将它们抽象出来并立即注册所有实例的相关回调是有意义的 但我了解到的
  • 动态添加 ASP.Net 控件

    我有一个存储过程 它根据数据库中存储的记录数返回多行 现在我想有一种方法来创建 div 带有包含该行值的控件的标记 如果从数据库返回 10 行 则 10 div 必须创建标签 我有下面的代码来从数据库中获取结果 但我不知道如何从这里继续 S
  • 将 MQTTNet 服务器与 MQTT.js 客户端结合使用

    我已经启动了一个 MQTT 服务器 就像this https github com chkr1011 MQTTnet tree master例子 该代码托管在 ASP Net Core 2 0 应用程序中 但我尝试过控制台应用程序 但没有成
  • 使用 C# 读取 Soap 消息

  • 按 Esc 按键关闭 Ajax Modal 弹出窗口

    我已经使用 Ajax 显示了一个面板弹出窗口 我要做的是当用户按 Esc 键时关闭该窗口 这可能吗 如果有人知道这一点或以前做过这一点 请帮助我 Thanks 通过以下链接 您可以通过按退出按钮轻松关闭窗口 http www codepro
  • 方法优化 - C#

    我开发了一种方法 允许我通过参数传入表 字符串 列数组 字符串 和值数组 对象 然后使用这些参数创建参数化查询 虽然它工作得很好 但代码的长度以及多个 for 循环散发出一种代码味道 特别是我觉得我用来在列和值之间插入逗号的方法可以用不同的
  • 如何部署“SQL Server Express + EF”应用程序

    这是我第一次部署使用 SQL Server Express 数据库的应用程序 我首先使用实体 框架模型来联系数据库 我使用 Install Shield 创建了一个安装向导来安装应用程序 这些是我在目标计算机中安装应用程序所执行的步骤 安装
  • C++ 条件编译

    我有以下代码片段 ifdef DO LOG define log p record p else define log p endif void record char data 现在如果我打电话log hello world 在我的代码中
  • 我的班级应该订阅自己的公共活动吗?

    我正在使用 C 3 0 遵循标准事件模式我有 public event EventHandler
  • 如何从 ODBC 连接获取可用表的列表?

    在 Excel 中 我可以转到 数据 gt 导入外部数据 gt 导入数据 然后选择要使用的数据源 然后在提供登录信息后 它会给我一个表格列表 我想知道如何使用 C 以编程方式获取该列表 您正在查询什么类型的数据源 SQL 服务器 使用权 看
  • 如何将 PostgreSql 与 EntityFramework 6.0.2 集成? [复制]

    这个问题在这里已经有答案了 我收到以下错误 实体框架提供程序类型的 实例 成员 Npgsql NpgsqlServices Npgsql 版本 2 0 14 2 文化 中性 PublicKeyToken 5d8b90d52f46fda7 没

随机推荐

  • 将地图标记设置为自定义颜色 Android

    我正在制作一个应用程序 可以在地图的某些点添加图钉 我希望我的图钉颜色与我们应用程序的主题颜色相匹配 抱歉我真的是菜鸟 int color Color rgb 255 201 14 mMap MapFragment getFragmentM
  • 如何解决由内联命名空间中的标识符冲突引起的不明确引用

    考虑以下代码 include
  • git 存档与 cp -R

    如果我有一个 git 存储库的克隆作为远程服务器上的缓存副本用于 capistrano vlad 样式部署 那么最好执行 A git archive format tar origin master cd destination tar x
  • TortoiseHg - 如何在不先提交的情况下创建补丁

    当我想从未提交的更改创建补丁时 我真的必须首先提交吗 TortoiseHg 是否不允许在不执行提交的情况下创建补丁 TortoiseHg 2 0 2 在工作台中 您可以右键单击Working Directory行并选择Export Copy
  • R可以画图吗?

    我想知道 R 中是否有任何包可以使用 x y 坐标和形状大小来绘制如下内容 我有车辆前中心的坐标及其尺寸 长度和宽度 Edit 原始数据集如下所示 gt head df Vehicle ID Frame ID Global X Global
  • 使用drawInRect时UIImage Aspect Fill?

    我尝试像内容模式一样绘制scaleAspectFill 我找到了如何使用 AVFoundation 制作 sacelAspectFit 但我找不到scaleAspectFill 如果我绘制水平图像 我不知道 x 值 image draw i
  • 检查 php 中是否存在 url [重复]

    这个问题在这里已经有答案了 if file exists http example com images thumbnail 1286954822 jpg filefound 0 为什么这不起作用 if file exists http e
  • Raspberry Pi 的 QTMultimedia 编译

    我只需要从 Raspberry Pi 上运行的 QT 5 1 应用程序播放简单的音频 wav 或 mp3 文件 我的控制台应用程序已成功构建并部署到 pi 但是 当我尝试播放该文件时收到一条消息 defaultServiceProvider
  • 在 Typescript 中,我可以创建强制需要属性的映射类型吗?

    在 Typescript 中 我们有映射类型 可以将属性从一种类型映射到另一种类型 一个常见的示例是 Partial 类型 它使泛型类型上的所有属性都成为 可选 我想实现相反的效果 比如 必需 其中所有属性都被设置为 必需 而不管它们预先的
  • 基于事件类型的单元格的 jQuery Datepicker 背景颜色

    我需要根据活动类型或当天的预订是否已满 以不同的颜色显示不可用的日期 下面的示例从数据库中获取日期 并将它们作为数组传递给 JavaScript 目前我在数组中传递四个参数 2012 7 15 Some events 例如年 月 日和年 我
  • 如何从颤振中的坐标获取位置名称?

    我想要一个可以获取用户位置并使用 GPS 显示地名的按钮 I tried map view https pub dartlang org packages map view但它只能获取纬度和经度 use the geocoder https
  • ImportError:无法从“google.protobuf.internal”导入名称“builder”

    我正在关注 22点22分 发现这段代码有错误 python SCRIPTS PATH generate tfrecord py x IMAGE PATH train l ANNOTATION PATH label map pbtxt o A
  • 如何通过 XHR onProgress 函数使用压缩/压缩内容?

    我之前见过很多类似的问题 但我还没有找到一个能够准确描述我当前问题的问题 所以这里是 我有一个页面通过 AJAX 加载一个大的 0 5 到 10 MB 之间 JSON 文档 以便客户端代码可以处理它 加载文件后 我不会遇到任何意外的问题 但
  • CakePHP 3 控制器事件实现示例

    CakePHP 3 0 文档包含如何使用模型创建事件的示例 我试了又试 但它不适合我 有谁有使用自定义事件的 CakePHP 3 x 示例 其中控制器在触发事件的控制器中设置变量 假设我们有一个管理仪表板 您希望使用事件将一些代码注入其中
  • 我真的需要为 const 对象实现用户提供的构造函数吗?

    我有代码 class A public A default private int i 1 int main const A a return 0 它在 g 上编译得很好 参见ideone http ideone com PryGs5 但在
  • 看不到远程分支

    我仍在学习 git 不确定一些基本的东西是如何工作的 我通过执行以下操作创建了本地分支 git branch AppStore 我不记得如何将该分支推送到 github com 但我可以在存储库上看到 MyBranch 当我做 git br
  • AngularJS 模块和外部控制器

    我有一个包含多个容器的页面 每个容器都有自己的控制器 但指向一个工厂 该工厂处理与 Web 服务 API 交互的所有逻辑 我想为每个控制器都有一个单独的文件BUT我希望所有这些都在一个模块中 我一生都找不到如何将不同文件中的控制器包含到一个
  • 我无法运行超过 100 个进程

    我有大量的 shell 命令通过授权服务的 AuthorizationExecuteWithPrivileges 调用以 root admin 权限执行 问题是 一段时间后 10 15 秒 可能是 100 个 shell 命令 程序停止响应
  • iOS 7 启动图像,仅在设备上显示黑屏

    我至少在 stakoverflow 检查了与此问题相关的所有问题 答案 但没有任何成功 到目前为止我的问题是 我创建了一个新的应用程序 目标 IOS 7 并且我在图像中添加了我的启动图像和我的应用程序图标 xcassets 文件夹 当我在模
  • Eigen:返回对带有编译时维度检查的矩阵块的引用

    我要问的是一个概括这个问题 https stackoverflow com questions 13548253 eigen library return a matrix block in a function as lvalue 具体来