Quaternion : add Flags on Quaternion's traits with the LvalueBit set if needed

Quaternion : change PacketAccess to IsAligned to mimic other traits
test : add a test and 4 failtest on Map<const Quaternion> based on Eigen::Map ones
This commit is contained in:
Mathieu Gautier 2011-04-12 14:49:50 +02:00
parent f85db18c1c
commit 392eb9fee8
2 changed files with 69 additions and 25 deletions

View File

@ -49,6 +49,9 @@ public:
typedef typename internal::traits<Derived>::Scalar Scalar;
typedef typename NumTraits<Scalar>::Real RealScalar;
typedef typename internal::traits<Derived>::Coefficients Coefficients;
enum {
Flags = Eigen::internal::traits<Derived>::Flags
};
// typedef typename Matrix<Scalar,4,1> Coefficients;
/** the type of a 3D vector */
@ -222,7 +225,8 @@ struct traits<Quaternion<_Scalar,_Options> >
typedef _Scalar Scalar;
typedef Matrix<_Scalar,4,1,_Options> Coefficients;
enum{
PacketAccess = _Options & DontAlign ? Unaligned : Aligned
IsAligned = bool(EIGEN_ALIGN) && ((int(_Options)&Aligned)==Aligned),
Flags = IsAligned ? (AlignedBit | LvalueBit) : LvalueBit
};
};
}
@ -294,33 +298,53 @@ typedef Quaternion<double> Quaterniond;
***************************************************************************/
namespace internal {
template<typename _Scalar, int _PacketAccess>
struct traits<Map<Quaternion<_Scalar>, _PacketAccess> >:
traits<Quaternion<_Scalar> >
{
typedef _Scalar Scalar;
typedef Map<Matrix<_Scalar,4,1>, _PacketAccess> Coefficients;
enum {
PacketAccess = _PacketAccess
template<typename _Scalar, int _Options>
struct traits<Map<Quaternion<_Scalar>, _Options> >:
traits<Quaternion<_Scalar, _Options> >
{
typedef _Scalar Scalar;
typedef Map<Matrix<_Scalar,4,1>, _Options> Coefficients;
typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
enum {
IsAligned = TraitsBase::IsAligned,
Flags = TraitsBase::Flags
};
};
}
namespace internal {
template<typename _Scalar, int _Options>
struct traits<Map<const Quaternion<_Scalar>, _Options> >:
traits<Quaternion<_Scalar> >
{
typedef _Scalar Scalar;
typedef Map<const Matrix<_Scalar,4,1>, _Options> Coefficients;
typedef traits<Quaternion<_Scalar, _Options> > TraitsBase;
enum {
IsAligned = TraitsBase::IsAligned,
Flags = TraitsBase::Flags & ~LvalueBit
};
};
};
}
/** \brief Quaternion expression mapping a constant memory buffer
*
* \param _Scalar the type of the Quaternion coefficients
* \param PacketAccess see class Map
* \param _Options see class Map
*
* This is a specialization of class Map for Quaternion. This class allows to view
* a 4 scalar memory buffer as an Eigen's Quaternion object.
*
* \sa class Map, class Quaternion, class QuaternionBase
*/
template<typename _Scalar, int PacketAccess>
class Map<const Quaternion<_Scalar>, PacketAccess >
: public QuaternionBase<Map<const Quaternion<_Scalar>, PacketAccess> >
template<typename _Scalar, int _Options>
class Map<const Quaternion<_Scalar>, _Options >
: public QuaternionBase<Map<const Quaternion<_Scalar>, _Options> >
{
typedef QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> > Base;
typedef QuaternionBase<Map<const Quaternion<_Scalar>, _Options> > Base;
public:
typedef _Scalar Scalar;
@ -333,7 +357,7 @@ class Map<const Quaternion<_Scalar>, PacketAccess >
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
* \code *coeffs == {x, y, z, w} \endcode
*
* If the template parameter PacketAccess is set to Aligned, then the pointer coeffs must be aligned. */
* If the template parameter _Options is set to Aligned, then the pointer coeffs must be aligned. */
EIGEN_STRONG_INLINE Map(const Scalar* coeffs) : m_coeffs(coeffs) {}
inline const Coefficients& coeffs() const { return m_coeffs;}
@ -345,18 +369,18 @@ class Map<const Quaternion<_Scalar>, PacketAccess >
/** \brief Expression of a quaternion from a memory buffer
*
* \param _Scalar the type of the Quaternion coefficients
* \param PacketAccess see class Map
* \param _Options see class Map
*
* This is a specialization of class Map for Quaternion. This class allows to view
* a 4 scalar memory buffer as an Eigen's Quaternion object.
*
* \sa class Map, class Quaternion, class QuaternionBase
*/
template<typename _Scalar, int PacketAccess>
class Map<Quaternion<_Scalar>, PacketAccess >
: public QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> >
template<typename _Scalar, int _Options>
class Map<Quaternion<_Scalar>, _Options >
: public QuaternionBase<Map<Quaternion<_Scalar>, _Options> >
{
typedef QuaternionBase<Map<Quaternion<_Scalar>, PacketAccess> > Base;
typedef QuaternionBase<Map<Quaternion<_Scalar>, _Options> > Base;
public:
typedef _Scalar Scalar;
@ -369,7 +393,7 @@ class Map<Quaternion<_Scalar>, PacketAccess >
* The pointer \a coeffs must reference the four coeffecients of Quaternion in the following order:
* \code *coeffs == {x, y, z, w} \endcode
*
* If the template parameter PacketAccess is set to Aligned, then the pointer coeffs must be aligned. */
* If the template parameter _Options is set to Aligned, then the pointer coeffs must be aligned. */
EIGEN_STRONG_INLINE Map(Scalar* coeffs) : m_coeffs(coeffs) {}
inline Coefficients& coeffs() { return m_coeffs; }
@ -399,7 +423,7 @@ typedef Map<Quaternion<double>, Aligned> QuaternionMapAlignedd;
// Generic Quaternion * Quaternion product
// This product can be specialized for a given architecture via the Arch template argument.
namespace internal {
template<int Arch, class Derived1, class Derived2, typename Scalar, int PacketAccess> struct quat_product
template<int Arch, class Derived1, class Derived2, typename Scalar, int _Options> struct quat_product
{
EIGEN_STRONG_INLINE static Quaternion<Scalar> run(const QuaternionBase<Derived1>& a, const QuaternionBase<Derived2>& b){
return Quaternion<Scalar>
@ -423,7 +447,7 @@ QuaternionBase<Derived>::operator* (const QuaternionBase<OtherDerived>& other) c
YOU_MIXED_DIFFERENT_NUMERIC_TYPES__YOU_NEED_TO_USE_THE_CAST_METHOD_OF_MATRIXBASE_TO_CAST_NUMERIC_TYPES_EXPLICITLY)
return internal::quat_product<Architecture::Target, Derived, OtherDerived,
typename internal::traits<Derived>::Scalar,
internal::traits<Derived>::PacketAccess && internal::traits<OtherDerived>::PacketAccess>::run(*this, other);
internal::traits<Derived>::IsAligned && internal::traits<OtherDerived>::IsAligned>::run(*this, other);
}
/** \sa operator*(Quaternion) */

View File

@ -124,7 +124,8 @@ template<typename Scalar, int Options> void quaternion(void)
template<typename Scalar> void mapQuaternion(void){
typedef Map<Quaternion<Scalar>, Aligned> MQuaternionA;
typedef Map<Quaternion<Scalar> > MQuaternionUA;
typedef Map<Quaternion<Scalar> > MQuaternionUA;
typedef Map<const Quaternion<Scalar> > MCQuaternionUA;
typedef Quaternion<Scalar> Quaternionx;
EIGEN_ALIGN16 Scalar array1[4];
@ -139,9 +140,11 @@ template<typename Scalar> void mapQuaternion(void){
Quaternionx q1 = MQuaternionA(array1);
Quaternionx q2 = MQuaternionA(array2);
Quaternionx q3 = MQuaternionUA(array3unaligned);
Quaternionx q4 = MCQuaternionUA(array3unaligned);
VERIFY_IS_APPROX(q1.coeffs(), q2.coeffs());
VERIFY_IS_APPROX(q1.coeffs(), q3.coeffs());
VERIFY_IS_APPROX(q4.coeffs(), q3.coeffs());
#ifdef EIGEN_VECTORIZE
VERIFY_RAISES_ASSERT((MQuaternionA(array3unaligned)));
#endif
@ -171,11 +174,28 @@ template<typename Scalar> void quaternionAlignment(void){
#endif
}
template<typename PlainObjectType> void check_const_correctness(const PlainObjectType&)
{
// there's a lot that we can't test here while still having this test compile!
// the only possible approach would be to run a script trying to compile stuff and checking that it fails.
// CMake can help with that.
// verify that map-to-const don't have LvalueBit
typedef typename internal::add_const<PlainObjectType>::type ConstPlainObjectType;
VERIFY( !(internal::traits<Map<ConstPlainObjectType> >::Flags & LvalueBit) );
VERIFY( !(internal::traits<Map<ConstPlainObjectType, Aligned> >::Flags & LvalueBit) );
VERIFY( !(Map<ConstPlainObjectType>::Flags & LvalueBit) );
VERIFY( !(Map<ConstPlainObjectType, Aligned>::Flags & LvalueBit) );
}
void 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_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>() ));