[Eigen中文文档] 断言

简介: 宏 eigen_assert默认定义为 eigen_plain_assert。我们使用 eigen_plain_assert而不是 assert来解决 GCC <= 4.3 的已知错误。基本上,eigen_plain_assert就是断言。

文档总目录

英文原文(Assertions)

断言

eigen_assert默认定义为 eigen_plain_assert。我们使用 eigen_plain_assert而不是 assert来解决 GCC <= 4.3 的已知错误。基本上,eigen_plain_assert就是断言。

重新定义断言

eigen_asserteigen_plain_assert两者都定义在Macros.h文件中。定义eigen_assert间接地提供了更改其行为的机会。如果您想执行其他操作(例如抛出异常),则可以重新定义此宏,并使用eigen_plain_assert返回其默认行为。以下代码告诉Eigen抛出一个std::runtime_error异常:

#include <stdexcept>
#undef eigen_assert
#define eigen_assert(x) \
  if (!(x)) { throw (std::runtime_error("Put your message here")); }

禁用断言

断言会消耗运行时间并且可以关闭。您可以通过在包含 Eigen 标头之前定义 EIGEN_NO_DEBUG来抑制 eigen_assertEIGEN_NO_DEBUG默认情况下未定义,除非定义了 NDEBUG

静态断言

静态断言直到 C++11 才标准化。然而,在 Eigen 库中,有很多条件可以而且应该在编译时检测到。例如,我们使用静态断言来防止下面的代码编译。

Matrix3d()  + Matrix4d();   // adding matrices of different sizes
Matrix4cd() * Vector3cd();  // invalid product known at compile time

静态断言在 StaticAssert.h 中定义。如果有原生的 static_assert,我们就使用它。否则,我们实现了一个断言宏,可以显示有限范围的消息。

可以轻松地提出没有消息的静态断言,例如:

#define STATIC_ASSERT(x) \
  switch(0) { case 0: case x:; }

然而,上面的例子显然无法说明断言失败的原因。因此,我们在命名空间 Eigen::internal 中定义一个结构体来处理可用的消息。

template<bool condition>
struct static_assertion {
   };

template<>
struct static_assertion<true>
{
   
  enum {
   
    YOU_TRIED_CALLING_A_VECTOR_METHOD_ON_A_MATRIX,
    YOU_MIXED_VECTORS_OF_DIFFERENT_SIZES,
    // see StaticAssert.h for all enums.
  };
};

然后,我们定义EIGEN_STATIC_ASSERT(CONDITION,MSG)以访问Eigen::internal::static_assertion<bool(CONDITION)>::MSG。如果条件计算为false,则编译器会显示许多消息,说明在static_assert<false>中不存在MSG。尽管如此,这不是我们感兴趣的。正如您所看到的,static_assert<true>的所有成员都是使用ALL_CAPS_AND_THEY_ARE_SHOUTING

警告:

使用此宏时,MSG 应该是 static_assertion<true> 的成员,否则静态断言总是失败。目前,它只能在函数范围内使用。

派生静态断言

还有其他从 EIGEN_STATIC_ASSERT 派生的宏来增强可读性。他们的名字是不言自明的。

  • EIGEN_STATIC_ASSERT_FIXED_SIZE(TYPE) 如果 TYPE 是固定大小则通过。
  • EIGEN_STATIC_ASSERT_DYNAMIC_SIZE(TYPE) 如果 TYPE 是动态大小则通过。
  • EIGEN_STATIC_ASSERT_LVALUE(Derived) 如果 Derived 是只读的,则失败。
  • EIGEN_STATIC_ASSERT_ARRAYXPR(Derived) 如果 Derived 是数组表达式,则通过。
  • EIGEN_STATIC_ASSERT_SAME_XPR_KIND(Derived1, Derived2) 如果两个表达式是数组和矩阵,则失败。

由于 Eigen 同时处理固定大小和动态大小表达式,因此某些条件无法在编译时明确确定。我们将它们分为严格断言和宽容断言。

严格断言

如果条件不满足,这些断言就会失败。例如,MatrixXd可能不是向量,因此它会失败 EIGEN_STATIC_ASSERT_VECTOR_ONLY

  • EIGEN_STATIC_ASSERT_VECTOR_ONLY(TYPE) 如果 TYPE 必须是向量类型,则通过。
  • EIGEN_STATIC_ASSERT_VECTOR_SPECIFIC_SIZE(TYPE, SIZE) 如果 TYPE 必须是给定大小的向量,则通过。
  • EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(TYPE, ROWS, COLS) 如果 TYPE 必须是具有给定行和列的矩阵,则通过。
宽容断言

如果无法满足条件,这些断言就会失败。例如,MatrixXdMatrix4d可能具有相同的大小,因此它们传递 EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE

  • EIGEN_STATIC_ASSERT_SAME_VECTOR_SIZE(TYPE0,TYPE1) 如果两个向量表达式类型必须具有不同的大小,则失败。
  • EIGEN_STATIC_ASSERT_SAME_MATRIX_SIZE(TYPE0,TYPE1) 如果两个矩阵表达式类型必须具有不同的大小,则失败。
  • EIGEN_STATIC_ASSERT_SIZE_1x1(TYPE) 如果 TYPE 不能是 1x1 表达式,则失败。

有关它们抛出的消息等详细信息,请参阅 StaticAssert.h

禁用静态断言

如果定义了 EIGEN_NO_STATIC_ASSERT,静态断言将变成 eigen_assert,工作方式如下:

#define EIGEN_STATIC_ASSERT(CONDITION,MSG) eigen_assert((CONDITION) && #MSG);

这节省了编译时间,但消耗了更多运行时间。默认情况下,EIGEN_NO_STATIC_ASSERT 未定义。

相关文章
|
并行计算 算法 测试技术
[Eigen中文文档] 稠密分解方法目录
本文介绍了 Eigen 提供的处理稠密矩阵分解方法的目录。
270 0
|
存储 编译器 C语言
[Eigen中文文档] 对未对齐数组断言的解释
本文将解释程序因断言失败而终止的问题。
384 0
|
存储 NoSQL API
[Eigen中文文档] Matrix类
在Eigen中,所有矩阵和向量都是Matrix模板类的对象。向量只是行数或者列数为1的特殊矩阵。
806 1
|
存储 C语言 C++
|
存储 编译器
|
存储 并行计算 算法
[Eigen中文文档] 概述(总目录)
Eigen是基于线性代数的C ++模板库,主要用于矩阵,向量,数值求解器和相关算法。常用的Ceres、G2O等项目均是基于Eigen库。 本系列文章将通过官方文档带你了解Eigen。
2615 1
|
安全 编译器 C++
[Eigen中文文档] 矩阵与向量运算
本文章旨在提供有关如何使用 Eigen 在矩阵、向量和标量之间执行算术操作的概述和一些详细信息。
814 0
|
存储 JavaScript 索引
[Eigen中文文档] 归约、访问者和广播
本文介绍了Eigen的归约、访问者和广播,以及它们如何与矩阵和数组一起使用。
393 0
|
存储 编译器 对象存储
[Eigen中文文档] 包含Eigen对象的结构体
如果定义的结构体包含固定大小的可向量化 Eigen 类型成员,则必须确保对其调用 operator new 来分配正确的对齐缓冲区。如果仅使用足够新的编译器(例如,GCC>=7、clang>=5、MSVC>=19.12)以 [c++17] 模式编译,那么编译器会自动处理所有事情,可以跳过本节。 否则,必须重载它的 operator new 以便它生成正确对齐的指针(例如,Vector4d 和 AVX 的 32 字节对齐)。幸运的是,Eigen 为提供了一个宏 EIGEN_MAKE_ALIGNED_OPERATOR_NEW 来完成这项工作。
415 0
|
存储
[Eigen中文文档] Reshape操作
从 Eigen3.4 开始,Eigen 发布了将矩阵或向量重塑为不同大小的便捷方法。所有的操作可以通过 DenseBase::reshaped(NRowsType,NColsType) 和 DenseBase::reshaped() 两个函数完成。这些函数并不直接改变原有的变量,而是返回一个重塑后的变量副本。
357 0