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:返回对带有编译时维度检查的矩阵块的引用 的相关文章

  • GCC C++ (ARM) 和指向结构体字段的 const 指针

    假设有一个简单的测试代码 typedef struct int first int second int third type t define ADDRESS 0x12345678 define REGISTER type t ADDRE
  • C++ 中的软(不是:弱)引用 - 这可能吗?有实施吗?

    在 C 中我正在使用boost shared ptr and boost weak ptr自动删除不再需要的对象 我知道这些与引用计数一起工作 在 Java 中 内存由垃圾收集器管理 它将内置对象引用视为strong WeakReferen
  • 将处理后的图形绘制到另一个图形中

    我想将一个经过处理的图形绘制到另一个图形中 I have two graphics var gHead Graphics FromImage h var gBackground Graphics FromImage b Transform
  • 如果.Net Core可以在Windows上运行,为什么不能在.Net Framework中引用.Net Core DLL?

    我明白为什么 Net Framework 可能会在 Net Core IE 中导致问题 因为不存在特定于 Windows 平台的 API 但是为什么不能直接引用 Net Core 作为 Net Framework 中的库呢 如果 Net C
  • 获取两个字符串之间的公共部分c# [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我需要的是获取两个单词之间的共同部分并获取差异 例子 场景1 word1 感言 word2 Test 将返回 公共部分Test 不同之
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • 处理 fanart.tv Web 服务响应 JSON 和 C#

    我正在尝试使用 fanart tv Webservice API 但有几个问题 我正在使用 Json Net Newtonsoft Json 并通过其他 Web 服务将 JSON 响应直接反序列化为 C 对象 这里的问题是元素名称正在更改
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • std::map 和二叉搜索树

    我读过 std map 是使用二叉搜索树数据结构实现的 BST 是一种顺序数据结构 类似于数组中的元素 它将元素存储在 BST 节点中并按其顺序维护元素 例如如果元素小于节点 则将其存储在节点的左侧 如果元素大于节点 则将其存储在节点的右侧
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • C++派生模板类继承自模板基类,无法调用基类构造函数[重复]

    这个问题在这里已经有答案了 我试图从基类 模板 继承 派生类也是模板 它们具有相同的类型 T 我收到编译错误 非法成员初始化 Base 不是基类或成员 为什么 如何调用基类构造函数 include
  • 单元测试失败,异常代码为 c0000005

    我正在尝试使用本机单元测试项目在 Visual Studios 2012 中创建单元测试 这是我的测试 TEST METHOD CalculationsRoundTests int result Calculations Round 1 0
  • 范围和临时初始化列表

    我试图将我认为是纯右值的内容传递到范围适配器闭包对象中 除非我将名称绑定到初始值设定项列表并使其成为左值 否则它不会编译 这里发生了什么 include
  • std::bind 重载解析

    下面的代码工作正常 include
  • 通过等待任务或访问其 Exception 属性都没有观察到任务的异常

    这些是我的任务 我应该如何修改它们以防止出现此错误 我检查了其他类似的线程 但我正在使用等待并继续 那么这个错误是怎么发生的呢 通过等待任务或访问其 Exception 属性都没有观察到任务的异常 结果 未观察到的异常被终结器线程重新抛出
  • Fluent NHibernate 日期时间 UTC

    我想创建一个流畅的 nhibernate 映射来通过以下方式映射 DateTime 字段 保存时 保存 UTC 值 读取时 调整为本地时区值 实现此映射的最佳方法是什么 就我个人而言 我会将日期存储在 UTC 格式的对象中 然后在读 写时在
  • 热重载时调用方法

    我正在使用 Visual Studio 2022 和 C 制作游戏 我想知道当您热重新加载应用程序 当它正在运行时 时是否可以触发一些代码 我基本上有 2 个名为 UnloadLevel 和 LoadLevel 的方法 我想在热重载时执行它
  • boost::program_options:带有固定和可变标记的参数?

    是否可以在 boost program options 中使用此类参数 program p1 123 p2 234 p3 345 p12 678 即 是否可以使用第一个标记指定参数名称 例如 p 后跟一个数字 是动态的吗 我想避免这种情况
  • Swagger 为 ASP.CORE 3 中的字典生成错误的 URL

    当从查询字符串中提取的模型将字典作为其属性之一时 Swagger 会生成不正确的 URL 如何告诉 Swagger 更改 URL 中字典的格式或手动定义输入参数模式而不自动生成 尝试使用 Swashbuckle 和 NSwag 控制器 pu
  • 如何确定母版页中正在显示哪个子页?

    我正在母版页上编写代码 我需要知道正在显示哪个子 内容 页面 我怎样才能以编程方式做到这一点 我用这个 string pageName this ContentPlaceHolder1 Page GetType FullName 它以 AS

随机推荐

  • 将地图标记设置为自定义颜色 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 具体来