gpt4 book ai didi

c++ - 一般产品中的特征自动类型推导

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:53:00 24 4
gpt4 key购买 nike

我有以下一段代码(我为稍大的代码道歉片段,这是我能够将我的问题减少到的最小示例):

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

// Dynamic Matrix over Scalar field
template <typename Scalar>
using DynMat = Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic>;

// Dynamic column vector over Scalar field
template <typename Scalar>
using DynVect = Eigen::Matrix<Scalar, Eigen::Dynamic, 1>;

// Returns the D x D Identity matrix over the field Derived::Scalar
// deduced from the expression Eigen::MatrixBase<Derived>& A
template<typename Derived>
DynMat<typename Derived::Scalar> Id(const Eigen::MatrixBase<Derived>& A, std::size_t D)
{
DynMat<typename Derived::Scalar> result =
DynMat<typename Derived::Scalar>::Identity(D, D);

return result;
}

int main()
{
//using ScalarField = std::complex<double>; // same issue even if I use complex numbers
using ScalarField = double; // we use doubles in this example

// A double dynamic matrix (i.e. MatrixXd)
DynMat<ScalarField> Foo; // used to deduce the type in Id<>()

// A double dynamic column vector (i.e. VectorXd)
DynVect<ScalarField> v(4);
v << 1., 0. , 0. ,0.; // plug in some values into it

// Make sure that Id(Foo, 4) correctly deduces the template parameters
std::cout << "Id(Foo, 4) is indeed the 4 x 4 identiy matrix over the ScalarField of "
<< "typeid().name(): " << typeid(ScalarField).name() << std::endl;
std::cout << Id(Foo, 4) << std::endl; // Indeed the 4 x 4 complex Identity matrix

// Use auto type deduction for GenMatProduct, junk is displayed. Why?!
std::cout << std::endl << "Use auto type deduction for GenMatProduct,\
sometimes junk is displayed. Why?!" << std::endl;
auto autoresult = Id(Foo, 4) * v; // evaluated result must be identically equal to v
for(int i=0; i<10; i++)
{
std::cout << autoresult.transpose(); // thought 1 0 0 0 is the result, but NO, junk
std::cout << " has norm: " << autoresult.norm() << std::endl; // junk
}

// Use implicit cast to Dynamic Matrix, works fine
std::cout << std::endl << "Use implicit cast to Dynamic Matrix, works fine" << std::endl;
DynMat<ScalarField> castresult = Id(Foo, 4) * v; // evaluated result must be identically equal to v
for(int i=0; i<10; i++)
{
std::cout << castresult.transpose(); // 1 0 0 0, works ok
std::cout << " has norm: " << castresult.norm() << std::endl; // ok
}
}

主要思想是模板函数Id<>()采用特征表达式 A作为参数,连同尺寸 D , 并产生单位矩阵在表达式的标量场上 A .这个功能本身工作正常。然而,当我在带有 auto 的 Eigen 产品中使用它时推导类型,例如在行中 auto autoresult = Id(Foo, 4) * v ,我希望乘以 vector v通过单位矩阵,所以最终结果应该是一个表达式,评估时,应完全等于 v .但这种情况并非如此,看第一个for循环,每当我显示结果并计算其范数时,我大部分时间都是垃圾。另一方面,如果我隐式投 Eigen 积 Id(Foo, 4) * v对于动态矩阵,一切正常,结果得到了适当的评估。

我在 OS X Yosemite 上使用 Eigen 3.2.2,得到同样奇怪的结果g++4.9.1 和Apple LLVM 版本 6.0 (clang-600.0.54)(基于 LLVM 3.5svn)

问题:

  • 我不明白第一个 for 发生了什么循环,为什么我用std::cout的时候不评价产品吗? ,甚至当我使用 norm方法?我错过了什么吗?没有别名涉及到这里,我真的对发生的事情感到困惑。我知道Eigen 使用惰性评估,并在以下情况下评估表达式需要,但这里似乎并非如此。这个问题是对我来说非常重要,因为我有很多相同的功能味道为Id<>() , 当用于 auto 时推导表达式可能会失败。

此问题经常发生,但并非总是如此。但是,如果您运行编程3-4次,你一定会看到。

我用来编译和运行它的命令是:

clang++ (g++) -std=c++11 -isystem ./eigen_3.2.2/ testeigen.cpp -otesteigen; ./testeigen

我在实际运行中得到的典型输出是:

Id(Foo, 4) is indeed the 4 x 4 identiy matrix over the ScalarField of typeid().name(): d
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

Use GenMatProduct, sometimes junk is displayed. Why?!
1 0 0 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf
3.10504e+231 3.10504e+231 3.95253e-323 0 has norm: inf

Use implicit cast to Dynamic Matrix, works fine
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1
1 0 0 0 has norm: 1

即使我使用 eval()

  std::cout << autoresult.eval().transpose(); // thought 1 0 0 0 is the result, but NO, junk
std::cout << " has norm: " << autoresult.eval().norm() << std::endl; // junk

我遇到了同样的奇怪行为。

最佳答案

问题在于 Id() 返回一个临时值,它通过引用存储在表示表达式 Id(Foo, 4) * v 的对象中。因此,在 auto 语句之后,autoresult 存储了对死对象的引用。如果您不想要抽象表达式而是实际结果,请不要使用 auto 或调用 eval 来强制求值:

auto autoresult = (Id(Foo, 4) * v).eval();

第三种选择是让 Id() 返回的对象可用于进一步的计算:

auto id4 = Id(Foo,4);
auto autoresult = id4 * v;

但在这种情况下,只要您使用autoresult,产品就会被重新评估,以下将输出不同的结果:

cout << autoresult;
v.setRandom();
cout << autoresult;

关于c++ - 一般产品中的特征自动类型推导,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26705446/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com