я следующий кусок кода (Извиняюсь за несколько больший код сниппета, это минимальный пример, который я смог уменьшить мою проблему к):собственный автоматический тип вычет в общем продукте
#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<>()
принимает значение Eigen A
в качестве параметра вместе с размером D
и создает идентификационную матрицу над скалярным полем выражения A
. Эта функция сама по себе отлично работает. Тем не менее, , когда я использую его в качестве продукта Эйгена с auto
выведенного типа, например, в линии auto autoresult = Id(Foo, 4) * v
, я ожидал бы умножать вектор v
единичной матрицы, так что чистый результат должен быть выражением, которое, когда оценивается, должно быть тождественно равным v
. Но это не так, см. Первый цикл for
, всякий раз, когда я показываю результат и вычисляет его норму, Я получаю большую часть времени мусор. Если, с другой стороны, я неявно отбрасываю собственный продукт Id(Foo, 4) * v
в динамическую матрицу, все работает нормально, результат правильно оценивается.
Я использую Эйгена 3.2.2 на OS X Yosemite, и получить такое же странное поведение как с г ++ 4.9.1 и компании Apple LLVM версии 6,0 (Звон-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
У меня такое же странное поведение.
Спасибо большое! Один последний вопрос: не временный объект, хранящийся через привязку ссылки const к временному, поэтому время жизни временного объекта совпадает с временем жизни выражения? – vsoftco
Да, временная информация хранится с помощью ссылки на константу, но это не продлевает срок ее службы, поскольку существует одно косвенное направление. Этот механизм расширения продолжительности жизни не является транзитивным. – ggael
спасибо, получилось. – vsoftco