Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion Eigen/src/Geometry/Quaternion.h
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,29 @@ class Quaternion : public QuaternionBase<Quaternion<_Scalar,_Options> >
EIGEN_DEVICE_FUNC explicit inline Quaternion(const Quaternion<OtherScalar, OtherOptions>& other)
{ m_coeffs = other.coeffs().template cast<Scalar>(); }

#if EIGEN_HAS_RVALUE_REFERENCES
// We define a copy constructor, which means we don't get an implicit move constructor or assignment operator.
/** Default move constructor */
EIGEN_DEVICE_FUNC inline Quaternion(Quaternion&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_constructible<Scalar>::value)
{
m_coeffs(std::move(other.coeffs()));
}

/** Default move assignment operator */
EIGEN_DEVICE_FUNC Quaternion& operator=(Quaternion&& other) EIGEN_NOEXCEPT_IF(std::is_nothrow_move_assignable<Scalar>::value)
{
m_coeffs = std::move(other.coeffs());
return *this;
}

// And now because we declared a constructor, we don't get an implicit copy constructor. Say we want one.
/** Default copy constructor */
EIGEN_DEVICE_FUNC Quaternion(const Quaternion& other)
{
m_coeffs = other.coeffs();
}
#endif

EIGEN_DEVICE_FUNC static Quaternion UnitRandom();

template<typename Derived1, typename Derived2>
Expand Down Expand Up @@ -623,7 +646,7 @@ EIGEN_DEVICE_FUNC Quaternion<Scalar,Options> Quaternion<Scalar,Options>::UnitRan
const Scalar u1 = internal::random<Scalar>(0, 1),
u2 = internal::random<Scalar>(0, 2*EIGEN_PI),
u3 = internal::random<Scalar>(0, 2*EIGEN_PI);
const Scalar a = sqrt(1 - u1),
const Scalar a = sqrt(Scalar(1) - u1),
b = sqrt(u1);
return Quaternion (a * sin(u2), a * cos(u2), b * sin(u3), b * cos(u3));
}
Expand Down
37 changes: 29 additions & 8 deletions test/geo_quaternion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <Eigen/Geometry>
#include <Eigen/LU>
#include <Eigen/SVD>
#include "AnnoyingScalar.h"

template<typename T> T bounded_acos(T v)
{
Expand Down Expand Up @@ -85,7 +86,7 @@ template<typename Scalar, int Options> void quaternion(void)
if (refangle>Scalar(EIGEN_PI))
refangle = Scalar(2)*Scalar(EIGEN_PI) - refangle;

if((q1.coeffs()-q2.coeffs()).norm() > 10*largeEps)
if((q1.coeffs()-q2.coeffs()).norm() > Scalar(10)*largeEps)
{
VERIFY_IS_MUCH_SMALLER_THAN(abs(q1.angularDistance(q2) - refangle), Scalar(1));
}
Expand Down Expand Up @@ -113,7 +114,7 @@ template<typename Scalar, int Options> void quaternion(void)

// Do not execute the test if the rotation angle is almost zero, or
// the rotation axis and v1 are almost parallel.
if (abs(aa.angle()) > 5*test_precision<Scalar>()
if (abs(aa.angle()) > Scalar(5)*test_precision<Scalar>()
&& (aa.axis() - v1.normalized()).norm() < Scalar(1.99)
&& (aa.axis() + v1.normalized()).norm() < Scalar(1.99))
{
Expand Down Expand Up @@ -272,18 +273,38 @@ template<typename PlainObjectType> void check_const_correctness(const PlainObjec
VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
}

void test_geo_quaternion()
#if EIGEN_HAS_RVALUE_REFERENCES

// Regression for bug 1573
struct MovableClass {
// The following line is a workaround for gcc 4.7 and 4.8 (see bug 1573 comments).
static_assert(std::is_nothrow_move_constructible<Quaternionf>::value,"");
MovableClass() = default;
MovableClass(const MovableClass&) = default;
MovableClass(MovableClass&&) noexcept = default;
MovableClass& operator=(const MovableClass&) = default;
MovableClass& operator=(MovableClass&&) = default;
Quaternionf m_quat;
};

#endif

EIGEN_DECLARE_TEST(geo_quaternion)
{
for(int i = 0; i < g_repeat; i++) {
CALL_SUBTEST_1(( quaternion<float,AutoAlign>() ));
CALL_SUBTEST_1( check_const_correctness(Quaternionf()) );
CALL_SUBTEST_1(( quaternion<float,DontAlign>() ));
CALL_SUBTEST_1(( quaternionAlignment<float>() ));
CALL_SUBTEST_1( mapQuaternion<float>() );

CALL_SUBTEST_2(( quaternion<double,AutoAlign>() ));
CALL_SUBTEST_2( check_const_correctness(Quaterniond()) );
CALL_SUBTEST_3(( quaternion<float,DontAlign>() ));
CALL_SUBTEST_4(( quaternion<double,DontAlign>() ));
CALL_SUBTEST_5(( quaternionAlignment<float>() ));
CALL_SUBTEST_6(( quaternionAlignment<double>() ));
CALL_SUBTEST_1( mapQuaternion<float>() );
CALL_SUBTEST_2(( quaternion<double,DontAlign>() ));
CALL_SUBTEST_2(( quaternionAlignment<double>() ));
CALL_SUBTEST_2( mapQuaternion<double>() );

AnnoyingScalar::dont_throw = true;
CALL_SUBTEST_3(( quaternion<AnnoyingScalar,AutoAlign>() ));
}
}